Merge branch 'master' into topaz

Conflicts:
	client/Makefile
	client/cmdhf.c
	client/cmdhf14a.c
This commit is contained in:
pwpiwi 2015-07-01 08:17:00 +02:00
commit db2b81ba11
119 changed files with 20403 additions and 4640 deletions

1
.gitignore vendored
View file

@ -12,6 +12,7 @@
*.bin *.bin
*.dll *.dll
*.moc.cpp *.moc.cpp
*.z
*.exe *.exe
proxmark proxmark
proxmark3 proxmark3

View file

@ -3,13 +3,38 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [Unreleased][unreleased] ## [Unreleased][unreleased]
### Changed
- Iclass read, `hf iclass read` now also reads tag config and prints configuration. (holiman)
### Fixed ### Changed
- Fixed issue #19, problems with LF T55xx commands (marshmellow) - Changed `hf 14b write` to `hf 14b sriwrite` as it only applied to sri tags (marshmellow)
- Added `hf 14b info` to `hf search` (marshmellow)
### Added ### Added
- Add `hf 14b info` to find and print info about std 14b tags and sri tags (using 14b raw commands in the client) (marshmellow)
- Add PACE replay functionality (frederikmoellers)
### Fixed
- t55xx write timing (marshmellow)
## [2.1.0][2015-06-23]
### Changed
- Added ultralight/ntag tag type detection to `hf 14a read` (marshmellow)
- Improved ultralight dump command to auto detect tag type, take authentication, and dump full memory (or subset specified) of known tag types (iceman1001 / marshmellow)
- Combined ultralight read/write commands and added authentication (iceman1001)
- Improved LF manchester and biphase demodulation and ask clock detection especially for reads with heavy clipping. (marshmellow)
- Iclass read, `hf iclass read` now also reads tag config and prints configuration. (holiman)
- *bootrom* needs to be flashed, due to new address boundaries between os and fpga, after a size optimization (piwi)
### Fixed
- Fixed EM4x50 read/demod of the tags broadcasted memory blocks. 'lf em4x em4x50read' (not page read) (marshmellow)
- Fixed issue #19, problems with LF T55xx commands (iceman1001, marshmellow)
- Fixed various problems with iso14443b, issue #103 (piwi, marshmellow)
### Added
- Added `hf search` - currently tests for 14443a tags, iclass tags, and 15693 tags (marshmellow)
- Added `hf mfu info` Ultralight/NTAG info command - reads tag configuration and info, allows authentication if needed (iceman1001, marshmellow)
- Added Mifare Ultralight C and Ultralight EV1/NTAG authentication. (iceman1001)
- Added changelog - Added changelog
## [2.0.0] - 2015-03-25 ## [2.0.0] - 2015-03-25

View file

@ -81,7 +81,31 @@ Download the ProxSpace environment archive and extract it to C:\
= Mac OS X = = Mac OS X =
============ ============
macport stuff should do ;) Tested on OSX 10.10 Yosemite
1 - Install Xcode and Xcode Command Line Tools
2 - Install Homebrew and dependencies
brew install readline
brew instal libusb
3 - Download DevKitARM for OSX
http://sourceforge.net/projects/devkitpro/files/devkitARM/devkitARM_r44/
Unpack devkitARM_r44-osx.tar.bz2 to proxmark3 directory.
4 - Edit proxmark3/client/Makefile adding path to readline
LDLIBS = -L/usr/local/Cellar/readline/6.3.8/lib/ -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthread -lm
CFLAGS = -std=c99 -I/usr/local/Cellar/readline/6.3.8/include/ -I. -I../include -I../common -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4
Replace path /usr/local/Cellar/readline/6.3.8 with your actuall readline path. See homebrew manuals.
5 - Set Environment
export DEVKITPRO=$HOME/proxmark3/
export DEVKITARM=$DEVKITPRO/devkitARM
export PATH=${PATH}:${DEVKITARM}/bin
============ ============
= Linux = = Linux =

View file

@ -1,9 +1,8 @@
include common/Makefile.common include common/Makefile.common
GZIP=gzip
FLASH_PORT=/dev/ttyACM0 FLASH_PORT=/dev/ttyACM0
all clean: %: bootrom/% armsrc/% client/% recovery/% all clean: %: client/% bootrom/% armsrc/% recovery/%
bootrom/%: FORCE bootrom/%: FORCE
$(MAKE) -C bootrom $(patsubst bootrom/%,%,$@) $(MAKE) -C bootrom $(patsubst bootrom/%,%,$@)
@ -15,8 +14,8 @@ recovery/%: FORCE
$(MAKE) -C recovery $(patsubst recovery/%,%,$@) $(MAKE) -C recovery $(patsubst recovery/%,%,$@)
FORCE: # Dummy target to force remake in the subdirectories, even if files exist (this Makefile doesn't know about the prerequisites) FORCE: # Dummy target to force remake in the subdirectories, even if files exist (this Makefile doesn't know about the prerequisites)
.PHONY: all clean help _test flash-bootrom flash-os flash-all FORCE
.PHONY: all clean help _test flash-bootrom flash-os flash-fpga flash-both flash-all FORCE
help: help:
@echo Multi-OS Makefile, you are running on $(DETECTED_OS) @echo Multi-OS Makefile, you are running on $(DETECTED_OS)
@echo Possible targets: @echo Possible targets:
@ -24,9 +23,7 @@ help:
@echo + client - Make only the OS-specific host directory @echo + client - Make only the OS-specific host directory
@echo + flash-bootrom - Make bootrom and flash it @echo + flash-bootrom - Make bootrom and flash it
@echo + flash-os - Make armsrc and flash os (includes fpga) @echo + flash-os - Make armsrc and flash os (includes fpga)
@echo + flash-fpga - (Deprecated:) Make armsrc and flash fpga @echo + flash-all - Make bootrom and armsrc and flash bootrom and os image
@echo + flash-both - Make armsrc and flash os and fpga image
@echo + flash-all - Make bootrom and armsrc and flash bootrom, os and fpga image
@echo + clean - Clean in bootrom, armsrc and the OS-specific host directory @echo + clean - Clean in bootrom, armsrc and the OS-specific host directory
client: client/all client: client/all
@ -34,16 +31,10 @@ client: client/all
flash-bootrom: bootrom/obj/bootrom.elf $(FLASH_TOOL) flash-bootrom: bootrom/obj/bootrom.elf $(FLASH_TOOL)
$(FLASH_TOOL) $(FLASH_PORT) -b $(subst /,$(PATHSEP),$<) $(FLASH_TOOL) $(FLASH_PORT) -b $(subst /,$(PATHSEP),$<)
flash-os: armsrc/obj/osimage.elf $(FLASH_TOOL) flash-os: armsrc/obj/fullimage.elf $(FLASH_TOOL)
$(FLASH_TOOL) $(FLASH_PORT) $(subst /,$(PATHSEP),$<) $(FLASH_TOOL) $(FLASH_PORT) $(subst /,$(PATHSEP),$<)
#flash-fpga: armsrc/obj/fpgaimage.elf $(FLASH_TOOL) flash-all: bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf $(FLASH_TOOL)
# $(FLASH_TOOL) $(FLASH_PORT) $(subst /,$(PATHSEP),$<)
flash-both: armsrc/obj/osimage.elf $(FLASH_TOOL)
$(FLASH_TOOL) $(FLASH_PORT) $(subst /,$(PATHSEP),$(filter-out $(FLASH_TOOL),$^))
flash-all: bootrom/obj/bootrom.elf armsrc/obj/osimage.elf $(FLASH_TOOL)
$(FLASH_TOOL) $(FLASH_PORT) -b $(subst /,$(PATHSEP),$(filter-out $(FLASH_TOOL),$^)) $(FLASH_TOOL) $(FLASH_PORT) -b $(subst /,$(PATHSEP),$(filter-out $(FLASH_TOOL),$^))
newtarbin: newtarbin:

View file

@ -40,7 +40,7 @@ your operating system. Please refer to the Wiki for details.
OBTAINING HARDWARE: OBTAINING HARDWARE:
The Proxmark 3 is available for purcahse (assembled and tested) from the The Proxmark 3 is available for purchase (assembled and tested) from the
following locations: following locations:
* http://proxmark3.com/ * http://proxmark3.com/

View file

@ -96,9 +96,6 @@ uint16_t BigBuf_max_traceLen(void)
} }
void clear_trace() { void clear_trace() {
uint8_t *trace = BigBuf_get_addr();
uint16_t max_traceLen = BigBuf_max_traceLen();
memset(trace, 0x44, max_traceLen);
traceLen = 0; traceLen = 0;
} }

View file

@ -10,21 +10,38 @@ APP_INCLUDES = apps.h
#remove one of the following defines and comment out the relevant line #remove one of the following defines and comment out the relevant line
#in the next section to remove that particular feature from compilation #in the next section to remove that particular feature from compilation
APP_CFLAGS = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG -DWITH_CRC -DON_DEVICE -fno-strict-aliasing -ffunction-sections -fdata-sections APP_CFLAGS = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG -DWITH_CRC -DON_DEVICE \
-fno-strict-aliasing -ffunction-sections -fdata-sections
#-DWITH_LCD #-DWITH_LCD
#SRC_LCD = fonts.c LCD.c #SRC_LCD = fonts.c LCD.c
SRC_LF = lfops.c hitag2.c lfsampling.c SRC_LF = lfops.c hitag2.c lfsampling.c
SRC_ISO15693 = iso15693.c iso15693tools.c SRC_ISO15693 = iso15693.c iso15693tools.c
SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c
SRC_ISO14443b = iso14443.c SRC_ISO14443b = iso14443b.c
SRC_CRAPTO1 = crapto1.c crypto1.c des.c aes.c SRC_CRAPTO1 = crapto1.c crypto1.c des.c aes.c
SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c
#the FPGA bitstream files. Note: order matters!
FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit
#the zlib source files required for decompressing the fpga config at run time
SRC_ZLIB = inflate.c inffast.c inftrees.c adler32.c zutil.c
#additional defines required to compile zlib
ZLIB_CFLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED
APP_CFLAGS += $(ZLIB_CFLAGS)
# zlib includes:
APP_CFLAGS += -I../zlib
# stdint.h provided locally until GCC 4.5 becomes C99 compliant
APP_CFLAGS += -I.
# Compile these in thumb mode (small size)
THUMBSRC = start.c \ THUMBSRC = start.c \
$(SRC_LCD) \ $(SRC_LCD) \
$(SRC_ISO15693) \ $(SRC_ISO15693) \
$(SRC_LF) \ $(SRC_LF) \
$(SRC_ZLIB) \
appmain.c \ appmain.c \
printf.c \ printf.c \
util.c \ util.c \
@ -45,50 +62,63 @@ ARMSRC = fpgaloader.c \
BigBuf.c \ BigBuf.c \
optimized_cipher.c optimized_cipher.c
# stdint.h provided locally until GCC 4.5 becomes C99 compliant
APP_CFLAGS += -I.
# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC # Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC
include ../common/Makefile.common include ../common/Makefile.common
OBJS = $(OBJDIR)/osimage.s19 OBJS = $(OBJDIR)/fullimage.s19
#$(OBJDIR)/fpgaimage.s19 FPGA_COMPRESSOR = ../client/fpga_compress
all: $(OBJS) all: $(OBJS)
$(OBJDIR)/fpga_lf.o: fpga_lf.bit .DELETE_ON_ERROR:
$(OBJCOPY) -O elf32-littlearm -I binary -B arm --redefine-sym _binary____fpga_fpga_lf_bit_start=_binary_fpga_lf_bit_start --redefine-sym _binary____fpga_fpga_lf_bit_end=_binary_fpga_lf_bit_end --prefix-sections=fpga_lf_bit $^ $@
$(OBJDIR)/fpga_hf.o: fpga_hf.bit $(OBJDIR)/fpga_all.o: $(OBJDIR)/fpga_all.bit.z
$(OBJCOPY) -O elf32-littlearm -I binary -B arm --redefine-sym _binary____fpga_fpga_hf_bit_start=_binary_fpga_hf_bit_start --redefine-sym _binary____fpga_fpga_hf_bit_end=_binary_fpga_hf_bit_end --prefix-sections=fpga_hf_bit $^ $@ $(OBJCOPY) -O elf32-littlearm -I binary -B arm --prefix-sections=fpga_all_bit $^ $@
$(OBJDIR)/fullimage.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_lf.o $(OBJDIR)/fpga_hf.o $(THUMBOBJ) $(ARMOBJ) $(OBJDIR)/fpga_all.bit.z: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR)
$(FPGA_COMPRESSOR) $(filter %.bit,$^) $@
$(FPGA_COMPRESSOR):
make -C ../client $(notdir $(FPGA_COMPRESSOR))
$(OBJDIR)/fullimage.stage1.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ)
$(CC) $(LDFLAGS) -Wl,-T,ldscript,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS) $(CC) $(LDFLAGS) -Wl,-T,ldscript,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS)
#$(OBJDIR)/fpgaimage.elf: $(OBJDIR)/fullimage.elf $(OBJDIR)/fullimage.nodata.bin: $(OBJDIR)/fullimage.stage1.elf
# $(OBJCOPY) -F elf32-littlearm --only-section .fpgaimage $^ $@ $(OBJCOPY) -O binary -I elf32-littlearm --remove-section .data $^ $@
$(OBJDIR)/fullimage.nodata.o: $(OBJDIR)/fullimage.nodata.bin
$(OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=stage1_image $^ $@
$(OBJDIR)/osimage.elf: $(OBJDIR)/fullimage.elf $(OBJDIR)/fullimage.data.bin: $(OBJDIR)/fullimage.stage1.elf
$(OBJCOPY) -F elf32-littlearm $^ $@ $(OBJCOPY) -O binary -I elf32-littlearm --only-section .data $^ $@
$(OBJDIR)/fullimage.data.bin.z: $(OBJDIR)/fullimage.data.bin $(FPGA_COMPRESSOR)
$(FPGA_COMPRESSOR) $(filter %.bin,$^) $@
$(OBJDIR)/fullimage.data.o: $(OBJDIR)/fullimage.data.bin.z
$(OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=compressed_data $^ $@
$(OBJDIR)/fullimage.elf: $(OBJDIR)/fullimage.nodata.o $(OBJDIR)/fullimage.data.o
$(CC) $(LDFLAGS) -Wl,-T,ldscript,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^
tarbin: $(OBJS) tarbin: $(OBJS)
$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(OBJS:%=armsrc/%) $(OBJS:%.s19=armsrc/%.elf) $(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(OBJS:%=armsrc/%) $(OBJS:%.s19=armsrc/%.elf)
clean: clean:
$(DELETE) $(OBJDIR)$(PATHSEP)*.o $(DELETE) $(OBJDIR)$(PATHSEP)*.o
$(DELETE) $(OBJDIR)$(PATHSEP)*.elf $(DELETE) $(OBJDIR)$(PATHSEP)*.elf
$(DELETE) $(OBJDIR)$(PATHSEP)*.s19 $(DELETE) $(OBJDIR)$(PATHSEP)*.s19
$(DELETE) $(OBJDIR)$(PATHSEP)*.map $(DELETE) $(OBJDIR)$(PATHSEP)*.map
$(DELETE) $(OBJDIR)$(PATHSEP)*.d $(DELETE) $(OBJDIR)$(PATHSEP)*.d
$(DELETE) $(OBJDIR)$(PATHSEP)*.z
$(DELETE) $(OBJDIR)$(PATHSEP)*.bin
$(DELETE) version.c $(DELETE) version.c
.PHONY: all clean help .PHONY: all clean help
help: help:
@echo Multi-OS Makefile, you are running on $(DETECTED_OS) @echo Multi-OS Makefile, you are running on $(DETECTED_OS)
@echo Possible targets: @echo Possible targets:
@echo + all - Make both: @echo + all - Build the full image $(OBJDIR)/fullimage.s19
@echo + $(OBJDIR)/osimage.s19 - The OS image @echo + clean - Clean $(OBJDIR)
@echo + $(OBJDIR)/fpgaimage.s19 - The FPGA image
@echo + clean - Clean $(OBJDIR)

View file

@ -1,4 +1,3 @@
#include "stdio.h"
#include "aes.h" #include "aes.h"
static const unsigned int Te0[256] = { static const unsigned int Te0[256] = {
@ -1138,6 +1137,9 @@ int AesDecrypt(AesCtx *pCtx, unsigned char *pCipher, unsigned char *pData, unsig
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
#ifndef EMBEDDED #ifndef EMBEDDED
#include <stdio.h>
int main() int main()
{ {
AesCtx ctx; AesCtx ctx;

View file

@ -250,55 +250,6 @@ void MeasureAntennaTuningHf(void)
} }
void SimulateTagHfListen(void)
{
// ToDo: historically this used the free buffer, which was 2744 Bytes long.
// There might be a better size to be defined:
#define HF_14B_SNOOP_BUFFER_SIZE 2744
uint8_t *dest = BigBuf_malloc(HF_14B_SNOOP_BUFFER_SIZE);
uint8_t v = 0;
int i;
int p = 0;
// We're using this mode just so that I can test it out; the simulated
// tag mode would work just as well and be simpler.
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP);
// We need to listen to the high-frequency, peak-detected path.
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
FpgaSetupSsc();
i = 0;
for(;;) {
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = 0xff;
}
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
uint8_t r = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
v <<= 1;
if(r & 1) {
v |= 1;
}
p++;
if(p >= 8) {
dest[i] = v;
v = 0;
p = 0;
i++;
if(i >= HF_14B_SNOOP_BUFFER_SIZE) {
break;
}
}
}
}
DbpString("simulate tag (now type bitsamples)");
}
void ReadMem(int addr) void ReadMem(int addr)
{ {
const uint8_t *data = ((uint8_t *)addr); const uint8_t *data = ((uint8_t *)addr);
@ -310,11 +261,11 @@ void ReadMem(int addr)
/* osimage version information is linked in */ /* osimage version information is linked in */
extern struct version_information version_information; extern struct version_information version_information;
/* bootrom version information is pointed to from _bootphase1_version_pointer */ /* bootrom version information is pointed to from _bootphase1_version_pointer */
extern char *_bootphase1_version_pointer, _flash_start, _flash_end; extern char *_bootphase1_version_pointer, _flash_start, _flash_end, _bootrom_start, _bootrom_end, __data_src_start__;
void SendVersion(void) void SendVersion(void)
{ {
char temp[512]; /* Limited data payload in USB packets */ char temp[USB_CMD_DATA_SIZE]; /* Limited data payload in USB packets */
DbpString("Prox/RFID mark3 RFID instrument"); char VersionString[USB_CMD_DATA_SIZE] = { '\0' };
/* Try to find the bootrom version information. Expect to find a pointer at /* Try to find the bootrom version information. Expect to find a pointer at
* symbol _bootphase1_version_pointer, perform slight sanity checks on the * symbol _bootphase1_version_pointer, perform slight sanity checks on the
@ -322,19 +273,24 @@ void SendVersion(void)
*/ */
char *bootrom_version = *(char**)&_bootphase1_version_pointer; char *bootrom_version = *(char**)&_bootphase1_version_pointer;
if( bootrom_version < &_flash_start || bootrom_version >= &_flash_end ) { if( bootrom_version < &_flash_start || bootrom_version >= &_flash_end ) {
DbpString("bootrom version information appears invalid"); strcat(VersionString, "bootrom version information appears invalid\n");
} else { } else {
FormatVersionInformation(temp, sizeof(temp), "bootrom: ", bootrom_version); FormatVersionInformation(temp, sizeof(temp), "bootrom: ", bootrom_version);
DbpString(temp); strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1);
} }
FormatVersionInformation(temp, sizeof(temp), "os: ", &version_information); FormatVersionInformation(temp, sizeof(temp), "os: ", &version_information);
DbpString(temp); strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1);
FpgaGatherVersion(temp, sizeof(temp)); FpgaGatherVersion(FPGA_BITSTREAM_LF, temp, sizeof(temp));
DbpString(temp); strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1);
// Send Chip ID FpgaGatherVersion(FPGA_BITSTREAM_HF, temp, sizeof(temp));
cmd_send(CMD_ACK,*(AT91C_DBGU_CIDR),0,0,NULL,0); strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1);
// Send Chip ID and used flash memory
uint32_t text_and_rodata_section_size = (uint32_t)&__data_src_start__ - (uint32_t)&_flash_start;
uint32_t compressed_data_section_size = common_area.arg1;
cmd_send(CMD_ACK, *(AT91C_DBGU_CIDR), text_and_rodata_section_size + compressed_data_section_size, 0, VersionString, strlen(VersionString));
} }
#ifdef WITH_LF #ifdef WITH_LF
@ -738,7 +694,7 @@ void UsbPacketReceived(uint8_t *packet, int len)
ReaderHitag((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes); ReaderHitag((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes);
break; break;
#endif #endif
#ifdef WITH_ISO15693 #ifdef WITH_ISO15693
case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693: case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693:
AcquireRawAdcSamplesIso15693(); AcquireRawAdcSamplesIso15693();
@ -782,20 +738,17 @@ void UsbPacketReceived(uint8_t *packet, int len)
#endif #endif
#ifdef WITH_ISO14443b #ifdef WITH_ISO14443b
case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443:
AcquireRawAdcSamplesIso14443(c->arg[0]);
break;
case CMD_READ_SRI512_TAG: case CMD_READ_SRI512_TAG:
ReadSTMemoryIso14443(0x0F); ReadSTMemoryIso14443b(0x0F);
break; break;
case CMD_READ_SRIX4K_TAG: case CMD_READ_SRIX4K_TAG:
ReadSTMemoryIso14443(0x7F); ReadSTMemoryIso14443b(0x7F);
break; break;
case CMD_SNOOP_ISO_14443: case CMD_SNOOP_ISO_14443B:
SnoopIso14443(); SnoopIso14443b();
break; break;
case CMD_SIMULATE_TAG_ISO_14443: case CMD_SIMULATE_TAG_ISO_14443B:
SimulateIso14443Tag(); SimulateIso14443bTag();
break; break;
case CMD_ISO_14443B_COMMAND: case CMD_ISO_14443B_COMMAND:
SendRawCommand14443B(c->arg[0],c->arg[1],c->arg[2],c->d.asBytes); SendRawCommand14443B(c->arg[0],c->arg[1],c->arg[2],c->d.asBytes);
@ -816,27 +769,27 @@ void UsbPacketReceived(uint8_t *packet, int len)
case CMD_EPA_PACE_COLLECT_NONCE: case CMD_EPA_PACE_COLLECT_NONCE:
EPA_PACE_Collect_Nonce(c); EPA_PACE_Collect_Nonce(c);
break; break;
case CMD_EPA_PACE_REPLAY:
EPA_PACE_Replay(c);
break;
case CMD_READER_MIFARE: case CMD_READER_MIFARE:
ReaderMifare(c->arg[0]); ReaderMifare(c->arg[0]);
break; break;
case CMD_MIFARE_READBL: case CMD_MIFARE_READBL:
MifareReadBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); MifareReadBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
break; break;
case CMD_MIFAREU_READBL: case CMD_MIFAREU_READBL:
MifareUReadBlock(c->arg[0],c->d.asBytes); MifareUReadBlock(c->arg[0],c->arg[1], c->d.asBytes);
break; break;
case CMD_MIFAREUC_AUTH1: case CMD_MIFAREUC_AUTH:
MifareUC_Auth1(c->arg[0],c->d.asBytes); MifareUC_Auth(c->arg[0],c->d.asBytes);
break;
case CMD_MIFAREUC_AUTH2:
MifareUC_Auth2(c->arg[0],c->d.asBytes);
break; break;
case CMD_MIFAREU_READCARD: case CMD_MIFAREU_READCARD:
MifareUReadCard(c->arg[0], c->arg[1], c->d.asBytes); MifareUReadCard(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
break; break;
case CMD_MIFAREUC_READCARD: case CMD_MIFAREUC_SETPWD:
MifareUReadCard(c->arg[0], c->arg[1], c->d.asBytes); MifareUSetPwd(c->arg[0], c->d.asBytes);
break; break;
case CMD_MIFARE_READSC: case CMD_MIFARE_READSC:
MifareReadSector(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); MifareReadSector(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
@ -844,12 +797,12 @@ void UsbPacketReceived(uint8_t *packet, int len)
case CMD_MIFARE_WRITEBL: case CMD_MIFARE_WRITEBL:
MifareWriteBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); MifareWriteBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
break; break;
case CMD_MIFAREU_WRITEBL_COMPAT: //case CMD_MIFAREU_WRITEBL_COMPAT:
MifareUWriteBlock(c->arg[0], c->d.asBytes); //MifareUWriteBlockCompat(c->arg[0], c->d.asBytes);
break; //break;
case CMD_MIFAREU_WRITEBL: case CMD_MIFAREU_WRITEBL:
MifareUWriteBlock_Special(c->arg[0], c->d.asBytes); MifareUWriteBlock(c->arg[0], c->arg[1], c->d.asBytes);
break; break;
case CMD_MIFARE_NESTED: case CMD_MIFARE_NESTED:
MifareNested(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); MifareNested(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
break; break;
@ -914,10 +867,6 @@ void UsbPacketReceived(uint8_t *packet, int len)
break; break;
#endif #endif
case CMD_SIMULATE_TAG_HF_LISTEN:
SimulateTagHfListen();
break;
case CMD_BUFF_CLEAR: case CMD_BUFF_CLEAR:
BigBuf_Clear(); BigBuf_Clear();
break; break;

View file

@ -19,6 +19,7 @@
#include "mifare.h" #include "mifare.h"
#include "../common/crc32.h" #include "../common/crc32.h"
#include "BigBuf.h" #include "BigBuf.h"
#include "fpgaloader.h"
extern const uint8_t OddByteParity[256]; extern const uint8_t OddByteParity[256];
extern int rsamples; // = 0; extern int rsamples; // = 0;
@ -50,60 +51,6 @@ void ListenReaderField(int limit);
extern int ToSendMax; extern int ToSendMax;
extern uint8_t ToSend[]; extern uint8_t ToSend[];
/// fpga.h
void FpgaSendCommand(uint16_t cmd, uint16_t v);
void FpgaWriteConfWord(uint8_t v);
void FpgaDownloadAndGo(int bitstream_version);
int FpgaGatherBitstreamVersion();
void FpgaGatherVersion(char *dst, int len);
void FpgaSetupSsc(void);
void SetupSpi(int mode);
bool FpgaSetupSscDma(uint8_t *buf, int len);
#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);
// Definitions for the FPGA commands.
#define FPGA_CMD_SET_CONFREG (1<<12)
#define FPGA_CMD_SET_DIVISOR (2<<12)
#define FPGA_CMD_SET_USER_BYTE1 (3<<12)
// Definitions for the FPGA configuration word.
// LF
#define FPGA_MAJOR_MODE_LF_ADC (0<<5)
#define FPGA_MAJOR_MODE_LF_EDGE_DETECT (1<<5)
#define FPGA_MAJOR_MODE_LF_PASSTHRU (2<<5)
// HF
#define FPGA_MAJOR_MODE_HF_READER_TX (0<<5)
#define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (1<<5)
#define FPGA_MAJOR_MODE_HF_SIMULATOR (2<<5)
#define FPGA_MAJOR_MODE_HF_ISO14443A (3<<5)
// BOTH
#define FPGA_MAJOR_MODE_OFF (7<<5)
// Options for LF_ADC
#define FPGA_LF_ADC_READER_FIELD (1<<0)
// Options for LF_EDGE_DETECT
#define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD FPGA_CMD_SET_USER_BYTE1
#define FPGA_LF_EDGE_DETECT_READER_FIELD (1<<0)
#define FPGA_LF_EDGE_DETECT_TOGGLE_MODE (1<<1)
// Options for the HF reader, tx to tag
#define FPGA_HF_READER_TX_SHALLOW_MOD (1<<0)
// Options for the HF reader, correlating against rx from tag
#define FPGA_HF_READER_RX_XCORR_848_KHZ (1<<0)
#define FPGA_HF_READER_RX_XCORR_SNOOP (1<<1)
#define FPGA_HF_READER_RX_XCORR_QUARTER_FREQ (1<<2)
// Options for the HF simulated tag, how to modulate
#define FPGA_HF_SIMULATOR_NO_MODULATION (0<<0)
#define FPGA_HF_SIMULATOR_MODULATE_BPSK (1<<0)
#define FPGA_HF_SIMULATOR_MODULATE_212K (2<<0)
#define FPGA_HF_SIMULATOR_MODULATE_424K (4<<0)
#define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 0x5//101
// Options for ISO14443A
#define FPGA_HF_ISO14443A_SNIFFER (0<<0)
#define FPGA_HF_ISO14443A_TAGSIM_LISTEN (1<<0)
#define FPGA_HF_ISO14443A_TAGSIM_MOD (2<<0)
#define FPGA_HF_ISO14443A_READER_LISTEN (3<<0)
#define FPGA_HF_ISO14443A_READER_MOD (4<<0)
/// lfops.h /// lfops.h
extern uint8_t decimation; extern uint8_t decimation;
@ -141,10 +88,10 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode);
void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode); void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode);
/// iso14443.h /// iso14443.h
void SimulateIso14443Tag(void); void SimulateIso14443bTag(void);
void AcquireRawAdcSamplesIso14443(uint32_t parameter); void AcquireRawAdcSamplesIso14443b(uint32_t parameter);
void ReadSTMemoryIso14443(uint32_t); void ReadSTMemoryIso14443b(uint32_t);
void RAMFUNC SnoopIso14443(void); void RAMFUNC SnoopIso14443b(void);
void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]); void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]);
/// iso14443a.h /// iso14443a.h
@ -160,19 +107,19 @@ void RAMFUNC SniffMifare(uint8_t param);
/// epa.h /// epa.h
void EPA_PACE_Collect_Nonce(UsbCommand * c); void EPA_PACE_Collect_Nonce(UsbCommand * c);
void EPA_PACE_Replay(UsbCommand *c);
// mifarecmd.h // mifarecmd.h
void ReaderMifare(bool first_try); void ReaderMifare(bool first_try);
int32_t dist_nt(uint32_t nt1, uint32_t nt2); int32_t dist_nt(uint32_t nt1, uint32_t nt2);
void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data); void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data);
void MifareUReadBlock(uint8_t arg0,uint8_t *datain); void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
void MifareUC_Auth1(uint8_t arg0, uint8_t *datain); void MifareUC_Auth(uint8_t arg0, uint8_t *datain);
void MifareUC_Auth2(uint32_t arg0, uint8_t *datain); void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
void MifareUReadCard(uint8_t arg0, int Pages, uint8_t *datain);
void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
void MifareUWriteBlock(uint8_t arg0,uint8_t *datain); //void MifareUWriteBlockCompat(uint8_t arg0,uint8_t *datain);
void MifareUWriteBlock_Special(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 MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void MifareChkKeys(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void MifareChkKeys(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
@ -184,6 +131,7 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); // Work with "magic Chinese" card void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); // Work with "magic Chinese" card
void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void MifareCIdent(); // is "magic chinese" card? void MifareCIdent(); // is "magic chinese" card?
void MifareUSetPwd(uint8_t arg0, uint8_t *datain);
//desfire //desfire
void Mifare_DES_Auth1(uint8_t arg0,uint8_t *datain); void Mifare_DES_Auth1(uint8_t arg0,uint8_t *datain);

View file

@ -378,6 +378,60 @@ void tdes_dec(void* out, void* in, const uint8_t* key){
des_dec(out, out, (uint8_t*)key + 0); des_dec(out, out, (uint8_t*)key + 0);
} }
void tdes_2key_enc(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]){
if( length % 8 ) return;
uint8_t i;
uint8_t* tin = (uint8_t*) in;
uint8_t* tout = (uint8_t*) out;
while( length > 0 )
{
for ( i = 0; i < 8; i++ )
tout[i] = (unsigned char)(tin[i] ^ iv[i]);
des_enc(tout, tin, (uint8_t*)key + 0);
des_dec(tout, tout, (uint8_t*)key + 8);
des_enc(tout, tout, (uint8_t*)key + 0);
memcpy(iv, tout, 8);
tin += 8;
tout += 8;
length -= 8;
}
}
void tdes_2key_dec(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]){
if( length % 8 ) return;
uint8_t i;
unsigned char temp[8];
uint8_t* tin = (uint8_t*) in;
uint8_t* tout = (uint8_t*) out;
while( length > 0 )
{
memcpy(temp, tin, 8);
des_dec(tout, tin, (uint8_t*)key + 0);
des_enc(tout, tout, (uint8_t*)key + 8);
des_dec(tout, tout, (uint8_t*)key + 0);
for (i = 0; i < 8; i++)
tout[i] = (unsigned char)(tout[i] ^ iv[i]);
memcpy(iv, temp, 8);
tin += 8;
tout += 8;
length -= 8;
}
}
/******************************************************************************/ /******************************************************************************/

View file

@ -97,6 +97,9 @@ void tdes_enc(void* out, const void* in, const void* key);
*/ */
void tdes_dec(void* out, const void* in, const void* key); void tdes_dec(void* out, const void* in, const void* key);
void tdes_2key_enc(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]);
void tdes_2key_dec(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]);
#endif /*DES_H_*/ #endif /*DES_H_*/
// Copied from des.h in desfire imp. // Copied from des.h in desfire imp.

View file

@ -5,7 +5,7 @@
// at your option, any later version. See the LICENSE.txt file for the text of // at your option, any later version. See the LICENSE.txt file for the text of
// the license. // the license.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Routines to support the German eletronic "Personalausweis" (ID card) // Routines to support the German electronic "Personalausweis" (ID card)
// Note that the functions which do not implement USB commands do NOT initialize // Note that the functions which do not implement USB commands do NOT initialize
// the card (with iso14443a_select_card etc.). If You want to use these // the card (with iso14443a_select_card etc.). If You want to use these
// functions, You need to do the setup before calling them! // functions, You need to do the setup before calling them!
@ -74,6 +74,32 @@ static const uint8_t oid_pace_start[] = {
0x04 // id-PACE 0x04 // id-PACE
}; };
// APDUs for replaying:
// MSE: Set AT (initiate PACE)
static uint8_t apdu_replay_mse_set_at_pace[41];
// General Authenticate (Get Nonce)
static uint8_t apdu_replay_general_authenticate_pace_get_nonce[8];
// General Authenticate (Map Nonce)
static uint8_t apdu_replay_general_authenticate_pace_map_nonce[75];
// General Authenticate (Mutual Authenticate)
static uint8_t apdu_replay_general_authenticate_pace_mutual_authenticate[75];
// General Authenticate (Perform Key Agreement)
static uint8_t apdu_replay_general_authenticate_pace_perform_key_agreement[18];
// pointers to the APDUs (for iterations)
static struct {
uint8_t len;
uint8_t *data;
} const apdus_replay[] = {
{sizeof(apdu_replay_mse_set_at_pace), apdu_replay_mse_set_at_pace},
{sizeof(apdu_replay_general_authenticate_pace_get_nonce), apdu_replay_general_authenticate_pace_get_nonce},
{sizeof(apdu_replay_general_authenticate_pace_map_nonce), apdu_replay_general_authenticate_pace_map_nonce},
{sizeof(apdu_replay_general_authenticate_pace_mutual_authenticate), apdu_replay_general_authenticate_pace_mutual_authenticate},
{sizeof(apdu_replay_general_authenticate_pace_perform_key_agreement), apdu_replay_general_authenticate_pace_perform_key_agreement}
};
// lengths of the replay APDUs
static uint8_t apdu_lengths_replay[5];
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Closes the communication channel and turns off the field // Closes the communication channel and turns off the field
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -101,7 +127,7 @@ size_t EPA_Parse_CardAccess(uint8_t *data,
pace_version_info_t *pace_info) pace_version_info_t *pace_info)
{ {
size_t index = 0; size_t index = 0;
while (index <= length - 2) { while (index <= length - 2) {
// determine type of element // determine type of element
// SET or SEQUENCE // SET or SEQUENCE
@ -158,7 +184,7 @@ size_t EPA_Parse_CardAccess(uint8_t *data,
index += 2 + data[index + 1]; index += 2 + data[index + 1];
} }
} }
// TODO: We should check whether we reached the end in error, but for that // TODO: We should check whether we reached the end in error, but for that
// we need a better parser (e.g. with states like IN_SET or IN_PACE_INFO) // we need a better parser (e.g. with states like IN_SET or IN_PACE_INFO)
return 0; return 0;
@ -176,7 +202,7 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length)
// we reserve 262 bytes here just to be safe (256-byte APDU + SW + ISO frame) // we reserve 262 bytes here just to be safe (256-byte APDU + SW + ISO frame)
uint8_t response_apdu[262]; uint8_t response_apdu[262];
int rapdu_length = 0; int rapdu_length = 0;
// select the file EF.CardAccess // select the file EF.CardAccess
rapdu_length = iso14_apdu((uint8_t *)apdu_select_binary_cardaccess, rapdu_length = iso14_apdu((uint8_t *)apdu_select_binary_cardaccess,
sizeof(apdu_select_binary_cardaccess), sizeof(apdu_select_binary_cardaccess),
@ -188,7 +214,7 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length)
Dbprintf("epa - no select cardaccess"); Dbprintf("epa - no select cardaccess");
return -1; return -1;
} }
// read the file // read the file
rapdu_length = iso14_apdu((uint8_t *)apdu_read_binary, rapdu_length = iso14_apdu((uint8_t *)apdu_read_binary,
sizeof(apdu_read_binary), sizeof(apdu_read_binary),
@ -200,7 +226,7 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length)
Dbprintf("epa - no read cardaccess"); Dbprintf("epa - no read cardaccess");
return -1; return -1;
} }
// copy the content into the buffer // copy the content into the buffer
// length of data available: apdu_length - 4 (ISO frame) - 2 (SW) // length of data available: apdu_length - 4 (ISO frame) - 2 (SW)
size_t to_copy = rapdu_length - 6; size_t to_copy = rapdu_length - 6;
@ -215,16 +241,11 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static void EPA_PACE_Collect_Nonce_Abort(uint8_t step, int func_return) static void EPA_PACE_Collect_Nonce_Abort(uint8_t step, int func_return)
{ {
// // step in which the failure occured
// ack->arg[0] = step;
// // last return code
// ack->arg[1] = func_return;
// power down the field // power down the field
EPA_Finish(); EPA_Finish();
// send the USB packet // send the USB packet
cmd_send(CMD_ACK,step,func_return,0,0,0); cmd_send(CMD_ACK,step,func_return,0,0,0);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -246,10 +267,6 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
// return value of a function // return value of a function
int func_return = 0; int func_return = 0;
// // initialize ack with 0s
// memset(ack->arg, 0, 12);
// memset(ack->d.asBytes, 0, 48);
// set up communication // set up communication
func_return = EPA_Setup(); func_return = EPA_Setup();
if (func_return != 0) { if (func_return != 0) {
@ -277,11 +294,11 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
EPA_PACE_Collect_Nonce_Abort(3, func_return); EPA_PACE_Collect_Nonce_Abort(3, func_return);
return; return;
} }
// initiate the PACE protocol // initiate the PACE protocol
// use the CAN for the password since that doesn't change // use the CAN for the password since that doesn't change
func_return = EPA_PACE_MSE_Set_AT(pace_version_info, 2); func_return = EPA_PACE_MSE_Set_AT(pace_version_info, 2);
// now get the nonce // now get the nonce
uint8_t nonce[256] = {0}; uint8_t nonce[256] = {0};
uint8_t requested_size = (uint8_t)c->arg[0]; uint8_t requested_size = (uint8_t)c->arg[0];
@ -292,14 +309,12 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
EPA_PACE_Collect_Nonce_Abort(4, func_return); EPA_PACE_Collect_Nonce_Abort(4, func_return);
return; return;
} }
// all done, return // all done, return
EPA_Finish(); EPA_Finish();
// save received information // save received information
// ack->arg[1] = func_return; cmd_send(CMD_ACK,0,func_return,0,nonce,func_return);
// memcpy(ack->d.asBytes, nonce, func_return);
cmd_send(CMD_ACK,0,func_return,0,nonce,func_return);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -320,7 +335,7 @@ int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce)
sizeof(apdu_general_authenticate_pace_get_nonce)); sizeof(apdu_general_authenticate_pace_get_nonce));
// append Le (requested length + 2 due to tag/length taking 2 bytes) in RAPDU // append Le (requested length + 2 due to tag/length taking 2 bytes) in RAPDU
apdu[sizeof(apdu_general_authenticate_pace_get_nonce)] = requested_length + 4; apdu[sizeof(apdu_general_authenticate_pace_get_nonce)] = requested_length + 4;
// send it // send it
uint8_t response_apdu[262]; uint8_t response_apdu[262];
int send_return = iso14_apdu(apdu, int send_return = iso14_apdu(apdu,
@ -333,7 +348,7 @@ int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce)
{ {
return -1; return -1;
} }
// if there is no nonce in the RAPDU, return here // if there is no nonce in the RAPDU, return here
if (send_return < 10) if (send_return < 10)
{ {
@ -348,7 +363,7 @@ int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce)
} }
// copy the nonce // copy the nonce
memcpy(nonce, response_apdu + 6, nonce_length); memcpy(nonce, response_apdu + 6, nonce_length);
return nonce_length; return nonce_length;
} }
@ -407,13 +422,79 @@ int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password)
return 0; return 0;
} }
//-----------------------------------------------------------------------------
// Perform the PACE protocol by replaying given APDUs
//-----------------------------------------------------------------------------
void EPA_PACE_Replay(UsbCommand *c)
{
uint32_t timings[sizeof(apdu_lengths_replay) / sizeof(apdu_lengths_replay[0])] = {0};
// if an APDU has been passed, save it
if (c->arg[0] != 0) {
// make sure it's not too big
if(c->arg[2] > apdus_replay[c->arg[0] - 1].len)
{
cmd_send(CMD_ACK, 1, 0, 0, NULL, 0);
}
memcpy(apdus_replay[c->arg[0] - 1].data + c->arg[1],
c->d.asBytes,
c->arg[2]);
// save/update APDU length
if (c->arg[1] == 0) {
apdu_lengths_replay[c->arg[0] - 1] = c->arg[2];
} else {
apdu_lengths_replay[c->arg[0] - 1] += c->arg[2];
}
cmd_send(CMD_ACK, 0, 0, 0, NULL, 0);
return;
}
// return value of a function
int func_return;
// set up communication
func_return = EPA_Setup();
if (func_return != 0) {
EPA_Finish();
cmd_send(CMD_ACK, 2, func_return, 0, NULL, 0);
return;
}
// increase the timeout (at least some cards really do need this!)/////////////
// iso14a_set_timeout(0x0003FFFF);
// response APDU
uint8_t response_apdu[300] = {0};
// now replay the data and measure the timings
for (int i = 0; i < sizeof(apdu_lengths_replay); i++) {
StartCountUS();
func_return = iso14_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
&& (func_return < 6
|| response_apdu[func_return - 4] != 0x90
|| response_apdu[func_return - 3] != 0x00))
{
EPA_Finish();
cmd_send(CMD_ACK, 3 + i, func_return, 0, timings, 20);
return;
}
}
EPA_Finish();
cmd_send(CMD_ACK,0,0,0,timings,20);
return;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Set up a communication channel (Card Select, PPS) // Set up a communication channel (Card Select, PPS)
// Returns 0 on success or a non-zero error code on failure // Returns 0 on success or a non-zero error code on failure
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int EPA_Setup() int EPA_Setup()
{ {
int return_code = 0; int return_code = 0;
uint8_t uid[10]; uint8_t uid[10];
uint8_t pps_response[3]; uint8_t pps_response[3];
@ -422,20 +503,16 @@ int EPA_Setup()
// power up the field // power up the field
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
// select the card // select the card
return_code = iso14443a_select_card(uid, &card_select_info, NULL); return_code = iso14443a_select_card(uid, &card_select_info, NULL);
if (return_code != 1) { if (return_code != 1) {
Dbprintf("Epa: Can't select card");
return 1; return 1;
} }
// send the PPS request // send the PPS request
ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL); ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL);
return_code = ReaderReceive(pps_response, pps_response_par); return_code = ReaderReceive(pps_response, pps_response_par);
if (return_code != 3 || pps_response[0] != 0xD0) { if (return_code != 3 || pps_response[0] != 0xD0) {
return return_code == 0 ? 2 : return_code; return return_code == 0 ? 2 : return_code;
} }
return 0; return 0;
} }

View file

@ -19,7 +19,7 @@ typedef struct {
uint8_t parameter_id; uint8_t parameter_id;
} pace_version_info_t; } pace_version_info_t;
// note: EPA_PACE_GetNonce is declared in apps.h // note: EPA_PACE_Collect_Nonce is declared in apps.h
// general functions // general functions
void EPA_Finish(); void EPA_Finish();
@ -33,4 +33,4 @@ int EPA_Setup();
int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password); int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password);
int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce); int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce);
#endif /* __EPA_H */ #endif /* __EPA_H */

View file

@ -9,10 +9,32 @@
// Routines to load the FPGA image, and then to configure the FPGA's major // Routines to load the FPGA image, and then to configure the FPGA's major
// mode once it is configured. // mode once it is configured.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "fpgaloader.h"
#include "proxmark3.h" #include "proxmark3.h"
#include "apps.h"
#include "util.h" #include "util.h"
#include "string.h" #include "string.h"
#include "BigBuf.h"
#include "zlib.h"
extern void Dbprintf(const char *fmt, ...);
// remember which version of the bitstream we have already downloaded to the FPGA
static int downloaded_bitstream = FPGA_BITSTREAM_ERR;
// this is where the bitstreams are located in memory:
extern uint8_t _binary_obj_fpga_all_bit_z_start, _binary_obj_fpga_all_bit_z_end;
static uint8_t *fpga_image_ptr = NULL;
static uint32_t uncompressed_bytes_cnt;
static const uint8_t _bitparse_fixed_header[] = {0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01};
#define FPGA_BITSTREAM_FIXED_HEADER_SIZE sizeof(_bitparse_fixed_header)
#define OUTPUT_BUFFER_LEN 80
#define FPGA_INTERLEAVE_SIZE 288
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Set up the Serial Peripheral Interface as master // Set up the Serial Peripheral Interface as master
@ -150,6 +172,94 @@ bool FpgaSetupSscDma(uint8_t *buf, int len)
return true; return true;
} }
//----------------------------------------------------------------------------
// Uncompress (inflate) the FPGA data. Returns one decompressed byte with
// each call.
//----------------------------------------------------------------------------
static int get_from_fpga_combined_stream(z_streamp compressed_fpga_stream, uint8_t *output_buffer)
{
if (fpga_image_ptr == compressed_fpga_stream->next_out) { // need more data
compressed_fpga_stream->next_out = output_buffer;
compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN;
fpga_image_ptr = output_buffer;
int res = inflate(compressed_fpga_stream, Z_SYNC_FLUSH);
if (res != Z_OK) {
Dbprintf("inflate returned: %d, %s", res, compressed_fpga_stream->msg);
}
if (res < 0) {
return res;
}
}
uncompressed_bytes_cnt++;
return *fpga_image_ptr++;
}
//----------------------------------------------------------------------------
// Undo the interleaving of several FPGA config files. FPGA config files
// are combined into one big file:
// 288 bytes from FPGA file 1, followed by 288 bytes from FGPA file 2, etc.
//----------------------------------------------------------------------------
static int get_from_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer)
{
while((uncompressed_bytes_cnt / FPGA_INTERLEAVE_SIZE) % FPGA_BITSTREAM_MAX != (bitstream_version - 1)) {
// skip undesired data belonging to other bitstream_versions
get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer);
}
return get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer);
}
static voidpf fpga_inflate_malloc(voidpf opaque, uInt items, uInt size)
{
return BigBuf_malloc(items*size);
}
static void fpga_inflate_free(voidpf opaque, voidpf address)
{
BigBuf_free();
}
//----------------------------------------------------------------------------
// Initialize decompression of the respective (HF or LF) FPGA stream
//----------------------------------------------------------------------------
static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer)
{
uint8_t header[FPGA_BITSTREAM_FIXED_HEADER_SIZE];
uncompressed_bytes_cnt = 0;
// initialize z_stream structure for inflate:
compressed_fpga_stream->next_in = &_binary_obj_fpga_all_bit_z_start;
compressed_fpga_stream->avail_in = &_binary_obj_fpga_all_bit_z_start - &_binary_obj_fpga_all_bit_z_end;
compressed_fpga_stream->next_out = output_buffer;
compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN;
compressed_fpga_stream->zalloc = &fpga_inflate_malloc;
compressed_fpga_stream->zfree = &fpga_inflate_free;
inflateInit2(compressed_fpga_stream, 0);
fpga_image_ptr = output_buffer;
for (uint16_t i = 0; i < FPGA_BITSTREAM_FIXED_HEADER_SIZE; i++) {
header[i] = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
}
// Check for a valid .bit file (starts with _bitparse_fixed_header)
if(memcmp(_bitparse_fixed_header, header, FPGA_BITSTREAM_FIXED_HEADER_SIZE) == 0) {
return true;
} else {
return false;
}
}
static void DownloadFPGA_byte(unsigned char w) static void DownloadFPGA_byte(unsigned char w)
{ {
#define SEND_BIT(x) { if(w & (1<<x) ) HIGH(GPIO_FPGA_DIN); else LOW(GPIO_FPGA_DIN); HIGH(GPIO_FPGA_CCLK); LOW(GPIO_FPGA_CCLK); } #define SEND_BIT(x) { if(w & (1<<x) ) HIGH(GPIO_FPGA_DIN); else LOW(GPIO_FPGA_DIN); HIGH(GPIO_FPGA_CCLK); LOW(GPIO_FPGA_CCLK); }
@ -163,10 +273,12 @@ static void DownloadFPGA_byte(unsigned char w)
SEND_BIT(0); SEND_BIT(0);
} }
// Download the fpga image starting at FpgaImage and with length FpgaImageLen bytes // Download the fpga image starting at current stream position with length FpgaImageLen bytes
// If bytereversal is set: reverse the byte order in each 4-byte word static void DownloadFPGA(int bitstream_version, int FpgaImageLen, z_streamp compressed_fpga_stream, uint8_t *output_buffer)
static void DownloadFPGA(const char *FpgaImage, int FpgaImageLen, int bytereversal)
{ {
Dbprintf("DownloadFPGA(len: %d)", FpgaImageLen);
int i=0; int i=0;
AT91C_BASE_PIOA->PIO_OER = GPIO_FPGA_ON; AT91C_BASE_PIOA->PIO_OER = GPIO_FPGA_ON;
@ -218,23 +330,15 @@ static void DownloadFPGA(const char *FpgaImage, int FpgaImageLen, int byterevers
return; return;
} }
if(bytereversal) { for(i = 0; i < FpgaImageLen; i++) {
/* This is only supported for uint32_t aligned images */ int b = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
if( ((int)FpgaImage % sizeof(uint32_t)) == 0 ) { if (b < 0) {
i=0; Dbprintf("Error %d during FpgaDownload", b);
while(FpgaImageLen-->0) break;
DownloadFPGA_byte(FpgaImage[(i++)^0x3]);
/* Explanation of the magic in the above line:
* i^0x3 inverts the lower two bits of the integer i, counting backwards
* for each 4 byte increment. The generated sequence of (i++)^3 is
* 3 2 1 0 7 6 5 4 11 10 9 8 15 14 13 12 etc. pp.
*/
} }
} else { DownloadFPGA_byte(b);
while(FpgaImageLen-->0)
DownloadFPGA_byte(*FpgaImage++);
} }
// continue to clock FPGA until ready signal goes high // continue to clock FPGA until ready signal goes high
i=100000; i=100000;
while ( (i--) && ( !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_DONE ) ) ) { while ( (i--) && ( !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_DONE ) ) ) {
@ -250,39 +354,21 @@ static void DownloadFPGA(const char *FpgaImage, int FpgaImageLen, int byterevers
LED_D_OFF(); LED_D_OFF();
} }
static char *bitparse_headers_start;
static char *bitparse_bitstream_end;
static int bitparse_initialized = 0;
/* Simple Xilinx .bit parser. The file starts with the fixed opaque byte sequence /* Simple Xilinx .bit parser. The file starts with the fixed opaque byte sequence
* 00 09 0f f0 0f f0 0f f0 0f f0 00 00 01 * 00 09 0f f0 0f f0 0f f0 0f f0 00 00 01
* After that the format is 1 byte section type (ASCII character), 2 byte length * After that the format is 1 byte section type (ASCII character), 2 byte length
* (big endian), <length> bytes content. Except for section 'e' which has 4 bytes * (big endian), <length> bytes content. Except for section 'e' which has 4 bytes
* length. * length.
*/ */
static const char _bitparse_fixed_header[] = {0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01}; static int bitparse_find_section(int bitstream_version, char section_name, unsigned int *section_length, z_streamp compressed_fpga_stream, uint8_t *output_buffer)
static int bitparse_init(void * start_address, void *end_address)
{ {
bitparse_initialized = 0;
if(memcmp(_bitparse_fixed_header, start_address, sizeof(_bitparse_fixed_header)) != 0) {
return 0; /* Not matched */
} else {
bitparse_headers_start= ((char*)start_address) + sizeof(_bitparse_fixed_header);
bitparse_bitstream_end= (char*)end_address;
bitparse_initialized = 1;
return 1;
}
}
int bitparse_find_section(char section_name, char **section_start, unsigned int *section_length)
{
char *pos = bitparse_headers_start;
int result = 0; int result = 0;
#define MAX_FPGA_BIT_STREAM_HEADER_SEARCH 100 // maximum number of bytes to search for the requested section
if(!bitparse_initialized) return 0; uint16_t numbytes = 0;
while(numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH) {
while(pos < bitparse_bitstream_end) { char current_name = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
char current_name = *pos++; numbytes++;
unsigned int current_length = 0; unsigned int current_length = 0;
if(current_name < 'a' || current_name > 'e') { if(current_name < 'a' || current_name > 'e') {
/* Strange section name, abort */ /* Strange section name, abort */
@ -292,11 +378,13 @@ int bitparse_find_section(char section_name, char **section_start, unsigned int
switch(current_name) { switch(current_name) {
case 'e': case 'e':
/* Four byte length field */ /* Four byte length field */
current_length += (*pos++) << 24; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 24;
current_length += (*pos++) << 16; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 16;
numbytes += 2;
default: /* Fall through, two byte length field */ default: /* Fall through, two byte length field */
current_length += (*pos++) << 8; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 8;
current_length += (*pos++) << 0; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 0;
numbytes += 2;
} }
if(current_name != 'e' && current_length > 255) { if(current_name != 'e' && current_length > 255) {
@ -306,111 +394,123 @@ int bitparse_find_section(char section_name, char **section_start, unsigned int
if(current_name == section_name) { if(current_name == section_name) {
/* Found it */ /* Found it */
*section_start = pos;
*section_length = current_length; *section_length = current_length;
result = 1; result = 1;
break; break;
} }
pos += current_length; /* Skip section */ for (uint16_t i = 0; i < current_length && numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH; i++) {
get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
numbytes++;
}
} }
return result; return result;
} }
//-----------------------------------------------------------------------------
// Find out which FPGA image format is stored in flash, then call DownloadFPGA //----------------------------------------------------------------------------
// with the right parameters to download the image // Check which FPGA image is currently loaded (if any). If necessary
//----------------------------------------------------------------------------- // decompress and load the correct (HF or LF) image to the FPGA
extern char _binary_fpga_lf_bit_start, _binary_fpga_lf_bit_end; //----------------------------------------------------------------------------
extern char _binary_fpga_hf_bit_start, _binary_fpga_hf_bit_end;
void FpgaDownloadAndGo(int bitstream_version) void FpgaDownloadAndGo(int bitstream_version)
{ {
void *bit_start; z_stream compressed_fpga_stream;
void *bit_end; uint8_t output_buffer[OUTPUT_BUFFER_LEN];
// check whether or not the bitstream is already loaded // check whether or not the bitstream is already loaded
if (FpgaGatherBitstreamVersion() == bitstream_version) if (downloaded_bitstream == bitstream_version)
return; return;
if (bitstream_version == FPGA_BITSTREAM_LF) { // make sure that we have enough memory to decompress
bit_start = &_binary_fpga_lf_bit_start; BigBuf_free();
bit_end = &_binary_fpga_lf_bit_end;
} else if (bitstream_version == FPGA_BITSTREAM_HF) { if (!reset_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer)) {
bit_start = &_binary_fpga_hf_bit_start;
bit_end = &_binary_fpga_hf_bit_end;
} else
return; return;
/* Check for the new flash image format: Should have the .bit file at &_binary_fpga_bit_start
*/
if(bitparse_init(bit_start, bit_end)) {
/* Successfully initialized the .bit parser. Find the 'e' section and
* send its contents to the FPGA.
*/
char *bitstream_start;
unsigned int bitstream_length;
if(bitparse_find_section('e', &bitstream_start, &bitstream_length)) {
DownloadFPGA(bitstream_start, bitstream_length, 0);
return; /* All done */
}
} }
/* Fallback for the old flash image format: Check for the magic marker 0xFFFFFFFF unsigned int bitstream_length;
* 0xAA995566 at address 0x102000. This is raw bitstream with a size of 336,768 bits if(bitparse_find_section(bitstream_version, 'e', &bitstream_length, &compressed_fpga_stream, output_buffer)) {
* = 10,524 uint32_t, stored as uint32_t e.g. little-endian in memory, but each DWORD DownloadFPGA(bitstream_version, bitstream_length, &compressed_fpga_stream, output_buffer);
* is still to be transmitted in MSBit first order. Set the invert flag to indicate downloaded_bitstream = bitstream_version;
* that the DownloadFPGA function should invert every 4 byte sequence when doing }
* the bytewise download.
*/
if( *(uint32_t*)0x102000 == 0xFFFFFFFF && *(uint32_t*)0x102004 == 0xAA995566 )
DownloadFPGA((char*)0x102000, 10524*4, 1);
}
int FpgaGatherBitstreamVersion() inflateEnd(&compressed_fpga_stream);
{ }
char temp[256];
FpgaGatherVersion(temp, sizeof (temp));
if (!memcmp("LF", temp, 2))
return FPGA_BITSTREAM_LF;
else if (!memcmp("HF", temp, 2))
return FPGA_BITSTREAM_HF;
return FPGA_BITSTREAM_ERR;
}
void FpgaGatherVersion(char *dst, int len)
//-----------------------------------------------------------------------------
// Gather version information from FPGA image. Needs to decompress the begin
// of the respective (HF or LF) image.
// Note: decompression makes use of (i.e. overwrites) BigBuf[]. It is therefore
// advisable to call this only once and store the results for later use.
//-----------------------------------------------------------------------------
void FpgaGatherVersion(int bitstream_version, char *dst, int len)
{ {
char *fpga_info;
unsigned int fpga_info_len; unsigned int fpga_info_len;
dst[0] = 0; char tempstr[40];
if(!bitparse_find_section('e', &fpga_info, &fpga_info_len)) { z_stream compressed_fpga_stream;
strncat(dst, "FPGA image: legacy image without version information", len-1); uint8_t output_buffer[OUTPUT_BUFFER_LEN];
} else {
/* USB packets only have 48 bytes data payload, so be terse */ dst[0] = '\0';
if(bitparse_find_section('a', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {
if (!memcmp("fpga_lf", fpga_info, 7)) // ensure that we can allocate enough memory for decompression:
strncat(dst, "LF ", len-1); BigBuf_free();
else if (!memcmp("fpga_hf", fpga_info, 7))
strncat(dst, "HF ", len-1); if (!reset_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer)) {
} return;
strncat(dst, "FPGA image built", len-1);
#if 0
if(bitparse_find_section('b', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {
strncat(dst, " for ", len-1);
strncat(dst, fpga_info, len-1);
}
#endif
if(bitparse_find_section('c', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {
strncat(dst, " on ", len-1);
strncat(dst, fpga_info, len-1);
}
if(bitparse_find_section('d', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {
strncat(dst, " at ", len-1);
strncat(dst, fpga_info, len-1);
}
} }
if(bitparse_find_section(bitstream_version, 'a', &fpga_info_len, &compressed_fpga_stream, output_buffer)) {
for (uint16_t i = 0; i < fpga_info_len; i++) {
char c = (char)get_from_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer);
if (i < sizeof(tempstr)) {
tempstr[i] = c;
}
}
if (!memcmp("fpga_lf", tempstr, 7))
strncat(dst, "LF ", len-1);
else if (!memcmp("fpga_hf", tempstr, 7))
strncat(dst, "HF ", len-1);
}
strncat(dst, "FPGA image built", len-1);
if(bitparse_find_section(bitstream_version, 'b', &fpga_info_len, &compressed_fpga_stream, output_buffer)) {
strncat(dst, " for ", len-1);
for (uint16_t i = 0; i < fpga_info_len; i++) {
char c = (char)get_from_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer);
if (i < sizeof(tempstr)) {
tempstr[i] = c;
}
}
strncat(dst, tempstr, len-1);
}
if(bitparse_find_section(bitstream_version, 'c', &fpga_info_len, &compressed_fpga_stream, output_buffer)) {
strncat(dst, " on ", len-1);
for (uint16_t i = 0; i < fpga_info_len; i++) {
char c = (char)get_from_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer);
if (i < sizeof(tempstr)) {
tempstr[i] = c;
}
}
strncat(dst, tempstr, len-1);
}
if(bitparse_find_section(bitstream_version, 'd', &fpga_info_len, &compressed_fpga_stream, output_buffer)) {
strncat(dst, " at ", len-1);
for (uint16_t i = 0; i < fpga_info_len; i++) {
char c = (char)get_from_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer);
if (i < sizeof(tempstr)) {
tempstr[i] = c;
}
}
strncat(dst, tempstr, len-1);
}
strncat(dst, "\n", len-1);
inflateEnd(&compressed_fpga_stream);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Send a 16 bit command/data pair to the FPGA. // Send a 16 bit command/data pair to the FPGA.
// The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 // The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0

71
armsrc/fpgaloader.h Normal file
View file

@ -0,0 +1,71 @@
//-----------------------------------------------------------------------------
// Jonathan Westhues, April 2006
// iZsh <izsh at fail0verflow.com>, 2014
//
// 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 load the FPGA image, and then to configure the FPGA's major
// mode once it is configured.
//-----------------------------------------------------------------------------
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);
#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);
// definitions for multiple FPGA config files support
#define FPGA_BITSTREAM_MAX 2 // the total number of FPGA bitstreams (configs)
#define FPGA_BITSTREAM_ERR 0
#define FPGA_BITSTREAM_LF 1
#define FPGA_BITSTREAM_HF 2
// Definitions for the FPGA commands.
#define FPGA_CMD_SET_CONFREG (1<<12)
#define FPGA_CMD_SET_DIVISOR (2<<12)
#define FPGA_CMD_SET_USER_BYTE1 (3<<12)
// Definitions for the FPGA configuration word.
// LF
#define FPGA_MAJOR_MODE_LF_ADC (0<<5)
#define FPGA_MAJOR_MODE_LF_EDGE_DETECT (1<<5)
#define FPGA_MAJOR_MODE_LF_PASSTHRU (2<<5)
// HF
#define FPGA_MAJOR_MODE_HF_READER_TX (0<<5)
#define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (1<<5)
#define FPGA_MAJOR_MODE_HF_SIMULATOR (2<<5)
#define FPGA_MAJOR_MODE_HF_ISO14443A (3<<5)
// BOTH
#define FPGA_MAJOR_MODE_OFF (7<<5)
// Options for LF_ADC
#define FPGA_LF_ADC_READER_FIELD (1<<0)
// Options for LF_EDGE_DETECT
#define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD FPGA_CMD_SET_USER_BYTE1
#define FPGA_LF_EDGE_DETECT_READER_FIELD (1<<0)
#define FPGA_LF_EDGE_DETECT_TOGGLE_MODE (1<<1)
// Options for the HF reader, tx to tag
#define FPGA_HF_READER_TX_SHALLOW_MOD (1<<0)
// Options for the HF reader, correlating against rx from tag
#define FPGA_HF_READER_RX_XCORR_848_KHZ (1<<0)
#define FPGA_HF_READER_RX_XCORR_SNOOP (1<<1)
#define FPGA_HF_READER_RX_XCORR_QUARTER_FREQ (1<<2)
// Options for the HF simulated tag, how to modulate
#define FPGA_HF_SIMULATOR_NO_MODULATION (0<<0)
#define FPGA_HF_SIMULATOR_MODULATE_BPSK (1<<0)
#define FPGA_HF_SIMULATOR_MODULATE_212K (2<<0)
#define FPGA_HF_SIMULATOR_MODULATE_424K (4<<0)
#define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 0x5//101
// Options for ISO14443A
#define FPGA_HF_ISO14443A_SNIFFER (0<<0)
#define FPGA_HF_ISO14443A_TAGSIM_LISTEN (1<<0)
#define FPGA_HF_ISO14443A_TAGSIM_MOD (2<<0)
#define FPGA_HF_ISO14443A_READER_LISTEN (3<<0)
#define FPGA_HF_ISO14443A_READER_MOD (4<<0)

View file

@ -710,22 +710,24 @@ void SnoopHitag(uint32_t type) {
byte_t rx[HITAG_FRAME_LEN]; byte_t rx[HITAG_FRAME_LEN];
size_t rxlen=0; size_t rxlen=0;
auth_table_len = 0; FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
auth_table_pos = 0;
BigBuf_free();
auth_table = (byte_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
// Clean up trace and prepare it for storing frames // Clean up trace and prepare it for storing frames
set_tracing(TRUE); set_tracing(TRUE);
clear_trace(); clear_trace();
auth_table_len = 0;
auth_table_pos = 0;
BigBuf_free();
auth_table = (byte_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
DbpString("Starting Hitag2 snoop"); DbpString("Starting Hitag2 snoop");
LED_D_ON(); LED_D_ON();
// Set up eavesdropping mode, frequency divisor which will drive the FPGA // Set up eavesdropping mode, frequency divisor which will drive the FPGA
// and analog mux selection. // and analog mux selection.
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
SetAdcMuxFor(GPIO_MUXSEL_LOPKD); SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
@ -922,6 +924,12 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
bool bQuitTraceFull = false; bool bQuitTraceFull = false;
bQuiet = false; bQuiet = false;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
// Clean up trace and prepare it for storing frames
set_tracing(TRUE);
clear_trace();
auth_table_len = 0; auth_table_len = 0;
auth_table_pos = 0; auth_table_pos = 0;
byte_t* auth_table; byte_t* auth_table;
@ -929,10 +937,6 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
auth_table = (byte_t *)BigBuf_malloc(AUTH_TABLE_LENGTH); auth_table = (byte_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
memset(auth_table, 0x00, AUTH_TABLE_LENGTH); memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
// Clean up trace and prepare it for storing frames
set_tracing(TRUE);
clear_trace();
DbpString("Starting Hitag2 simulation"); DbpString("Starting Hitag2 simulation");
LED_D_ON(); LED_D_ON();
hitag2_init(); hitag2_init();
@ -953,7 +957,6 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
// Set up simulator mode, frequency divisor which will drive the FPGA // Set up simulator mode, frequency divisor which will drive the FPGA
// and analog mux selection. // and analog mux selection.
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
SetAdcMuxFor(GPIO_MUXSEL_LOPKD); SetAdcMuxFor(GPIO_MUXSEL_LOPKD);

View file

@ -1125,7 +1125,6 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf)
int resp_cc_len; int resp_cc_len;
uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
memset(receivedCmd, 0x44, MAX_FRAME_SIZE);
int len; int len;
// Prepare card messages // Prepare card messages
@ -1336,7 +1335,6 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf)
} }
} }
memset(receivedCmd, 0x44, MAX_FRAME_SIZE);
} }
//Dbprintf("%x", cmdsRecvd); //Dbprintf("%x", cmdsRecvd);
@ -1675,8 +1673,9 @@ uint8_t handshakeIclassTag(uint8_t *card_data)
// Reader iClass Anticollission // Reader iClass Anticollission
void ReaderIClass(uint8_t arg0) { void ReaderIClass(uint8_t arg0) {
uint8_t card_data[6 * 8]={0xFF}; uint8_t card_data[6 * 8]={0};
uint8_t last_csn[8]={0}; memset(card_data, 0xFF, sizeof(card_data));
uint8_t last_csn[8]={0};
//Read conf block CRC(0x01) => 0xfa 0x22 //Read conf block CRC(0x01) => 0xfa 0x22
uint8_t readConf[] = { ICLASS_CMD_READ_OR_IDENTIFY,0x01, 0xfa, 0x22}; uint8_t readConf[] = { ICLASS_CMD_READ_OR_IDENTIFY,0x01, 0xfa, 0x22};
@ -1684,16 +1683,18 @@ void ReaderIClass(uint8_t arg0) {
uint8_t readAA[] = { ICLASS_CMD_READ_OR_IDENTIFY,0x05, 0xde, 0x64}; uint8_t readAA[] = { ICLASS_CMD_READ_OR_IDENTIFY,0x05, 0xde, 0x64};
int read_status= 0; int read_status= 0;
uint8_t result_status = 0; uint8_t result_status = 0;
bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE; bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE;
bool try_once = arg0 & FLAG_ICLASS_READER_ONE_TRY;
set_tracing(TRUE); set_tracing(TRUE);
setupIclassReader(); setupIclassReader();
uint16_t tryCnt=0;
while(!BUTTON_PRESS()) while(!BUTTON_PRESS())
{ {
if (try_once && tryCnt > 5) break;
tryCnt++;
if(!tracing) { if(!tracing) {
DbpString("Trace full"); DbpString("Trace full");
break; break;
@ -1760,7 +1761,7 @@ void ReaderIClass(uint8_t arg0) {
} }
LED_B_OFF(); LED_B_OFF();
} }
cmd_send(CMD_ACK,0,0,0,card_data, 0); cmd_send(CMD_ACK,0,0,0,card_data, 0);
LED_A_OFF(); LED_A_OFF();
} }

View file

@ -555,12 +555,8 @@ void RAMFUNC SnoopIso14443a(uint8_t param) {
LEDsoff(); LEDsoff();
// We won't start recording the frames that we acquire until we trigger; iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER);
// a good trigger condition to get started is probably when we see a
// response from the tag.
// triggered == FALSE -- to wait first for card
bool triggered = !(param & 0x03);
// Allocate memory from BigBuf for some buffers // Allocate memory from BigBuf for some buffers
// free all previous allocations first // free all previous allocations first
BigBuf_free(); BigBuf_free();
@ -587,8 +583,6 @@ void RAMFUNC SnoopIso14443a(uint8_t param) {
bool TagIsActive = FALSE; bool TagIsActive = FALSE;
bool ReaderIsActive = FALSE; bool ReaderIsActive = FALSE;
iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER);
// Set up the demodulator for tag -> reader responses. // Set up the demodulator for tag -> reader responses.
DemodInit(receivedResponse, receivedResponsePar); DemodInit(receivedResponse, receivedResponsePar);
@ -598,6 +592,12 @@ void RAMFUNC SnoopIso14443a(uint8_t param) {
// Setup and start DMA. // Setup and start DMA.
FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE);
// 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
// response from the tag.
// triggered == FALSE -- to wait first for card
bool triggered = !(param & 0x03);
// And now we loop, receiving samples. // And now we loop, receiving samples.
for(uint32_t rsamples = 0; TRUE; ) { for(uint32_t rsamples = 0; TRUE; ) {
@ -1033,6 +1033,9 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
.modulation_n = 0 .modulation_n = 0
}; };
// We need to listen to the high-frequency, peak-detected path.
iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
BigBuf_free_keep_EM(); BigBuf_free_keep_EM();
// allocate buffers: // allocate buffers:
@ -1061,9 +1064,6 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
int happened2 = 0; int happened2 = 0;
int cmdsRecvd = 0; int cmdsRecvd = 0;
// We need to listen to the high-frequency, peak-detected path.
iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
cmdsRecvd = 0; cmdsRecvd = 0;
tag_response_info_t* p_response; tag_response_info_t* p_response;
@ -2010,7 +2010,7 @@ int32_t dist_nt(uint32_t nt1, uint32_t nt2) {
nttmp1 = prng_successor(nttmp1, 1); nttmp1 = prng_successor(nttmp1, 1);
if (nttmp1 == nt2) return i; if (nttmp1 == nt2) return i;
nttmp2 = prng_successor(nttmp2, 1); nttmp2 = prng_successor(nttmp2, 1);
if (nttmp2 == nt1) return -i; if (nttmp2 == nt1) return -i;
} }
return(-99999); // either nt1 or nt2 are invalid nonces return(-99999); // either nt1 or nt2 are invalid nonces
@ -2033,6 +2033,10 @@ void ReaderMifare(bool first_try)
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
if (first_try) {
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
}
// free eventually allocated BigBuf memory. We want all for tracing. // free eventually allocated BigBuf memory. We want all for tracing.
BigBuf_free(); BigBuf_free();
@ -2061,7 +2065,6 @@ void ReaderMifare(bool first_try)
if (first_try) { if (first_try) {
mf_nr_ar3 = 0; mf_nr_ar3 = 0;
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
sync_time = GetCountSspClk() & 0xfffffff8; sync_time = GetCountSspClk() & 0xfffffff8;
sync_cycles = 65536; // theory: Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). sync_cycles = 65536; // theory: Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces).
nt_attacked = 0; nt_attacked = 0;
@ -2079,18 +2082,21 @@ void ReaderMifare(bool first_try)
LED_B_OFF(); LED_B_OFF();
LED_C_OFF(); LED_C_OFF();
#define DARKSIDE_MAX_TRIES 32 // number of tries to sync on PRNG cycle. Then give up.
uint16_t unsuccessfull_tries = 0;
for(uint16_t i = 0; TRUE; i++) { for(uint16_t i = 0; TRUE; i++) {
LED_C_ON();
WDT_HIT(); WDT_HIT();
// Test if the action was cancelled // Test if the action was cancelled
if(BUTTON_PRESS()) { if(BUTTON_PRESS()) {
isOK = -1;
break; break;
} }
LED_C_ON();
if(!iso14443a_select_card(uid, NULL, &cuid)) { if(!iso14443a_select_card(uid, NULL, &cuid)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Can't select card"); if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Can't select card");
continue; continue;
@ -2125,8 +2131,14 @@ void ReaderMifare(bool first_try)
nt_attacked = nt; nt_attacked = nt;
} }
else { else {
if (nt_distance == -99999) { // invalid nonce received, try again if (nt_distance == -99999) { // invalid nonce received
continue; unsuccessfull_tries++;
if (!nt_attacked && unsuccessfull_tries > DARKSIDE_MAX_TRIES) {
isOK = -3; // Card has an unpredictable PRNG. Give up
break;
} else {
continue; // continue trying...
}
} }
sync_cycles = (sync_cycles - nt_distance); sync_cycles = (sync_cycles - nt_distance);
if (MF_DBGLEVEL >= 3) Dbprintf("calibrating in cycle %d. nt_distance=%d, Sync_cycles: %d\n", i, nt_distance, sync_cycles); if (MF_DBGLEVEL >= 3) Dbprintf("calibrating in cycle %d. nt_distance=%d, Sync_cycles: %d\n", i, nt_distance, sync_cycles);
@ -2188,6 +2200,10 @@ void ReaderMifare(bool first_try)
if (nt_diff == 0 && first_try) if (nt_diff == 0 && first_try)
{ {
par[0]++; par[0]++;
if (par[0] == 0x00) { // tried all 256 possible parities without success. Card doesn't send NACK.
isOK = -2;
break;
}
} else { } else {
par[0] = ((par[0] & 0x1F) + 1) | par_low; par[0] = ((par[0] & 0x1F) + 1) | par_low;
} }
@ -2204,7 +2220,7 @@ void ReaderMifare(bool first_try)
memcpy(buf + 16, ks_list, 8); memcpy(buf + 16, ks_list, 8);
memcpy(buf + 24, mf_nr_ar, 4); memcpy(buf + 24, mf_nr_ar, 4);
cmd_send(CMD_ACK,isOK,0,0,buf,28); cmd_send(CMD_ACK, isOK, 0, 0, buf, 28);
// Thats it... // Thats it...
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
@ -2265,13 +2281,6 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
uint32_t ar_nr_responses[] = {0,0,0,0,0,0,0,0}; uint32_t ar_nr_responses[] = {0,0,0,0,0,0,0,0};
uint8_t ar_nr_collected = 0; uint8_t ar_nr_collected = 0;
// free eventually allocated BigBuf memory but keep Emulator Memory
BigBuf_free_keep_EM();
// clear trace
clear_trace();
set_tracing(TRUE);
// Authenticate response - nonce // Authenticate response - nonce
uint32_t nonce = bytes_to_num(rAUTH_NT, 4); uint32_t nonce = bytes_to_num(rAUTH_NT, 4);
@ -2309,13 +2318,10 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
if (_7BUID) { if (_7BUID) {
rATQA[0] = 0x44; rATQA[0] = 0x44;
rUIDBCC1[0] = 0x88; rUIDBCC1[0] = 0x88;
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
} }
// We need to listen to the high-frequency, peak-detected path.
iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
if (MF_DBGLEVEL >= 1) { if (MF_DBGLEVEL >= 1) {
if (!_7BUID) { if (!_7BUID) {
Dbprintf("4B UID: %02x%02x%02x%02x", Dbprintf("4B UID: %02x%02x%02x%02x",
@ -2327,6 +2333,17 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
} }
} }
// We need to listen to the high-frequency, peak-detected path.
iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
// free eventually allocated BigBuf memory but keep Emulator Memory
BigBuf_free_keep_EM();
// clear trace
clear_trace();
set_tracing(TRUE);
bool finished = FALSE; bool finished = FALSE;
while (!BUTTON_PRESS() && !finished) { while (!BUTTON_PRESS() && !finished) {
WDT_HIT(); WDT_HIT();
@ -2548,13 +2565,13 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
|| receivedCmd[0] == 0xB0) { // transfer || receivedCmd[0] == 0xB0) { // transfer
if (receivedCmd[1] >= 16 * 4) { if (receivedCmd[1] >= 16 * 4) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02) on out of range block: %d (0x%02x), nacking",receivedCmd[0],receivedCmd[1],receivedCmd[1]); if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking",receivedCmd[0],receivedCmd[1],receivedCmd[1]);
break; break;
} }
if (receivedCmd[1] / 4 != cardAUTHSC) { if (receivedCmd[1] / 4 != cardAUTHSC) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02) on block (0x%02x) not authenticated for (0x%02x), nacking",receivedCmd[0],receivedCmd[1],cardAUTHSC); if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02x) on block (0x%02x) not authenticated for (0x%02x), nacking",receivedCmd[0],receivedCmd[1],cardAUTHSC);
break; break;
} }
} }
@ -2745,10 +2762,8 @@ void RAMFUNC SniffMifare(uint8_t param) {
uint8_t receivedResponse[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedResponse[MAX_MIFARE_FRAME_SIZE];
uint8_t receivedResponsePar[MAX_MIFARE_PARITY_SIZE]; uint8_t receivedResponsePar[MAX_MIFARE_PARITY_SIZE];
// As we receive stuff, we copy it from receivedCmd or receivedResponse iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER);
// into trace, along with its length and other annotations.
//uint8_t *trace = (uint8_t *)BigBuf;
// free eventually allocated BigBuf memory // free eventually allocated BigBuf memory
BigBuf_free(); BigBuf_free();
// allocate the DMA buffer, used to stream samples from the FPGA // allocate the DMA buffer, used to stream samples from the FPGA
@ -2760,8 +2775,6 @@ void RAMFUNC SniffMifare(uint8_t param) {
bool ReaderIsActive = FALSE; bool ReaderIsActive = FALSE;
bool TagIsActive = FALSE; bool TagIsActive = FALSE;
iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER);
// Set up the demodulator for tag -> reader responses. // Set up the demodulator for tag -> reader responses.
DemodInit(receivedResponse, receivedResponsePar); DemodInit(receivedResponse, receivedResponsePar);

File diff suppressed because it is too large Load diff

View file

@ -877,12 +877,12 @@ int SendDataTag(uint8_t *send, int sendlen, int init, int speed, uint8_t **recv)
LED_C_OFF(); LED_C_OFF();
LED_D_OFF(); LED_D_OFF();
if (init) Iso15693InitReader();
int answerLen=0; int answerLen=0;
uint8_t *answer = BigBuf_get_addr() + 3660; uint8_t *answer = BigBuf_get_addr() + 3660;
if (recv != NULL) memset(answer, 0, 100); if (recv != NULL) memset(answer, 0, 100);
if (init) Iso15693InitReader();
if (!speed) { if (!speed) {
// low speed (1 out of 256) // low speed (1 out of 256)
CodeIso15693AsReader256(send, sendlen); CodeIso15693AsReader256(send, sendlen);
@ -999,10 +999,6 @@ void ReaderIso15693(uint32_t parameter)
LED_C_OFF(); LED_C_OFF();
LED_D_OFF(); LED_D_OFF();
uint8_t *answer1 = BigBuf_get_addr() + 3660;
uint8_t *answer2 = BigBuf_get_addr() + 3760;
uint8_t *answer3 = BigBuf_get_addr() + 3860;
int answerLen1 = 0; int answerLen1 = 0;
int answerLen2 = 0; int answerLen2 = 0;
int answerLen3 = 0; int answerLen3 = 0;
@ -1013,19 +1009,21 @@ void ReaderIso15693(uint32_t parameter)
int elapsed = 0; int elapsed = 0;
uint8_t TagUID[8] = {0x00}; uint8_t TagUID[8] = {0x00};
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
uint8_t *answer1 = BigBuf_get_addr() + 3660;
uint8_t *answer2 = BigBuf_get_addr() + 3760;
uint8_t *answer3 = BigBuf_get_addr() + 3860;
// Blank arrays // Blank arrays
memset(answer1, 0x00, 300); memset(answer1, 0x00, 300);
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
SetAdcMuxFor(GPIO_MUXSEL_HIPKD); SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
// Setup SSC // Setup SSC
FpgaSetupSsc(); FpgaSetupSsc();
// Start from off (no field generated) // Start from off (no field generated)
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelay(200); SpinDelay(200);
// Give the tags time to energize // Give the tags time to energize
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
@ -1111,24 +1109,22 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid)
LED_C_OFF(); LED_C_OFF();
LED_D_OFF(); LED_D_OFF();
uint8_t *buf = BigBuf_get_addr() + 3660;
int answerLen1 = 0; int answerLen1 = 0;
int samples = 0; int samples = 0;
int tsamples = 0; int tsamples = 0;
int wait = 0; int wait = 0;
int elapsed = 0; int elapsed = 0;
memset(buf, 0x00, 100);
FpgaDownloadAndGo(FPGA_BITSTREAM_HF); FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
uint8_t *buf = BigBuf_get_addr() + 3660;
memset(buf, 0x00, 100);
SetAdcMuxFor(GPIO_MUXSEL_HIPKD); SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
FpgaSetupSsc(); FpgaSetupSsc();
// Start from off (no field generated) // Start from off (no field generated)
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelay(200); SpinDelay(200);
LED_A_OFF(); LED_A_OFF();

View file

@ -24,6 +24,7 @@ SECTIONS
} >osimage :text } >osimage :text
.text : { .text : {
KEEP(*(stage1_image))
*(.text) *(.text)
*(.text.*) *(.text.*)
*(.eh_frame) *(.eh_frame)
@ -34,14 +35,13 @@ SECTIONS
.rodata : { .rodata : {
*(.rodata) *(.rodata)
*(.rodata.*) *(.rodata.*)
*(fpga_lf_bit.data) *(fpga_all_bit.data)
*(fpga_hf_bit.data)
KEEP(*(.version_information)) KEEP(*(.version_information))
. = ALIGN(8);
} >osimage :text } >osimage :text
. = ALIGN(4);
.data : { .data : {
KEEP(*(compressed_data))
*(.data) *(.data)
*(.data.*) *(.data.*)
*(.ramfunc) *(.ramfunc)
@ -51,6 +51,7 @@ SECTIONS
__data_src_start__ = LOADADDR(.data); __data_src_start__ = LOADADDR(.data);
__data_start__ = ADDR(.data); __data_start__ = ADDR(.data);
__data_end__ = __data_start__ + SIZEOF(.data); __data_end__ = __data_start__ + SIZEOF(.data);
__os_size__ = SIZEOF(.text) + SIZEOF(.data) + SIZEOF(.rodata);
.bss : { .bss : {
__bss_start__ = .; __bss_start__ = .;

View file

@ -651,7 +651,7 @@ void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream)
int ledcontrol = 1; int ledcontrol = 1;
int n=0, i=0; int n=0, i=0;
uint8_t clk = (arg1 >> 8) & 0xFF; uint8_t clk = (arg1 >> 8) & 0xFF;
uint8_t encoding = arg1 & 1; uint8_t encoding = arg1 & 0xFF;
uint8_t separator = arg2 & 1; uint8_t separator = arg2 & 1;
uint8_t invert = (arg2 >> 8) & 1; uint8_t invert = (arg2 >> 8) & 1;
@ -861,7 +861,7 @@ void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol)
size = BigBuf_max_traceLen(); size = BigBuf_max_traceLen();
//askdemod and manchester decode //askdemod and manchester decode
if (size > 16385) size = 16385; //big enough to catch 2 sequences of largest format if (size > 16385) size = 16385; //big enough to catch 2 sequences of largest format
errCnt = askmandemod(dest, &size, &clk, &invert, maxErr); errCnt = askdemod(dest, &size, &clk, &invert, maxErr, 0, 1);
WDT_HIT(); WDT_HIT();
if (errCnt<0) continue; if (errCnt<0) continue;
@ -1024,10 +1024,10 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
* To compensate antenna falling times shorten the write times * To compensate antenna falling times shorten the write times
* and enlarge the gap ones. * and enlarge the gap ones.
*/ */
#define START_GAP 50*8 // 10 - 50fc 250 #define START_GAP 31*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (or 15fc)
#define WRITE_GAP 20*8 // - 30fc 160 #define WRITE_GAP 20*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (or 10fc)
#define WRITE_0 24*8 // 16 - 63fc 54fc 144 #define WRITE_0 18*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (or 24fc)
#define WRITE_1 54*8 // 48 - 63fc 54fc 432 for T55x7; 448 for E5550 //400 #define WRITE_1 50*8 // was 400 // SPEC: 48*8 to 64*8 - typ 56*8 (or 56fc) 432 for T55x7; 448 for E5550
#define T55xx_SAMPLES_SIZE 12000 // 32 x 32 x 10 (32 bit times numofblock (7), times clock skip..) #define T55xx_SAMPLES_SIZE 12000 // 32 x 32 x 10 (32 bit times numofblock (7), times clock skip..)

View file

@ -16,9 +16,13 @@
#include "mifarecmd.h" #include "mifarecmd.h"
#include "apps.h" #include "apps.h"
#include "util.h" #include "util.h"
#include "crc.h" #include "crc.h"
// the block number for the ISO14443-4 PCB
uint8_t pcb_blocknum = 0;
// Deselect card by sending a s-block. the crc is precalced for speed
static uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Select, Authenticate, Read a MIFARE tag. // Select, Authenticate, Read a MIFARE tag.
// read block // read block
@ -40,10 +44,10 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
struct Crypto1State *pcs; struct Crypto1State *pcs;
pcs = &mpcs; pcs = &mpcs;
// clear trace
clear_trace();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
clear_trace();
LED_A_ON(); LED_A_ON();
LED_B_OFF(); LED_B_OFF();
LED_C_OFF(); LED_C_OFF();
@ -86,107 +90,93 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
LEDsoff(); LEDsoff();
} }
void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes){
void MifareUC_Auth1(uint8_t arg0, uint8_t *datain){ bool turnOffField = (arg0 == 1);
byte_t isOK = 0; LED_A_ON(); LED_B_OFF(); LED_C_OFF();
byte_t dataoutbuf[16] = {0x00};
uint8_t uid[10] = {0x00};
uint32_t cuid;
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
clear_trace();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
if(!iso14443a_select_card(uid, NULL, &cuid)) { clear_trace();
if (MF_DBGLEVEL >= MF_DBG_ERROR)
Dbprintf("Can't select card"); if(!iso14443a_select_card(NULL, NULL, NULL)) {
//OnError(0); if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card");
OnError(0);
return; return;
}; };
if(mifare_ultra_auth1(cuid, dataoutbuf)){ if(!mifare_ultra_auth(keybytes)){
if (MF_DBGLEVEL >= MF_DBG_ERROR) if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed");
Dbprintf("Authentication part1: Fail."); OnError(1);
//OnError(1);
return; return;
} }
isOK = 1; if (turnOffField) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
DbpString("AUTH 1 FINISHED"); LEDsoff();
cmd_send(CMD_ACK,isOK,cuid,0,dataoutbuf,11);
LEDsoff();
}
void MifareUC_Auth2(uint32_t arg0, uint8_t *datain){
uint32_t cuid = arg0;
uint8_t key[16] = {0x00};
byte_t isOK = 0;
byte_t dataoutbuf[16] = {0x00};
memcpy(key, datain, 16);
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
if(mifare_ultra_auth2(cuid, key, dataoutbuf)){
if (MF_DBGLEVEL >= MF_DBG_ERROR)
Dbprintf("Authentication part2: Fail...");
//OnError(1);
return;
} }
cmd_send(CMD_ACK,1,0,0,0,0);
isOK = 1;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED)
DbpString("AUTH 2 FINISHED");
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,11);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
} }
void MifareUReadBlock(uint8_t arg0,uint8_t *datain) // Arg0 = BlockNo,
// Arg1 = UsePwd bool
// datain = PWD bytes,
void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)
{ {
uint8_t blockNo = arg0; uint8_t blockNo = arg0;
byte_t dataout[16] = {0x00}; byte_t dataout[16] = {0x00};
uint8_t uid[10] = {0x00}; bool useKey = (arg1 == 1); //UL_C
uint32_t cuid; bool usePwd = (arg1 == 2); //UL_EV1/NTAG
LEDsoff();
LED_A_ON(); LED_A_ON();
LED_B_OFF();
LED_C_OFF();
clear_trace();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
int len = iso14443a_select_card(uid, NULL, &cuid); clear_trace();
int len = iso14443a_select_card(NULL, NULL, NULL);
if(!len) { if(!len) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%02X)",len);
//OnError(1); OnError(1);
return; return;
}; }
len = mifare_ultra_readblock(cuid, blockNo, dataout); // UL-C authentication
if(len) { if ( useKey ) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error"); uint8_t key[16] = {0x00};
//OnError(2); memcpy(key, datain, sizeof(key) );
if ( !mifare_ultra_auth(key) ) {
OnError(1);
return;
}
}
// UL-EV1 / NTAG authentication
if ( usePwd ) {
uint8_t pwd[4] = {0x00};
memcpy(pwd, datain, 4);
uint8_t pack[4] = {0,0,0,0};
if (!mifare_ul_ev1_auth(pwd, pack)) {
OnError(1);
return;
}
}
if( mifare_ultra_readblock(blockNo, dataout) ) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error");
OnError(2);
return; return;
}; }
len = mifare_ultra_halt(cuid); if( mifare_ultra_halt() ) {
if(len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error");
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error"); OnError(3);
//OnError(3);
return; return;
}; }
cmd_send(CMD_ACK,1,0,0,dataout,16); cmd_send(CMD_ACK,1,0,0,dataout,16);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff(); LEDsoff();
} }
@ -212,11 +202,10 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
struct Crypto1State *pcs; struct Crypto1State *pcs;
pcs = &mpcs; pcs = &mpcs;
// clear trace
clear_trace();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
clear_trace();
LED_A_ON(); LED_A_ON();
LED_B_OFF(); LED_B_OFF();
LED_C_OFF(); LED_C_OFF();
@ -259,73 +248,103 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
LEDsoff(); LEDsoff();
} }
void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain) // arg0 = blockNo (start)
// arg1 = Pages (number of blocks)
// arg2 = useKey
// datain = KEY bytes
void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
{ {
// params LEDsoff();
uint8_t sectorNo = arg0;
int Pages = arg1;
int count_Pages = 0;
byte_t dataout[176] = {0x00};;
uint8_t uid[10] = {0x00};
uint32_t cuid;
LED_A_ON(); LED_A_ON();
LED_B_OFF();
LED_C_OFF();
if (MF_DBGLEVEL >= MF_DBG_ALL)
Dbprintf("Pages %d",Pages);
clear_trace();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
int len = iso14443a_select_card(uid, NULL, &cuid); // free eventually allocated BigBuf memory
BigBuf_free();
if (!len) { clear_trace();
if (MF_DBGLEVEL >= MF_DBG_ERROR)
Dbprintf("Can't select card"); // params
//OnError(1); uint8_t blockNo = arg0;
uint16_t blocks = arg1;
bool useKey = (arg2 == 1); //UL_C
bool usePwd = (arg2 == 2); //UL_EV1/NTAG
uint32_t countblocks = 0;
uint8_t *dataout = BigBuf_malloc(CARD_MEMORY_SIZE);
if (dataout == NULL){
Dbprintf("out of memory");
OnError(1);
return; return;
} }
for (int i = 0; i < Pages; i++){ int len = iso14443a_select_card(NULL, NULL, NULL);
if (!len) {
len = mifare_ultra_readblock(cuid, sectorNo * 4 + i, dataout + 4 * i); if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%d)",len);
OnError(1);
if (len) { return;
if (MF_DBGLEVEL >= MF_DBG_ERROR) }
Dbprintf("Read block %d error",i);
//OnError(2); // UL-C authentication
if ( useKey ) {
uint8_t key[16] = {0x00};
memcpy(key, datain, sizeof(key) );
if ( !mifare_ultra_auth(key) ) {
OnError(1);
return; return;
} else {
count_Pages++;
} }
} }
len = mifare_ultra_halt(cuid); // UL-EV1 / NTAG authentication
if (usePwd) {
uint8_t pwd[4] = {0x00};
memcpy(pwd, datain, sizeof(pwd));
uint8_t pack[4] = {0,0,0,0};
if (!mifare_ul_ev1_auth(pwd, pack)){
OnError(1);
return;
}
}
for (int i = 0; i < blocks; i++){
if ((i*4) + 4 >= CARD_MEMORY_SIZE) {
Dbprintf("Data exceeds buffer!!");
break;
}
len = mifare_ultra_readblock(blockNo + i, dataout + 4 * i);
if (len) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block %d error",i);
// if no blocks read - error out
if (i==0){
OnError(2);
return;
} else {
//stop at last successful read block and return what we got
break;
}
} else {
countblocks++;
}
}
len = mifare_ultra_halt();
if (len) { if (len) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error");
Dbprintf("Halt error"); OnError(3);
//OnError(3);
return; return;
} }
if (MF_DBGLEVEL >= MF_DBG_ALL) {
Dbprintf("Pages read %d", count_Pages);
}
len = 16*4; //64 bytes if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Blocks read %d", countblocks);
// Read a UL-C
if (Pages == 44 && count_Pages > 16)
len = 176;
cmd_send(CMD_ACK, 1, 0, 0, dataout, len); countblocks *= 4;
cmd_send(CMD_ACK, 1, countblocks, BigBuf_max_traceLen(), 0, 0);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff(); LEDsoff();
BigBuf_free();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Select, Authenticate, Write a MIFARE tag. // Select, Authenticate, Write a MIFARE tag.
// read block // read block
@ -349,11 +368,10 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
struct Crypto1State *pcs; struct Crypto1State *pcs;
pcs = &mpcs; pcs = &mpcs;
// clear trace
clear_trace();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
clear_trace();
LED_A_ON(); LED_A_ON();
LED_B_OFF(); LED_B_OFF();
LED_C_OFF(); LED_C_OFF();
@ -398,96 +416,179 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
LEDsoff(); LEDsoff();
} }
void MifareUWriteBlock(uint8_t arg0, uint8_t *datain) /* // Command not needed but left for future testing
void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain)
{ {
// params uint8_t blockNo = arg0;
uint8_t blockNo = arg0;
byte_t blockdata[16] = {0x00}; byte_t blockdata[16] = {0x00};
memcpy(blockdata, datain,16); memcpy(blockdata, datain, 16);
// variables
byte_t isOK = 0;
uint8_t uid[10] = {0x00}; uint8_t uid[10] = {0x00};
uint32_t cuid;
clear_trace(); LED_A_ON(); LED_B_OFF(); LED_C_OFF();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
while (true) {
if(!iso14443a_select_card(uid, NULL, &cuid)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
break;
};
if(mifare_ultra_writeblock(cuid, blockNo, blockdata)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
break;
};
if(mifare_ultra_halt(cuid)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
break;
};
isOK = 1;
break;
}
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
cmd_send(CMD_ACK,isOK,0,0,0,0);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
void MifareUWriteBlock_Special(uint8_t arg0, uint8_t *datain)
{
// params
uint8_t blockNo = arg0;
byte_t blockdata[4] = {0x00};
memcpy(blockdata, datain,4);
// variables
byte_t isOK = 0;
uint8_t uid[10] = {0x00};
uint32_t cuid;
clear_trace(); clear_trace();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
LED_A_ON(); if(!iso14443a_select_card(uid, NULL, NULL)) {
LED_B_OFF(); if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
LED_C_OFF(); OnError(0);
return;
};
while (true) { if(mifare_ultra_writeblock_compat(blockNo, blockdata)) {
if(!iso14443a_select_card(uid, NULL, &cuid)) { if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); OnError(0);
break; return; };
};
if(mifare_ultra_special_writeblock(cuid, blockNo, blockdata)) { if(mifare_ultra_halt()) {
if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
break; OnError(0);
}; return;
};
if(mifare_ultra_halt(cuid)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
break;
};
isOK = 1;
break;
}
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
cmd_send(CMD_ACK,isOK,0,0,0,0); cmd_send(CMD_ACK,1,0,0,0,0);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
*/
// Arg0 : Block to write to.
// Arg1 : 0 = use no authentication.
// 1 = use 0x1A authentication.
// 2 = use 0x1B authentication.
// datain : 4 first bytes is data to be written.
// : 4/16 next bytes is authentication key.
void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)
{
uint8_t blockNo = arg0;
bool useKey = (arg1 == 1); //UL_C
bool usePwd = (arg1 == 2); //UL_EV1/NTAG
byte_t blockdata[4] = {0x00};
memcpy(blockdata, datain,4);
LEDsoff();
LED_A_ON();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
clear_trace();
if(!iso14443a_select_card(NULL, NULL, NULL)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
OnError(0);
return;
};
// UL-C authentication
if ( useKey ) {
uint8_t key[16] = {0x00};
memcpy(key, datain+4, sizeof(key) );
if ( !mifare_ultra_auth(key) ) {
OnError(1);
return;
}
}
// UL-EV1 / NTAG authentication
if (usePwd) {
uint8_t pwd[4] = {0x00};
memcpy(pwd, datain+4, 4);
uint8_t pack[4] = {0,0,0,0};
if (!mifare_ul_ev1_auth(pwd, pack)) {
OnError(1);
return;
}
}
if(mifare_ultra_writeblock(blockNo, blockdata)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
OnError(0);
return;
};
if(mifare_ultra_halt()) {
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
OnError(0);
return;
};
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
cmd_send(CMD_ACK,1,0,0,0,0);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
void MifareUSetPwd(uint8_t arg0, uint8_t *datain){
uint8_t pwd[16] = {0x00};
byte_t blockdata[4] = {0x00};
memcpy(pwd, datain, 16);
LED_A_ON(); LED_B_OFF(); LED_C_OFF();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
clear_trace();
if(!iso14443a_select_card(NULL, NULL, NULL)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
OnError(0);
return;
};
blockdata[0] = pwd[7];
blockdata[1] = pwd[6];
blockdata[2] = pwd[5];
blockdata[3] = pwd[4];
if(mifare_ultra_writeblock( 44, blockdata)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
OnError(44);
return;
};
blockdata[0] = pwd[3];
blockdata[1] = pwd[2];
blockdata[2] = pwd[1];
blockdata[3] = pwd[0];
if(mifare_ultra_writeblock( 45, blockdata)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
OnError(45);
return;
};
blockdata[0] = pwd[15];
blockdata[1] = pwd[14];
blockdata[2] = pwd[13];
blockdata[3] = pwd[12];
if(mifare_ultra_writeblock( 46, blockdata)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
OnError(46);
return;
};
blockdata[0] = pwd[11];
blockdata[1] = pwd[10];
blockdata[2] = pwd[9];
blockdata[3] = pwd[8];
if(mifare_ultra_writeblock( 47, blockdata)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
OnError(47);
return;
};
if(mifare_ultra_halt()) {
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
OnError(0);
return;
};
cmd_send(CMD_ACK,1,0,0,0,0);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff(); LEDsoff();
} }
@ -534,19 +635,20 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
uint32_t auth1_time, auth2_time; uint32_t auth1_time, auth2_time;
static uint16_t delta_time; static uint16_t delta_time;
LED_A_ON();
LED_C_OFF();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
// free eventually allocated BigBuf memory // free eventually allocated BigBuf memory
BigBuf_free(); BigBuf_free();
// clear trace
clear_trace(); clear_trace();
set_tracing(false); set_tracing(false);
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
LED_A_ON();
LED_C_OFF();
// statistics on nonce distance // statistics on nonce distance
int16_t isOK = 0;
#define NESTED_MAX_TRIES 12
uint16_t unsuccessfull_tries = 0;
if (calibrate) { // for first call only. Otherwise reuse previous calibration if (calibrate) { // for first call only. Otherwise reuse previous calibration
LED_B_ON(); LED_B_ON();
WDT_HIT(); WDT_HIT();
@ -557,6 +659,12 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
for (rtr = 0; rtr < 17; rtr++) { for (rtr = 0; rtr < 17; rtr++) {
// Test if the action was cancelled
if(BUTTON_PRESS()) {
isOK = -2;
break;
}
// prepare next select. No need to power down the card. // prepare next select. No need to power down the card.
if(mifare_classic_halt(pcs, cuid)) { if(mifare_classic_halt(pcs, cuid)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Halt error"); if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Halt error");
@ -604,14 +712,17 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
delta_time = auth2_time - auth1_time + 32; // allow some slack for proper timing delta_time = auth2_time - auth1_time + 32; // allow some slack for proper timing
} }
if (MF_DBGLEVEL >= 3) Dbprintf("Nested: calibrating... ntdist=%d", i); if (MF_DBGLEVEL >= 3) Dbprintf("Nested: calibrating... ntdist=%d", i);
} else {
unsuccessfull_tries++;
if (unsuccessfull_tries > NESTED_MAX_TRIES) { // card isn't vulnerable to nested attack (random numbers are not predictable)
isOK = -3;
}
} }
} }
if (rtr <= 1) return;
davg = (davg + (rtr - 1)/2) / (rtr - 1); davg = (davg + (rtr - 1)/2) / (rtr - 1);
if (MF_DBGLEVEL >= 3) Dbprintf("min=%d max=%d avg=%d, delta_time=%d", dmin, dmax, davg, delta_time); if (MF_DBGLEVEL >= 3) Dbprintf("rtr=%d isOK=%d min=%d max=%d avg=%d, delta_time=%d", rtr, isOK, dmin, dmax, davg, delta_time);
dmin = davg - 2; dmin = davg - 2;
dmax = davg + 2; dmax = davg + 2;
@ -619,12 +730,12 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
LED_B_OFF(); LED_B_OFF();
} }
// ------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------
LED_C_ON(); LED_C_ON();
// get crypted nonces for target sector // get crypted nonces for target sector
for(i=0; i < 2; i++) { // look for exactly two different nonces for(i=0; i < 2 && !isOK; i++) { // look for exactly two different nonces
target_nt[i] = 0; target_nt[i] = 0;
while(target_nt[i] == 0) { // continue until we have an unambiguous nonce while(target_nt[i] == 0) { // continue until we have an unambiguous nonce
@ -648,7 +759,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
// nested authentication // nested authentication
auth2_time = auth1_time + delta_time; auth2_time = auth1_time + delta_time;
len = mifare_sendcmd_shortex(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, &auth2_time); len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, &auth2_time);
if (len != 4) { if (len != 4) {
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error len=%d", len); if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error len=%d", len);
continue; continue;
@ -702,7 +813,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
memcpy(buf+16, &target_ks[1], 4); memcpy(buf+16, &target_ks[1], 4);
LED_B_ON(); LED_B_ON();
cmd_send(CMD_ACK, 0, 2, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf)); cmd_send(CMD_ACK, isOK, 0, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf));
LED_B_OFF(); LED_B_OFF();
if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED"); if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED");
@ -737,15 +848,13 @@ void MifareChkKeys(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
int OLD_MF_DBGLEVEL = MF_DBGLEVEL; int OLD_MF_DBGLEVEL = MF_DBGLEVEL;
MF_DBGLEVEL = MF_DBG_NONE; MF_DBGLEVEL = MF_DBG_NONE;
// clear trace
clear_trace();
set_tracing(TRUE);
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
LED_A_ON(); LED_A_ON();
LED_B_OFF(); LED_B_OFF();
LED_C_OFF(); LED_C_OFF();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
clear_trace();
set_tracing(TRUE);
for (i = 0; i < keyCount; i++) { for (i = 0; i < keyCount; i++) {
if(mifare_classic_halt(pcs, cuid)) { if(mifare_classic_halt(pcs, cuid)) {
@ -792,16 +901,23 @@ void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Work with emulator memory // Work with emulator memory
// //
// Note: we call FpgaDownloadAndGo(FPGA_BITSTREAM_HF) here although FPGA is not
// involved in dealing with emulator memory. But if it is called later, it might
// destroy the Emulator Memory.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
emlClearMem(); emlClearMem();
} }
void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
emlSetMem(datain, arg0, arg1); // data, block num, blocks count emlSetMem(datain, arg0, arg1); // data, block num, blocks count
} }
void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
byte_t buf[USB_CMD_DATA_SIZE]; byte_t buf[USB_CMD_DATA_SIZE];
emlGetMem(buf, arg0, arg1); // data, block num, blocks count (max 4) emlGetMem(buf, arg0, arg1); // data, block num, blocks count (max 4)
@ -828,15 +944,13 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
byte_t dataoutbuf2[16]; byte_t dataoutbuf2[16];
uint8_t uid[10]; uint8_t uid[10];
// clear trace
clear_trace();
set_tracing(false);
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
LED_A_ON(); LED_A_ON();
LED_B_OFF(); LED_B_OFF();
LED_C_OFF(); LED_C_OFF();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
clear_trace();
set_tracing(false);
bool isOK = true; bool isOK = true;
@ -930,10 +1044,10 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
LED_A_ON(); LED_A_ON();
LED_B_OFF(); LED_B_OFF();
LED_C_OFF(); LED_C_OFF();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
clear_trace(); clear_trace();
set_tracing(TRUE); set_tracing(TRUE);
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
} }
while (true) { while (true) {
@ -1048,10 +1162,10 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
LED_A_ON(); LED_A_ON();
LED_B_OFF(); LED_B_OFF();
LED_C_OFF(); LED_C_OFF();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
clear_trace(); clear_trace();
set_tracing(TRUE); set_tracing(TRUE);
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
} }
while (true) { while (true) {
@ -1126,7 +1240,7 @@ void MifareCIdent(){
cmd_send(CMD_ACK,isOK,0,0,0,0); cmd_send(CMD_ACK,isOK,0,0,0,0);
} }
// //
// DESFIRE // DESFIRE
// //
@ -1136,26 +1250,23 @@ void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){
uint8_t uid[10] = {0x00}; uint8_t uid[10] = {0x00};
uint32_t cuid; uint32_t cuid;
clear_trace();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
clear_trace();
int len = iso14443a_select_card(uid, NULL, &cuid); int len = iso14443a_select_card(uid, NULL, &cuid);
if(!len) { if(!len) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card");
Dbprintf("Can't select card"); OnError(1);
//OnError(1);
return; return;
}; };
if(mifare_desfire_des_auth1(cuid, dataout)){ if(mifare_desfire_des_auth1(cuid, dataout)){
if (MF_DBGLEVEL >= MF_DBG_ERROR) if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication part1: Fail.");
Dbprintf("Authentication part1: Fail."); OnError(4);
//OnError(4);
return; return;
} }
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED");
cmd_send(CMD_ACK,1,cuid,0,dataout, sizeof(dataout)); cmd_send(CMD_ACK,1,cuid,0,dataout, sizeof(dataout));
} }
@ -1171,16 +1282,29 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){
isOK = mifare_desfire_des_auth2(cuid, key, dataout); isOK = mifare_desfire_des_auth2(cuid, key, dataout);
if( isOK) { if( isOK) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication part2: Failed");
Dbprintf("Authentication part2: Failed"); OnError(4);
//OnError(4);
return; return;
} }
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED");
DbpString("AUTH 2 FINISHED");
cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout)); cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout));
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff(); LEDsoff();
} }
void OnSuccess(){
pcb_blocknum = 0;
ReaderTransmit(deselect_cmd, 3 , NULL);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
void OnError(uint8_t reason){
pcb_blocknum = 0;
ReaderTransmit(deselect_cmd, 3 , NULL);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
cmd_send(CMD_ACK,0,reason,0,0,0);
LEDsoff();
}

View file

@ -18,6 +18,7 @@
#include "iso14443a.h" #include "iso14443a.h"
#include "crapto1.h" #include "crapto1.h"
#include "mifareutil.h" #include "mifareutil.h"
#include "des.h"
int MF_DBGLEVEL = MF_DBG_ALL; int MF_DBGLEVEL = MF_DBG_ALL;
@ -64,55 +65,27 @@ uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data) {
return bt; return bt;
} }
// send commands // send X byte basic commands
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing) int mifare_sendcmd(uint8_t cmd, uint8_t* data, uint8_t data_size, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing)
{ {
return mifare_sendcmd_shortex(pcs, crypted, cmd, data, answer, answer_parity, timing); uint8_t dcmd[data_size+3];
} dcmd[0] = cmd;
memcpy(dcmd+1,data,data_size);
int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing) AppendCrc14443a(dcmd, data_size+1);
{ ReaderTransmit(dcmd, sizeof(dcmd), timing);
uint8_t dcmd[8]; int len = ReaderReceive(answer, answer_parity);
dcmd[0] = cmd; if(!len) {
dcmd[1] = data[0]; if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("%02X Cmd failed. Card timeout.", cmd);
dcmd[2] = data[1]; len = ReaderReceive(answer,answer_parity);
dcmd[3] = data[2]; //return 0;
dcmd[4] = data[3]; }
dcmd[5] = data[4];
AppendCrc14443a(dcmd, 6);
ReaderTransmit(dcmd, sizeof(dcmd), NULL);
int len = ReaderReceive(answer, answer_parity);
if(!len) {
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout.");
return 2;
}
return len; return len;
} }
int mifare_sendcmd_short_mfucauth(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) // send 2 byte commands
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing)
{ {
uint8_t dcmd[19]; uint8_t dcmd[4], ecmd[4];
int len;
dcmd[0] = cmd;
memcpy(dcmd+1,data,16);
AppendCrc14443a(dcmd, 17);
ReaderTransmit(dcmd, sizeof(dcmd), timing);
len = ReaderReceive(answer, answer_parity);
if(!len) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed. Card timeout.");
len = ReaderReceive(answer,answer_parity);
}
if(len==1) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("NAK - Authentication failed.");
return 1;
}
return len;
}
int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing)
{
uint8_t dcmd[4], ecmd[4];
uint16_t pos, res; uint16_t pos, res;
uint8_t par[1]; // 1 Byte parity is enough here uint8_t par[1]; // 1 Byte parity is enough here
dcmd[0] = cmd; dcmd[0] = cmd;
@ -284,97 +257,152 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
} }
memcpy(blockData, receivedAnswer, 16); memcpy(blockData, receivedAnswer, 16);
return 0; return 0;
} }
// mifare ultralight commands // mifare ultralight commands
int mifare_ultra_auth1(uint32_t uid, uint8_t *blockData){ int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack){
uint16_t len; uint16_t len;
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t resp[4];
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; uint8_t respPar[1];
uint8_t key[4] = {0x00};
len = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, receivedAnswer,receivedAnswerPar ,NULL); memcpy(key, keybytes, 4);
if (len == 1) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) if (MF_DBGLEVEL >= MF_DBG_EXTENDED)
Dbprintf("Cmd Error: %02x", receivedAnswer[0]); Dbprintf("EV1 Auth : %02x%02x%02x%02x", key[0], key[1], key[2], key[3]);
return 1; len = mifare_sendcmd(0x1B, key, sizeof(key), resp, respPar, NULL);
//len = mifare_sendcmd_short_mfuev1auth(NULL, 0, 0x1B, key, resp, respPar, NULL);
if (len != 4) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x %u", resp[0], len);
return 0;
} }
if (len != 11)
return 1; if (MF_DBGLEVEL >= MF_DBG_EXTENDED)
Dbprintf("Auth Resp: %02x%02x%02x%02x", resp[0],resp[1],resp[2],resp[3]);
memcpy(pack, resp, 4);
return 1;
}
int mifare_ultra_auth(uint8_t *keybytes){
/// 3des2k
uint8_t random_a[8] = {1,1,1,1,1,1,1,1};
uint8_t random_b[8] = {0x00};
uint8_t enc_random_b[8] = {0x00};
uint8_t rnd_ab[16] = {0x00};
uint8_t IV[8] = {0x00};
uint8_t key[16] = {0x00};
memcpy(key, keybytes, 16);
uint16_t len;
uint8_t resp[19] = {0x00};
uint8_t respPar[3] = {0,0,0};
// REQUEST AUTHENTICATION
len = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, resp, respPar ,NULL);
if (len != 11) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]);
return 0;
}
// tag nonce.
memcpy(enc_random_b,resp+1,8);
// decrypt nonce.
tdes_2key_dec(random_b, enc_random_b, sizeof(random_b), key, IV );
rol(random_b,8);
memcpy(rnd_ab ,random_a,8);
memcpy(rnd_ab+8,random_b,8);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
Dbprintf("Auth1 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", Dbprintf("enc_B: %02x %02x %02x %02x %02x %02x %02x %02x",
receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4], enc_random_b[0],enc_random_b[1],enc_random_b[2],enc_random_b[3],enc_random_b[4],enc_random_b[5],enc_random_b[6],enc_random_b[7]);
receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9],
receivedAnswer[10]); Dbprintf(" B: %02x %02x %02x %02x %02x %02x %02x %02x",
} random_b[0],random_b[1],random_b[2],random_b[3],random_b[4],random_b[5],random_b[6],random_b[7]);
memcpy(blockData, receivedAnswer, 11);
Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x",
rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3],rnd_ab[4],rnd_ab[5],rnd_ab[6],rnd_ab[7]);
Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x",
rnd_ab[8],rnd_ab[9],rnd_ab[10],rnd_ab[11],rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15] );
}
// encrypt out, in, length, key, iv
tdes_2key_enc(rnd_ab, rnd_ab, sizeof(rnd_ab), key, enc_random_b);
//len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, resp, respPar, NULL);
len = mifare_sendcmd(0xAF, rnd_ab, sizeof(rnd_ab), resp, respPar, NULL);
if (len != 11) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]);
return 0;
}
uint8_t enc_resp[8] = { 0,0,0,0,0,0,0,0 };
uint8_t resp_random_a[8] = { 0,0,0,0,0,0,0,0 };
memcpy(enc_resp, resp+1, 8);
// decrypt out, in, length, key, iv
tdes_2key_dec(resp_random_a, enc_resp, 8, key, enc_random_b);
if ( memcmp(resp_random_a, random_a, 8) != 0 ) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("failed authentication");
return 0;
}
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x",
rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3],
rnd_ab[4],rnd_ab[5],rnd_ab[6],rnd_ab[7]);
Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x",
rnd_ab[8],rnd_ab[9],rnd_ab[10],rnd_ab[11],
rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15]);
Dbprintf("a: %02x %02x %02x %02x %02x %02x %02x %02x",
random_a[0],random_a[1],random_a[2],random_a[3],
random_a[4],random_a[5],random_a[6],random_a[7]);
Dbprintf("b: %02x %02x %02x %02x %02x %02x %02x %02x",
resp_random_a[0],resp_random_a[1],resp_random_a[2],resp_random_a[3],
resp_random_a[4],resp_random_a[5],resp_random_a[6],resp_random_a[7]);
}
return 1;
}
int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData)
{
uint16_t len;
uint8_t bt[2];
uint8_t receivedAnswer[MAX_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_PARITY_SIZE];
len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL);
if (len == 1) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
return 1;
}
if (len != 18) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: card timeout. len: %x", len);
return 2;
}
memcpy(bt, receivedAnswer + 16, 2);
AppendCrc14443a(receivedAnswer, 16);
if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd CRC response error.");
return 3;
}
memcpy(blockData, receivedAnswer, 14);
return 0; return 0;
} }
int mifare_ultra_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData)
{
uint16_t len; // variables
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, key, receivedAnswer, receivedAnswerPar, NULL);
if (len == 1) {
if (MF_DBGLEVEL >= MF_DBG_ERROR)
Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
return 1;
}
if (len != 11)
return 1;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
Dbprintf("Auth2 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4],
receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9],
receivedAnswer[10]);
}
memcpy(blockData, receivedAnswer, 11);
return 0;
}
int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
{
uint16_t len;
uint8_t bt[2];
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
// command MIFARE_CLASSIC_READBLOCK
len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL);
if (len == 1) {
if (MF_DBGLEVEL >= MF_DBG_ERROR)
Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
return 1;
}
if (len != 18) {
if (MF_DBGLEVEL >= MF_DBG_ERROR)
Dbprintf("Cmd Error: card timeout. len: %x", len);
return 2;
}
memcpy(bt, receivedAnswer + 16, 2);
AppendCrc14443a(receivedAnswer, 16);
if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {
if (MF_DBGLEVEL >= MF_DBG_ERROR)
Dbprintf("Cmd CRC response error.");
return 3;
}
memcpy(blockData, receivedAnswer, 14);
return 0;
}
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData)
{
// variables
uint16_t len, i; uint16_t len, i;
uint32_t pos; uint32_t pos;
uint8_t par[3] = {0}; // enough for 18 Bytes to send uint8_t par[3] = {0}; // enough for 18 Bytes to send
@ -416,65 +444,66 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
return 2; return 2;
} }
return 0; return 0;
} }
int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData) /* // command not needed, but left for future testing
{ int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData)
uint16_t len; {
uint8_t par[3] = {0}; // enough for 18 parity bits uint16_t len;
uint8_t d_block[18] = {0x00}; uint8_t par[3] = {0}; // enough for 18 parity bits
uint8_t d_block[18] = {0x00};
uint8_t receivedAnswer[MAX_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_PARITY_SIZE];
len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
if (MF_DBGLEVEL >= MF_DBG_ERROR)
Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]);
return 1;
}
memcpy(d_block, blockData, 16);
AppendCrc14443a(d_block, 16);
ReaderTransmitPar(d_block, sizeof(d_block), par, NULL);
len = ReaderReceive(receivedAnswer, receivedAnswerPar);
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
if (MF_DBGLEVEL >= MF_DBG_ERROR)
Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len);
return 2;
}
return 0;
}
*/
int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData)
{
uint16_t len;
uint8_t d_block[5] = {0x00};
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
// command MIFARE_CLASSIC_WRITEBLOCK // command MIFARE_CLASSIC_WRITEBLOCK
len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL); d_block[0]= blockNo;
memcpy(d_block+1,blockData,4);
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK //AppendCrc14443a(d_block, 6);
len = mifare_sendcmd(0xA2, d_block, sizeof(d_block), receivedAnswer, receivedAnswerPar, NULL);
if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK
if (MF_DBGLEVEL >= MF_DBG_ERROR) if (MF_DBGLEVEL >= MF_DBG_ERROR)
Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]); Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len);
return 1; return 1;
} }
return 0;
memcpy(d_block, blockData, 16); }
AppendCrc14443a(d_block, 16);
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
ReaderTransmitPar(d_block, sizeof(d_block), par, NULL); {
len = ReaderReceive(receivedAnswer, receivedAnswerPar);
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
if (MF_DBGLEVEL >= MF_DBG_ERROR)
Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len);
return 2;
}
return 0;
}
int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
{
uint16_t len;
uint8_t d_block[8] = {0x00};
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
// command MIFARE_CLASSIC_WRITEBLOCK
d_block[0]= blockNo;
memcpy(d_block+1,blockData,4);
AppendCrc14443a(d_block, 6);
len = mifare_sendcmd_short_special(NULL, 1, 0xA2, d_block, receivedAnswer, receivedAnswerPar, NULL);
if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK
if (MF_DBGLEVEL >= MF_DBG_ERROR)
Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len);
return 1;
}
return 0;
}
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
{
uint16_t len; uint16_t len;
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
@ -486,24 +515,24 @@ int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
return 1; return 1;
} }
return 0; return 0;
} }
int mifare_ultra_halt(uint32_t uid) int mifare_ultra_halt()
{ {
uint16_t len; uint16_t len;
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
len = mifare_sendcmd_short(NULL, true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd_short(NULL, true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL);
if (len != 0) { if (len != 0) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) if (MF_DBGLEVEL >= MF_DBG_ERROR)
Dbprintf("halt error. response len: %x", len); Dbprintf("halt error. response len: %x", len);
return 1; return 1;
} }
return 0; return 0;
} }
// Mifare Memory Structure: up to 32 Sectors with 4 blocks each (1k and 2k cards), // Mifare Memory Structure: up to 32 Sectors with 4 blocks each (1k and 2k cards),
// plus evtl. 8 sectors with 16 blocks each (4k cards) // plus evtl. 8 sectors with 16 blocks each (4k cards)
@ -525,9 +554,9 @@ uint8_t FirstBlockOfSector(uint8_t sectorNo)
} }
// work with emulator memory // work with emulator memory
void emlSetMem(uint8_t *data, int blockNum, int blocksCount) { void emlSetMem(uint8_t *data, int blockNum, int blocksCount) {
uint8_t* emCARD = BigBuf_get_EM_addr(); uint8_t* emCARD = BigBuf_get_EM_addr();
memcpy(emCARD + blockNum * 16, data, blocksCount * 16); memcpy(emCARD + blockNum * 16, data, blocksCount * 16);
} }
@ -654,8 +683,8 @@ int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData){
int len; int len;
// load key, keynumber // load key, keynumber
uint8_t data[2]={0x0a, 0x00}; uint8_t data[2]={0x0a, 0x00};
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswer[MAX_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; uint8_t receivedAnswerPar[MAX_PARITY_SIZE];
len = mifare_sendcmd_special(NULL, 1, 0x02, data, receivedAnswer,receivedAnswerPar,NULL); len = mifare_sendcmd_special(NULL, 1, 0x02, data, receivedAnswer,receivedAnswerPar,NULL);
if (len == 1) { if (len == 1) {
@ -706,4 +735,4 @@ int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){
return 0; return 0;
} }
return 1; return 1;
} }

View file

@ -52,33 +52,33 @@ extern int MF_DBGLEVEL;
#define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF(); #define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF();
//functions //functions
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); int mifare_sendcmd(uint8_t cmd, uint8_t *data, uint8_t data_size, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_sendcmd_short_mfucauth(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing); // mifare classic
int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested); int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested);
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing); int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing);
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
int mifare_ultra_auth1(uint32_t cuid, uint8_t *blockData); int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid);
int mifare_ultra_auth2(uint32_t cuid, uint8_t *key, uint8_t *blockData); int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData);
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); // Ultralight/NTAG...
int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData); int mifare_ul_ev1_auth(uint8_t *key, uint8_t *pack);
int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData); int mifare_ultra_auth(uint8_t *key);
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData);
int mifare_ultra_halt(uint32_t uid); //int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData);
int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData);
int mifare_ultra_halt();
// desfire // desfire
int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_sendcmd_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer,uint8_t *answer_parity, uint32_t *timing); int mifare_sendcmd_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer,uint8_t *answer_parity, uint32_t *timing);
int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData); int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData);
int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData); int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData);
// crypto functions // crypto functions
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *receivedCmd, int len); void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *receivedCmd, int len);
void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par); void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par);
uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data); uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data);
@ -93,7 +93,7 @@ void emlGetMem(uint8_t *data, int blockNum, int blocksCount);
void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount); void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount);
uint64_t emlGetKey(int sectorNum, int keyType); uint64_t emlGetKey(int sectorNum, int keyType);
int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum); int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum);
int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum); int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum);
int emlCheckValBl(int blockNum); int emlCheckValBl(int blockNum);
#endif #endif

View file

@ -61,12 +61,10 @@
**/ **/
#include "optimized_cipher.h" #include "optimized_cipher.h"
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <time.h>
#define opt_T(s) (0x1 & ((s->t >> 15) ^ (s->t >> 14)^ (s->t >> 10)^ (s->t >> 8)^ (s->t >> 5)^ (s->t >> 4)^ (s->t >> 1)^ s->t)) #define opt_T(s) (0x1 & ((s->t >> 15) ^ (s->t >> 14)^ (s->t >> 10)^ (s->t >> 8)^ (s->t >> 5)^ (s->t >> 4)^ (s->t >> 1)^ s->t))

View file

@ -11,23 +11,75 @@
#include "proxmark3.h" #include "proxmark3.h"
#include "apps.h" #include "apps.h"
#include "zlib.h"
#include "BigBuf.h"
static uint8_t *next_free_memory;
extern struct common_area common_area;
extern char __data_src_start__, __data_start__, __data_end__, __bss_start__, __bss_end__;
static voidpf inflate_malloc(voidpf opaque, uInt items, uInt size)
{
uint8_t *allocated_memory;
allocated_memory = next_free_memory;
next_free_memory += items*size;
return allocated_memory;
}
static void inflate_free(voidpf opaque, voidpf address)
{
// nothing to do
}
static void uncompress_data_section(void)
{
z_stream data_section;
next_free_memory = BigBuf_get_addr();
// initialize zstream structure
data_section.next_in = (uint8_t *) &__data_src_start__;
data_section.avail_in = &__data_end__ - &__data_start__; // uncompressed size. Wrong but doesn't matter.
data_section.next_out = (uint8_t *) &__data_start__;
data_section.avail_out = &__data_end__ - &__data_start__; // uncompressed size. Correct.
data_section.zalloc = &inflate_malloc;
data_section.zfree = &inflate_free;
data_section.opaque = NULL;
// initialize zlib for inflate
inflateInit2(&data_section, 15);
// uncompress data segment to RAM
inflate(&data_section, Z_FINISH);
// save the size of the compressed data section
common_area.arg1 = data_section.total_in;
}
extern char __data_start__, __data_src_start__, __data_end__, __bss_start__, __bss_end__;
void __attribute__((section(".startos"))) Vector(void) void __attribute__((section(".startos"))) Vector(void)
{ {
/* Stack should have been set up by the bootloader */ /* Stack should have been set up by the bootloader */
char *src, *dst, *end; // char *src;
char *dst, *end;
uncompress_data_section();
/* Set up (that is: clear) BSS. */ /* Set up (that is: clear) BSS. */
dst = &__bss_start__; dst = &__bss_start__;
end = &__bss_end__; end = &__bss_end__;
while(dst < end) *dst++ = 0; while(dst < end) *dst++ = 0;
/* Set up data segment: Copy from flash to ram */ // Set up data segment: Copy from flash to ram
src = &__data_src_start__; // src = &__data_src_start__;
dst = &__data_start__; // dst = &__data_start__;
end = &__data_end__; // end = &__data_end__;
while(dst < end) *dst++ = *src++; // while(dst < end) *dst++ = *src++;
AppMain(); AppMain();
} }

View file

@ -268,15 +268,15 @@ void FormatVersionInformation(char *dst, int len, const char *prefix, void *vers
dst[0] = 0; dst[0] = 0;
strncat(dst, prefix, len-1); strncat(dst, prefix, len-1);
if(v->magic != VERSION_INFORMATION_MAGIC) { if(v->magic != VERSION_INFORMATION_MAGIC) {
strncat(dst, "Missing/Invalid version information", len - strlen(dst) - 1); strncat(dst, "Missing/Invalid version information\n", len - strlen(dst) - 1);
return; return;
} }
if(v->versionversion != 1) { if(v->versionversion != 1) {
strncat(dst, "Version information not understood", len - strlen(dst) - 1); strncat(dst, "Version information not understood\n", len - strlen(dst) - 1);
return; return;
} }
if(!v->present) { if(!v->present) {
strncat(dst, "Version information not available", len - strlen(dst) - 1); strncat(dst, "Version information not available\n", len - strlen(dst) - 1);
return; return;
} }
@ -289,6 +289,7 @@ void FormatVersionInformation(char *dst, int len, const char *prefix, void *vers
strncat(dst, " ", len - strlen(dst) - 1); strncat(dst, " ", len - strlen(dst) - 1);
strncat(dst, v->buildtime, len - strlen(dst) - 1); strncat(dst, v->buildtime, len - strlen(dst) - 1);
strncat(dst, "\n", len - strlen(dst) - 1);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------

View file

@ -9,12 +9,13 @@ include ../common/Makefile.common
CC=gcc CC=gcc
CXX=g++ CXX=g++
#COMMON_FLAGS = -m32 #COMMON_FLAGS = -m32
VPATH = ../common VPATH = ../common ../zlib
OBJDIR = obj OBJDIR = obj
LDLIBS = -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthread -lm LDLIBS = -L/opt/local/lib -L/usr/local/lib -lreadline -lpthread -lm
LUALIB = ../liblua/liblua.a
LDFLAGS = $(COMMON_FLAGS) LDFLAGS = $(COMMON_FLAGS)
CFLAGS = -std=c99 -I. -I../include -I../common -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4 CFLAGS = -std=c99 -I. -I../include -I../common -I../zlib -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4
LUAPLATFORM = generic LUAPLATFORM = generic
ifneq (,$(findstring MINGW,$(platform))) ifneq (,$(findstring MINGW,$(platform)))
@ -35,14 +36,13 @@ else ifeq ($(platform),Darwin)
else else
CXXFLAGS = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null) -Wall -O4 CXXFLAGS = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null) -Wall -O4
QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null) QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null)
LUALIB += -ldl
MOC = $(shell pkg-config --variable=moc_location QtCore) MOC = $(shell pkg-config --variable=moc_location QtCore)
LDLIBS += -ldl
# Below is a variant you can use if you have problems compiling with QT5 on ubuntu. see http://www.proxmark.org/forum/viewtopic.php?id=1661 for more info. # Below is a variant you can use if you have problems compiling with QT5 on ubuntu. see http://www.proxmark.org/forum/viewtopic.php?id=1661 for more info.
#MOC = /usr/lib/x86_64-linux-gnu/qt4/bin/moc #MOC = /usr/lib/x86_64-linux-gnu/qt4/bin/moc
LUAPLATFORM = linux LUAPLATFORM = linux
endif endif
ifneq ($(QTLDLIBS),) ifneq ($(QTLDLIBS),)
QTGUI = $(OBJDIR)/proxgui.o $(OBJDIR)/proxguiqt.o $(OBJDIR)/proxguiqt.moc.o QTGUI = $(OBJDIR)/proxgui.o $(OBJDIR)/proxguiqt.o $(OBJDIR)/proxguiqt.moc.o
CFLAGS += -DHAVE_GUI CFLAGS += -DHAVE_GUI
@ -57,65 +57,73 @@ CORESRCS = uart.c \
CMDSRCS = nonce2key/crapto1.c\ CMDSRCS = nonce2key/crapto1.c\
nonce2key/crypto1.c\ nonce2key/crypto1.c\
nonce2key/nonce2key.c\ nonce2key/nonce2key.c\
loclass/cipher.c \ loclass/cipher.c \
loclass/cipherutils.c \ loclass/cipherutils.c \
loclass/des.c \ loclass/des.c \
loclass/ikeys.c \ loclass/ikeys.c \
loclass/elite_crack.c\ loclass/elite_crack.c\
loclass/fileutils.c\ loclass/fileutils.c\
mifarehost.c\ mifarehost.c\
crc.c \ crc.c \
crc16.c \ crc16.c \
iso14443crc.c \ crc64.c \
iso15693tools.c \ iso14443crc.c \
data.c \ iso15693tools.c \
graph.c \ data.c \
ui.c \ graph.c \
cmddata.c \ ui.c \
lfdemod.c \ cmddata.c \
cmdhf.c \ lfdemod.c \
cmdhf14a.c \ cmdhf.c \
cmdhf14b.c \ cmdhf14a.c \
cmdhf15.c \ cmdhf14b.c \
cmdhfepa.c \ cmdhf15.c \
cmdhflegic.c \ cmdhfepa.c \
cmdhficlass.c \ cmdhflegic.c \
cmdhfmf.c \ cmdhficlass.c \
cmdhfmfu.c \ cmdhfmf.c \
cmdhftopaz.c \ cmdhfmfu.c \
cmdhw.c \ cmdhftopaz.c \
cmdlf.c \ cmdhw.c \
cmdlfio.c \ cmdlf.c \
cmdlfhid.c \ cmdlfio.c \
cmdlfem4x.c \ cmdlfhid.c \
cmdlfhitag.c \ cmdlfem4x.c \
cmdlfti.c \ cmdlfhitag.c \
cmdparser.c \ cmdlfti.c \
cmdmain.c \ cmdparser.c \
cmdlft55xx.c \ cmdmain.c \
cmdlfpcf7931.c\ cmdlft55xx.c \
pm3_binlib.c\ cmdlfpcf7931.c\
scripting.c\ pm3_binlib.c\
cmdscript.c\ scripting.c\
pm3_bitlib.c\ cmdscript.c\
aes.c\ pm3_bitlib.c\
protocols.c aes.c\
protocols.c\
sha1.c\
ZLIBSRCS = deflate.c adler32.c trees.c zutil.c inflate.c inffast.c inftrees.c
ZLIB_FLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED
#-DDEBUG -Dverbose=1
COREOBJS = $(CORESRCS:%.c=$(OBJDIR)/%.o) COREOBJS = $(CORESRCS:%.c=$(OBJDIR)/%.o)
CMDOBJS = $(CMDSRCS:%.c=$(OBJDIR)/%.o) CMDOBJS = $(CMDSRCS:%.c=$(OBJDIR)/%.o)
ZLIBOBJS = $(ZLIBSRCS:%.c=$(OBJDIR)/%.o)
RM = rm -f RM = rm -f
BINS = proxmark3 flasher #snooper cli BINS = proxmark3 flasher fpga_compress #snooper cli
CLEAN = cli cli.exe flasher flasher.exe proxmark3 proxmark3.exe snooper snooper.exe $(CMDOBJS) $(OBJDIR)/*.o *.o *.moc.cpp CLEAN = cli cli.exe flasher flasher.exe proxmark3 proxmark3.exe fpga_compress fpga_compress.exe snooper snooper.exe $(CMDOBJS) $(OBJDIR)/*.o *.o *.moc.cpp
all: lua_build $(BINS) all: lua_build $(BINS)
all-static: LDLIBS:=-static $(LDLIBS) all-static: LDLIBS:=-static $(LDLIBS)
all-static: snooper cli flasher all-static: snooper cli flasher fpga_compress
proxmark3: LDLIBS+=$(QTLDLIBS) proxmark3: LDLIBS+=$(LUALIB) $(QTLDLIBS)
proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(QTGUI) proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(QTGUI)
$(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $@ $(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $@
@ -128,8 +136,11 @@ cli: $(OBJDIR)/cli.o $(COREOBJS) $(CMDOBJS) $(OBJDIR)/guidummy.o
flasher: $(OBJDIR)/flash.o $(OBJDIR)/flasher.o $(COREOBJS) flasher: $(OBJDIR)/flash.o $(OBJDIR)/flasher.o $(COREOBJS)
$(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $@ $(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $@
fpga_compress: $(OBJDIR)/fpga_compress.o $(ZLIBOBJS)
$(CXX) $(CXXFLAGS) $(ZLIB_FLAGS) $^ $(LDLIBS) -o $@
$(OBJDIR)/%.o: %.c $(OBJDIR)/%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $< $(CC) $(CFLAGS) $(ZLIB_FLAGS) -c -o $@ $<
$(OBJDIR)/%.o: %.cpp $(OBJDIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $< $(CXX) $(CXXFLAGS) -c -o $@ $<

File diff suppressed because it is too large Load diff

View file

@ -15,10 +15,7 @@ command_t * CmdDataCommands();
int CmdData(const char *Cmd); int CmdData(const char *Cmd);
void printDemodBuff(void); void printDemodBuff(void);
void printBitStream(uint8_t BitStream[], uint32_t bitLen);
void setDemodBuf(uint8_t *buff, size_t size, size_t startIdx); void setDemodBuf(uint8_t *buff, size_t size, size_t startIdx);
int CmdAmp(const char *Cmd);
int Cmdaskdemod(const char *Cmd);
int CmdAskEM410xDemod(const char *Cmd); int CmdAskEM410xDemod(const char *Cmd);
int CmdG_Prox_II_Demod(const char *Cmd); int CmdG_Prox_II_Demod(const char *Cmd);
int Cmdaskrawdemod(const char *Cmd); int Cmdaskrawdemod(const char *Cmd);
@ -27,12 +24,11 @@ int AutoCorrelate(int window, bool SaveGrph, bool verbose);
int CmdAutoCorr(const char *Cmd); int CmdAutoCorr(const char *Cmd);
int CmdBiphaseDecodeRaw(const char *Cmd); int CmdBiphaseDecodeRaw(const char *Cmd);
int CmdBitsamples(const char *Cmd); int CmdBitsamples(const char *Cmd);
int CmdBitstream(const char *Cmd);
int CmdBuffClear(const char *Cmd); int CmdBuffClear(const char *Cmd);
int CmdDec(const char *Cmd); int CmdDec(const char *Cmd);
int CmdDetectClockRate(const char *Cmd); int CmdDetectClockRate(const char *Cmd);
int CmdFDXBdemodBI(const char *Cmd);
int CmdFSKdemodAWID(const char *Cmd); int CmdFSKdemodAWID(const char *Cmd);
int CmdFSKdemod(const char *Cmd);
int CmdFSKdemodHID(const char *Cmd); int CmdFSKdemodHID(const char *Cmd);
int CmdFSKdemodIO(const char *Cmd); int CmdFSKdemodIO(const char *Cmd);
int CmdFSKdemodParadox(const char *Cmd); int CmdFSKdemodParadox(const char *Cmd);
@ -40,6 +36,7 @@ int CmdFSKdemodPyramid(const char *Cmd);
int CmdFSKrawdemod(const char *Cmd); int CmdFSKrawdemod(const char *Cmd);
int CmdPSK1rawDemod(const char *Cmd); int CmdPSK1rawDemod(const char *Cmd);
int CmdPSK2rawDemod(const char *Cmd); int CmdPSK2rawDemod(const char *Cmd);
int CmdPSKNexWatch(const char *Cmd);
int CmdGrid(const char *Cmd); int CmdGrid(const char *Cmd);
int CmdGetBitStream(const char *Cmd); int CmdGetBitStream(const char *Cmd);
int CmdHexsamples(const char *Cmd); int CmdHexsamples(const char *Cmd);
@ -49,24 +46,22 @@ int CmdLoad(const char *Cmd);
int CmdLtrim(const char *Cmd); int CmdLtrim(const char *Cmd);
int CmdRtrim(const char *Cmd); int CmdRtrim(const char *Cmd);
int Cmdmandecoderaw(const char *Cmd); int Cmdmandecoderaw(const char *Cmd);
int CmdManchesterDemod(const char *Cmd);
int CmdManchesterMod(const char *Cmd);
int CmdNorm(const char *Cmd); int CmdNorm(const char *Cmd);
int CmdNRZrawDemod(const char *Cmd); int CmdNRZrawDemod(const char *Cmd);
int CmdPlot(const char *Cmd); int CmdPlot(const char *Cmd);
int CmdPrintDemodBuff(const char *Cmd);
int CmdRawDemod(const char *Cmd); int CmdRawDemod(const char *Cmd);
int CmdSamples(const char *Cmd); int CmdSamples(const char *Cmd);
int CmdTuneSamples(const char *Cmd); int CmdTuneSamples(const char *Cmd);
int CmdSave(const char *Cmd); int CmdSave(const char *Cmd);
int CmdScale(const char *Cmd); int CmdScale(const char *Cmd);
int CmdThreshold(const char *Cmd);
int CmdDirectionalThreshold(const char *Cmd); int CmdDirectionalThreshold(const char *Cmd);
int CmdZerocrossings(const char *Cmd); int CmdZerocrossings(const char *Cmd);
int CmdIndalaDecode(const char *Cmd); int CmdIndalaDecode(const char *Cmd);
int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo); int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo );
int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose);
int ASKbiphaseDemod(const char *Cmd, bool verbose); int ASKbiphaseDemod(const char *Cmd, bool verbose);
int ASKmanDemod(const char *Cmd, bool verbose, bool emSearch); int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType);
int ASKrawDemod(const char *Cmd, bool verbose);
int FSKrawDemod(const char *Cmd, bool verbose); int FSKrawDemod(const char *Cmd, bool verbose);
int PSKDemod(const char *Cmd, bool verbose); int PSKDemod(const char *Cmd, bool verbose);
int NRZrawDemod(const char *Cmd, bool verbose); int NRZrawDemod(const char *Cmd, bool verbose);
@ -76,8 +71,8 @@ int getSamples(const char *Cmd, bool silent);
#define MAX_DEMOD_BUF_LEN (1024*128) #define MAX_DEMOD_BUF_LEN (1024*128)
extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN]; extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
extern int DemodBufferLen; extern size_t DemodBufferLen;
extern uint8_t g_debugMode;
#define BIGBUF_SIZE 40000 #define BIGBUF_SIZE 40000
#endif #endif

View file

@ -72,11 +72,57 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
case MIFARE_CMD_DEC: snprintf(exp,size,"DEC(%d)",cmd[1]); break; case MIFARE_CMD_DEC: snprintf(exp,size,"DEC(%d)",cmd[1]); break;
case MIFARE_CMD_RESTORE: snprintf(exp,size,"RESTORE(%d)",cmd[1]); break; case MIFARE_CMD_RESTORE: snprintf(exp,size,"RESTORE(%d)",cmd[1]); break;
case MIFARE_CMD_TRANSFER: snprintf(exp,size,"TRANSFER(%d)",cmd[1]); break; case MIFARE_CMD_TRANSFER: snprintf(exp,size,"TRANSFER(%d)",cmd[1]); break;
case MIFARE_AUTH_KEYA: snprintf(exp,size,"AUTH-A(%d)",cmd[1]); break; case MIFARE_AUTH_KEYA:{
if ( cmdsize > 3)
snprintf(exp,size,"AUTH-A(%d)",cmd[1]);
else
// case MIFARE_ULEV1_VERSION : both 0x60.
snprintf(exp,size,"EV1 VERSION");
break;
}
case MIFARE_AUTH_KEYB: snprintf(exp,size,"AUTH-B(%d)",cmd[1]); break; case MIFARE_AUTH_KEYB: snprintf(exp,size,"AUTH-B(%d)",cmd[1]); break;
case MIFARE_MAGICWUPC1: snprintf(exp,size,"MAGIC WUPC1"); break; case MIFARE_MAGICWUPC1: snprintf(exp,size,"MAGIC WUPC1"); break;
case MIFARE_MAGICWUPC2: snprintf(exp,size,"MAGIC WUPC2"); break; case MIFARE_MAGICWUPC2: snprintf(exp,size,"MAGIC WUPC2"); break;
case MIFARE_MAGICWIPEC: snprintf(exp,size,"MAGIC WIPEC"); break; case MIFARE_MAGICWIPEC: snprintf(exp,size,"MAGIC WIPEC"); break;
case MIFARE_ULC_AUTH_1: snprintf(exp,size,"AUTH "); break;
case MIFARE_ULC_AUTH_2: snprintf(exp,size,"AUTH_ANSW"); break;
case MIFARE_ULEV1_AUTH:
if ( cmdsize == 7 )
snprintf(exp,size,"PWD-AUTH KEY: 0x%02x%02x%02x%02x", cmd[1], cmd[2], cmd[3], cmd[4] );
else
snprintf(exp,size,"PWD-AUTH");
break;
case MIFARE_ULEV1_FASTREAD:{
if ( cmdsize >=3 && cmd[2] <= 0xE6)
snprintf(exp,size,"READ RANGE (%d-%d)",cmd[1],cmd[2]);
else
snprintf(exp,size,"?");
break;
}
case MIFARE_ULC_WRITE:{
if ( cmd[1] < 0x21 )
snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]);
else
snprintf(exp,size,"?");
break;
}
case MIFARE_ULEV1_READ_CNT:{
if ( cmd[1] < 5 )
snprintf(exp,size,"READ CNT(%d)",cmd[1]);
else
snprintf(exp,size,"?");
break;
}
case MIFARE_ULEV1_INCR_CNT:{
if ( cmd[1] < 5 )
snprintf(exp,size,"INCR(%d)",cmd[1]);
else
snprintf(exp,size,"?");
break;
}
case MIFARE_ULEV1_READSIG: snprintf(exp,size,"READ_SIG"); break;
case MIFARE_ULEV1_CHECKTEAR: snprintf(exp,size,"CHK_TEARING(%d)",cmd[1]); break;
case MIFARE_ULEV1_VCSL: snprintf(exp,size,"VCSL"); break;
default: snprintf(exp,size,"?"); break; default: snprintf(exp,size,"?"); break;
} }
return; return;
@ -438,8 +484,8 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01); oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
} }
uint8_t parityBits = parityBytes[j>>3]; uint8_t parityBits = parityBytes[j>>3];
if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) { if (protocol != ISO_14443B && isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
snprintf(line[j/16]+(( j % 16) * 4), 110, " %02x!", frame[j]); snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]);
} else { } else {
snprintf(line[j/16]+(( j % 16) * 4), 110, " %02x ", frame[j]); snprintf(line[j/16]+(( j % 16) * 4), 110, " %02x ", frame[j]);
} }
@ -615,9 +661,36 @@ int CmdHFList(const char *Cmd)
return 0; return 0;
} }
int CmdHFSearch(const char *Cmd){
int ans = 0;
PrintAndLog("");
ans = CmdHF14AReader("s");
if (ans > 0) {
PrintAndLog("\nValid ISO14443A Tag Found - Quiting Search\n");
return ans;
}
ans = HF14BInfo(false);
if (ans) {
PrintAndLog("\nValid ISO14443B Tag Found - Quiting Search\n");
return ans;
}
ans = HFiClassReader("", false, false);
if (ans) {
PrintAndLog("\nValid iClass Tag (or PicoPass Tag) Found - Quiting Search\n");
return ans;
}
ans = HF15Reader("", false);
if (ans) {
PrintAndLog("\nValid ISO15693 Tag Found - Quiting Search\n");
return ans;
}
PrintAndLog("\nno known/supported 13.56 MHz tags found\n");
return 0;
}
static command_t CommandTable[] = static command_t CommandTable[] =
{ {
<<<<<<< HEAD
{"help", CmdHelp, 1, "This help"}, {"help", CmdHelp, 1, "This help"},
{"14a", CmdHF14A, 1, "{ ISO14443A RFIDs... }"}, {"14a", CmdHF14A, 1, "{ ISO14443A RFIDs... }"},
{"14b", CmdHF14B, 1, "{ ISO14443B RFIDs... }"}, {"14b", CmdHF14B, 1, "{ ISO14443B RFIDs... }"},
@ -631,6 +704,21 @@ static command_t CommandTable[] =
{"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"}, {"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"},
{"list", CmdHFList, 1, "List protocol data in trace buffer"}, {"list", CmdHFList, 1, "List protocol data in trace buffer"},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
=======
{"help", CmdHelp, 1, "This help"},
{"14a", CmdHF14A, 1, "{ ISO14443A RFIDs... }"},
{"14b", CmdHF14B, 1, "{ ISO14443B RFIDs... }"},
{"15", CmdHF15, 1, "{ ISO15693 RFIDs... }"},
{"epa", CmdHFEPA, 1, "{ German Identification Card... }"},
{"legic", CmdHFLegic, 0, "{ LEGIC RFIDs... }"},
{"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"},
{"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"},
{"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"},
{"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"},
{"list", CmdHFList, 1, "List protocol data in trace buffer"},
{"search", CmdHFSearch, 1, "Search for known HF tags [preliminary]"},
{NULL, NULL, 0, NULL}
>>>>>>> master
}; };
int CmdHF(const char *Cmd) int CmdHF(const char *Cmd)

View file

@ -23,6 +23,7 @@
#include "common.h" #include "common.h"
#include "cmdmain.h" #include "cmdmain.h"
#include "mifare.h" #include "mifare.h"
#include "cmdhfmfu.h"
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
static void waitCmd(uint8_t iLen); static void waitCmd(uint8_t iLen);
@ -143,7 +144,7 @@ int CmdHF14AReader(const char *Cmd)
uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
if(select_status == 0) { if(select_status == 0) {
PrintAndLog("iso14443a card select failed"); if (Cmd[0] != 's') PrintAndLog("iso14443a card select failed");
// disconnect // disconnect
c.arg[0] = 0; c.arg[0] = 0;
c.arg[1] = 0; c.arg[1] = 0;
@ -163,19 +164,68 @@ int CmdHF14AReader(const char *Cmd)
return 0; return 0;
} }
PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]);
PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen)); PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen));
PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]);
PrintAndLog(" SAK : %02x [%d]", card.sak, resp.arg[0]); PrintAndLog(" SAK : %02x [%d]", card.sak, resp.arg[0]);
// Double & triple sized UID, can be mapped to a manufacturer.
// HACK: does this apply for Ultralight cards?
if ( card.uidlen > 4 ) {
PrintAndLog("MANUFACTURER : %s", getTagInfo(card.uid[0]));
}
switch (card.sak) { switch (card.sak) {
case 0x00: PrintAndLog("TYPE : NXP MIFARE Ultralight | Ultralight C"); break; case 0x00:
//***************************************test****************
// disconnect
c.arg[0] = 0;
c.arg[1] = 0;
c.arg[2] = 0;
SendCommand(&c);
uint32_t tagT = GetHF14AMfU_Type();
ul_print_type(tagT, 0);
//reconnect for further tests
c.arg[0] = ISO14A_CONNECT | ISO14A_NO_DISCONNECT;
c.arg[1] = 0;
c.arg[2] = 0;
SendCommand(&c);
UsbCommand resp;
WaitForResponse(CMD_ACK,&resp);
memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS
if(select_status == 0) {
//PrintAndLog("iso14443a card select failed");
// disconnect
c.arg[0] = 0;
c.arg[1] = 0;
c.arg[2] = 0;
SendCommand(&c);
return 0;
}
/* orig
// check if the tag answers to GETVERSION (0x60)
c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT;
c.arg[1] = 1;
c.arg[2] = 0;
c.d.asBytes[0] = 0x60;
SendCommand(&c);
WaitForResponse(CMD_ACK,&resp);
uint8_t version[10] = {0};
memcpy(version, resp.d.asBytes, resp.arg[0] < sizeof(version) ? resp.arg[0] : sizeof(version));
uint8_t len = resp.arg[0] & 0xff;
switch ( len ){
// todo, identify "Magic UL-C tags". // they usually have a static nonce response to 0x1A command.
// UL-EV1, size, check version[6] == 0x0b (smaller) 0x0b * 4 == 48
case 0x0A:PrintAndLog("TYPE : NXP MIFARE Ultralight EV1 %d bytes", (version[6] == 0xB) ? 48 : 128);break;
case 0x01:PrintAndLog("TYPE : NXP MIFARE Ultralight C");break;
case 0x00:PrintAndLog("TYPE : NXP MIFARE Ultralight");break;
}
*/
break;
case 0x01: PrintAndLog("TYPE : NXP TNP3xxx Activision Game Appliance"); break; case 0x01: PrintAndLog("TYPE : NXP TNP3xxx Activision Game Appliance"); break;
case 0x04: PrintAndLog("TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); break; case 0x04: PrintAndLog("TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); break;
case 0x08: PrintAndLog("TYPE : NXP MIFARE CLASSIC 1k | Plus 2k SL1"); break; case 0x08: PrintAndLog("TYPE : NXP MIFARE CLASSIC 1k | Plus 2k SL1"); break;
@ -192,6 +242,12 @@ int CmdHF14AReader(const char *Cmd)
default: ; default: ;
} }
// Double & triple sized UID, can be mapped to a manufacturer.
// HACK: does this apply for Ultralight cards?
if ( card.uidlen > 4 ) {
PrintAndLog("MANUFACTURER : %s", getTagInfo(card.uid[0]));
}
// try to request ATS even if tag claims not to support it // try to request ATS even if tag claims not to support it
if (select_status == 2) { if (select_status == 2) {
uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
@ -202,7 +258,7 @@ int CmdHF14AReader(const char *Cmd)
SendCommand(&c); SendCommand(&c);
WaitForResponse(CMD_ACK,&resp); WaitForResponse(CMD_ACK,&resp);
memcpy(&card.ats, resp.d.asBytes, resp.arg[0]); memcpy(card.ats, resp.d.asBytes, resp.arg[0]);
card.ats_len = resp.arg[0]; // note: ats_len includes CRC Bytes card.ats_len = resp.arg[0]; // note: ats_len includes CRC Bytes
} }

View file

@ -22,157 +22,29 @@
#include "cmdparser.h" #include "cmdparser.h"
#include "cmdhf14b.h" #include "cmdhf14b.h"
#include "cmdmain.h" #include "cmdmain.h"
#include "cmdhf14a.h"
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
int CmdHF14BDemod(const char *Cmd)
{
int i, j, iold;
int isum, qsum;
int outOfWeakAt;
bool negateI, negateQ;
uint8_t data[256];
int dataLen = 0;
// As received, the samples are pairs, correlations against I and Q
// square waves. So estimate angle of initial carrier (or just
// quadrant, actually), and then do the demod.
// First, estimate where the tag starts modulating.
for (i = 0; i < GraphTraceLen; i += 2) {
if (abs(GraphBuffer[i]) + abs(GraphBuffer[i + 1]) > 40) {
break;
}
}
if (i >= GraphTraceLen) {
PrintAndLog("too weak to sync");
return 0;
}
PrintAndLog("out of weak at %d", i);
outOfWeakAt = i;
// Now, estimate the phase in the initial modulation of the tag
isum = 0;
qsum = 0;
for (; i < (outOfWeakAt + 16); i += 2) {
isum += GraphBuffer[i + 0];
qsum += GraphBuffer[i + 1];
}
negateI = (isum < 0);
negateQ = (qsum < 0);
// Turn the correlation pairs into soft decisions on the bit.
j = 0;
for (i = 0; i < GraphTraceLen / 2; i++) {
int si = GraphBuffer[j];
int sq = GraphBuffer[j + 1];
if (negateI) si = -si;
if (negateQ) sq = -sq;
GraphBuffer[i] = si + sq;
j += 2;
}
GraphTraceLen = i;
i = outOfWeakAt / 2;
while (GraphBuffer[i] > 0 && i < GraphTraceLen)
i++;
if (i >= GraphTraceLen) goto demodError;
iold = i;
while (GraphBuffer[i] < 0 && i < GraphTraceLen)
i++;
if (i >= GraphTraceLen) goto demodError;
if ((i - iold) > 23) goto demodError;
PrintAndLog("make it to demod loop");
for (;;) {
iold = i;
while (GraphBuffer[i] >= 0 && i < GraphTraceLen)
i++;
if (i >= GraphTraceLen) goto demodError;
if ((i - iold) > 6) goto demodError;
uint16_t shiftReg = 0;
if (i + 20 >= GraphTraceLen) goto demodError;
for (j = 0; j < 10; j++) {
int soft = GraphBuffer[i] + GraphBuffer[i + 1];
if (abs(soft) < (abs(isum) + abs(qsum)) / 20) {
PrintAndLog("weak bit");
}
shiftReg >>= 1;
if(GraphBuffer[i] + GraphBuffer[i+1] >= 0) {
shiftReg |= 0x200;
}
i+= 2;
}
if ((shiftReg & 0x200) && !(shiftReg & 0x001))
{
// valid data byte, start and stop bits okay
PrintAndLog(" %02x", (shiftReg >> 1) & 0xff);
data[dataLen++] = (shiftReg >> 1) & 0xff;
if (dataLen >= sizeof(data)) {
return 0;
}
} else if (shiftReg == 0x000) {
// this is EOF
break;
} else {
goto demodError;
}
}
uint8_t first, second;
ComputeCrc14443(CRC_14443_B, data, dataLen-2, &first, &second);
PrintAndLog("CRC: %02x %02x (%s)\n", first, second,
(first == data[dataLen-2] && second == data[dataLen-1]) ?
"ok" : "****FAIL****");
RepaintGraphWindow();
return 0;
demodError:
PrintAndLog("demod error");
RepaintGraphWindow();
return 0;
}
int CmdHF14BList(const char *Cmd) int CmdHF14BList(const char *Cmd)
{ {
PrintAndLog("Deprecated command, use 'hf list 14b' instead"); PrintAndLog("Deprecated command, use 'hf list 14b' instead");
return 0; return 0;
} }
int CmdHF14BRead(const char *Cmd)
{
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443, {strtol(Cmd, NULL, 0), 0, 0}};
SendCommand(&c);
return 0;
}
int CmdHF14Sim(const char *Cmd) int CmdHF14BSim(const char *Cmd)
{ {
UsbCommand c={CMD_SIMULATE_TAG_ISO_14443}; UsbCommand c={CMD_SIMULATE_TAG_ISO_14443B};
SendCommand(&c); clearCommandBuffer();
return 0;
}
int CmdHFSimlisten(const char *Cmd)
{
UsbCommand c = {CMD_SIMULATE_TAG_HF_LISTEN};
SendCommand(&c); SendCommand(&c);
return 0; return 0;
} }
int CmdHF14BSnoop(const char *Cmd) int CmdHF14BSnoop(const char *Cmd)
{ {
UsbCommand c = {CMD_SNOOP_ISO_14443}; UsbCommand c = {CMD_SNOOP_ISO_14443B};
clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
return 0; return 0;
} }
@ -184,6 +56,7 @@ int CmdHF14BSnoop(const char *Cmd)
int CmdSri512Read(const char *Cmd) int CmdSri512Read(const char *Cmd)
{ {
UsbCommand c = {CMD_READ_SRI512_TAG, {strtol(Cmd, NULL, 0), 0, 0}}; UsbCommand c = {CMD_READ_SRI512_TAG, {strtol(Cmd, NULL, 0), 0, 0}};
clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
return 0; return 0;
} }
@ -195,127 +68,356 @@ int CmdSri512Read(const char *Cmd)
int CmdSrix4kRead(const char *Cmd) int CmdSrix4kRead(const char *Cmd)
{ {
UsbCommand c = {CMD_READ_SRIX4K_TAG, {strtol(Cmd, NULL, 0), 0, 0}}; UsbCommand c = {CMD_READ_SRIX4K_TAG, {strtol(Cmd, NULL, 0), 0, 0}};
clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
return 0; return 0;
} }
int CmdHF14BCmdRaw (const char *cmd) { int rawClose(void){
UsbCommand resp; UsbCommand resp;
uint8_t *recv; UsbCommand c = {CMD_ISO_14443B_COMMAND, {0, 0, 0}};
UsbCommand c = {CMD_ISO_14443B_COMMAND, {0, 0, 0}}; // len,recv? clearCommandBuffer();
uint8_t reply=1; SendCommand(&c);
uint8_t crc=0; if (!WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
uint8_t power=0; return 0;
char buf[5]=""; }
int i=0; return 0;
uint8_t data[100] = {0x00};
unsigned int datalen=0, temp;
char *hexout;
if (strlen(cmd)<3) {
PrintAndLog("Usage: hf 14b raw [-r] [-c] [-p] <0A 0B 0C ... hex>");
PrintAndLog(" -r do not read response");
PrintAndLog(" -c calculate and append CRC");
PrintAndLog(" -p leave the field on after receive");
return 0;
}
// strip
while (*cmd==' ' || *cmd=='\t') cmd++;
while (cmd[i]!='\0') {
if (cmd[i]==' ' || cmd[i]=='\t') { i++; continue; }
if (cmd[i]=='-') {
switch (cmd[i+1]) {
case 'r':
case 'R':
reply=0;
break;
case 'c':
case 'C':
crc=1;
break;
case 'p':
case 'P':
power=1;
break;
default:
PrintAndLog("Invalid option");
return 0;
}
i+=2;
continue;
}
if ((cmd[i]>='0' && cmd[i]<='9') ||
(cmd[i]>='a' && cmd[i]<='f') ||
(cmd[i]>='A' && cmd[i]<='F') ) {
buf[strlen(buf)+1]=0;
buf[strlen(buf)]=cmd[i];
i++;
if (strlen(buf)>=2) {
sscanf(buf,"%x",&temp);
data[datalen]=(uint8_t)(temp & 0xff);
datalen++;
*buf=0;
}
continue;
}
PrintAndLog("Invalid char on input");
return 1;
}
if (datalen == 0)
{
PrintAndLog("Missing data input");
return 0;
}
if(crc)
{
uint8_t first, second;
ComputeCrc14443(CRC_14443_B, data, datalen, &first, &second);
data[datalen++] = first;
data[datalen++] = second;
}
c.arg[0] = datalen;
c.arg[1] = reply;
c.arg[2] = power;
memcpy(c.d.asBytes,data,datalen);
SendCommand(&c);
if (reply) {
if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
recv = resp.d.asBytes;
PrintAndLog("received %i octets",resp.arg[0]);
if(!resp.arg[0])
return 0;
hexout = (char *)malloc(resp.arg[0] * 3 + 1);
if (hexout != NULL) {
uint8_t first, second;
for (int i = 0; i < resp.arg[0]; i++) { // data in hex
sprintf(&hexout[i * 3], "%02X ", recv[i]);
}
PrintAndLog("%s", hexout);
free(hexout);
ComputeCrc14443(CRC_14443_B, recv, resp.arg[0]-2, &first, &second);
if(recv[resp.arg[0]-2]==first && recv[resp.arg[0]-1]==second) {
PrintAndLog("CRC OK");
} else {
PrintAndLog("CRC failed");
}
} else {
PrintAndLog("malloc failed your client has low memory?");
}
} else {
PrintAndLog("timeout while waiting for reply.");
}
} // if reply
return 0;
} }
int CmdHF14BWrite( const char *Cmd){ int HF14BCmdRaw(bool reply, bool *crc, bool power, uint8_t *data, uint8_t *datalen, bool verbose){
UsbCommand resp;
UsbCommand c = {CMD_ISO_14443B_COMMAND, {0, 0, 0}}; // len,recv,power
if(*crc)
{
uint8_t first, second;
ComputeCrc14443(CRC_14443_B, data, *datalen, &first, &second);
data[*datalen] = first;
data[*datalen + 1] = second;
*datalen += 2;
}
c.arg[0] = *datalen;
c.arg[1] = reply;
c.arg[2] = power;
memcpy(c.d.asBytes,data,*datalen);
clearCommandBuffer();
SendCommand(&c);
if (!reply) return 1;
if (!WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
if (verbose) PrintAndLog("timeout while waiting for reply.");
return 0;
}
*datalen = resp.arg[0];
if (verbose) PrintAndLog("received %u octets", *datalen);
if(*datalen<2) return 0;
memcpy(data, resp.d.asBytes, *datalen);
if (verbose) PrintAndLog("%s", sprint_hex(data, *datalen));
uint8_t first, second;
ComputeCrc14443(CRC_14443_B, data, *datalen-2, &first, &second);
if(data[*datalen-2] == first && data[*datalen-1] == second) {
if (verbose) PrintAndLog("CRC OK");
*crc = true;
} else {
if (verbose) PrintAndLog("CRC failed");
*crc = false;
}
return 1;
}
int CmdHF14BCmdRaw (const char *Cmd) {
bool reply = true;
bool crc = false;
bool power = false;
char buf[5] = "";
uint8_t data[100] = {0x00};
uint8_t datalen = 0;
unsigned int temp;
int i = 0;
if (strlen(Cmd)<3) {
PrintAndLog("Usage: hf 14b raw [-r] [-c] [-p] <0A 0B 0C ... hex>");
PrintAndLog(" -r do not read response");
PrintAndLog(" -c calculate and append CRC");
PrintAndLog(" -p leave the field on after receive");
return 0;
}
// strip
while (*Cmd==' ' || *Cmd=='\t') Cmd++;
while (Cmd[i]!='\0') {
if (Cmd[i]==' ' || Cmd[i]=='\t') { i++; continue; }
if (Cmd[i]=='-') {
switch (Cmd[i+1]) {
case 'r':
case 'R':
reply = false;
break;
case 'c':
case 'C':
crc = true;
break;
case 'p':
case 'P':
power = true;
break;
default:
PrintAndLog("Invalid option");
return 0;
}
i+=2;
continue;
}
if ((Cmd[i]>='0' && Cmd[i]<='9') ||
(Cmd[i]>='a' && Cmd[i]<='f') ||
(Cmd[i]>='A' && Cmd[i]<='F') ) {
buf[strlen(buf)+1]=0;
buf[strlen(buf)]=Cmd[i];
i++;
if (strlen(buf)>=2) {
sscanf(buf,"%x",&temp);
data[datalen++]=(uint8_t)(temp & 0xff);
*buf=0;
}
continue;
}
PrintAndLog("Invalid char on input");
return 1;
}
if (datalen == 0)
{
PrintAndLog("Missing data input");
return 0;
}
return HF14BCmdRaw(reply, &crc, power, data, &datalen, true);
}
static void print_atqb_resp(uint8_t *data){
PrintAndLog (" UID: %s", sprint_hex(data+1,4));
PrintAndLog (" App Data: %s", sprint_hex(data+5,4));
PrintAndLog (" Protocol: %s", sprint_hex(data+9,3));
uint8_t BitRate = data[9];
if (!BitRate)
PrintAndLog (" Bit Rate: 106 kbit/s only PICC <-> PCD");
if (BitRate & 0x10)
PrintAndLog (" Bit Rate: 212 kbit/s PICC -> PCD supported");
if (BitRate & 0x20)
PrintAndLog (" Bit Rate: 424 kbit/s PICC -> PCD supported");
if (BitRate & 0x40)
PrintAndLog (" Bit Rate: 847 kbit/s PICC -> PCD supported");
if (BitRate & 0x01)
PrintAndLog (" Bit Rate: 212 kbit/s PICC <- PCD supported");
if (BitRate & 0x02)
PrintAndLog (" Bit Rate: 424 kbit/s PICC <- PCD supported");
if (BitRate & 0x04)
PrintAndLog (" Bit Rate: 847 kbit/s PICC <- PCD supported");
if (BitRate & 0x80)
PrintAndLog (" Same bit rate <-> required");
uint16_t maxFrame = data[10]>>4;
if (maxFrame < 5)
maxFrame = 8*maxFrame + 16;
else if (maxFrame == 5)
maxFrame = 64;
else if (maxFrame == 6)
maxFrame = 96;
else if (maxFrame == 7)
maxFrame = 128;
else if (maxFrame == 8)
maxFrame = 256;
else
maxFrame = 257;
PrintAndLog ("Max Frame Size: %d%s",maxFrame, (maxFrame == 257) ? "+ RFU" : "");
uint8_t protocolT = data[10] & 0xF;
PrintAndLog (" Protocol Type: Protocol is %scompliant with ISO/IEC 14443-4",(protocolT) ? "" : "not " );
PrintAndLog ("Frame Wait Int: %d", data[11]>>4);
PrintAndLog (" App Data Code: Application is %s",(data[11]&4) ? "Standard" : "Proprietary");
PrintAndLog (" Frame Options: NAD is %ssupported",(data[11]&2) ? "" : "not ");
PrintAndLog (" Frame Options: CID is %ssupported",(data[11]&1) ? "" : "not ");
return;
}
char *get_ST_Chip_Model(uint8_t data){
static char model[20];
char *retStr = model;
memset(model,0, sizeof(model));
switch (data) {
case 0x0: sprintf(retStr, "SRIX4K (Special)"); break;
case 0x2: sprintf(retStr, "SR176"); break;
case 0x3: sprintf(retStr, "SRIX4K"); break;
case 0x4: sprintf(retStr, "SRIX512"); break;
case 0x6: sprintf(retStr, "SRI512"); break;
case 0x7: sprintf(retStr, "SRI4K"); break;
case 0xC: sprintf(retStr, "SRT512"); break;
default : sprintf(retStr, "Unknown"); break;
}
return retStr;
}
static void print_st_info(uint8_t *data){
//uid = first 8 bytes in data
PrintAndLog(" UID: %s", sprint_hex(SwapEndian64(data,8,8),8));
PrintAndLog(" MFG: %02X, %s", data[6], getTagInfo(data[6]));
PrintAndLog("Chip: %02X, %s", data[5]>>2, get_ST_Chip_Model(data[5]>>2));
return;
}
int HF14BStdInfo(uint8_t *data, uint8_t *datalen){
//05 00 00 = find one tag in field
//1d xx xx xx xx 20 00 08 01 00 = attrib xx=crc
//a3 = ? (resp 03 e2 c2)
//02 = ? (resp 02 6a d3)
// 022b (resp 02 67 00 [29 5b])
// 0200a40400 (resp 02 67 00 [29 5b])
// 0200a4040c07a0000002480300 (resp 02 67 00 [29 5b])
// 0200a4040c07a0000002480200 (resp 02 67 00 [29 5b])
// 0200a4040006a0000000010100 (resp 02 6a 82 [4b 4c])
// 0200a4040c09d27600002545500200 (resp 02 67 00 [29 5b])
// 0200a404000cd2760001354b414e4d30310000 (resp 02 6a 82 [4b 4c])
// 0200a404000ca000000063504b43532d313500 (resp 02 6a 82 [4b 4c])
// 0200a4040010a000000018300301000000000000000000 (resp 02 6a 82 [4b 4c])
//03 = ? (resp 03 [e3 c2])
//c2 = ? (resp c2 [66 15])
//b2 = ? (resp a3 [e9 67])
bool crc = true;
*datalen = 3;
//std read cmd
data[0] = 0x05;
data[1] = 0x00;
data[2] = 0x00;
if (HF14BCmdRaw(true, &crc, false, data, datalen, false)==0) return 0;
if (data[0] != 0x50 || *datalen != 14 || !crc) return 0;
PrintAndLog ("\n14443-3b tag found:");
print_atqb_resp(data);
return 1;
}
int HF14B_ST_Info(uint8_t *data, uint8_t *datalen){
bool crc = true;
*datalen = 2;
//wake cmd
data[0] = 0x06;
data[1] = 0x00;
//leave power on
// verbose on for now for testing - turn off when functional
if (HF14BCmdRaw(true, &crc, true, data, datalen, false)==0) return rawClose();
if (*datalen != 3 || !crc) return rawClose();
uint8_t chipID = data[0];
// select
data[0] = 0x0E;
data[1] = chipID;
*datalen = 2;
//leave power on
// verbose on for now for testing - turn off when functional
if (HF14BCmdRaw(true, &crc, true, data, datalen, false)==0) return rawClose();
if (*datalen != 3 || !crc || data[0] != chipID) return rawClose();
// get uid
data[0] = 0x0B;
*datalen = 1;
//power off
// verbose on for now for testing - turn off when functional
if (HF14BCmdRaw(true, &crc, true, data, datalen, false)==0) return 0;
rawClose();
if (*datalen != 10 || !crc) return 0;
PrintAndLog("\n14443-3b ST tag found:");
print_st_info(data);
return 1;
}
// test for other 14b type tags (mimic another reader - don't have tags to identify)
int HF14B_Other_Info(uint8_t *data, uint8_t *datalen){
bool crc = true;
*datalen = 4;
//std read cmd
data[0] = 0x00;
data[1] = 0x0b;
data[2] = 0x3f;
data[3] = 0x80;
if (HF14BCmdRaw(true, &crc, false, data, datalen, false)!=0) {
if (*datalen > 2 || !crc) {
PrintAndLog ("\n14443-3b tag found:");
PrintAndLog ("Unknown tag type answered to a 0x000b3f80 command ans:");
PrintAndLog ("%s",sprint_hex(data,*datalen));
return 1;
}
}
crc = false;
*datalen = 1;
data[0] = 0x0a;
if (HF14BCmdRaw(true, &crc, false, data, datalen, false)!=0) {
if (*datalen > 0) {
PrintAndLog ("\n14443-3b tag found:");
PrintAndLog ("Unknown tag type answered to a 0x0A command ans:");
PrintAndLog ("%s",sprint_hex(data,*datalen));
return 1;
}
}
crc = false;
*datalen = 1;
data[0] = 0x0c;
if (HF14BCmdRaw(true, &crc, false, data, datalen, false)!=0) {
if (*datalen > 0) {
PrintAndLog ("\n14443-3b tag found:");
PrintAndLog ("Unknown tag type answered to a 0x0C command ans:");
PrintAndLog ("%s",sprint_hex(data,*datalen));
return 1;
}
}
return 0;
}
int HF14BInfo(bool verbose){
uint8_t data[100];
uint8_t datalen = 5;
// try std 14b (atqb)
if (HF14BStdInfo(data, &datalen)) return 1;
// try st 14b
if (HF14B_ST_Info(data, &datalen)) return 1;
// try unknown 14b read commands (to be identified later)
// could be read of calypso, CEPAS, moneo, or pico pass.
if (HF14B_Other_Info(data, &datalen)) return 1;
if (verbose) PrintAndLog("no 14443B tag found");
return 0;
}
int CmdHF14Binfo(const char *Cmd){
return HF14BInfo(true);
}
int CmdSriWrite( const char *Cmd){
/* /*
* For SRIX4K blocks 00 - 7F * For SRIX4K blocks 00 - 7F
* hf 14b raw -c -p 09 $srix4kwblock $srix4kwdata * hf 14b raw -c -p 09 $srix4kwblock $srix4kwdata
@ -385,16 +487,14 @@ int CmdHF14BWrite( const char *Cmd){
static command_t CommandTable[] = static command_t CommandTable[] =
{ {
{"help", CmdHelp, 1, "This help"}, {"help", CmdHelp, 1, "This help"},
{"demod", CmdHF14BDemod, 1, "Demodulate ISO14443 Type B from tag"}, {"info", CmdHF14Binfo, 0, "Find and print info about a 14b type tag (HF ISO 14443b)"},
{"list", CmdHF14BList, 0, "[Deprecated] List ISO 14443b history"}, {"list", CmdHF14BList, 0, "[Deprecated] List ISO 14443b history"},
{"read", CmdHF14BRead, 0, "Read HF tag (ISO 14443)"}, {"sim", CmdHF14BSim, 0, "Fake ISO 14443B tag"},
{"sim", CmdHF14Sim, 0, "Fake ISO 14443 tag"}, {"snoop", CmdHF14BSnoop, 0, "Eavesdrop ISO 14443B"},
{"simlisten", CmdHFSimlisten, 0, "Get HF samples as fake tag"},
{"snoop", CmdHF14BSnoop, 0, "Eavesdrop ISO 14443"},
{"sri512read", CmdSri512Read, 0, "Read contents of a SRI512 tag"}, {"sri512read", CmdSri512Read, 0, "Read contents of a SRI512 tag"},
{"srix4kread", CmdSrix4kRead, 0, "Read contents of a SRIX4K tag"}, {"srix4kread", CmdSrix4kRead, 0, "Read contents of a SRIX4K tag"},
{"sriwrite", CmdSriWrite, 0, "Write data to a SRI512 | SRIX4K tag"},
{"raw", CmdHF14BCmdRaw, 0, "Send raw hex data to tag"}, {"raw", CmdHF14BCmdRaw, 0, "Send raw hex data to tag"},
{"write", CmdHF14BWrite, 0, "Write data to a SRI512 | SRIX4K tag"},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };

View file

@ -12,15 +12,13 @@
#define CMDHF14B_H__ #define CMDHF14B_H__
int CmdHF14B(const char *Cmd); int CmdHF14B(const char *Cmd);
int CmdHF14BDemod(const char *Cmd);
int CmdHF14BList(const char *Cmd); int CmdHF14BList(const char *Cmd);
int CmdHF14BRead(const char *Cmd); int CmdHF14BInfo(const char *Cmd);
int CmdHF14Sim(const char *Cmd); int CmdHF14BSim(const char *Cmd);
int CmdHFSimlisten(const char *Cmd);
int CmdHF14BSnoop(const char *Cmd); int CmdHF14BSnoop(const char *Cmd);
int CmdSri512Read(const char *Cmd); int CmdSri512Read(const char *Cmd);
int CmdSrix4kRead(const char *Cmd); int CmdSrix4kRead(const char *Cmd);
int CmdHF14BWrite( const char *cmd); int CmdHF14BWrite( const char *cmd);
int HF14BInfo(bool verbose);
#endif #endif

View file

@ -374,6 +374,20 @@ int CmdHF15Record(const char *Cmd)
return 0; return 0;
} }
int HF15Reader(const char *Cmd, bool verbose)
{
uint8_t uid[8];
if (!getUID(uid)) {
if (verbose) PrintAndLog("No Tag found.");
return 0;
}
PrintAndLog("Tag UID : %s",sprintUID(NULL,uid));
PrintAndLog("Tag Info: %s",getTagInfo(uid));
return 1;
}
int CmdHF15Reader(const char *Cmd) int CmdHF15Reader(const char *Cmd)
{ {
UsbCommand c = {CMD_READER_ISO_15693, {strtol(Cmd, NULL, 0), 0, 0}}; UsbCommand c = {CMD_READER_ISO_15693, {strtol(Cmd, NULL, 0), 0, 0}};
@ -469,7 +483,7 @@ int CmdHF15DumpMem(const char*Cmd) {
// PrintAndLog("bn=%i",blocknum); // PrintAndLog("bn=%i",blocknum);
} else { } else {
PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1])); PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1]));
return 0; return 1;
} }
} // else PrintAndLog("crc"); } // else PrintAndLog("crc");
} // else PrintAndLog("r null"); } // else PrintAndLog("r null");
@ -481,7 +495,7 @@ int CmdHF15DumpMem(const char*Cmd) {
// PrintAndLog("CRC Failed"); // PrintAndLog("CRC Failed");
// else // else
// PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1])); // PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1]));
return 0; return 1;
} }

View file

@ -15,6 +15,7 @@ int CmdHF15(const char *Cmd);
int CmdHF15Demod(const char *Cmd); int CmdHF15Demod(const char *Cmd);
int CmdHF15Read(const char *Cmd); int CmdHF15Read(const char *Cmd);
int HF15Reader(const char *Cmd, bool verbose);
int CmdHF15Reader(const char *Cmd); int CmdHF15Reader(const char *Cmd);
int CmdHF15Sim(const char *Cmd); int CmdHF15Sim(const char *Cmd);
int CmdHF15Record(const char *Cmd); int CmdHF15Record(const char *Cmd);

View file

@ -9,7 +9,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "util.h" #include "util.h"
//#include "proxusb.h"
#include "proxmark3.h" #include "proxmark3.h"
#include "ui.h" #include "ui.h"
#include "cmdparser.h" #include "cmdparser.h"
@ -29,9 +29,9 @@ int CmdHFEPACollectPACENonces(const char *Cmd)
unsigned int n = 0; unsigned int n = 0;
// delay between requests // delay between requests
unsigned int d = 0; unsigned int d = 0;
sscanf(Cmd, "%u %u %u", &m, &n, &d); sscanf(Cmd, "%u %u %u", &m, &n, &d);
// values are expected to be > 0 // values are expected to be > 0
m = m > 0 ? m : 1; m = m > 0 ? m : 1;
n = n > 0 ? n : 1; n = n > 0 ? n : 1;
@ -44,7 +44,7 @@ int CmdHFEPACollectPACENonces(const char *Cmd)
UsbCommand c = {CMD_EPA_PACE_COLLECT_NONCE, {(int)m, 0, 0}}; UsbCommand c = {CMD_EPA_PACE_COLLECT_NONCE, {(int)m, 0, 0}};
SendCommand(&c); SendCommand(&c);
UsbCommand resp; UsbCommand resp;
WaitForResponse(CMD_ACK,&resp); WaitForResponse(CMD_ACK,&resp);
// check if command failed // check if command failed
@ -68,13 +68,123 @@ int CmdHFEPACollectPACENonces(const char *Cmd)
return 1; return 1;
} }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////The commands lie below here/////////////////////////////////////////////////////////////////////////////////////////
// perform the PACE protocol by replaying APDUs
int CmdHFEPAPACEReplay(const char *Cmd)
{
// the 4 APDUs which are replayed + their lengths
uint8_t msesa_apdu[41], gn_apdu[8], map_apdu[75];
uint8_t pka_apdu[75], ma_apdu[18], apdu_lengths[5] = {0};
// pointers to the arrays to be able to iterate
uint8_t *apdus[] = {msesa_apdu, gn_apdu, map_apdu, pka_apdu, ma_apdu};
// usage message
static const char const *usage_msg =
"Please specify 5 APDUs separated by spaces. "
"Example:\n preplay 0022C1A4 1068000000 1086000002 1234ABCDEF 1A2B3C4D";
// Proxmark response
UsbCommand resp;
int skip = 0, skip_add = 0, scan_return = 0;
// for each APDU
for (int i = 0; i < sizeof(apdu_lengths); i++) {
// scan to next space or end of string
while (Cmd[skip] != ' ' && Cmd[skip] != '\0') {
// convert
scan_return = sscanf(Cmd + skip, "%2X%n",
(unsigned int *) (apdus[i] + apdu_lengths[i]),
&skip_add);
if (scan_return < 1) {
PrintAndLog((char *)usage_msg);
PrintAndLog("Not enough APDUs! Try again!");
return 0;
}
skip += skip_add;
apdu_lengths[i]++;
}
// break on EOF
if (Cmd[skip] == '\0') {
if (i < sizeof(apdu_lengths) - 1) {
PrintAndLog((char *)usage_msg);
return 0;
}
break;
}
// skip the space
skip++;
}
// transfer the APDUs to the Proxmark
UsbCommand usb_cmd;
usb_cmd.cmd = CMD_EPA_PACE_REPLAY;
for (int i = 0; i < sizeof(apdu_lengths); i++) {
// APDU number
usb_cmd.arg[0] = i + 1;
// transfer the APDU in several parts if necessary
for (int j = 0; j * sizeof(usb_cmd.d.asBytes) < apdu_lengths[i]; j++) {
// offset into the APDU
usb_cmd.arg[1] = j * sizeof(usb_cmd.d.asBytes);
// amount of data in this packet
int packet_length = apdu_lengths[i] - (j * sizeof(usb_cmd.d.asBytes));
if (packet_length > sizeof(usb_cmd.d.asBytes)) {
packet_length = sizeof(usb_cmd.d.asBytes);
}
usb_cmd.arg[2] = packet_length;
memcpy(usb_cmd.d.asBytes, // + (j * sizeof(usb_cmd.d.asBytes)),
apdus[i] + (j * sizeof(usb_cmd.d.asBytes)),
packet_length);
SendCommand(&usb_cmd);
WaitForResponse(CMD_ACK, &resp);
if (resp.arg[0] != 0) {
PrintAndLog("Transfer of APDU #%d Part %d failed!", i, j);
return 0;
}
}
}
// now perform the replay
usb_cmd.arg[0] = 0;
SendCommand(&usb_cmd);
WaitForResponse(CMD_ACK, &resp);
if (resp.arg[0] != 0) {
PrintAndLog("\nPACE replay failed in step %u!", (uint32_t)resp.arg[0]);
PrintAndLog("Measured times:");
PrintAndLog("MSE Set AT: %u us", resp.d.asDwords[0]);
PrintAndLog("GA Get Nonce: %u us", resp.d.asDwords[1]);
PrintAndLog("GA Map Nonce: %u us", resp.d.asDwords[2]);
PrintAndLog("GA Perform Key Agreement: %u us", resp.d.asDwords[3]);
PrintAndLog("GA Mutual Authenticate: %u us", resp.d.asDwords[4]);
} else {
PrintAndLog("PACE replay successfull!");
PrintAndLog("MSE Set AT: %u us", resp.d.asDwords[0]);
PrintAndLog("GA Get Nonce: %u us", resp.d.asDwords[1]);
PrintAndLog("GA Map Nonce: %u us", resp.d.asDwords[2]);
PrintAndLog("GA Perform Key Agreement: %u us", resp.d.asDwords[3]);
PrintAndLog("GA Mutual Authenticate: %u us", resp.d.asDwords[4]);
}
return 1;
}
////////////////////////////////The new commands lie above here/////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// UI-related stuff // UI-related stuff
static const command_t CommandTable[] = static const command_t CommandTable[] =
{ {
{"help", CmdHelp, 1, "This help"}, {"help", CmdHelp, 1, "This help"},
{"cnonces", CmdHFEPACollectPACENonces, 0, {"cnonces", CmdHFEPACollectPACENonces, 0,
"<m> <n> <d> Acquire n>0 encrypted PACE nonces of size m>0 with d sec pauses"}, "<m> <n> <d> Acquire n>0 encrypted PACE nonces of size m>0 with d sec pauses"},
{"preplay", CmdHFEPAPACEReplay, 0,
"<mse> <get> <map> <pka> <ma> Perform PACE protocol by replaying given APDUs"},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };
@ -92,4 +202,4 @@ int CmdHFEPA(const char *Cmd)
// parse // parse
CmdsParse(CommandTable, Cmd); CmdsParse(CommandTable, Cmd);
return 0; return 0;
} }

View file

@ -165,34 +165,47 @@ int CmdHFiClassSim(const char *Cmd)
return 0; return 0;
} }
int CmdHFiClassReader(const char *Cmd) int HFiClassReader(const char *Cmd, bool loop, bool verbose)
{ {
bool tagFound = false;
UsbCommand c = {CMD_READER_ICLASS, {FLAG_ICLASS_READER_CSN| UsbCommand c = {CMD_READER_ICLASS, {FLAG_ICLASS_READER_CSN|
FLAG_ICLASS_READER_CONF|FLAG_ICLASS_READER_AA}}; FLAG_ICLASS_READER_CONF|FLAG_ICLASS_READER_AA}};
if (!loop) c.arg[0] |= FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_ONE_TRY;
SendCommand(&c); SendCommand(&c);
UsbCommand resp; UsbCommand resp;
while(!ukbhit()){ while(!ukbhit()){
if (WaitForResponseTimeout(CMD_ACK,&resp,4500)) { if (WaitForResponseTimeout(CMD_ACK,&resp, 4500)) {
uint8_t readStatus = resp.arg[0] & 0xff; uint8_t readStatus = resp.arg[0] & 0xff;
uint8_t * data = resp.d.asBytes; uint8_t *data = resp.d.asBytes;
PrintAndLog("Readstatus:%02x", readStatus); if (verbose)
PrintAndLog("Readstatus:%02x", readStatus);
if( readStatus == 0){ if( readStatus == 0){
//Aborted //Aborted
PrintAndLog("Quitting..."); if (verbose) PrintAndLog("Quitting...");
return 0; return 0;
} }
if( readStatus & FLAG_ICLASS_READER_CSN) PrintAndLog("CSN: %s",sprint_hex(data,8)); if( readStatus & FLAG_ICLASS_READER_CSN){
PrintAndLog("CSN: %s",sprint_hex(data,8));
tagFound = true;
}
if( readStatus & FLAG_ICLASS_READER_CC) PrintAndLog("CC: %s",sprint_hex(data+16,8)); if( readStatus & FLAG_ICLASS_READER_CC) PrintAndLog("CC: %s",sprint_hex(data+16,8));
if( readStatus & FLAG_ICLASS_READER_CONF){ if( readStatus & FLAG_ICLASS_READER_CONF){
printIclassDumpInfo(data); printIclassDumpInfo(data);
} }
if (tagFound && !loop) return 1;
} else { } else {
PrintAndLog("Command execute timeout"); if (verbose) PrintAndLog("Command execute timeout");
} }
if (!loop) break;
} }
return 0; return 0;
}
int CmdHFiClassReader(const char *Cmd)
{
return HFiClassReader(Cmd, true, true);
} }
int CmdHFiClassReader_Replay(const char *Cmd) int CmdHFiClassReader_Replay(const char *Cmd)
@ -345,7 +358,7 @@ int CmdHFiClassReader_Dump(const char *Cmd)
if(dataLength > 0) if(dataLength > 0)
{ {
PrintAndLog("Got %d bytes data (total so far %d)" ,dataLength,iclass_datalen); PrintAndLog("Got %d bytes data (total so far %d)" ,dataLength,iclass_datalen);
memcpy(iclass_data, resp.d.asBytes,dataLength); memcpy(iclass_data+iclass_datalen, resp.d.asBytes,dataLength);
iclass_datalen += dataLength; iclass_datalen += dataLength;
}else }else
{//Last transfer, datalength 0 means the dump is finished {//Last transfer, datalength 0 means the dump is finished

View file

@ -17,6 +17,7 @@ int CmdHFiClass(const char *Cmd);
int CmdHFiClassSnoop(const char *Cmd); int CmdHFiClassSnoop(const char *Cmd);
int CmdHFiClassSim(const char *Cmd); int CmdHFiClassSim(const char *Cmd);
int CmdHFiClassList(const char *Cmd); int CmdHFiClassList(const char *Cmd);
int HFiClassReader(const char *Cmd, bool loop, bool verbose);
int CmdHFiClassReader(const char *Cmd); int CmdHFiClassReader(const char *Cmd);
int CmdHFiClassReader_Replay(const char *Cmd); int CmdHFiClassReader_Replay(const char *Cmd);

View file

@ -17,7 +17,7 @@ int CmdHF14AMifare(const char *Cmd)
uint32_t uid = 0; uint32_t uid = 0;
uint32_t nt = 0, nr = 0; uint32_t nt = 0, nr = 0;
uint64_t par_list = 0, ks_list = 0, r_key = 0; uint64_t par_list = 0, ks_list = 0, r_key = 0;
uint8_t isOK = 0; int16_t isOK = 0;
uint8_t keyBlock[8] = {0}; uint8_t keyBlock[8] = {0};
UsbCommand c = {CMD_READER_MIFARE, {true, 0, 0}}; UsbCommand c = {CMD_READER_MIFARE, {true, 0, 0}};
@ -25,7 +25,7 @@ int CmdHF14AMifare(const char *Cmd)
// message // message
printf("-------------------------------------------------------------------------\n"); printf("-------------------------------------------------------------------------\n");
printf("Executing command. Expected execution time: 25sec on average :-)\n"); printf("Executing command. Expected execution time: 25sec on average :-)\n");
printf("Press the key on the proxmark3 device to abort both proxmark3 and client.\n"); printf("Press button on the proxmark3 device to abort both proxmark3 and client.\n");
printf("-------------------------------------------------------------------------\n"); printf("-------------------------------------------------------------------------\n");
@ -47,15 +47,20 @@ start:
} }
UsbCommand resp; UsbCommand resp;
if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) { if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {
isOK = resp.arg[0] & 0xff; isOK = resp.arg[0];
uid = (uint32_t)bytes_to_num(resp.d.asBytes + 0, 4); uid = (uint32_t)bytes_to_num(resp.d.asBytes + 0, 4);
nt = (uint32_t)bytes_to_num(resp.d.asBytes + 4, 4); nt = (uint32_t)bytes_to_num(resp.d.asBytes + 4, 4);
par_list = bytes_to_num(resp.d.asBytes + 8, 8); par_list = bytes_to_num(resp.d.asBytes + 8, 8);
ks_list = bytes_to_num(resp.d.asBytes + 16, 8); ks_list = bytes_to_num(resp.d.asBytes + 16, 8);
nr = bytes_to_num(resp.d.asBytes + 24, 4); nr = bytes_to_num(resp.d.asBytes + 24, 4);
printf("\n\n"); printf("\n\n");
if (!isOK) PrintAndLog("Proxmark can't get statistic info. Execution aborted.\n"); switch (isOK) {
case -1 : PrintAndLog("Button pressed. Aborted.\n"); break;
case -2 : PrintAndLog("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).\n"); break;
case -3 : PrintAndLog("Card is not vulnerable to Darkside attack (its random number generator is not predictable).\n"); break;
default: ;
}
break; break;
} }
} }
@ -434,7 +439,7 @@ int CmdHF14AMfRestore(const char *Cmd)
{ {
uint8_t sectorNo,blockNo; uint8_t sectorNo,blockNo;
uint8_t keyType = 0; uint8_t keyType = 0;
uint8_t key[6] = {0xFF}; uint8_t key[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
uint8_t bldata[16] = {0x00}; uint8_t bldata[16] = {0x00};
uint8_t keyA[40][6]; uint8_t keyA[40][6];
uint8_t keyB[40][6]; uint8_t keyB[40][6];
@ -547,7 +552,7 @@ int CmdHF14AMfNested(const char *Cmd)
uint8_t trgKeyType = 0; uint8_t trgKeyType = 0;
uint8_t SectorsCnt = 0; uint8_t SectorsCnt = 0;
uint8_t key[6] = {0, 0, 0, 0, 0, 0}; uint8_t key[6] = {0, 0, 0, 0, 0, 0};
uint8_t keyBlock[13*6]; uint8_t keyBlock[14*6];
uint64_t key64 = 0; uint64_t key64 = 0;
bool transferToEml = false; bool transferToEml = false;
@ -622,8 +627,14 @@ int CmdHF14AMfNested(const char *Cmd)
if (cmdp == 'o') { if (cmdp == 'o') {
PrintAndLog("--target block no:%3d, target key type:%c ", trgBlockNo, trgKeyType?'B':'A'); PrintAndLog("--target block no:%3d, target key type:%c ", trgBlockNo, trgKeyType?'B':'A');
if (mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock, true)) { int16_t isOK = mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock, true);
PrintAndLog("Nested error."); if (isOK) {
switch (isOK) {
case -1 : PrintAndLog("Error: No response from Proxmark.\n"); break;
case -2 : PrintAndLog("Button pressed. Aborted.\n"); break;
case -3 : PrintAndLog("Tag isn't vulnerable to Nested Attack (random numbers are not predictable).\n"); break;
default : PrintAndLog("Unknown Error.\n");
}
return 2; return 2;
} }
key64 = bytes_to_num(keyBlock, 6); key64 = bytes_to_num(keyBlock, 6);
@ -696,11 +707,17 @@ int CmdHF14AMfNested(const char *Cmd)
for (trgKeyType = 0; trgKeyType < 2; trgKeyType++) { for (trgKeyType = 0; trgKeyType < 2; trgKeyType++) {
if (e_sector[sectorNo].foundKey[trgKeyType]) continue; if (e_sector[sectorNo].foundKey[trgKeyType]) continue;
PrintAndLog("-----------------------------------------------"); PrintAndLog("-----------------------------------------------");
if(mfnested(blockNo, keyType, key, FirstBlockOfSector(sectorNo), trgKeyType, keyBlock, calibrate)) { int16_t isOK = mfnested(blockNo, keyType, key, FirstBlockOfSector(sectorNo), trgKeyType, keyBlock, calibrate);
PrintAndLog("Nested error.\n"); if(isOK) {
switch (isOK) {
case -1 : PrintAndLog("Error: No response from Proxmark.\n"); break;
case -2 : PrintAndLog("Button pressed. Aborted.\n"); break;
case -3 : PrintAndLog("Tag isn't vulnerable to Nested Attack (random numbers are not predictable).\n"); break;
default : PrintAndLog("Unknown Error.\n");
}
free(e_sector); free(e_sector);
return 2; } return 2;
else { } else {
calibrate = false; calibrate = false;
} }
@ -1200,7 +1217,7 @@ int CmdHF14AMfELoad(const char *Cmd)
len = param_getstr(Cmd,nameParamNo,filename); len = param_getstr(Cmd,nameParamNo,filename);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; if (len > FILE_PATH_SIZE - 4) len = FILE_PATH_SIZE - 4;
fnameptr += len; fnameptr += len;
@ -1299,17 +1316,20 @@ int CmdHF14AMfESave(const char *Cmd)
len = param_getstr(Cmd,nameParamNo,filename); len = param_getstr(Cmd,nameParamNo,filename);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; if (len > FILE_PATH_SIZE - 4) len = FILE_PATH_SIZE - 4;
// user supplied filename? // user supplied filename?
if (len < 1) { if (len < 1) {
// get filename (UID from memory) // get filename (UID from memory)
if (mfEmlGetMem(buf, 0, 1)) { if (mfEmlGetMem(buf, 0, 1)) {
PrintAndLog("Can\'t get UID from block: %d", 0); PrintAndLog("Can\'t get UID from block: %d", 0);
sprintf(filename, "dump.eml"); len = sprintf(fnameptr, "dump");
fnameptr += len;
}
else {
for (j = 0; j < 7; j++, fnameptr += 2)
sprintf(fnameptr, "%02X", buf[j]);
} }
for (j = 0; j < 7; j++, fnameptr += 2)
sprintf(fnameptr, "%02X", buf[j]);
} else { } else {
fnameptr += len; fnameptr += len;
} }
@ -1499,16 +1519,16 @@ int CmdHF14AMfCSetUID(const char *Cmd)
int CmdHF14AMfCSetBlk(const char *Cmd) int CmdHF14AMfCSetBlk(const char *Cmd)
{ {
uint8_t uid[8] = {0x00};
uint8_t memBlock[16] = {0x00}; uint8_t memBlock[16] = {0x00};
uint8_t blockNo = 0; uint8_t blockNo = 0;
bool wipeCard = FALSE;
int res; int res;
if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') { if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {
PrintAndLog("Usage: hf mf csetblk <block number> <block data (32 hex symbols)>"); PrintAndLog("Usage: hf mf csetblk <block number> <block data (32 hex symbols)> [w]");
PrintAndLog("sample: hf mf csetblk 1 01020304050607080910111213141516"); PrintAndLog("sample: hf mf csetblk 1 01020304050607080910111213141516");
PrintAndLog("Set block data for magic Chinese card (only works with!!!)"); PrintAndLog("Set block data for magic Chinese card (only works with such cards)");
PrintAndLog("If you want wipe card then add 'w' into command line. \n"); PrintAndLog("If you also want wipe the card then add 'w' at the end of the command line");
return 0; return 0;
} }
@ -1519,14 +1539,15 @@ int CmdHF14AMfCSetBlk(const char *Cmd)
return 1; return 1;
} }
char ctmp = param_getchar(Cmd, 2);
wipeCard = (ctmp == 'w' || ctmp == 'W');
PrintAndLog("--block number:%2d data:%s", blockNo, sprint_hex(memBlock, 16)); PrintAndLog("--block number:%2d data:%s", blockNo, sprint_hex(memBlock, 16));
res = mfCSetBlock(blockNo, memBlock, uid, 0, CSETBLOCK_SINGLE_OPER); res = mfCSetBlock(blockNo, memBlock, NULL, wipeCard, CSETBLOCK_SINGLE_OPER);
if (res) { if (res) {
PrintAndLog("Can't write block. error=%d", res); PrintAndLog("Can't write block. error=%d", res);
return 1; return 1;
} }
return 0; return 0;
} }
@ -1571,7 +1592,7 @@ int CmdHF14AMfCLoad(const char *Cmd)
return 0; return 0;
} else { } else {
len = strlen(Cmd); len = strlen(Cmd);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; if (len > FILE_PATH_SIZE - 4) len = FILE_PATH_SIZE - 4;
memcpy(filename, Cmd, len); memcpy(filename, Cmd, len);
fnameptr += len; fnameptr += len;
@ -1591,6 +1612,7 @@ int CmdHF14AMfCLoad(const char *Cmd)
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
if (fgets(buf, sizeof(buf), f) == NULL) { if (fgets(buf, sizeof(buf), f) == NULL) {
fclose(f);
PrintAndLog("File reading error."); PrintAndLog("File reading error.");
return 2; return 2;
} }
@ -1599,6 +1621,7 @@ int CmdHF14AMfCLoad(const char *Cmd)
if(strlen(buf) && feof(f)) if(strlen(buf) && feof(f))
break; break;
PrintAndLog("File content error. Block data must include 32 HEX symbols"); PrintAndLog("File content error. Block data must include 32 HEX symbols");
fclose(f);
return 2; return 2;
} }
for (i = 0; i < 32; i += 2) for (i = 0; i < 32; i += 2)
@ -1637,7 +1660,7 @@ int CmdHF14AMfCGetBlk(const char *Cmd) {
if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') { if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {
PrintAndLog("Usage: hf mf cgetblk <block number>"); PrintAndLog("Usage: hf mf cgetblk <block number>");
PrintAndLog("sample: hf mf cgetblk 1"); PrintAndLog("sample: hf mf cgetblk 1");
PrintAndLog("Get block data from magic Chinese card (only works with!!!)\n"); PrintAndLog("Get block data from magic Chinese card (only works with such cards)\n");
return 0; return 0;
} }
@ -1664,7 +1687,7 @@ int CmdHF14AMfCGetSc(const char *Cmd) {
if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') { if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {
PrintAndLog("Usage: hf mf cgetsc <sector number>"); PrintAndLog("Usage: hf mf cgetsc <sector number>");
PrintAndLog("sample: hf mf cgetsc 0"); PrintAndLog("sample: hf mf cgetsc 0");
PrintAndLog("Get sector data from magic Chinese card (only works with!!!)\n"); PrintAndLog("Get sector data from magic Chinese card (only works with such cards)\n");
return 0; return 0;
} }
@ -1738,16 +1761,19 @@ int CmdHF14AMfCSave(const char *Cmd) {
return 0; return 0;
} else { } else {
len = strlen(Cmd); len = strlen(Cmd);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; if (len > FILE_PATH_SIZE - 4) len = FILE_PATH_SIZE - 4;
if (len < 1) { if (len < 1) {
// get filename // get filename
if (mfCGetBlock(0, buf, CSETBLOCK_SINGLE_OPER)) { if (mfCGetBlock(0, buf, CSETBLOCK_SINGLE_OPER)) {
PrintAndLog("Cant get block: %d", 0); PrintAndLog("Cant get block: %d", 0);
return 1; len = sprintf(fnameptr, "dump");
fnameptr += len;
}
else {
for (j = 0; j < 7; j++, fnameptr += 2)
sprintf(fnameptr, "%02x", buf[j]);
} }
for (j = 0; j < 7; j++, fnameptr += 2)
sprintf(fnameptr, "%02x", buf[j]);
} else { } else {
memcpy(filename, Cmd, len); memcpy(filename, Cmd, len);
fnameptr += len; fnameptr += len;

File diff suppressed because it is too large Load diff

View file

@ -1,19 +1,55 @@
#include "cmdhfmf.h" #include "cmdhfmf.h"
#include "cmdhf14a.h" #include "cmdhf14a.h"
//standard ultralight #ifndef CMDHFMFU_H__
#define CMDHFMFU_H__
int CmdHF14AMfUWrBl(const char *Cmd); int CmdHF14AMfUWrBl(const char *Cmd);
int CmdHF14AMfURdBl(const char *Cmd); int CmdHF14AMfURdBl(const char *Cmd);
//Crypto Cards //Crypto Cards
int CmdHF14AMfUCRdBl(const char *Cmd);
int CmdHF14AMfUCRdCard(const char *Cmd);
int CmdHF14AMfucAuth(const char *Cmd); int CmdHF14AMfucAuth(const char *Cmd);
//general stuff //general stuff
int CmdHF14AMfUDump(const char *Cmd); int CmdHF14AMfUDump(const char *Cmd);
void rol (uint8_t *data, const size_t len); int CmdHF14AMfUInfo(const char *Cmd);
uint32_t GetHF14AMfU_Type(void);
int ul_print_type(uint32_t tagtype, uint8_t spacer);
void ul_switch_off_field(void);
int usage_hf_mfu_dump(void);
int usage_hf_mfu_info(void);
int usage_hf_mfu_rdbl(void);
int usage_hf_mfu_wrbl(void);
int CmdHFMFUltra(const char *Cmd); int CmdHFMFUltra(const char *Cmd);
int CmdHF14AMfUInfo(const char *Cmd);
typedef enum TAGTYPE_UL {
UNKNOWN = 0x000000,
UL = 0x000001,
UL_C = 0x000002,
UL_EV1_48 = 0x000004,
UL_EV1_128 = 0x000008,
NTAG = 0x000010,
NTAG_203 = 0x000020,
NTAG_210 = 0x000040,
NTAG_212 = 0x000080,
NTAG_213 = 0x000100,
NTAG_215 = 0x000200,
NTAG_216 = 0x000400,
MY_D = 0x000800,
MY_D_NFC = 0x001000,
MY_D_MOVE = 0x002000,
MY_D_MOVE_NFC = 0x004000,
MY_D_MOVE_LEAN= 0x008000,
NTAG_I2C_1K = 0x010000,
NTAG_I2C_2K = 0x020000,
FUDAN_UL = 0x040000,
MAGIC = 0x080000,
UL_MAGIC = UL | MAGIC,
UL_C_MAGIC = UL_C | MAGIC,
UL_ERROR = 0xFFFFFF,
} TagTypeUL_t;
#endif

View file

@ -23,9 +23,11 @@
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
static void lookupChipID(uint32_t iChipID) static void lookupChipID(uint32_t iChipID, uint32_t mem_used)
{ {
char asBuff[100]; char asBuff[100];
uint32_t mem_avail = 0;
switch(iChipID) switch(iChipID)
{ {
case 0x270B0A40: case 0x270B0A40:
@ -103,37 +105,43 @@ static void lookupChipID(uint32_t iChipID)
switch((iChipID&0xF00)>>8) switch((iChipID&0xF00)>>8)
{ {
case 0: case 0:
sprintf(asBuff,"None"); mem_avail = 0;
break; break;
case 1: case 1:
sprintf(asBuff,"8K bytes"); mem_avail = 8;
break; break;
case 2: case 2:
sprintf(asBuff,"16K bytes"); mem_avail = 16;
break; break;
case 3: case 3:
sprintf(asBuff,"32K bytes"); mem_avail = 32;
break; break;
case 5: case 5:
sprintf(asBuff,"64K bytes"); mem_avail = 64;
break; break;
case 7: case 7:
sprintf(asBuff,"128K bytes"); mem_avail = 128;
break; break;
case 9: case 9:
sprintf(asBuff,"256K bytes"); mem_avail = 256;
break; break;
case 10: case 10:
sprintf(asBuff,"512K bytes"); mem_avail = 512;
break; break;
case 12: case 12:
sprintf(asBuff,"1024K bytes"); mem_avail = 1024;
break; break;
case 14: case 14:
sprintf(asBuff,"2048K bytes"); mem_avail = 2048;
break; break;
} }
PrintAndLog("Nonvolatile Program Memory Size: %s",asBuff); PrintAndLog("Nonvolatile Program Memory Size: %dK bytes. Used: %d bytes (%2.0f\%). Free: %d bytes (%2.0f\%).",
mem_avail,
mem_used,
mem_avail == 0 ? 0 : (float)mem_used/(mem_avail*1024)*100,
mem_avail*1024 - mem_used,
mem_avail == 0 ? 0 : (float)(mem_avail*1024-mem_used)/(mem_avail*1024)*100
);
switch((iChipID&0xF000)>>12) switch((iChipID&0xF000)>>12)
{ {
case 0: case 0:
@ -396,13 +404,24 @@ int CmdTune(const char *Cmd)
int CmdVersion(const char *Cmd) int CmdVersion(const char *Cmd)
{ {
UsbCommand c = {CMD_VERSION};
UsbCommand resp; UsbCommand c = {CMD_VERSION};
SendCommand(&c); static UsbCommand resp = {0, {0, 0, 0}};
if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
lookupChipID(resp.arg[0]); if (resp.arg[0] == 0 && resp.arg[1] == 0) { // no cached information available
} SendCommand(&c);
return 0; if (WaitForResponseTimeout(CMD_ACK,&resp,1000) && Cmd != NULL) {
PrintAndLog("Prox/RFID mark3 RFID instrument");
PrintAndLog((char*)resp.d.asBytes);
lookupChipID(resp.arg[0], resp.arg[1]);
}
} else if (Cmd != NULL) {
PrintAndLog("Prox/RFID mark3 RFID instrument");
PrintAndLog((char*)resp.d.asBytes);
lookupChipID(resp.arg[0], resp.arg[1]);
}
return 0;
} }
static command_t CommandTable[] = static command_t CommandTable[] =

View file

@ -522,7 +522,8 @@ static void ChkBitstream(const char *str)
} }
} }
} }
//appears to attempt to simulate manchester //Attempt to simulate any wave in buffer (one bit per output sample)
// converts GraphBuffer to bitstream (based on zero crossings) if needed.
int CmdLFSim(const char *Cmd) int CmdLFSim(const char *Cmd)
{ {
int i,j; int i,j;
@ -530,11 +531,11 @@ int CmdLFSim(const char *Cmd)
sscanf(Cmd, "%i", &gap); sscanf(Cmd, "%i", &gap);
/* convert to bitstream if necessary */ // convert to bitstream if necessary
ChkBitstream(Cmd); ChkBitstream(Cmd);
//can send 512 bits at a time (1 byte sent per bit...) //can send only 512 bits at a time (1 byte sent per bit...)
printf("Sending [%d bytes]", GraphTraceLen); printf("Sending [%d bytes]", GraphTraceLen);
for (i = 0; i < GraphTraceLen; i += USB_CMD_DATA_SIZE) { for (i = 0; i < GraphTraceLen; i += USB_CMD_DATA_SIZE) {
UsbCommand c={CMD_DOWNLOADED_SIM_SAMPLES_125K, {i, 0, 0}}; UsbCommand c={CMD_DOWNLOADED_SIM_SAMPLES_125K, {i, 0, 0}};
@ -606,8 +607,8 @@ int usage_lf_simpsk(void)
// - allow pull data from DemodBuffer // - allow pull data from DemodBuffer
int CmdLFfskSim(const char *Cmd) int CmdLFfskSim(const char *Cmd)
{ {
//might be able to autodetect FC and clock from Graphbuffer if using demod buffer //might be able to autodetect FCs and clock from Graphbuffer if using demod buffer
//will need FChigh, FClow, Clock, and bitstream // otherwise will need FChigh, FClow, Clock, and bitstream
uint8_t fcHigh=0, fcLow=0, clk=0; uint8_t fcHigh=0, fcLow=0, clk=0;
uint8_t invert=0; uint8_t invert=0;
bool errors = FALSE; bool errors = FALSE;
@ -682,6 +683,8 @@ int CmdLFfskSim(const char *Cmd)
} else { } else {
setDemodBuf(data, dataLen, 0); setDemodBuf(data, dataLen, 0);
} }
//default if not found
if (clk == 0) clk = 50; if (clk == 0) clk = 50;
if (fcHigh == 0) fcHigh = 10; if (fcHigh == 0) fcHigh = 10;
if (fcLow == 0) fcLow = 8; if (fcLow == 0) fcLow = 8;
@ -706,9 +709,8 @@ int CmdLFfskSim(const char *Cmd)
int CmdLFaskSim(const char *Cmd) int CmdLFaskSim(const char *Cmd)
{ {
//autodetect clock from Graphbuffer if using demod buffer //autodetect clock from Graphbuffer if using demod buffer
//will need clock, invert, manchester/raw as m or r, separator as s, and bitstream // needs clock, invert, manchester/raw as m or r, separator as s, and bitstream
uint8_t encoding = 1, separator = 0; uint8_t encoding = 1, separator = 0;
//char cmdp = Cmd[0], par3='m', par4=0;
uint8_t clk=0, invert=0; uint8_t clk=0, invert=0;
bool errors = FALSE; bool errors = FALSE;
char hexData[32] = {0x00}; char hexData[32] = {0x00};
@ -913,30 +915,6 @@ int CmdLFSimBidir(const char *Cmd)
return 0; return 0;
} }
/* simulate an LF Manchester encoded tag with specified bitstream, clock rate and inter-id gap */
/*
int CmdLFSimManchester(const char *Cmd)
{
static int clock, gap;
static char data[1024], gapstring[8];
sscanf(Cmd, "%i %s %i", &clock, &data[0], &gap);
ClearGraph(0);
for (int i = 0; i < strlen(data) ; ++i)
AppendGraph(0, clock, data[i]- '0');
CmdManchesterMod("");
RepaintGraphWindow();
sprintf(&gapstring[0], "%i", gap);
CmdLFSim(gapstring);
return 0;
}
*/
int CmdVchDemod(const char *Cmd) int CmdVchDemod(const char *Cmd)
{ {
// Is this the entire sync pattern, or does this also include some // Is this the entire sync pattern, or does this also include some
@ -1033,8 +1011,8 @@ int CmdLFfind(const char *Cmd)
} }
if (!offline && (cmdp != '1')){ if (!offline && (cmdp != '1')){
ans=CmdLFRead(""); CmdLFRead("s");
ans=CmdSamples("20000"); getSamples("30000",false);
} else if (GraphTraceLen < 1000) { } else if (GraphTraceLen < 1000) {
PrintAndLog("Data in Graphbuffer was too small."); PrintAndLog("Data in Graphbuffer was too small.");
return 0; return 0;
@ -1094,26 +1072,42 @@ int CmdLFfind(const char *Cmd)
return 1; return 1;
} }
ans=CmdFDXBdemodBI("");
if (ans>0) {
PrintAndLog("\nValid FDX-B ID Found!");
return 1;
}
ans=EM4x50Read("", false);
if (ans>0) {
PrintAndLog("\nValid EM4x50 ID Found!");
return 1;
}
ans=CmdPSKNexWatch("");
if (ans>0) {
PrintAndLog("\nValid NexWatch ID Found!");
return 1;
}
PrintAndLog("\nNo Known Tags Found!\n"); PrintAndLog("\nNo Known Tags Found!\n");
if (testRaw=='u' || testRaw=='U'){ if (testRaw=='u' || testRaw=='U'){
//test unknown tag formats (raw mode) //test unknown tag formats (raw mode)
PrintAndLog("\nChecking for Unknown tags:\n"); PrintAndLog("\nChecking for Unknown tags:\n");
ans=AutoCorrelate(4000, FALSE, FALSE); ans=AutoCorrelate(4000, FALSE, FALSE);
if (ans > 0) PrintAndLog("Possible Auto Correlation of %d repeating samples",ans); if (ans > 0) PrintAndLog("Possible Auto Correlation of %d repeating samples",ans);
ans=GetFskClock("",FALSE,FALSE); //CmdDetectClockRate("F"); // ans=GetFskClock("",FALSE,FALSE);
if (ans != 0){ //fsk if (ans != 0){ //fsk
ans=FSKrawDemod("",FALSE); ans=FSKrawDemod("",TRUE);
if (ans>0) { if (ans>0) {
PrintAndLog("\nUnknown FSK Modulated Tag Found!"); PrintAndLog("\nUnknown FSK Modulated Tag Found!");
printDemodBuff();
return 1; return 1;
} }
} }
ans=ASKmanDemod("",FALSE,FALSE); ans=ASKDemod("0 0 0",TRUE,FALSE,1);
if (ans>0) { if (ans>0) {
PrintAndLog("\nUnknown ASK Modulated and Manchester encoded Tag Found!"); PrintAndLog("\nUnknown ASK Modulated and Manchester encoded Tag Found!");
PrintAndLog("\nif it does not look right it could instead be ASK/Biphase - try 'data rawdemod ab'"); PrintAndLog("\nif it does not look right it could instead be ASK/Biphase - try 'data rawdemod ab'");
printDemodBuff();
return 1; return 1;
} }
ans=CmdPSK1rawDemod(""); ans=CmdPSK1rawDemod("");
@ -1121,7 +1115,6 @@ int CmdLFfind(const char *Cmd)
PrintAndLog("Possible unknown PSK1 Modulated Tag Found above!\n\nCould also be PSK2 - try 'data rawdemod p2'"); PrintAndLog("Possible unknown PSK1 Modulated Tag Found above!\n\nCould also be PSK2 - try 'data rawdemod p2'");
PrintAndLog("\nCould also be PSK3 - [currently not supported]"); PrintAndLog("\nCould also be PSK3 - [currently not supported]");
PrintAndLog("\nCould also be NRZ - try 'data nrzrawdemod"); PrintAndLog("\nCould also be NRZ - try 'data nrzrawdemod");
printDemodBuff();
return 1; return 1;
} }
PrintAndLog("\nNo Data Found!\n"); PrintAndLog("\nNo Data Found!\n");
@ -1147,7 +1140,6 @@ static command_t CommandTable[] =
{"simfsk", CmdLFfskSim, 0, "[c <clock>] [i] [H <fcHigh>] [L <fcLow>] [d <hexdata>] -- Simulate LF FSK tag from demodbuffer or input"}, {"simfsk", CmdLFfskSim, 0, "[c <clock>] [i] [H <fcHigh>] [L <fcLow>] [d <hexdata>] -- Simulate LF FSK tag from demodbuffer or input"},
{"simpsk", CmdLFpskSim, 0, "[1|2|3] [c <clock>] [i] [r <carrier>] [d <raw hex to sim>] -- Simulate LF PSK tag from demodbuffer or input"}, {"simpsk", CmdLFpskSim, 0, "[1|2|3] [c <clock>] [i] [r <carrier>] [d <raw hex to sim>] -- Simulate LF PSK tag from demodbuffer or input"},
{"simbidir", CmdLFSimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"}, {"simbidir", CmdLFSimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
//{"simman", CmdLFSimManchester, 0, "<Clock> <Bitstream> [GAP] Simulate arbitrary Manchester LF tag"},
{"snoop", CmdLFSnoop, 0, "['l'|'h'|<divisor>] [trigger threshold]-- Snoop LF (l:125khz, h:134khz)"}, {"snoop", CmdLFSnoop, 0, "['l'|'h'|<divisor>] [trigger threshold]-- Snoop LF (l:125khz, h:134khz)"},
{"ti", CmdLFTI, 1, "{ TI RFIDs... }"}, {"ti", CmdLFTI, 1, "{ TI RFIDs... }"},
{"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"}, {"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"},

View file

@ -23,7 +23,6 @@ int CmdLFaskSim(const char *Cmd);
int CmdLFfskSim(const char *Cmd); int CmdLFfskSim(const char *Cmd);
int CmdLFpskSim(const char *Cmd); int CmdLFpskSim(const char *Cmd);
int CmdLFSimBidir(const char *Cmd); int CmdLFSimBidir(const char *Cmd);
//int CmdLFSimManchester(const char *Cmd);
int CmdLFSnoop(const char *Cmd); int CmdLFSnoop(const char *Cmd);
int CmdVchDemod(const char *Cmd); int CmdVchDemod(const char *Cmd);
int CmdLFfind(const char *Cmd); int CmdLFfind(const char *Cmd);

View file

@ -19,6 +19,10 @@
#include "cmddata.h" #include "cmddata.h"
#include "cmdlf.h" #include "cmdlf.h"
#include "cmdlfem4x.h" #include "cmdlfem4x.h"
#include "lfdemod.h"
#define llx PRIx64
char *global_em410xId; char *global_em410xId;
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
@ -26,11 +30,11 @@ static int CmdHelp(const char *Cmd);
int CmdEMdemodASK(const char *Cmd) int CmdEMdemodASK(const char *Cmd)
{ {
char cmdp = param_getchar(Cmd, 0); char cmdp = param_getchar(Cmd, 0);
int findone = (cmdp == '1') ? 1 : 0; int findone = (cmdp == '1') ? 1 : 0;
UsbCommand c={CMD_EM410X_DEMOD}; UsbCommand c={CMD_EM410X_DEMOD};
c.arg[0]=findone; c.arg[0]=findone;
SendCommand(&c); SendCommand(&c);
return 0; return 0;
} }
/* Read the ID of an EM410x tag. /* Read the ID of an EM410x tag.
@ -43,21 +47,21 @@ int CmdEMdemodASK(const char *Cmd)
*/ */
int CmdEM410xRead(const char *Cmd) int CmdEM410xRead(const char *Cmd)
{ {
uint32_t hi=0; uint32_t hi=0;
uint64_t lo=0; uint64_t lo=0;
if(!AskEm410xDemod("", &hi, &lo)) return 0; if(!AskEm410xDemod("", &hi, &lo, false)) return 0;
PrintAndLog("EM410x pattern found: "); PrintAndLog("EM410x pattern found: ");
printEM410x(hi, lo); printEM410x(hi, lo);
if (hi){ if (hi){
PrintAndLog ("EM410x XL pattern found"); PrintAndLog ("EM410x XL pattern found");
return 0; return 0;
} }
char id[12] = {0x00}; char id[12] = {0x00};
sprintf(id, "%010llx",lo); sprintf(id, "%010llx",lo);
global_em410xId = id; global_em410xId = id;
return 1; return 1;
} }
// emulate an EM410X tag // emulate an EM410X tag
@ -83,52 +87,52 @@ int CmdEM410xSim(const char *Cmd)
PrintAndLog("Starting simulating UID %02X%02X%02X%02X%02X", uid[0],uid[1],uid[2],uid[3],uid[4]); PrintAndLog("Starting simulating UID %02X%02X%02X%02X%02X", uid[0],uid[1],uid[2],uid[3],uid[4]);
PrintAndLog("Press pm3-button to about simulation"); PrintAndLog("Press pm3-button to about simulation");
/* clock is 64 in EM410x tags */ /* clock is 64 in EM410x tags */
int clock = 64; int clock = 64;
/* clear our graph */ /* clear our graph */
ClearGraph(0); ClearGraph(0);
/* write 9 start bits */ /* write 9 start bits */
for (i = 0; i < 9; i++) for (i = 0; i < 9; i++)
AppendGraph(0, clock, 1); AppendGraph(0, clock, 1);
/* for each hex char */ /* for each hex char */
parity[0] = parity[1] = parity[2] = parity[3] = 0; parity[0] = parity[1] = parity[2] = parity[3] = 0;
for (i = 0; i < 10; i++) for (i = 0; i < 10; i++)
{ {
/* read each hex char */ /* read each hex char */
sscanf(&Cmd[i], "%1x", &n); sscanf(&Cmd[i], "%1x", &n);
for (j = 3; j >= 0; j--, n/= 2) for (j = 3; j >= 0; j--, n/= 2)
binary[j] = n % 2; binary[j] = n % 2;
/* append each bit */ /* append each bit */
AppendGraph(0, clock, binary[0]); AppendGraph(0, clock, binary[0]);
AppendGraph(0, clock, binary[1]); AppendGraph(0, clock, binary[1]);
AppendGraph(0, clock, binary[2]); AppendGraph(0, clock, binary[2]);
AppendGraph(0, clock, binary[3]); AppendGraph(0, clock, binary[3]);
/* append parity bit */ /* append parity bit */
AppendGraph(0, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]); AppendGraph(0, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);
/* keep track of column parity */ /* keep track of column parity */
parity[0] ^= binary[0]; parity[0] ^= binary[0];
parity[1] ^= binary[1]; parity[1] ^= binary[1];
parity[2] ^= binary[2]; parity[2] ^= binary[2];
parity[3] ^= binary[3]; parity[3] ^= binary[3];
} }
/* parity columns */ /* parity columns */
AppendGraph(0, clock, parity[0]); AppendGraph(0, clock, parity[0]);
AppendGraph(0, clock, parity[1]); AppendGraph(0, clock, parity[1]);
AppendGraph(0, clock, parity[2]); AppendGraph(0, clock, parity[2]);
AppendGraph(0, clock, parity[3]); AppendGraph(0, clock, parity[3]);
/* stop bit */ /* stop bit */
AppendGraph(1, clock, 0); AppendGraph(1, clock, 0);
CmdLFSim("0"); //240 start_gap. CmdLFSim("0"); //240 start_gap.
return 0; return 0;
} }
/* Function is equivalent of lf read + data samples + em410xread /* Function is equivalent of lf read + data samples + em410xread
@ -139,7 +143,6 @@ int CmdEM410xSim(const char *Cmd)
* rate gets lower, then grow the number of samples * rate gets lower, then grow the number of samples
* Changed by martin, 4000 x 4 = 16000, * Changed by martin, 4000 x 4 = 16000,
* see http://www.proxmark.org/forum/viewtopic.php?pid=7235#p7235 * see http://www.proxmark.org/forum/viewtopic.php?pid=7235#p7235
*/ */
int CmdEM410xWatch(const char *Cmd) int CmdEM410xWatch(const char *Cmd)
{ {
@ -150,12 +153,13 @@ int CmdEM410xWatch(const char *Cmd)
} }
CmdLFRead("s"); CmdLFRead("s");
getSamples("8192",true); //capture enough to get 2 full messages getSamples("8201",true); //capture enough to get 2 complete preambles (4096*2+9)
} while (!CmdEM410xRead("")); } while (!CmdEM410xRead(""));
return 0; return 0;
} }
//currently only supports manchester modulations
int CmdEM410xWatchnSpoof(const char *Cmd) int CmdEM410xWatchnSpoof(const char *Cmd)
{ {
CmdEM410xWatch(Cmd); CmdEM410xWatch(Cmd);
@ -164,154 +168,10 @@ int CmdEM410xWatchnSpoof(const char *Cmd)
return 0; return 0;
} }
/* Read the transmitted data of an EM4x50 tag
* Format:
*
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
* CCCCCCCC <- column parity bits
* 0 <- stop bit
* LW <- Listen Window
*
* This pattern repeats for every block of data being transmitted.
* Transmission starts with two Listen Windows (LW - a modulated
* pattern of 320 cycles each (32/32/128/64/64)).
*
* Note that this data may or may not be the UID. It is whatever data
* is stored in the blocks defined in the control word First and Last
* Word Read values. UID is stored in block 32.
*/
int CmdEM4x50Read(const char *Cmd)
{
int i, j, startblock, skip, block, start, end, low, high;
bool complete= false;
int tmpbuff[MAX_GRAPH_TRACE_LEN / 64];
char tmp[6];
high= low= 0;
memset(tmpbuff, 0, MAX_GRAPH_TRACE_LEN / 64);
/* first get high and low values */
for (i = 0; i < GraphTraceLen; i++)
{
if (GraphBuffer[i] > high)
high = GraphBuffer[i];
else if (GraphBuffer[i] < low)
low = GraphBuffer[i];
}
/* populate a buffer with pulse lengths */
i= 0;
j= 0;
while (i < GraphTraceLen)
{
// measure from low to low
while ((GraphBuffer[i] > low) && (i<GraphTraceLen))
++i;
start= i;
while ((GraphBuffer[i] < high) && (i<GraphTraceLen))
++i;
while ((GraphBuffer[i] > low) && (i<GraphTraceLen))
++i;
if (j>=(MAX_GRAPH_TRACE_LEN/64)) {
break;
}
tmpbuff[j++]= i - start;
}
/* look for data start - should be 2 pairs of LW (pulses of 192,128) */
start= -1;
skip= 0;
for (i= 0; i < j - 4 ; ++i)
{
skip += tmpbuff[i];
if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194)
if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130)
if (tmpbuff[i+2] >= 190 && tmpbuff[i+2] <= 194)
if (tmpbuff[i+3] >= 126 && tmpbuff[i+3] <= 130)
{
start= i + 3;
break;
}
}
startblock= i + 3;
/* skip over the remainder of the LW */
skip += tmpbuff[i+1]+tmpbuff[i+2];
while (skip < MAX_GRAPH_TRACE_LEN && GraphBuffer[skip] > low)
++skip;
skip += 8;
/* now do it again to find the end */
end= start;
for (i += 3; i < j - 4 ; ++i)
{
end += tmpbuff[i];
if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194)
if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130)
if (tmpbuff[i+2] >= 190 && tmpbuff[i+2] <= 194)
if (tmpbuff[i+3] >= 126 && tmpbuff[i+3] <= 130)
{
complete= true;
break;
}
}
if (start >= 0)
PrintAndLog("Found data at sample: %i",skip);
else
{
PrintAndLog("No data found!");
PrintAndLog("Try again with more samples.");
return 0;
}
if (!complete)
{
PrintAndLog("*** Warning!");
PrintAndLog("Partial data - no end found!");
PrintAndLog("Try again with more samples.");
}
/* get rid of leading crap */
sprintf(tmp,"%i",skip);
CmdLtrim(tmp);
/* now work through remaining buffer printing out data blocks */
block= 0;
i= startblock;
while (block < 6)
{
PrintAndLog("Block %i:", block);
// mandemod routine needs to be split so we can call it for data
// just print for now for debugging
CmdManchesterDemod("i 64");
skip= 0;
/* look for LW before start of next block */
for ( ; i < j - 4 ; ++i)
{
skip += tmpbuff[i];
if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194)
if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130)
break;
}
while (GraphBuffer[skip] > low)
++skip;
skip += 8;
sprintf(tmp,"%i",skip);
CmdLtrim(tmp);
start += skip;
block++;
}
return 0;
}
int CmdEM410xWrite(const char *Cmd) int CmdEM410xWrite(const char *Cmd)
{ {
uint64_t id = 0xFFFFFFFFFFFFFFFF; // invalid id value uint64_t id = 0xFFFFFFFFFFFFFFFF; // invalid id value
int card = 0xFF; // invalid card value int card = 0xFF; // invalid card value
unsigned int clock = 0; // invalid clock value unsigned int clock = 0; // invalid clock value
sscanf(Cmd, "%" PRIx64 " %d %d", &id, &card, &clock); sscanf(Cmd, "%" PRIx64 " %d %d", &id, &card, &clock);
@ -370,133 +230,404 @@ int CmdEM410xWrite(const char *Cmd)
return 0; return 0;
} }
UsbCommand c = {CMD_EM410X_WRITE_TAG, {card, (uint32_t)(id >> 32), (uint32_t)id}}; UsbCommand c = {CMD_EM410X_WRITE_TAG, {card, (uint32_t)(id >> 32), (uint32_t)id}};
SendCommand(&c); SendCommand(&c);
return 0; return 0;
}
bool EM_EndParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType)
{
if (rows*cols>size) return false;
uint8_t colP=0;
//assume last col is a parity and do not test
for (uint8_t colNum = 0; colNum < cols-1; colNum++) {
for (uint8_t rowNum = 0; rowNum < rows; rowNum++) {
colP ^= BitStream[(rowNum*cols)+colNum];
}
if (colP != pType) return false;
}
return true;
}
bool EM_ByteParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType)
{
if (rows*cols>size) return false;
uint8_t rowP=0;
//assume last row is a parity row and do not test
for (uint8_t rowNum = 0; rowNum < rows-1; rowNum++) {
for (uint8_t colNum = 0; colNum < cols; colNum++) {
rowP ^= BitStream[(rowNum*cols)+colNum];
}
if (rowP != pType) return false;
}
return true;
}
uint32_t OutputEM4x50_Block(uint8_t *BitStream, size_t size, bool verbose, bool pTest)
{
if (size<45) return 0;
uint32_t code = bytebits_to_byte(BitStream,8);
code = code<<8 | bytebits_to_byte(BitStream+9,8);
code = code<<8 | bytebits_to_byte(BitStream+18,8);
code = code<<8 | bytebits_to_byte(BitStream+27,8);
if (verbose || g_debugMode){
for (uint8_t i = 0; i<5; i++){
if (i == 4) PrintAndLog(""); //parity byte spacer
PrintAndLog("%d%d%d%d%d%d%d%d %d -> 0x%02x",
BitStream[i*9],
BitStream[i*9+1],
BitStream[i*9+2],
BitStream[i*9+3],
BitStream[i*9+4],
BitStream[i*9+5],
BitStream[i*9+6],
BitStream[i*9+7],
BitStream[i*9+8],
bytebits_to_byte(BitStream+i*9,8)
);
}
if (pTest)
PrintAndLog("Parity Passed");
else
PrintAndLog("Parity Failed");
}
return code;
}
/* Read the transmitted data of an EM4x50 tag
* Format:
*
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
* CCCCCCCC <- column parity bits
* 0 <- stop bit
* LW <- Listen Window
*
* This pattern repeats for every block of data being transmitted.
* Transmission starts with two Listen Windows (LW - a modulated
* pattern of 320 cycles each (32/32/128/64/64)).
*
* Note that this data may or may not be the UID. It is whatever data
* is stored in the blocks defined in the control word First and Last
* Word Read values. UID is stored in block 32.
*/
//completed by Marshmellow
int EM4x50Read(const char *Cmd, bool verbose)
{
uint8_t fndClk[] = {8,16,32,40,50,64,128};
int clk = 0;
int invert = 0;
int tol = 0;
int i, j, startblock, skip, block, start, end, low, high, minClk;
bool complete = false;
int tmpbuff[MAX_GRAPH_TRACE_LEN / 64];
uint32_t Code[6];
char tmp[6];
char tmp2[20];
int phaseoff;
high = low = 0;
memset(tmpbuff, 0, MAX_GRAPH_TRACE_LEN / 64);
// get user entry if any
sscanf(Cmd, "%i %i", &clk, &invert);
// save GraphBuffer - to restore it later
save_restoreGB(1);
// first get high and low values
for (i = 0; i < GraphTraceLen; i++) {
if (GraphBuffer[i] > high)
high = GraphBuffer[i];
else if (GraphBuffer[i] < low)
low = GraphBuffer[i];
}
i = 0;
j = 0;
minClk = 255;
// get to first full low to prime loop and skip incomplete first pulse
while ((GraphBuffer[i] < high) && (i < GraphTraceLen))
++i;
while ((GraphBuffer[i] > low) && (i < GraphTraceLen))
++i;
skip = i;
// populate tmpbuff buffer with pulse lengths
while (i < GraphTraceLen) {
// measure from low to low
while ((GraphBuffer[i] > low) && (i < GraphTraceLen))
++i;
start= i;
while ((GraphBuffer[i] < high) && (i < GraphTraceLen))
++i;
while ((GraphBuffer[i] > low) && (i < GraphTraceLen))
++i;
if (j>=(MAX_GRAPH_TRACE_LEN/64)) {
break;
}
tmpbuff[j++]= i - start;
if (i-start < minClk && i < GraphTraceLen) {
minClk = i - start;
}
}
// set clock
if (!clk) {
for (uint8_t clkCnt = 0; clkCnt<7; clkCnt++) {
tol = fndClk[clkCnt]/8;
if (minClk >= fndClk[clkCnt]-tol && minClk <= fndClk[clkCnt]+1) {
clk=fndClk[clkCnt];
break;
}
}
if (!clk) return 0;
} else tol = clk/8;
// look for data start - should be 2 pairs of LW (pulses of clk*3,clk*2)
start = -1;
for (i= 0; i < j - 4 ; ++i) {
skip += tmpbuff[i];
if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol) //3 clocks
if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol) //2 clocks
if (tmpbuff[i+2] >= clk*3-tol && tmpbuff[i+2] <= clk*3+tol) //3 clocks
if (tmpbuff[i+3] >= clk-tol) //1.5 to 2 clocks - depends on bit following
{
start= i + 4;
break;
}
}
startblock = i + 4;
// skip over the remainder of LW
skip += tmpbuff[i+1] + tmpbuff[i+2] + clk;
if (tmpbuff[i+3]>clk)
phaseoff = tmpbuff[i+3]-clk;
else
phaseoff = 0;
// now do it again to find the end
end = skip;
for (i += 3; i < j - 4 ; ++i) {
end += tmpbuff[i];
if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol) //3 clocks
if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol) //2 clocks
if (tmpbuff[i+2] >= clk*3-tol && tmpbuff[i+2] <= clk*3+tol) //3 clocks
if (tmpbuff[i+3] >= clk-tol) //1.5 to 2 clocks - depends on bit following
{
complete= true;
break;
}
}
end = i;
// report back
if (verbose || g_debugMode) {
if (start >= 0) {
PrintAndLog("\nNote: one block = 50 bits (32 data, 12 parity, 6 marker)");
} else {
PrintAndLog("No data found!, clock tried:%d",clk);
PrintAndLog("Try again with more samples.");
PrintAndLog(" or after a 'data askedge' command to clean up the read");
return 0;
}
} else if (start < 0) return 0;
start = skip;
snprintf(tmp2, sizeof(tmp2),"%d %d 1000 %d", clk, invert, clk*47);
// get rid of leading crap
snprintf(tmp, sizeof(tmp), "%i", skip);
CmdLtrim(tmp);
bool pTest;
bool AllPTest = true;
// now work through remaining buffer printing out data blocks
block = 0;
i = startblock;
while (block < 6) {
if (verbose || g_debugMode) PrintAndLog("\nBlock %i:", block);
skip = phaseoff;
// look for LW before start of next block
for ( ; i < j - 4 ; ++i) {
skip += tmpbuff[i];
if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol)
if (tmpbuff[i+1] >= clk-tol)
break;
}
if (i >= j-4) break; //next LW not found
skip += clk;
if (tmpbuff[i+1]>clk)
phaseoff = tmpbuff[i+1]-clk;
else
phaseoff = 0;
i += 2;
if (ASKDemod(tmp2, false, false, 1) < 1) {
save_restoreGB(0);
return 0;
}
//set DemodBufferLen to just one block
DemodBufferLen = skip/clk;
//test parities
pTest = EM_ByteParityTest(DemodBuffer,DemodBufferLen,5,9,0);
pTest &= EM_EndParityTest(DemodBuffer,DemodBufferLen,5,9,0);
AllPTest &= pTest;
//get output
Code[block] = OutputEM4x50_Block(DemodBuffer,DemodBufferLen,verbose, pTest);
if (g_debugMode) PrintAndLog("\nskipping %d samples, bits:%d", skip, skip/clk);
//skip to start of next block
snprintf(tmp,sizeof(tmp),"%i",skip);
CmdLtrim(tmp);
block++;
if (i >= end) break; //in case chip doesn't output 6 blocks
}
//print full code:
if (verbose || g_debugMode || AllPTest){
if (!complete) {
PrintAndLog("*** Warning!");
PrintAndLog("Partial data - no end found!");
PrintAndLog("Try again with more samples.");
}
PrintAndLog("Found data at sample: %i - using clock: %i", start, clk);
end = block;
for (block=0; block < end; block++){
PrintAndLog("Block %d: %08x",block,Code[block]);
}
if (AllPTest) {
PrintAndLog("Parities Passed");
} else {
PrintAndLog("Parities Failed");
PrintAndLog("Try cleaning the read samples with 'data askedge'");
}
}
//restore GraphBuffer
save_restoreGB(0);
return (int)AllPTest;
}
int CmdEM4x50Read(const char *Cmd)
{
return EM4x50Read(Cmd, true);
} }
int CmdReadWord(const char *Cmd) int CmdReadWord(const char *Cmd)
{ {
int Word = -1; //default to invalid word int Word = -1; //default to invalid word
UsbCommand c; UsbCommand c;
sscanf(Cmd, "%d", &Word); sscanf(Cmd, "%d", &Word);
if ( (Word > 15) | (Word < 0) ) { if ( (Word > 15) | (Word < 0) ) {
PrintAndLog("Word must be between 0 and 15"); PrintAndLog("Word must be between 0 and 15");
return 1; return 1;
} }
PrintAndLog("Reading word %d", Word); PrintAndLog("Reading word %d", Word);
c.cmd = CMD_EM4X_READ_WORD; c.cmd = CMD_EM4X_READ_WORD;
c.d.asBytes[0] = 0x0; //Normal mode c.d.asBytes[0] = 0x0; //Normal mode
c.arg[0] = 0; c.arg[0] = 0;
c.arg[1] = Word; c.arg[1] = Word;
c.arg[2] = 0; c.arg[2] = 0;
SendCommand(&c); SendCommand(&c);
return 0; return 0;
} }
int CmdReadWordPWD(const char *Cmd) int CmdReadWordPWD(const char *Cmd)
{ {
int Word = -1; //default to invalid word int Word = -1; //default to invalid word
int Password = 0xFFFFFFFF; //default to blank password int Password = 0xFFFFFFFF; //default to blank password
UsbCommand c; UsbCommand c;
sscanf(Cmd, "%d %x", &Word, &Password); sscanf(Cmd, "%d %x", &Word, &Password);
if ( (Word > 15) | (Word < 0) ) { if ( (Word > 15) | (Word < 0) ) {
PrintAndLog("Word must be between 0 and 15"); PrintAndLog("Word must be between 0 and 15");
return 1; return 1;
} }
PrintAndLog("Reading word %d with password %08X", Word, Password); PrintAndLog("Reading word %d with password %08X", Word, Password);
c.cmd = CMD_EM4X_READ_WORD; c.cmd = CMD_EM4X_READ_WORD;
c.d.asBytes[0] = 0x1; //Password mode c.d.asBytes[0] = 0x1; //Password mode
c.arg[0] = 0; c.arg[0] = 0;
c.arg[1] = Word; c.arg[1] = Word;
c.arg[2] = Password; c.arg[2] = Password;
SendCommand(&c); SendCommand(&c);
return 0; return 0;
} }
int CmdWriteWord(const char *Cmd) int CmdWriteWord(const char *Cmd)
{ {
int Word = 16; //default to invalid block int Word = 16; //default to invalid block
int Data = 0xFFFFFFFF; //default to blank data int Data = 0xFFFFFFFF; //default to blank data
UsbCommand c; UsbCommand c;
sscanf(Cmd, "%x %d", &Data, &Word); sscanf(Cmd, "%x %d", &Data, &Word);
if (Word > 15) { if (Word > 15) {
PrintAndLog("Word must be between 0 and 15"); PrintAndLog("Word must be between 0 and 15");
return 1; return 1;
} }
PrintAndLog("Writing word %d with data %08X", Word, Data); PrintAndLog("Writing word %d with data %08X", Word, Data);
c.cmd = CMD_EM4X_WRITE_WORD; c.cmd = CMD_EM4X_WRITE_WORD;
c.d.asBytes[0] = 0x0; //Normal mode c.d.asBytes[0] = 0x0; //Normal mode
c.arg[0] = Data; c.arg[0] = Data;
c.arg[1] = Word; c.arg[1] = Word;
c.arg[2] = 0; c.arg[2] = 0;
SendCommand(&c); SendCommand(&c);
return 0; return 0;
} }
int CmdWriteWordPWD(const char *Cmd) int CmdWriteWordPWD(const char *Cmd)
{ {
int Word = 16; //default to invalid word int Word = 16; //default to invalid word
int Data = 0xFFFFFFFF; //default to blank data int Data = 0xFFFFFFFF; //default to blank data
int Password = 0xFFFFFFFF; //default to blank password int Password = 0xFFFFFFFF; //default to blank password
UsbCommand c; UsbCommand c;
sscanf(Cmd, "%x %d %x", &Data, &Word, &Password); sscanf(Cmd, "%x %d %x", &Data, &Word, &Password);
if (Word > 15) { if (Word > 15) {
PrintAndLog("Word must be between 0 and 15"); PrintAndLog("Word must be between 0 and 15");
return 1; return 1;
} }
PrintAndLog("Writing word %d with data %08X and password %08X", Word, Data, Password); PrintAndLog("Writing word %d with data %08X and password %08X", Word, Data, Password);
c.cmd = CMD_EM4X_WRITE_WORD; c.cmd = CMD_EM4X_WRITE_WORD;
c.d.asBytes[0] = 0x1; //Password mode c.d.asBytes[0] = 0x1; //Password mode
c.arg[0] = Data; c.arg[0] = Data;
c.arg[1] = Word; c.arg[1] = Word;
c.arg[2] = Password; c.arg[2] = Password;
SendCommand(&c); SendCommand(&c);
return 0; return 0;
} }
static command_t CommandTable[] = static command_t CommandTable[] =
{ {
{"help", CmdHelp, 1, "This help"}, {"help", CmdHelp, 1, "This help"},
{"em410xdemod", CmdEMdemodASK, 0, "[findone] -- Extract ID from EM410x tag (option 0 for continuous loop, 1 for only 1 tag)"}, {"em410xdemod", CmdEMdemodASK, 0, "[findone] -- Extract ID from EM410x tag (option 0 for continuous loop, 1 for only 1 tag)"},
{"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag"}, {"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag in GraphBuffer"},
{"em410xsim", CmdEM410xSim, 0, "<UID> -- Simulate EM410x tag"}, {"em410xsim", CmdEM410xSim, 0, "<UID> -- Simulate EM410x tag"},
{"em410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"}, {"em410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
{"em410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" }, {"em410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" },
{"em410xwrite", CmdEM410xWrite, 1, "<UID> <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"}, {"em410xwrite", CmdEM410xWrite, 0, "<UID> <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"},
{"em4x50read", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"}, {"em4x50read", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"},
{"readword", CmdReadWord, 1, "<Word> -- Read EM4xxx word data"}, {"readword", CmdReadWord, 1, "<Word> -- Read EM4xxx word data"},
{"readwordPWD", CmdReadWordPWD, 1, "<Word> <Password> -- Read EM4xxx word data in password mode"}, {"readwordPWD", CmdReadWordPWD, 1, "<Word> <Password> -- Read EM4xxx word data in password mode"},
{"writeword", CmdWriteWord, 1, "<Data> <Word> -- Write EM4xxx word data"}, {"writeword", CmdWriteWord, 1, "<Data> <Word> -- Write EM4xxx word data"},
{"writewordPWD", CmdWriteWordPWD, 1, "<Data> <Word> <Password> -- Write EM4xxx word data in password mode"}, {"writewordPWD", CmdWriteWordPWD, 1, "<Data> <Word> <Password> -- Write EM4xxx word data in password mode"},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };
int CmdLFEM4X(const char *Cmd) int CmdLFEM4X(const char *Cmd)
{ {
CmdsParse(CommandTable, Cmd); CmdsParse(CommandTable, Cmd);
return 0; return 0;
} }
int CmdHelp(const char *Cmd) int CmdHelp(const char *Cmd)
{ {
CmdsHelp(CommandTable); CmdsHelp(CommandTable);
return 0; return 0;
} }

View file

@ -11,7 +11,6 @@
#ifndef CMDLFEM4X_H__ #ifndef CMDLFEM4X_H__
#define CMDLFEM4X_H__ #define CMDLFEM4X_H__
int CmdLFEM4X(const char *Cmd);
int CmdEMdemodASK(const char *Cmd); int CmdEMdemodASK(const char *Cmd);
int CmdEM410xRead(const char *Cmd); int CmdEM410xRead(const char *Cmd);
int CmdEM410xSim(const char *Cmd); int CmdEM410xSim(const char *Cmd);
@ -19,9 +18,11 @@ int CmdEM410xWatch(const char *Cmd);
int CmdEM410xWatchnSpoof(const char *Cmd); int CmdEM410xWatchnSpoof(const char *Cmd);
int CmdEM410xWrite(const char *Cmd); int CmdEM410xWrite(const char *Cmd);
int CmdEM4x50Read(const char *Cmd); int CmdEM4x50Read(const char *Cmd);
int CmdLFEM4X(const char *Cmd);
int CmdReadWord(const char *Cmd); int CmdReadWord(const char *Cmd);
int CmdReadWordPWD(const char *Cmd); int CmdReadWordPWD(const char *Cmd);
int CmdWriteWord(const char *Cmd); int CmdWriteWord(const char *Cmd);
int CmdWriteWordPWD(const char *Cmd); int CmdWriteWordPWD(const char *Cmd);
int EM4x50Read(const char *Cmd, bool verbose);
#endif #endif

View file

@ -17,7 +17,7 @@
#include "cmdlfhid.h" #include "cmdlfhid.h"
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
/*
int CmdHIDDemod(const char *Cmd) int CmdHIDDemod(const char *Cmd)
{ {
if (GraphTraceLen < 4800) { if (GraphTraceLen < 4800) {
@ -36,7 +36,7 @@ int CmdHIDDemod(const char *Cmd)
RepaintGraphWindow(); RepaintGraphWindow();
return 0; return 0;
} }
*/
int CmdHIDDemodFSK(const char *Cmd) int CmdHIDDemodFSK(const char *Cmd)
{ {
int findone=0; int findone=0;
@ -106,7 +106,7 @@ int CmdHIDClone(const char *Cmd)
static command_t CommandTable[] = static command_t CommandTable[] =
{ {
{"help", CmdHelp, 1, "This help"}, {"help", CmdHelp, 1, "This help"},
{"demod", CmdHIDDemod, 1, "Demodulate HID Prox Card II (not optimal)"}, //{"demod", CmdHIDDemod, 1, "Demodulate HID Prox Card II (not optimal)"},
{"fskdemod", CmdHIDDemodFSK, 0, "['1'] Realtime HID FSK demodulator (option '1' for one tag only)"}, {"fskdemod", CmdHIDDemodFSK, 0, "['1'] Realtime HID FSK demodulator (option '1' for one tag only)"},
{"sim", CmdHIDSim, 0, "<ID> -- HID tag simulator"}, {"sim", CmdHIDSim, 0, "<ID> -- HID tag simulator"},
{"clone", CmdHIDClone, 0, "<ID> ['l'] -- Clone HID to T55x7 (tag must be in antenna)(option 'l' for 84bit ID)"}, {"clone", CmdHIDClone, 0, "<ID> ['l'] -- Clone HID to T55x7 (tag must be in antenna)(option 'l' for 84bit ID)"},

View file

@ -12,9 +12,9 @@
#define CMDLFHID_H__ #define CMDLFHID_H__
int CmdLFHID(const char *Cmd); int CmdLFHID(const char *Cmd);
//int CmdHIDDemod(const char *Cmd);
int CmdHIDDemod(const char *Cmd);
int CmdHIDDemodFSK(const char *Cmd); int CmdHIDDemodFSK(const char *Cmd);
int CmdHIDSim(const char *Cmd); int CmdHIDSim(const char *Cmd);
int CmdHIDClone(const char *Cmd);
#endif #endif

View file

@ -24,7 +24,7 @@ int CmdIODemodFSK(const char *Cmd)
SendCommand(&c); SendCommand(&c);
return 0; return 0;
} }
/*
int CmdIOProxDemod(const char *Cmd){ int CmdIOProxDemod(const char *Cmd){
if (GraphTraceLen < 4800) { if (GraphTraceLen < 4800) {
PrintAndLog("too short; need at least 4800 samples"); PrintAndLog("too short; need at least 4800 samples");
@ -37,7 +37,7 @@ int CmdIOProxDemod(const char *Cmd){
RepaintGraphWindow(); RepaintGraphWindow();
return 0; return 0;
} }
*/
int CmdIOClone(const char *Cmd) int CmdIOClone(const char *Cmd)
{ {
unsigned int hi = 0, lo = 0; unsigned int hi = 0, lo = 0;
@ -67,7 +67,7 @@ int CmdIOClone(const char *Cmd)
static command_t CommandTable[] = static command_t CommandTable[] =
{ {
{"help", CmdHelp, 1, "This help"}, {"help", CmdHelp, 1, "This help"},
{"demod", CmdIOProxDemod, 1, "Demodulate Stream"}, //{"demod", CmdIOProxDemod, 1, "Demodulate Stream"},
{"fskdemod", CmdIODemodFSK, 0, "['1'] Realtime IO FSK demodulator (option '1' for one tag only)"}, {"fskdemod", CmdIODemodFSK, 0, "['1'] Realtime IO FSK demodulator (option '1' for one tag only)"},
{"clone", CmdIOClone, 0, "Clone ioProx Tag"}, {"clone", CmdIOClone, 0, "Clone ioProx Tag"},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
@ -83,4 +83,4 @@ int CmdHelp(const char *Cmd)
{ {
CmdsHelp(CommandTable); CmdsHelp(CommandTable);
return 0; return 0;
} }

View file

@ -10,6 +10,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <inttypes.h> #include <inttypes.h>
#include <time.h>
#include "proxmark3.h" #include "proxmark3.h"
#include "ui.h" #include "ui.h"
#include "graph.h" #include "graph.h"
@ -49,24 +50,24 @@ int usage_t55xx_config(){
} }
int usage_t55xx_read(){ int usage_t55xx_read(){
PrintAndLog("Usage: lf t55xx read <block> <password>"); PrintAndLog("Usage: lf t55xx read <block> <password>");
PrintAndLog(" <block>, block number to read. Between 0-7"); PrintAndLog(" <block>, block number to read. Between 0-7");
PrintAndLog(" <password>, OPTIONAL password (8 hex characters)"); PrintAndLog(" <password>, OPTIONAL password (8 hex characters)");
PrintAndLog(""); PrintAndLog("");
PrintAndLog("Examples:"); PrintAndLog("Examples:");
PrintAndLog(" lf t55xx read 0 - read data from block 0"); PrintAndLog(" lf t55xx read 0 - read data from block 0");
PrintAndLog(" lf t55xx read 0 feedbeef - read data from block 0 password feedbeef"); PrintAndLog(" lf t55xx read 0 feedbeef - read data from block 0 password feedbeef");
PrintAndLog(""); PrintAndLog("");
return 0; return 0;
} }
int usage_t55xx_write(){ int usage_t55xx_write(){
PrintAndLog("Usage: lf t55xx wr <block> <data> [password]"); PrintAndLog("Usage: lf t55xx wr <block> <data> [password]");
PrintAndLog(" <block>, block number to read. Between 0-7"); PrintAndLog(" <block>, block number to write. Between 0-7");
PrintAndLog(" <data>, 4 bytes of data to write (8 hex characters)"); PrintAndLog(" <data>, 4 bytes of data to write (8 hex characters)");
PrintAndLog(" [password], OPTIONAL password 4bytes (8 hex characters)"); PrintAndLog(" [password], OPTIONAL password 4bytes (8 hex characters)");
PrintAndLog(""); PrintAndLog("");
PrintAndLog("Examples:"); PrintAndLog("Examples:");
PrintAndLog(" lf t55xx wd 3 11223344 - write 11223344 to block 3"); PrintAndLog(" lf t55xx wr 3 11223344 - write 11223344 to block 3");
PrintAndLog(" lf t55xx wd 3 11223344 feedbeef - write 11223344 to block 3 password feedbeef"); PrintAndLog(" lf t55xx wr 3 11223344 feedbeef - write 11223344 to block 3 password feedbeef");
PrintAndLog(""); PrintAndLog("");
return 0; return 0;
} }
@ -147,31 +148,37 @@ int CmdT55xxSetConfig(const char *Cmd) {
param_getstr(Cmd, cmdp+1, modulation); param_getstr(Cmd, cmdp+1, modulation);
cmdp += 2; cmdp += 2;
if ( strcmp(modulation, "FSK" ) == 0) if ( strcmp(modulation, "FSK" ) == 0) {
config.modulation = DEMOD_FSK; config.modulation = DEMOD_FSK;
else if ( strcmp(modulation, "FSK1" ) == 0) } else if ( strcmp(modulation, "FSK1" ) == 0) {
config.modulation = DEMOD_FSK1; config.modulation = DEMOD_FSK1;
else if ( strcmp(modulation, "FSK1a" ) == 0) config.inverted=1;
} else if ( strcmp(modulation, "FSK1a" ) == 0) {
config.modulation = DEMOD_FSK1a; config.modulation = DEMOD_FSK1a;
else if ( strcmp(modulation, "FSK2" ) == 0) config.inverted=0;
} else if ( strcmp(modulation, "FSK2" ) == 0) {
config.modulation = DEMOD_FSK2; config.modulation = DEMOD_FSK2;
else if ( strcmp(modulation, "FSK2a" ) == 0) config.inverted=0;
} else if ( strcmp(modulation, "FSK2a" ) == 0) {
config.modulation = DEMOD_FSK2a; config.modulation = DEMOD_FSK2a;
else if ( strcmp(modulation, "ASK" ) == 0) config.inverted=1;
} else if ( strcmp(modulation, "ASK" ) == 0) {
config.modulation = DEMOD_ASK; config.modulation = DEMOD_ASK;
else if ( strcmp(modulation, "NRZ" ) == 0) } else if ( strcmp(modulation, "NRZ" ) == 0) {
config.modulation = DEMOD_NRZ; config.modulation = DEMOD_NRZ;
else if ( strcmp(modulation, "PSK1" ) == 0) } else if ( strcmp(modulation, "PSK1" ) == 0) {
config.modulation = DEMOD_PSK1; config.modulation = DEMOD_PSK1;
else if ( strcmp(modulation, "PSK2" ) == 0) } else if ( strcmp(modulation, "PSK2" ) == 0) {
config.modulation = DEMOD_PSK2; config.modulation = DEMOD_PSK2;
else if ( strcmp(modulation, "PSK3" ) == 0) } else if ( strcmp(modulation, "PSK3" ) == 0) {
config.modulation = DEMOD_PSK3; config.modulation = DEMOD_PSK3;
else if ( strcmp(modulation, "BIa" ) == 0) } else if ( strcmp(modulation, "BIa" ) == 0) {
config.modulation = DEMOD_BIa; config.modulation = DEMOD_BIa;
else if ( strcmp(modulation, "BI" ) == 0) config.inverted=1;
} else if ( strcmp(modulation, "BI" ) == 0) {
config.modulation = DEMOD_BI; config.modulation = DEMOD_BI;
else { config.inverted=0;
} else {
PrintAndLog("Unknown modulation '%s'", modulation); PrintAndLog("Unknown modulation '%s'", modulation);
errors = TRUE; errors = TRUE;
} }
@ -255,77 +262,51 @@ int CmdT55xxReadBlock(const char *Cmd) {
bool DecodeT55xxBlock(){ bool DecodeT55xxBlock(){
char buf[8] = {0x00}; char buf[30] = {0x00};
char *cmdStr = buf; char *cmdStr = buf;
int ans = 0; int ans = 0;
uint8_t bitRate[8] = {8,16,32,40,50,64,100,128}; uint8_t bitRate[8] = {8,16,32,40,50,64,100,128};
DemodBufferLen = 0x00; DemodBufferLen = 0x00;
//trim 1/2 a clock from beginning
snprintf(cmdStr, sizeof(buf),"%d", bitRate[config.bitrate]/2 );
CmdLtrim(cmdStr);
switch( config.modulation ){ switch( config.modulation ){
case DEMOD_FSK: case DEMOD_FSK:
//CmdLtrim("26"); snprintf(cmdStr, sizeof(buf),"%d %d", bitRate[config.bitrate], config.inverted );
sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 );
CmdLtrim(cmdStr);
sprintf(cmdStr,"%d %d", bitRate[config.bitrate], config.inverted );
ans = FSKrawDemod(cmdStr, FALSE); ans = FSKrawDemod(cmdStr, FALSE);
break; break;
case DEMOD_FSK1: case DEMOD_FSK1:
//CmdLtrim("26");
sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 );
CmdLtrim(cmdStr);
sprintf(cmdStr,"%d 1 8 5", bitRate[config.bitrate] );
ans = FSKrawDemod(cmdStr, FALSE);
break;
case DEMOD_FSK1a: case DEMOD_FSK1a:
//CmdLtrim("26"); snprintf(cmdStr, sizeof(buf),"%d %d 8 5", bitRate[config.bitrate], config.inverted );
sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 );
CmdLtrim(cmdStr);
sprintf(cmdStr,"%d 0 8 5", bitRate[config.bitrate] );
ans = FSKrawDemod(cmdStr, FALSE); ans = FSKrawDemod(cmdStr, FALSE);
break; break;
case DEMOD_FSK2: case DEMOD_FSK2:
//CmdLtrim("26");
sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 );
CmdLtrim(cmdStr);
sprintf(cmdStr,"%d 0 10 8", bitRate[config.bitrate] );
ans = FSKrawDemod(cmdStr, FALSE);
break;
case DEMOD_FSK2a: case DEMOD_FSK2a:
//CmdLtrim("26"); snprintf(cmdStr, sizeof(buf),"%d %d 10 8", bitRate[config.bitrate], config.inverted );
sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 );
CmdLtrim(cmdStr);
sprintf(cmdStr,"%d 1 10 8", bitRate[config.bitrate] );
ans = FSKrawDemod(cmdStr, FALSE); ans = FSKrawDemod(cmdStr, FALSE);
break; break;
case DEMOD_ASK: case DEMOD_ASK:
sprintf(cmdStr,"%d %d 1", bitRate[config.bitrate], config.inverted ); snprintf(cmdStr, sizeof(buf),"%d %d 0", bitRate[config.bitrate], config.inverted );
ans = ASKmanDemod(cmdStr, FALSE, FALSE); ans = ASKDemod(cmdStr, FALSE, FALSE, 1);
break; break;
case DEMOD_PSK1: case DEMOD_PSK1:
sprintf(cmdStr,"%d %d 1", bitRate[config.bitrate], config.inverted ); snprintf(cmdStr, sizeof(buf),"%d %d 0", bitRate[config.bitrate], config.inverted );
ans = PSKDemod(cmdStr, FALSE); ans = PSKDemod(cmdStr, FALSE);
break; break;
case DEMOD_PSK2: case DEMOD_PSK2: //inverted won't affect this
sprintf(cmdStr,"%d 1", bitRate[config.bitrate] ); case DEMOD_PSK3: //not fully implemented
ans = PSKDemod(cmdStr, FALSE); snprintf(cmdStr, sizeof(buf),"%d 0 1", bitRate[config.bitrate] );
psk1TOpsk2(DemodBuffer, DemodBufferLen);
break;
case DEMOD_PSK3:
sprintf(cmdStr,"%d %d 1", bitRate[config.bitrate], config.inverted );
ans = PSKDemod(cmdStr, FALSE); ans = PSKDemod(cmdStr, FALSE);
psk1TOpsk2(DemodBuffer, DemodBufferLen); psk1TOpsk2(DemodBuffer, DemodBufferLen);
break; break;
case DEMOD_NRZ: case DEMOD_NRZ:
sprintf(cmdStr,"%d %d 1", bitRate[config.bitrate], config.inverted ); snprintf(cmdStr, sizeof(buf),"%d %d 1", bitRate[config.bitrate], config.inverted );
ans = NRZrawDemod(cmdStr, FALSE); ans = NRZrawDemod(cmdStr, FALSE);
break; break;
case DEMOD_BI: case DEMOD_BI:
sprintf(cmdStr,"0 %d 0 1", bitRate[config.bitrate] );
ans = ASKbiphaseDemod(cmdStr, FALSE);
break;
case DEMOD_BIa: case DEMOD_BIa:
sprintf(cmdStr,"0 %d 1 1", bitRate[config.bitrate] ); snprintf(cmdStr, sizeof(buf),"0 %d %d 0", bitRate[config.bitrate], config.inverted );
ans = ASKbiphaseDemod(cmdStr, FALSE); ans = ASKbiphaseDemod(cmdStr, FALSE);
break; break;
default: default:
@ -354,114 +335,141 @@ bool tryDetectModulation(){
char cmdStr[8] = {0}; char cmdStr[8] = {0};
uint8_t hits = 0; uint8_t hits = 0;
t55xx_conf_block_t tests[15]; t55xx_conf_block_t tests[15];
int bitRate=0;
uint8_t fc1 = 0, fc2 = 0, clk=0;
save_restoreGB(1);
if (GetFskClock("", FALSE, FALSE)){ if (GetFskClock("", FALSE, FALSE)){
uint8_t fc1 = 0, fc2 = 0, clk=0;
fskClocks(&fc1, &fc2, &clk, FALSE); fskClocks(&fc1, &fc2, &clk, FALSE);
sprintf(cmdStr,"%d", clk/2); sprintf(cmdStr,"%d", clk/2);
CmdLtrim(cmdStr); CmdLtrim(cmdStr);
if ( FSKrawDemod("0 0", FALSE) && test(DEMOD_FSK, &tests[hits].offset)){ if ( FSKrawDemod("0 0", FALSE) && test(DEMOD_FSK, &tests[hits].offset, &bitRate)){
tests[hits].modulation = DEMOD_FSK; tests[hits].modulation = DEMOD_FSK;
if (fc1==8 && fc2 == 5) if (fc1==8 && fc2 == 5)
tests[hits].modulation = DEMOD_FSK1a; tests[hits].modulation = DEMOD_FSK1a;
else if (fc1==10 && fc2 == 8) else if (fc1==10 && fc2 == 8)
tests[hits].modulation = DEMOD_FSK2; tests[hits].modulation = DEMOD_FSK2;
tests[hits].bitrate = bitRate;
tests[hits].inverted = FALSE; tests[hits].inverted = FALSE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits; ++hits;
} }
if ( FSKrawDemod("0 1", FALSE) && test(DEMOD_FSK, &tests[hits].offset)) { if ( FSKrawDemod("0 1", FALSE) && test(DEMOD_FSK, &tests[hits].offset, &bitRate)) {
tests[hits].modulation = DEMOD_FSK; tests[hits].modulation = DEMOD_FSK;
if (fc1==8 && fc2 == 5) if (fc1 == 8 && fc2 == 5)
tests[hits].modulation = DEMOD_FSK1; tests[hits].modulation = DEMOD_FSK1;
else if (fc1==10 && fc2 == 8) else if (fc1 == 10 && fc2 == 8)
tests[hits].modulation = DEMOD_FSK2a; tests[hits].modulation = DEMOD_FSK2a;
tests[hits].bitrate = bitRate;
tests[hits].inverted = TRUE; tests[hits].inverted = TRUE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits; ++hits;
} }
} else { } else {
if ( ASKmanDemod("0 0 1", FALSE, FALSE) && test(DEMOD_ASK, &tests[hits].offset)) { clk = GetAskClock("", FALSE, FALSE);
tests[hits].modulation = DEMOD_ASK; if (clk>0) {
tests[hits].inverted = FALSE; sprintf(cmdStr,"%d", clk/2);
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); CmdLtrim(cmdStr);
++hits; if ( ASKDemod("0 0 0", FALSE, FALSE, 1) && test(DEMOD_ASK, &tests[hits].offset, &bitRate)) {
} tests[hits].modulation = DEMOD_ASK;
tests[hits].bitrate = bitRate;
if ( ASKmanDemod("0 1 1", FALSE, FALSE) && test(DEMOD_ASK, &tests[hits].offset)) {
tests[hits].modulation = DEMOD_ASK;
tests[hits].inverted = TRUE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
if ( NRZrawDemod("0 0 1", FALSE) && test(DEMOD_NRZ, &tests[hits].offset)) {
tests[hits].modulation = DEMOD_NRZ;
tests[hits].inverted = FALSE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
if ( NRZrawDemod("0 1 1", FALSE) && test(DEMOD_NRZ, &tests[hits].offset)) {
tests[hits].modulation = DEMOD_NRZ;
tests[hits].inverted = TRUE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
if ( PSKDemod("0 0 1", FALSE) && test(DEMOD_PSK1, &tests[hits].offset)) {
tests[hits].modulation = DEMOD_PSK1;
tests[hits].inverted = FALSE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
if ( PSKDemod("0 1 1", FALSE) && test(DEMOD_PSK1, &tests[hits].offset)) {
tests[hits].modulation = DEMOD_PSK1;
tests[hits].inverted = TRUE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
// PSK2 - needs a call to psk1TOpsk2.
if ( PSKDemod("0 0 1", FALSE)) {
psk1TOpsk2(DemodBuffer, DemodBufferLen);
if (test(DEMOD_PSK2, &tests[hits].offset)){
tests[hits].modulation = DEMOD_PSK2;
tests[hits].inverted = FALSE; tests[hits].inverted = FALSE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits; ++hits;
} }
} // inverse waves does not affect this demod if ( ASKDemod("0 1 0", FALSE, FALSE, 1) && test(DEMOD_ASK, &tests[hits].offset, &bitRate)) {
tests[hits].modulation = DEMOD_ASK;
// PSK3 - needs a call to psk1TOpsk2. tests[hits].bitrate = bitRate;
if ( PSKDemod("0 0 1", FALSE)) { tests[hits].inverted = TRUE;
psk1TOpsk2(DemodBuffer, DemodBufferLen); tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
if (test(DEMOD_PSK3, &tests[hits].offset)){ ++hits;
tests[hits].modulation = DEMOD_PSK3; }
if ( ASKbiphaseDemod("0 0 0 0", FALSE) && test(DEMOD_BI, &tests[hits].offset, &bitRate) ) {
tests[hits].modulation = DEMOD_BI;
tests[hits].bitrate = bitRate;
tests[hits].inverted = FALSE; tests[hits].inverted = FALSE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits; ++hits;
} }
} // inverse waves does not affect this demod if ( ASKbiphaseDemod("0 0 1 0", FALSE) && test(DEMOD_BIa, &tests[hits].offset, &bitRate) ) {
tests[hits].modulation = DEMOD_BIa;
if ( ASKbiphaseDemod("0 0 0 1", FALSE) && test(DEMOD_BI, &tests[hits].offset) ) { tests[hits].bitrate = bitRate;
tests[hits].modulation = DEMOD_BI; tests[hits].inverted = TRUE;
tests[hits].inverted = FALSE; tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); ++hits;
++hits; }
} }
if ( ASKbiphaseDemod("0 0 1 1", FALSE) && test(DEMOD_BIa, &tests[hits].offset) ) { //undo trim from ask
tests[hits].modulation = DEMOD_BIa; save_restoreGB(0);
tests[hits].inverted = TRUE; clk = GetNrzClock("", FALSE, FALSE);
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); if (clk>0) {
++hits; sprintf(cmdStr,"%d", clk/2);
CmdLtrim(cmdStr);
if ( NRZrawDemod("0 0 1", FALSE) && test(DEMOD_NRZ, &tests[hits].offset, &bitRate)) {
tests[hits].modulation = DEMOD_NRZ;
tests[hits].bitrate = bitRate;
tests[hits].inverted = FALSE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
if ( NRZrawDemod("0 1 1", FALSE) && test(DEMOD_NRZ, &tests[hits].offset, &bitRate)) {
tests[hits].modulation = DEMOD_NRZ;
tests[hits].bitrate = bitRate;
tests[hits].inverted = TRUE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
}
//undo trim from nrz
save_restoreGB(0);
clk = GetPskClock("", FALSE, FALSE);
if (clk>0) {
PrintAndLog("clk %d",clk);
sprintf(cmdStr,"%d", clk/2);
CmdLtrim(cmdStr);
if ( PSKDemod("0 0 1", FALSE) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate)) {
tests[hits].modulation = DEMOD_PSK1;
tests[hits].bitrate = bitRate;
tests[hits].inverted = FALSE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
if ( PSKDemod("0 1 1", FALSE) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate)) {
tests[hits].modulation = DEMOD_PSK1;
tests[hits].bitrate = bitRate;
tests[hits].inverted = TRUE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
// PSK2 - needs a call to psk1TOpsk2.
if ( PSKDemod("0 0 1", FALSE)) {
psk1TOpsk2(DemodBuffer, DemodBufferLen);
if (test(DEMOD_PSK2, &tests[hits].offset, &bitRate)){
tests[hits].modulation = DEMOD_PSK2;
tests[hits].bitrate = bitRate;
tests[hits].inverted = FALSE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
} // inverse waves does not affect this demod
// PSK3 - needs a call to psk1TOpsk2.
if ( PSKDemod("0 0 1", FALSE)) {
psk1TOpsk2(DemodBuffer, DemodBufferLen);
if (test(DEMOD_PSK3, &tests[hits].offset, &bitRate)){
tests[hits].modulation = DEMOD_PSK3;
tests[hits].bitrate = bitRate;
tests[hits].inverted = FALSE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
} // inverse waves does not affect this demod
} }
} }
if ( hits == 1) { if ( hits == 1) {
config.modulation = tests[0].modulation; config.modulation = tests[0].modulation;
config.bitrate = tests[0].bitrate;
config.inverted = tests[0].inverted; config.inverted = tests[0].inverted;
config.offset = tests[0].offset; config.offset = tests[0].offset;
config.block0 = tests[0].block0; config.block0 = tests[0].block0;
@ -516,81 +524,32 @@ bool testBitRate(uint8_t readRate, uint8_t mod){
uint8_t detRate = 0; uint8_t detRate = 0;
switch( mod ){ switch( mod ){
case DEMOD_FSK: case DEMOD_FSK:
detRate = GetFskClock("",FALSE, FALSE);
if (expected[readRate] == detRate) {
config.bitrate = readRate;
return TRUE;
}
break;
case DEMOD_FSK1: case DEMOD_FSK1:
detRate = GetFskClock("",FALSE, FALSE);
if (expected[readRate] == detRate) {
config.bitrate = readRate;
return TRUE;
}
break;
case DEMOD_FSK1a: case DEMOD_FSK1a:
detRate = GetFskClock("",FALSE, FALSE);
if (expected[readRate] == detRate) {
config.bitrate = readRate;
return TRUE;
}
break;
case DEMOD_FSK2: case DEMOD_FSK2:
detRate = GetFskClock("",FALSE, FALSE);
if (expected[readRate] == detRate) {
config.bitrate = readRate;
return TRUE;
}
break;
case DEMOD_FSK2a: case DEMOD_FSK2a:
detRate = GetFskClock("",FALSE, FALSE); detRate = GetFskClock("",FALSE, FALSE);
if (expected[readRate] == detRate) { if (expected[readRate] == detRate)
config.bitrate = readRate;
return TRUE; return TRUE;
}
break; break;
case DEMOD_ASK: case DEMOD_ASK:
case DEMOD_BI:
case DEMOD_BIa:
detRate = GetAskClock("",FALSE, FALSE); detRate = GetAskClock("",FALSE, FALSE);
if (expected[readRate] == detRate) { if (expected[readRate] == detRate)
config.bitrate = readRate;
return TRUE; return TRUE;
}
break; break;
case DEMOD_PSK1: case DEMOD_PSK1:
detRate = GetPskClock("",FALSE, FALSE);
if (expected[readRate] == detRate) {
config.bitrate = readRate;
return TRUE;
}
break;
case DEMOD_PSK2: case DEMOD_PSK2:
detRate = GetPskClock("",FALSE, FALSE);
if (expected[readRate] == detRate) {
config.bitrate = readRate;
return TRUE;
}
break;
case DEMOD_PSK3: case DEMOD_PSK3:
detRate = GetPskClock("",FALSE, FALSE); detRate = GetPskClock("",FALSE, FALSE);
if (expected[readRate] == detRate) { if (expected[readRate] == detRate)
config.bitrate = readRate;
return TRUE; return TRUE;
}
break; break;
case DEMOD_NRZ: case DEMOD_NRZ:
detRate = GetNrzClock("",FALSE, FALSE); detRate = GetNrzClock("",FALSE, FALSE);
if (expected[readRate] == detRate) { if (expected[readRate] == detRate)
config.bitrate = readRate;
return TRUE; return TRUE;
}
break;
case DEMOD_BI:
detRate = GetAskClock("",FALSE, FALSE);
if (expected[readRate] == detRate) {
config.bitrate = readRate;
return TRUE;
}
break; break;
default: default:
return FALSE; return FALSE;
@ -598,26 +557,27 @@ bool testBitRate(uint8_t readRate, uint8_t mod){
return FALSE; return FALSE;
} }
bool test(uint8_t mode, uint8_t *offset){ bool test(uint8_t mode, uint8_t *offset, int *fndBitRate){
if ( !DemodBufferLen) return FALSE; if ( DemodBufferLen < 64 ) return FALSE;
uint8_t si = 0; uint8_t si = 0;
for (uint8_t idx = 0; idx < 64; idx++){ for (uint8_t idx = 0; idx < 64; idx++){
si = idx; si = idx;
if ( PackBits(si, 32, DemodBuffer) == 0x00 ) continue; if ( PackBits(si, 32, DemodBuffer) == 0x00 ) continue;
uint8_t safer = PackBits(si, 4, DemodBuffer); si += 4; //master key uint8_t safer = PackBits(si, 4, DemodBuffer); si += 4; //master key
uint8_t resv = PackBits(si, 4, DemodBuffer); si += 4; //was 7 & +=7+3 //should be only 4 bits if extended mode uint8_t resv = PackBits(si, 4, DemodBuffer); si += 4; //was 7 & +=7+3 //should be only 4 bits if extended mode
// 2nibble must be zeroed. // 2nibble must be zeroed.
// moved test to here, since this gets most faults first. // moved test to here, since this gets most faults first.
if ( resv > 0x00) continue; if ( resv > 0x00) continue;
uint8_t xtRate = PackBits(si, 3, DemodBuffer); si += 3; //new uint8_t xtRate = PackBits(si, 3, DemodBuffer); si += 3; //extended mode part of rate
uint8_t bitRate = PackBits(si, 3, DemodBuffer); si += 3; //new could check bit rate int bitRate = PackBits(si, 3, DemodBuffer); si += 3; //bit rate
if (bitRate > 7) continue;
uint8_t extend = PackBits(si, 1, DemodBuffer); si += 1; //bit 15 extended mode uint8_t extend = PackBits(si, 1, DemodBuffer); si += 1; //bit 15 extended mode
uint8_t modread = PackBits(si, 5, DemodBuffer); si += 5+2+1; //new uint8_t modread = PackBits(si, 5, DemodBuffer); si += 5+2+1;
//uint8_t pskcr = PackBits(si, 2, DemodBuffer); si += 2+1; //new could check psk cr //uint8_t pskcr = PackBits(si, 2, DemodBuffer); si += 2+1; //could check psk cr
uint8_t nml01 = PackBits(si, 1, DemodBuffer); si += 1+5; //bit 24 , 30, 31 could be tested for 0 if not extended mode uint8_t nml01 = PackBits(si, 1, DemodBuffer); si += 1+5; //bit 24, 30, 31 could be tested for 0 if not extended mode
uint8_t nml02 = PackBits(si, 2, DemodBuffer); si += 2; uint8_t nml02 = PackBits(si, 2, DemodBuffer); si += 2;
//if extended mode //if extended mode
@ -628,15 +588,15 @@ bool test(uint8_t mode, uint8_t *offset){
} }
//test modulation //test modulation
if (!testModulation(mode, modread)) continue; if (!testModulation(mode, modread)) continue;
*offset = idx;
if (!testBitRate(bitRate, mode)) continue; if (!testBitRate(bitRate, mode)) continue;
*fndBitRate = bitRate;
*offset = idx;
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
} }
void printT55xxBlock(const char *demodStr){ void printT55xxBlock(const char *blockNum){
uint8_t i = config.offset; uint8_t i = config.offset;
uint8_t endpos = 32 + i; uint8_t endpos = 32 + i;
@ -654,7 +614,7 @@ void printT55xxBlock(const char *demodStr){
bits[i - config.offset]=DemodBuffer[i]; bits[i - config.offset]=DemodBuffer[i];
blockData = PackBits(0, 32, bits); blockData = PackBits(0, 32, bits);
PrintAndLog("0x%08X %s [%s]", blockData, sprint_bin(bits,32), demodStr); PrintAndLog("[%s] 0x%08X %s", blockNum, blockData, sprint_bin(bits,32));
} }
int special(const char *Cmd) { int special(const char *Cmd) {
@ -746,16 +706,28 @@ int CmdT55xxReadTrace(const char *Cmd)
uint32_t bl0 = PackBits(si, 32, DemodBuffer); uint32_t bl0 = PackBits(si, 32, DemodBuffer);
uint32_t bl1 = PackBits(si+32, 32, DemodBuffer); uint32_t bl1 = PackBits(si+32, 32, DemodBuffer);
uint32_t acl = PackBits(si, 8, DemodBuffer); si += 8; uint32_t acl = PackBits(si, 8, DemodBuffer); si += 8;
uint32_t mfc = PackBits(si, 8, DemodBuffer); si += 8; uint32_t mfc = PackBits(si, 8, DemodBuffer); si += 8;
uint32_t cid = PackBits(si, 5, DemodBuffer); si += 5; uint32_t cid = PackBits(si, 5, DemodBuffer); si += 5;
uint32_t icr = PackBits(si, 3, DemodBuffer); si += 3; uint32_t icr = PackBits(si, 3, DemodBuffer); si += 3;
uint32_t year = PackBits(si, 4, DemodBuffer); si += 4; uint32_t year = PackBits(si, 4, DemodBuffer); si += 4;
uint32_t quarter = PackBits(si, 2, DemodBuffer); si += 2; uint32_t quarter = PackBits(si, 2, DemodBuffer); si += 2;
uint32_t lotid = PackBits(si, 14, DemodBuffer); si += 14; uint32_t lotid = PackBits(si, 14, DemodBuffer); si += 14;
uint32_t wafer = PackBits(si, 5, DemodBuffer); si += 5; uint32_t wafer = PackBits(si, 5, DemodBuffer); si += 5;
uint32_t dw = PackBits(si, 15, DemodBuffer); uint32_t dw = PackBits(si, 15, DemodBuffer);
time_t t = time(NULL);
struct tm tm = *localtime(&t);
if ( year > tm.tm_year-110)
year += 2000;
else
year += 2010;
if ( acl != 0xE0 ) {
PrintAndLog("The modulation is most likely wrong since the ACL is not 0xE0. ");
return 1;
}
PrintAndLog(""); PrintAndLog("");
PrintAndLog("-- T55xx Trace Information ----------------------------------"); PrintAndLog("-- T55xx Trace Information ----------------------------------");
PrintAndLog("-------------------------------------------------------------"); PrintAndLog("-------------------------------------------------------------");
@ -764,7 +736,7 @@ int CmdT55xxReadTrace(const char *Cmd)
PrintAndLog(" CID : 0x%02X (%d) - %s", cid, cid, GetModelStrFromCID(cid)); PrintAndLog(" CID : 0x%02X (%d) - %s", cid, cid, GetModelStrFromCID(cid));
PrintAndLog(" ICR IC Revision : %d",icr ); PrintAndLog(" ICR IC Revision : %d",icr );
PrintAndLog(" Manufactured"); PrintAndLog(" Manufactured");
PrintAndLog(" Year/Quarter : 20?%d/%d",year, quarter); PrintAndLog(" Year/Quarter : %d/%d",year, quarter);
PrintAndLog(" Lot ID : %d", lotid ); PrintAndLog(" Lot ID : %d", lotid );
PrintAndLog(" Wafer number : %d", wafer); PrintAndLog(" Wafer number : %d", wafer);
PrintAndLog(" Die Number : %d", dw); PrintAndLog(" Die Number : %d", dw);
@ -774,8 +746,6 @@ int CmdT55xxReadTrace(const char *Cmd)
PrintAndLog(" Block 1 : 0x%08X %s", bl1, sprint_bin(DemodBuffer+config.offset+repeat+32,32) ); PrintAndLog(" Block 1 : 0x%08X %s", bl1, sprint_bin(DemodBuffer+config.offset+repeat+32,32) );
PrintAndLog("-------------------------------------------------------------"); PrintAndLog("-------------------------------------------------------------");
if ( acl != 0xE0 )
PrintAndLog("The modulation is most likely wrong since the ACL is not 0xE0. ");
/* /*
TRACE - BLOCK O TRACE - BLOCK O
Bits Definition HEX Bits Definition HEX
@ -809,10 +779,10 @@ int CmdT55xxInfo(const char *Cmd){
if (strlen(Cmd)==0) if (strlen(Cmd)==0)
AquireData( CONFIGURATION_BLOCK ); AquireData( CONFIGURATION_BLOCK );
if (!DecodeT55xxBlock()) return 1; if (!DecodeT55xxBlock()) return 1;
if ( !DemodBufferLen) return 1; if ( DemodBufferLen < 32) return 1;
uint8_t si = config.offset; uint8_t si = config.offset;
uint32_t bl0 = PackBits(si, 32, DemodBuffer); uint32_t bl0 = PackBits(si, 32, DemodBuffer);
@ -922,7 +892,8 @@ int AquireData( uint8_t block ){
} }
char * GetBitRateStr(uint32_t id){ char * GetBitRateStr(uint32_t id){
static char buf[40]; static char buf[25];
char *retStr = buf; char *retStr = buf;
switch (id){ switch (id){
case 0: case 0:
@ -957,7 +928,6 @@ char * GetBitRateStr(uint32_t id){
return buf; return buf;
} }
char * GetSaferStr(uint32_t id){ char * GetSaferStr(uint32_t id){
static char buf[40]; static char buf[40];
char *retStr = buf; char *retStr = buf;
@ -974,7 +944,7 @@ char * GetSaferStr(uint32_t id){
} }
char * GetModulationStr( uint32_t id){ char * GetModulationStr( uint32_t id){
static char buf[40]; static char buf[60];
char *retStr = buf; char *retStr = buf;
switch (id){ switch (id){
@ -1003,7 +973,7 @@ char * GetModulationStr( uint32_t id){
snprintf(retStr,sizeof(buf),"%d - FSK 2a RF/10 RF/8",id); snprintf(retStr,sizeof(buf),"%d - FSK 2a RF/10 RF/8",id);
break; break;
case 8: case 8:
snprintf(retStr,sizeof(buf),"%d - Manschester",id); snprintf(retStr,sizeof(buf),"%d - Manchester",id);
break; break;
case 16: case 16:
snprintf(retStr,sizeof(buf),"%d - Biphase",id); snprintf(retStr,sizeof(buf),"%d - Biphase",id);
@ -1026,8 +996,8 @@ char * GetModelStrFromCID(uint32_t cid){
static char buf[10]; static char buf[10];
char *retStr = buf; char *retStr = buf;
if (cid == 1) sprintf(retStr,"ATA5577M1"); if (cid == 1) snprintf(retStr, sizeof(buf),"ATA5577M1");
if (cid == 2) sprintf(retStr,"ATA5577M2"); if (cid == 2) snprintf(retStr, sizeof(buf),"ATA5577M2");
return buf; return buf;
} }

View file

@ -53,13 +53,13 @@ char * GetSaferStr(uint32_t id);
char * GetModulationStr( uint32_t id); char * GetModulationStr( uint32_t id);
char * GetModelStrFromCID(uint32_t cid); char * GetModelStrFromCID(uint32_t cid);
char * GetSelectedModulationStr( uint8_t id); char * GetSelectedModulationStr( uint8_t id);
uint32_t PackBits(uint8_t start, uint8_t len, uint8_t* bitstream); uint32_t PackBits(uint8_t start, uint8_t len, uint8_t *bitstream);
void printT55xxBlock(const char *demodStr); void printT55xxBlock(const char *demodStr);
void printConfiguration( t55xx_conf_block_t b); void printConfiguration( t55xx_conf_block_t b);
bool DecodeT55xxBlock(); bool DecodeT55xxBlock();
bool tryDetectModulation(); bool tryDetectModulation();
bool test(uint8_t mode, uint8_t *offset); bool test(uint8_t mode, uint8_t *offset, int *fndBitRate);
int special(const char *Cmd); int special(const char *Cmd);
int AquireData( uint8_t block ); int AquireData( uint8_t block );

View file

@ -83,7 +83,7 @@ int CmdList(const char *Cmd)
{ {
while ((ep = readdir (dp)) != NULL) while ((ep = readdir (dp)) != NULL)
{ {
if(ep->d_name != NULL && str_ends_with(ep->d_name, ".lua")) if(str_ends_with(ep->d_name, ".lua"))
PrintAndLog("%-16s %s", ep->d_name, "A script file"); PrintAndLog("%-16s %s", ep->d_name, "A script file");
} }
(void) closedir (dp); (void) closedir (dp);

View file

@ -11,7 +11,7 @@ d3f7d3f7d3f7,
587ee5f9350f, 587ee5f9350f,
a0478cc39091, a0478cc39091,
533cb6c723f6, 533cb6c723f6,
8fd0a4f256e9 8fd0a4f256e9,
# more Keys from mf_default_keys.lua # more Keys from mf_default_keys.lua
000000000001, 000000000001,
000000000002, 000000000002,
@ -42,6 +42,7 @@ a0478cc39091,
47524f555041,--RKFJOJOGROUPKeyA 47524f555041,--RKFJOJOGROUPKeyA
47524f555042,--RKFJOJOGROUPKeyB 47524f555042,--RKFJOJOGROUPKeyB
4AF9D7ADEBE4,--DirectoryandeventlogKeyA 4AF9D7ADEBE4,--DirectoryandeventlogKeyA
4b0b20107ccb,--TNP3xxx
505249564141,--RKFJOJOPRIVAKeyA 505249564141,--RKFJOJOPRIVAKeyA
505249564142,--RKFJOJOPRIVAKeyB 505249564142,--RKFJOJOPRIVAKeyB
505249565441, 505249565441,
@ -49,14 +50,19 @@ a0478cc39091,
54726176656c,--VästtrafikenKeyA 54726176656c,--VästtrafikenKeyA
555555555555, 555555555555,
55f5a5dd38c9, 55f5a5dd38c9,
569369c5a0e5,--kiev
5c598c9c58b5,--RKFSLKeyB 5c598c9c58b5,--RKFSLKeyB
632193be1c3c,--kiev
644672bd4afe,--kiev
666666666666, 666666666666,
722bfcc5375f,--RKFRejskortDanmarkKeyA 722bfcc5375f,--RKFRejskortDanmarkKeyA
776974687573,--VästtrafikenKeyB 776974687573,--VästtrafikenKeyB
777777777777, 777777777777,
888888888888, 888888888888,
8fe644038790,--kiev
999999999999, 999999999999,
99c636334433, 99c636334433,
9de89e070277,--kiev
a00000000000, a00000000000,
a053a292a4af, a053a292a4af,
a64598a77478,--RKFSLKeyA a64598a77478,--RKFSLKeyA
@ -65,6 +71,7 @@ aaaaaaaaaaaa,
abcdef123456,--Keyfromladyada.net abcdef123456,--Keyfromladyada.net
b00000000000, b00000000000,
b127c6f41436, b127c6f41436,
b5ff67cba951,--kiev
bbbbbbbbbbbb, bbbbbbbbbbbb,
bd493a3962b6, bd493a3962b6,
c934fe34d934, c934fe34d934,
@ -73,7 +80,15 @@ dddddddddddd,
e4d2770a89be,--RKFSLKeyB e4d2770a89be,--RKFSLKeyB
ee0042f88840,--VästtrafikenKeyB ee0042f88840,--VästtrafikenKeyB
eeeeeeeeeeee, eeeeeeeeeeee,
eff603e1efe9,--kiev
f14ee7cae863,--kiev
f1a97341a9fc, f1a97341a9fc,
f1d83f964314,--RKFRejskortDanmarkKeyB f1d83f964314,--RKFRejskortDanmarkKeyB
fc00018778f7,--VästtrafikenKeyA fc00018778f7,--VästtrafikenKeyA
fc0001877bf7,--RKFÖstgötaTrafikenKeyA fc0001877bf7,--RKFÖstgötaTrafikenKeyA
44ab09010845,-- hotel system
85fed980ea5a,-- hotel system
314B49474956,--VIGIK1KeyA
564c505f4d41,--VIGIK1KeyB
f4a9ef2afc6d,--BCARD KeyB
a9f953def0a3,--

287
client/fpga_compress.c Normal file
View file

@ -0,0 +1,287 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
// Compression tool for FPGA config files. Compress several *.bit files at
// compile time. Decompression is done at run time (see fpgaloader.c).
// This uses the zlib library tuned to this specific case. The small file sizes
// allow to use "insane" parameters for optimum compression ratio.
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "zlib.h"
#define MAX(a,b) ((a)>(b)?(a):(b))
// zlib configuration
#define COMPRESS_LEVEL 9 // use best possible compression
#define COMPRESS_WINDOW_BITS 15 // default = max = 15 for a window of 2^15 = 32KBytes
#define COMPRESS_MEM_LEVEL 9 // determines the amount of memory allocated during compression. Default = 8.
/* COMPRESS_STRATEGY can be
Z_DEFAULT_STRATEGY (the default),
Z_FILTERED (more huffmann, less string matching),
Z_HUFFMAN_ONLY (huffman only, no string matching)
Z_RLE (distances limited to one)
Z_FIXED (prevents the use of dynamic Huffman codes)
*/
#define COMPRESS_STRATEGY Z_DEFAULT_STRATEGY
// zlib tuning parameters:
#define COMPRESS_GOOD_LENGTH 258
#define COMPRESS_MAX_LAZY 258
#define COMPRESS_MAX_NICE_LENGTH 258
#define COMPRESS_MAX_CHAIN 8192
#define FPGA_INTERLEAVE_SIZE 288 // (the FPGA's internal config frame size is 288 bits. Interleaving with 288 bytes should give best compression)
#define FPGA_CONFIG_SIZE 42336 // our current fpga_[lh]f.bit files are 42175 bytes. Rounded up to next multiple of FPGA_INTERLEAVE_SIZE
static void usage(void)
{
fprintf(stderr, "Usage: fpga_compress <infile1> <infile2> ... <infile_n> <outfile>\n");
fprintf(stderr, " Combine n FPGA bitstream files and compress them into one.\n\n");
fprintf(stderr, " fpga_compress -d <infile> <outfile>");
fprintf(stderr, " Decompress <infile>. Write result to <outfile>");
}
static voidpf fpga_deflate_malloc(voidpf opaque, uInt items, uInt size)
{
return malloc(items*size);
}
static void fpga_deflate_free(voidpf opaque, voidpf address)
{
return free(address);
}
static bool all_feof(FILE *infile[], uint8_t num_infiles)
{
for (uint16_t i = 0; i < num_infiles; i++) {
if (!feof(infile[i])) {
return false;
}
}
return true;
}
int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile)
{
uint8_t *fpga_config;
uint32_t i;
int ret;
uint8_t c;
z_stream compressed_fpga_stream;
fpga_config = malloc(num_infiles * FPGA_CONFIG_SIZE);
// read the input files. Interleave them into fpga_config[]
i = 0;
do {
if (i >= num_infiles * FPGA_CONFIG_SIZE) {
fprintf(stderr, "Input files too big (total > %lu bytes). These are probably not PM3 FPGA config files.\n", num_infiles*FPGA_CONFIG_SIZE);
for(uint16_t j = 0; j < num_infiles; j++) {
fclose(infile[j]);
}
return(EXIT_FAILURE);
}
for(uint16_t j = 0; j < num_infiles; j++) {
for(uint16_t k = 0; k < FPGA_INTERLEAVE_SIZE; k++) {
c = fgetc(infile[j]);
if (!feof(infile[j])) {
fpga_config[i++] = c;
} else if (num_infiles > 1) {
fpga_config[i++] = '\0';
}
}
}
} while (!all_feof(infile, num_infiles));
// initialize zlib structures
compressed_fpga_stream.next_in = fpga_config;
compressed_fpga_stream.avail_in = i;
compressed_fpga_stream.zalloc = fpga_deflate_malloc;
compressed_fpga_stream.zfree = fpga_deflate_free;
ret = deflateInit2(&compressed_fpga_stream,
COMPRESS_LEVEL,
Z_DEFLATED,
COMPRESS_WINDOW_BITS,
COMPRESS_MEM_LEVEL,
COMPRESS_STRATEGY);
// estimate the size of the compressed output
unsigned int outsize_max = deflateBound(&compressed_fpga_stream, compressed_fpga_stream.avail_in);
uint8_t *outbuf = malloc(outsize_max);
compressed_fpga_stream.next_out = outbuf;
compressed_fpga_stream.avail_out = outsize_max;
if (ret == Z_OK) {
ret = deflateTune(&compressed_fpga_stream,
COMPRESS_GOOD_LENGTH,
COMPRESS_MAX_LAZY,
COMPRESS_MAX_NICE_LENGTH,
COMPRESS_MAX_CHAIN);
}
if (ret == Z_OK) {
ret = deflate(&compressed_fpga_stream, Z_FINISH);
}
fprintf(stderr, "compressed %lu input bytes to %lu output bytes\n", i, compressed_fpga_stream.total_out);
if (ret != Z_STREAM_END) {
fprintf(stderr, "Error in deflate(): %d %s\n", ret, compressed_fpga_stream.msg);
free(outbuf);
deflateEnd(&compressed_fpga_stream);
for(uint16_t j = 0; j < num_infiles; j++) {
fclose(infile[j]);
}
fclose(outfile);
free(infile);
free(fpga_config);
return(EXIT_FAILURE);
}
for (i = 0; i < compressed_fpga_stream.total_out; i++) {
fputc(outbuf[i], outfile);
}
free(outbuf);
deflateEnd(&compressed_fpga_stream);
for(uint16_t j = 0; j < num_infiles; j++) {
fclose(infile[j]);
}
fclose(outfile);
free(infile);
free(fpga_config);
return(EXIT_SUCCESS);
}
int zlib_decompress(FILE *infile, FILE *outfile)
{
#define DECOMPRESS_BUF_SIZE 1024
uint8_t outbuf[DECOMPRESS_BUF_SIZE];
uint8_t inbuf[DECOMPRESS_BUF_SIZE];
int ret;
z_stream compressed_fpga_stream;
// initialize zlib structures
compressed_fpga_stream.next_in = inbuf;
compressed_fpga_stream.avail_in = 0;
compressed_fpga_stream.next_out = outbuf;
compressed_fpga_stream.avail_out = DECOMPRESS_BUF_SIZE;
compressed_fpga_stream.zalloc = fpga_deflate_malloc;
compressed_fpga_stream.zfree = fpga_deflate_free;
ret = inflateInit2(&compressed_fpga_stream, 0);
do {
if (compressed_fpga_stream.avail_in == 0) {
compressed_fpga_stream.next_in = inbuf;
uint16_t i = 0;
do {
uint8_t c = fgetc(infile);
if (!feof(infile)) {
inbuf[i++] = c;
compressed_fpga_stream.avail_in++;
} else {
break;
}
} while (i < DECOMPRESS_BUF_SIZE);
}
ret = inflate(&compressed_fpga_stream, Z_SYNC_FLUSH);
if (ret != Z_OK && ret != Z_STREAM_END) {
break;
}
if (compressed_fpga_stream.avail_out == 0) {
for (uint16_t i = 0; i < DECOMPRESS_BUF_SIZE; i++) {
fputc(outbuf[i], outfile);
}
compressed_fpga_stream.avail_out = DECOMPRESS_BUF_SIZE;
compressed_fpga_stream.next_out = outbuf;
}
} while (ret == Z_OK);
if (ret == Z_STREAM_END) { // reached end of input
uint16_t i = 0;
while (compressed_fpga_stream.avail_out < DECOMPRESS_BUF_SIZE) {
fputc(outbuf[i++], outfile);
compressed_fpga_stream.avail_out++;
}
fclose(outfile);
fclose(infile);
return(EXIT_SUCCESS);
} else {
fprintf(stderr, "Error. Inflate() returned error %d, %s", ret, compressed_fpga_stream.msg);
fclose(outfile);
fclose(infile);
return(EXIT_FAILURE);
}
}
int main(int argc, char **argv)
{
FILE **infiles;
FILE *outfile;
if (argc == 1 || argc == 2) {
usage();
return(EXIT_FAILURE);
}
if (!strcmp(argv[1], "-d")) { // Decompress
infiles = calloc(1, sizeof(FILE*));
if (argc != 4) {
usage();
return(EXIT_FAILURE);
}
infiles[0] = fopen(argv[2], "rb");
if (infiles[0] == NULL) {
fprintf(stderr, "Error. Cannot open input file %s", argv[2]);
return(EXIT_FAILURE);
}
outfile = fopen(argv[3], "wb");
if (outfile == NULL) {
fprintf(stderr, "Error. Cannot open output file %s", argv[3]);
return(EXIT_FAILURE);
}
return zlib_decompress(infiles[0], outfile);
} else { // Compress
infiles = calloc(argc-2, sizeof(FILE*));
for (uint16_t i = 0; i < argc-2; i++) {
infiles[i] = fopen(argv[i+1], "rb");
if (infiles[i] == NULL) {
fprintf(stderr, "Error. Cannot open input file %s", argv[i+1]);
return(EXIT_FAILURE);
}
}
outfile = fopen(argv[argc-1], "wb");
if (outfile == NULL) {
fprintf(stderr, "Error. Cannot open output file %s", argv[argc-1]);
return(EXIT_FAILURE);
}
return zlib_compress(infiles, argc-2, outfile);
}
}

View file

@ -17,7 +17,6 @@
int GraphBuffer[MAX_GRAPH_TRACE_LEN]; int GraphBuffer[MAX_GRAPH_TRACE_LEN];
int GraphTraceLen; int GraphTraceLen;
/* write a manchester bit to the graph */ /* write a manchester bit to the graph */
void AppendGraph(int redraw, int clock, int bit) void AppendGraph(int redraw, int clock, int bit)
{ {
@ -46,6 +45,24 @@ int ClearGraph(int redraw)
return gtl; return gtl;
} }
// option '1' to save GraphBuffer any other to restore
void save_restoreGB(uint8_t saveOpt)
{
static int SavedGB[MAX_GRAPH_TRACE_LEN];
static int SavedGBlen;
static bool GB_Saved = false;
if (saveOpt==1) { //save
memcpy(SavedGB, GraphBuffer, sizeof(GraphBuffer));
SavedGBlen = GraphTraceLen;
GB_Saved=true;
} else if (GB_Saved){ //restore
memcpy(GraphBuffer, SavedGB, sizeof(GraphBuffer));
GraphTraceLen = SavedGBlen;
RepaintGraphWindow();
}
return;
}
// DETECT CLOCK NOW IN LFDEMOD.C // DETECT CLOCK NOW IN LFDEMOD.C
@ -126,10 +143,10 @@ int GetAskClock(const char str[], bool printAns, bool verbose)
PrintAndLog("Failed to copy from graphbuffer"); PrintAndLog("Failed to copy from graphbuffer");
return -1; return -1;
} }
DetectASKClock(grph, size, &clock, 20); int start = DetectASKClock(grph, size, &clock, 20);
// Only print this message if we're not looping something // Only print this message if we're not looping something
if (printAns){ if (printAns){
PrintAndLog("Auto-detected clock rate: %d", clock); PrintAndLog("Auto-detected clock rate: %d, Best Starting Position: %d", clock, start);
} }
return clock; return clock;
} }

View file

@ -23,6 +23,7 @@ uint8_t GetNrzClock(const char str[], bool printAns, bool verbose);
uint8_t GetFskClock(const char str[], bool printAns, bool verbose); uint8_t GetFskClock(const char str[], bool printAns, bool verbose);
uint8_t fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, bool verbose); uint8_t fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, bool verbose);
void setGraphBuf(uint8_t *buff, size_t size); void setGraphBuf(uint8_t *buff, size_t size);
void save_restoreGB(uint8_t saveOpt);
bool HasGraphData(); bool HasGraphData();
void DetectHighLowInGraph(int *high, int *low, bool addFuzz); void DetectHighLowInGraph(int *high, int *low, bool addFuzz);

View file

@ -89,7 +89,6 @@ typedef struct {
// For the 13.56 MHz tags // For the 13.56 MHz tags
#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300 #define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300
#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443 0x0301
#define CMD_READ_SRI512_TAG 0x0303 #define CMD_READ_SRI512_TAG 0x0303
#define CMD_READ_SRIX4K_TAG 0x0304 #define CMD_READ_SRIX4K_TAG 0x0304
#define CMD_READER_ISO_15693 0x0310 #define CMD_READER_ISO_15693 0x0310
@ -105,9 +104,8 @@ typedef struct {
#define CMD_SIMULATE_HITAG 0x0371 #define CMD_SIMULATE_HITAG 0x0371
#define CMD_READER_HITAG 0x0372 #define CMD_READER_HITAG 0x0372
#define CMD_SIMULATE_TAG_HF_LISTEN 0x0380 #define CMD_SIMULATE_TAG_ISO_14443B 0x0381
#define CMD_SIMULATE_TAG_ISO_14443 0x0381 #define CMD_SNOOP_ISO_14443B 0x0382
#define CMD_SNOOP_ISO_14443 0x0382
#define CMD_SNOOP_ISO_14443a 0x0383 #define CMD_SNOOP_ISO_14443a 0x0383
#define CMD_SIMULATE_TAG_ISO_14443a 0x0384 #define CMD_SIMULATE_TAG_ISO_14443a 0x0384
#define CMD_READER_ISO_14443a 0x0385 #define CMD_READER_ISO_14443a 0x0385

View file

@ -59,7 +59,6 @@ local _commands = {
--// For the 13.56 MHz tags --// For the 13.56 MHz tags
CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 = 0x0300, CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 = 0x0300,
CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443 = 0x0301,
CMD_READ_SRI512_TAG = 0x0303, CMD_READ_SRI512_TAG = 0x0303,
CMD_READ_SRIX4K_TAG = 0x0304, CMD_READ_SRIX4K_TAG = 0x0304,
CMD_READER_ISO_15693 = 0x0310, CMD_READER_ISO_15693 = 0x0310,
@ -76,9 +75,8 @@ local _commands = {
CMD_SIMULATE_HITAG = 0x0371, CMD_SIMULATE_HITAG = 0x0371,
CMD_READER_HITAG = 0x0372, CMD_READER_HITAG = 0x0372,
CMD_SIMULATE_TAG_HF_LISTEN = 0x0380, CMD_SIMULATE_TAG_ISO_14443B = 0x0381,
CMD_SIMULATE_TAG_ISO_14443 = 0x0381, CMD_SNOOP_ISO_14443B = 0x0382,
CMD_SNOOP_ISO_14443 = 0x0382,
CMD_SNOOP_ISO_14443a = 0x0383, CMD_SNOOP_ISO_14443a = 0x0383,
CMD_SIMULATE_TAG_ISO_14443a = 0x0384, CMD_SIMULATE_TAG_ISO_14443a = 0x0384,
CMD_READER_ISO_14443a = 0x0385, CMD_READER_ISO_14443a = 0x0385,
@ -135,9 +133,9 @@ local _commands = {
CMD_MIFARE_SNIFFER = 0x0630, CMD_MIFARE_SNIFFER = 0x0630,
--//ultralightC --//ultralightC
CMD_MIFAREUC_AUTH1 = 0x0724, CMD_MIFAREUC_AUTH = 0x0724,
CMD_MIFAREUC_AUTH2 = 0x0725, CMD_MIFAREUC_SETPWD = 0x0727,
CMD_MIFAREUC_READCARD = 0x0726, CMD_MIFAREU_SETUID = 0x0728,
--// mifare desfire --// mifare desfire
CMD_MIFARE_DESFIRE_READBL = 0x0728, CMD_MIFARE_DESFIRE_READBL = 0x0728,
@ -153,10 +151,10 @@ local _commands = {
local _reverse_lookup,k,v = {} local _reverse_lookup,k,v = {}
for k, v in pairs(_commands) do for k, v in pairs(_commands) do
_reverse_lookup[v] = k _reverse_lookup[v] = k
end end
_commands.tostring = function(command) _commands.tostring = function(command)
if(type(command) == 'number') then if(type(command) == 'number') then
return ("%s (%d)"):format(_reverse_lookup[command]or "ERROR UNDEFINED!", command) return ("%s (%d)"):format(_reverse_lookup[command]or "ERROR UNDEFINED!", command)
end end
@ -217,7 +215,6 @@ function Command:getBytes()
local data = self.data local data = self.data
local cmd = self.cmd local cmd = self.cmd
local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3 local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3
return bin.pack("LLLLH",cmd, arg1, arg2, arg3, data);
return bin.pack("LLLLH",cmd, arg1, arg2, arg3,data);
end end
return _commands return _commands

View file

@ -1,196 +1,377 @@
local _names = { local _names = {
--[[ --[[ decimal, hexadecimal, ccc, elements, group, name
--]] --]]
["0000"]="WHIRLWIND", {"0", "0000", "0030", "air", "regular", "Whirlwind"},
["0100"]="SONIC BOOM", --{"0", "0000", "0030", "air", "regular", "Elite Whirlwind"},
["0200"]="WARNADO", --{"0", "0000", "0030", "air", "regular", "Polar Whirlwind"},
["0300"]="LIGHTNINGROD", {"1", "0100", "0030", "air", "regular", "Sonic Boom"},
["0400"]="BASH", {"2", "0200", "0030", "air", "regular", "Warnado"},
["0500"]="TERRAFIN", {"3", "0300", "0030", "air", "regular", "Lightning Rod"},
["0600"]="DINORANG" , {"4", "0400", "0030", "earth", "regular", "Bash"},
["0700"]="LIGHTCORE PRISM BREAK", --{"4", "0400", "0030", "earth", "regular", "Birthday Bash"},
["0800"]="SUNBURN", {"5", "0500", "0030", "earth", "regular", "Terrafin"},
["0900"]="LIGHTCORE ERUPTOR", --{"5", "0500", "0030", "earth", "regular", "Elite Terrafin"},
["0A00"]="IGNITOR", {"6", "0600", "0030", "earth", "regular", "Dino Rang"},
["0B00"]="FLAMESLINGER", {"7", "0700", "0030", "earth", "regular", "Prism Break"}, --lightcore
["0C00"]="ZAP", {"8", "0800", "0030", "fire", "regular", "Sunburn"},
["0D00"]="WHAM SHELL", {"9", "0900", "0030", "fire", "regular", "Eruptor"}, --lightcore
["0E00"]="GILL GRUNT", --{"9", "0900", "0030", "fire", "regular", "Elite Eruptor"},
["0F00"]="SLAMBAM", --{"9", "0900", "0030", "fire", "regular", "Volcanic Eruptor"},
["1000"]="SPYRO", {"10", "0a00", "0030", "fire", "regular", "Ignitor"},
["1100"]="VOODOOD", {"11", "0b00", "0030", "fire", "regular", "Flameslinger"},
["1200"]="DOUBLE TROUBLE", --{"11", "0b00", "0030", "fire", "regular", "Cupid Flameslinger"},
["1300"]="TRIGGER HAPPY", {"12", "0c00", "0030", "water", "regular", "Zap"},
["1400"]="DROBOT", {"13", "0d00", "0030", "water", "regular", "Wham Shell"},
["1500"]="DRILLSERGEANT", {"14", "0e00", "0030", "water", "regular", "Gill Grunt"},
["1600"]="BOOMER", --{"14", "0e00", "0030", "water", "regular", "Elite Gill Grunt"},
["1700"]="WRECKING BALL", --{"14", "0e00", "0030", "water", "regular", "Tidal Wave Gill Grunt"},
["1800"]="CAMO", {"15", "0f00", "0030", "water", "regular", "Slam Bam"},
["1900"]="ZOOK", --{"15", "0f00", "0030", "water", "regular", "Surfer Slam Bam"},
["1A00"]="STEALTH ELF", {"16", "1000", "0030", "magic", "regular", "Spyro"},
["1B00"]="STUMP SMASH", {"17", "1100", "0030", "magic", "regular", "Voodood"},
["1D00"]="HEX", {"18", "1200", "0030", "magic", "regular", "Double Trouble"},
["1C00"]="DARK SPYRO", --{"18", "1200", "0030", "magic", "regular", "Royal Double Trouble"},
["1E00"]="CHOPCHOP", {"19", "1300", "0030", "tech", "regular", "Trigger Happy"},
["1F00"]="GHOST ROASTER", --{"19", "1300", "0030", "tech", "regular", "Elite Trigger Happy"},
["2000"]="CYNDER", --{"19", "1300", "0030", "tech", "regular", "Springtime Trigger Happy"},
--[[ {"20", "1400", "0030", "tech", "regular", "Drobot"},
GIANTS {"21", "1500", "0030", "tech", "regular", "Drill Sergeant"},
--]] {"22", "1600", "0030", "tech", "regular", "Boomer"},
["6400"]="GIANT JET-VAC", --{"22", "1600", "0030", "tech", "regular", "Lucky Boomer"},
["6500"]="GIANT SWARM", {"23", "1700", "0030", "magic", "regular", "Wrecking Ball"},
["6600"]="GIANT CRUSHER", --{"23", "1700", "0030", "magic", "regular", "Buddy Wrecking Ball"},
["6700"]="GIANT FLASHWING", {"24", "1800", "0030", "life", "regular", "Camo"},
["6800"]="GIANT HOTHEAD", {"25", "1900", "0030", "life", "regular", "Zook"},
["6900"]="GIANT HOTDOG", {"26", "1a00", "0030", "life", "regular", "Stealth Elf"},
["6A00"]="GIANT CHILL", --{"26", "1a00", "0030", "life", "regular", "Elite Stealth Elf"},
["6B00"]="GIANT THUMPBACK", --{"26", "1a00", "0528", "life", "regular", "Dark Stealth Elf"},
["6C00"]="GIANT POPFIZZ", {"26", "1a00", "0528", "life", "swapforce", "Ninja Stealth Elf"},
["6D00"]="GIANT NINJINI", {"27", "1b00", "0030", "life", "regular", "Stump Smash"},
["6E00"]="GIANT BOUNCER", {"27", "1b00", "0118", "life", "regular", "Stump Smash"},
["6F00"]="GIANT SPROCKET", --{"27", "1b00", "0030", "life", "regular", "Autumn Stump Smash"},
["7000"]="GIANT TREE REX", {"28", "1c00", "0030", "magic", "regular", "Dark Spyro"},
["7100"]="LIGHTCORE SHROOMBOOM", --{"28", "1c00", "0030", "magic", "regular", "Elite Spyro"},
["7200"]="GIANT EYEBROAWL", {"29", "1d00", "0030", "undead", "regular", "Hex"},
["7300"]="GIANT FRIGHTRIDER", --{"29", "1d00", "0030", "undead", "regular", "Hallows' Eve Hex"},
{"30", "1e00", "0030", "undead", "regular", "Chop Chop"},
--{"30", "1e00", "0030", "undead", "regular", "Elite Chop Chop"},
--{"30", "1e00", "0030", "undead", "regular", "Grill Master Chop Chop"},
{"31", "1f00", "0030", "undead", "regular", "Ghost Roaster"},
{"32", "2000", "0030", "undead", "regular", "Cynder"},
--{"32", "2000", "0030", "undead", "regular", "Skeletal Cynder"},
--[[ {"100", "6400", "0030", "air", "giant", "Jet Vac"},
ITEM --{"100", "6400", "0030", "air", "giant", "Full blast Jet Vac"},
--]] {"101", "6500", "0030", "air", "giant", "Swarm"},
["C800"]="ANVIL", {"102", "6600", "0030", "earth", "giant", "Crusher"},
["C900"]="SECRET STASH", {"103", "6700", "0030", "earth", "giant", "Flashwing"},
["CA00"]="REGENERATION", --{"103", "6700", "0030", "earth", "giant", "Jade Flashwing"},
["CD00"]="SHIELD", {"104", "6800", "0030", "fire", "giant", "Hot Head"},
["CB00"]="CROSSED SWORDS", {"105", "6900", "0030", "fire", "giant", "Hot Dog"},
["CC00"]="HOURGLASS", --{"105", "6900", "0030", "fire", "giant", "Molten Hot Dog"},
["CE00"]="SPEED BOOTS", {"106", "6a00", "0030", "water", "giant", "Chill"},
["CF00"]="SPARX", {"107", "6b00", "0030", "water", "giant", "Thumpback"},
["D000"]="CANNON", --{"107", "6b00", "0030", "water", "giant", "Admiral Thumpback"},
["D100"]="SCORPIONSTRIKER", {"108", "6c00", "0030", "magic", "giant", "Pop Fizz"},
--{"108", "6c00", "0030", "magic", "giant", "Hoppity Pop Fizz"},
{"108", "6c00", "023c", "magic", "giant", "Love Potion Pop Fizz"},
--{"108", "6c00", "0030", "magic", "giant", "Punch Pop Fizz"},
--{"108", "6c00", "0030", "magic", "giant", "Fizzy Frenzy Pop Fizz"},
{"109", "6d00", "0030", "magic", "giant", "Nin Jini"},
{"110", "6e00", "0030", "tech", "giant", "Bouncer"},
{"111", "6f00", "0030", "tech", "giant", "Sprocket"},
{"112", "7000", "0030", "life", "giant", "Tree Rex"},
--{"112", "7000", "0030", "life", "giant", "Gnarly Tree Rex"},
{"113", "7100", "0030", "life", "giant", "Shroomboom"},
--{"113", "7100", "0030", "life", "giant", "Sure shot Shroomboom"},
{"114", "7200", "0030", "undead", "giant", "Eye Broawl"},
{"115", "7300", "0030", "undead", "giant", "Fright Rider"},
--[[ {"200", "c800", "0030", "", "item", "Anvil Rain"},
ITEM TRAPS {"201", "c900", "0030", "", "item", "Platinum Treasure Chest"},
--]] {"202", "ca00", "0030", "", "item", "Healing Elixer"},
["D200"]="MAGIC TRAP", {"203", "cb00", "0030", "", "item", "Ghost Pirate Swords"},
["D300"]="WATER TRAP", {"204", "cc00", "0030", "", "item", "Time Twist Hourglass"},
["D400"]="AIR TRAP", {"205", "cd00", "0030", "", "item", "Sky Iron Shield"},
["D500"]="UNDEAD TRAP", {"206", "ce00", "0030", "", "item", "Winged Boots"},
["D600"]="TECH TRAP", {"207", "cf00", "0030", "", "item", "Sparx"},
["D700"]="FIRE TRAP", {"208", "d000", "0030", "", "item", "Cannon"},
["D800"]="EARTH TRAP", {"209", "d100", "0030", "", "item", "Scorpion Striker"},
["D900"]="LIFE TRAP",
["DA00"]="DARK TRAP",
["DB00"]="LIGHT TRAP",
["DC00"]="KAOS TRAP",
--[[ {"210", "d200", "0230", "magic", "trap", "Biter's Bane"},
ITEM {"210", "d200", "0830", "magic", "trap", "Sorcerous Skull"},
--]] -- legendary Sorcerous Skull?
["E600"]="HAND OF FATE", {"210", "d200", "0b30", "magic", "trap", "Axe Of Illusion"},
["E700"]="PIGGYBANK", {"210", "d200", "0e30", "magic", "trap", "Arcane Hourglass"},
["E800"]="ROCKET RAM", {"210", "d200", "1230", "magic", "trap", "Spell Slapper"},
["E900"]="TIKI SPEAKY", {"210", "d200", "1430", "magic", "trap", "Rune Rocket"},
{"211", "d300", "0130", "water", "trap", "Tidal Tiki"},
{"211", "d300", "0230", "water", "trap", "Wet Walter"},
{"211", "d300", "0630", "water", "trap", "Flood Flask"},
-- legendary flood flask?
{"211", "d300", "0730", "water", "trap", "Soaking Staff"},
{"211", "d300", "0b30", "water", "trap", "Aqua Axe"},
{"211", "d300", "1630", "water", "trap", "Frost Helm"},
{"212", "d400", "0330", "air", "trap", "Breezy Bird"},
{"212", "d400", "0630", "air", "trap", "Drafty Decanter"},
{"212", "d400", "0d30", "air", "trap", "Tempest Timer"},
{"212", "d400", "1030", "air", "trap", "Cloudy Cobra"},
{"212", "d400", "1130", "air", "trap", "Storm Warning"},
{"212", "d400", "1830", "air", "trap", "Cycone Saber"},
{"213", "d500", "0430", "undead", "trap", "Spirit Sphere"},
{"213", "d500", "0830", "undead", "trap", "Spectral Skull"},
{"213", "d500", "0b30", "undead", "trap", "Haunted Hatchet"},
{"213", "d500", "0c30", "undead", "trap", "Grim Gripper"},
{"213", "d500", "1030", "undead", "trap", "Spooky Snake"},
{"213", "d500", "1730", "undead", "trap", "Dream Piercer"},
{"214", "d600", "0030", "tech", "trap", "tech Totem"},
{"214", "d600", "0730", "tech", "trap", "Automatic Angel"},
{"214", "d600", "0930", "tech", "trap", "Factory Flower"},
{"214", "d600", "0c30", "tech", "trap", "Grabbing Gadget"},
{"214", "d600", "1630", "tech", "trap", "Makers Mana"},
{"214", "d600", "1a30", "tech", "trap", "Topsy techy"},
{"215", "d700", "0530", "fire", "trap", "Eternal Flame"},
{"215", "d700", "0930", "fire", "trap", "fire Flower"},
{"215", "d700", "1130", "fire", "trap", "Scorching Stopper"},
{"215", "d700", "1230", "fire", "trap", "Searing Spinner"},
{"215", "d700", "1730", "fire", "trap", "Spark Spear"},
{"215", "d700", "1b30", "fire", "trap", "Blazing Belch"},
{"216", "d800", "0030", "earth", "trap", "Banded Boulder"},
{"216", "d800", "0330", "earth", "trap", "Rock Hawk"},
{"216", "d800", "0a30", "earth", "trap", "Slag Hammer"},
{"216", "d800", "0e30", "earth", "trap", "Dust Of Time"},
{"216", "d800", "1330", "earth", "trap", "Spinning Sandstorm"},
{"216", "d800", "1a30", "earth", "trap", "Rubble Trouble"},
{"217", "d900", "0330", "life", "trap", "Oak Eagle"},
{"217", "d900", "0530", "life", "trap", "Emerald Energy"},
{"217", "d900", "0a30", "life", "trap", "Weed Whacker"},
{"217", "d900", "1030", "life", "trap", "Seed Serpent"},
{"217", "d900", "1830", "life", "trap", "Jade Blade"},
{"217", "d900", "1b30", "life", "trap", "Shrub Shrieker"},
{"218", "da00", "0030", "dark", "trap", "dark Dagger"},
{"218", "da00", "1430", "dark", "trap", "Shadow Spider"},
{"218", "da00", "1a30", "dark", "trap", "Ghastly Grimace"},
{"219", "db00", "0030", "light", "trap", "Shining Ship"},
{"219", "db00", "0f30", "light", "trap", "Heavenly Hawk"},
{"219", "db00", "1b30", "light", "trap", "Beam Scream"},
{"220", "dc00", "3030", "kaos", "trap", "Kaos trap!"},
--{"220", "dc00", "3130", "kaos", "trap", "Ultimate Kaos trap!"}, ?
--[[ {"230", "e600", "0030", "none", "item", "Hand Of Fate"},
EXPANSION {"231", "e700", "0030", "none", "item", "Piggy Bank"},
--]] {"232", "e800", "0030", "none", "item", "Rocket Ram"},
["012C"]="DRAGONS PEAK", {"233", "e900", "0030", "none", "item", "Tiki Speaky"},
["012D"]="EMPIRE OF ICE",
["012E"]="PIRATE SEAS", {"300", "2c01", "0030", "none", "location", "Dragons Peak"},
["012F"]="DARKLIGHT CRYPT", {"301", "2d01", "0030", "none", "location", "Empire Of Ice"},
["0130"]="VOLCANIC VAULT", {"302", "2e01", "0030", "none", "location", "Pirate Seas"},
["0131"]="MIRROR OF MYSTERY", {"303", "2f01", "0030", "none", "location", "darklight Crypt"},
["0132"]="NIGHTMARE EXPRESS", {"304", "3001", "0030", "none", "location", "Volcanic Vault"},
["0133"]="SUNSCRAPER SPIRE", {"305", "3101", "0030", "none", "location", "Mirror Of Mystery"},
["0134"]="MIDNIGHT MUSEUM", {"306", "3201", "0030", "none", "location", "Nightmare Express"},
{"307", "3301", "0030", "light", "location", "Sunscraper Spire"},
{"308", "3401", "0030", "dark", "location", "Midnight Museum"},
{"404", "9401", "0030", "earth", "legendary","Bash"},
{"416", "a001", "0030", "magic", "legendary", "Spyro"},
--{"", "", "0030", "magic", "legendary", "Deja Vu"},
{"419", "a301", "0030", "tech", "legendary", "Trigger Happy"},
--{"", "", "0030", "tech", "legendary", "bouncer"},
--{"", "", "0030", "tech", "legendary", "jawbreaker"},
{"430", "ae01", "0030", "undead", "legendary", "Chop Chop"},
--{"", "", "0030", "undead", "legendary", "grim creeper"},
--{"", "", "0030", "undead", "legendary", "night shift"},
--[[ --{"", "", "0030", "air", "legendary", "blades"},
LEGENDARY --{"", "", "0030", "air", "legendary", "jet vac"},
--]] --{"", "", "0030", "air", "legendary", "Free Ranger"},
["0194"]="LEGENDARY BASH", --{"", "", "0030", "life", "legendary", "stealth elf"},
["01A0"]="LEGENDARY SPYRO", --{"", "", "0030", "life", "legendary", "Bushwhack"},
["01A3"]="LEGENDARY TRIGGER HAPPY", --{"", "", "0030", "fire", "legendary", "ignitor"},
["01AE"]="LEGENDARY CHOPCHOP", --{"", "", "0030", "water", "legendary", "slam bam"},
--{"", "", "0030", "water", "legendary", "chill"},
--{"", "", "0030", "", "legendary", "zoo lou"},
--[[ {"450", "c201", "0030", "air", "trapmaster", "Gusto"},
TRAPTEAM --{"450", "c201", "0234", "air", "trapmaster", "Special Gusto"},
--]] {"451", "c301", "0030", "air", "trapmaster", "Thunderbolt"},
["01C2"]="TRAPTEAM GUSTO", --{"451", "c301", "0234", "air", "trapmaster", "Special Thunderbolt"},
["01C3"]="TRAPTEAM THUNDERBOLT", {"452", "c401", "0030", "air", "regular", "Fling Kong"},
["01C4"]="TRAPTEAM FLING KONG", {"453", "c501", "0030", "air", "regular", "Blades"},
["01C5"]="TRAPTEAM BLADES", {"454", "c601", "0030", "earth", "trapmaster", "Wallop"},
["01C6"]="TRAPTEAM WALLOP", --{"454", "c601", "0234", "earth", "trapmaster", "Special Wallop"},
["01C7"]="TRAPTEAM HEAD RUSH", {"455", "c701", "0030", "earth", "trapmaster", "Head Rush"},
["01C8"]="TRAPTEAM FIST BUMP", {"455", "c701", "0234", "earth", "trapmaster", "Nitro Head Rush"},
["01C9"]="TRAPTEAM ROCKY ROLL", {"456", "c801", "0030", "earth", "regular", "Fist Bump"},
["01CA"]="TRAPTEAM WILDFIRE", {"457", "c901", "0030", "earth", "regular", "Rocky Roll"},
["01CB"]="TRAPTEAM KA BOOM", --{"457", "c901", "0030", "earth", "regular", "Rocky Egg Roll"},
["01CC"]="TRAPTEAM TRAIL BLAZER", {"458", "ca01", "0030", "fire", "trapmaster", "Wildfire"},
["01CD"]="TRAPTEAM TORCH", {"458", "ca01", "0234", "fire", "trapmaster", "Dark Wildfire"},
["01CE"]="TRAPTEAM SNAP SHOT", {"459", "cb01", "0030", "fire", "trapmaster", "Ka Boom"},
["01CF"]="TRAPTEAM LOB STAR", --{"459", "cb01", "0234", "fire", "trapmaster", "Special Ka Boom"},
["01D0"]="TRAPTEAM FLIP WRECK", {"460", "cc01", "0030", "fire", "regular", "Trail Blazer"},
["01D1"]="TRAPTEAM ECHO", {"461", "cd01", "0030", "fire", "regular", "Torch"},
["01D2"]="TRAPTEAM BLASTERMIND", {"462", "ce01", "0030", "water", "trapmaster", "Snap Shot"},
["01D3"]="TRAPTEAM ENIGMA", {"462", "ce01", "0234", "water", "trapmaster", "Dark Snap Shot"},
["01D4"]="TRAPTEAM DEJA VU", {"462", "6c00", "023c", "water", "trapmaster", "Instant Snap Shot"},
["01D5"]="TRAPTEAM COBRA CADABRA", --, "water", "trapmaster", "Merry Snap Shot"},
["01D6"]="TRAPTEAM JAWBREAKER", {"463", "cf01", "0030", "water", "trapmaster", "Lob Star"},
["01D7"]="TRAPTEAM GEARSHIFT", {"463", "cf01", "0234", "water", "trapmaster", "Winterfest Lob Star"},
["01D8"]="TRAPTEAM CHOPPER", {"464", "d001", "0030", "water", "regular", "Flip Wreck"},
["01D9"]="TRAPTEAM TREAD HEAD", {"465", "d101", "0030", "water", "regular", "Echo"},
["01DA"]="TRAPTEAM BUSHWHACK", {"466", "d201", "0030", "magic", "trapmaster", "Blastermind"},
["01DB"]="TRAPTEAM TUFF LUCK", --{"466", "d201", "0234", "magic", "trapmaster", "Special Blastermind"},
["01DC"]="TRAPTEAM FOOD FIGHT", {"467", "d301", "0030", "magic", "trapmaster", "Enigma"},
["01DD"]="TRAPTEAM HIGH FIVE", --{"467", "d301", "0234", "magic", "trapmaster", "Special Enigma"},
["01DE"]="TRAPTEAM NITRO KRYPT KING", {"468", "d401", "0030", "magic", "regular", "Deja Vu"},
["01DF"]="TRAPTEAM SHORT CUT", {"469", "d501", "0030", "magic", "regular", "Cobra Cadabra"},
["01E0"]="TRAPTEAM BAT SPIN", --{"469", "d501", "0030", "magic", "regular", "Charming Cobra Cadabra"},
["01E1"]="TRAPTEAM FUNNY BONE", --{"469", "d501", "0030", "magic", "regular", "King Cobra Cadabra"},
["01E2"]="TRAPTEAM KNIGHT LIGHT", {"470", "d601", "0030", "tech", "trapmaster", "Jawbreaker"},
["01E3"]="TRAPTEAM SPOTLIGHT", --{"470", "d601", "0234", "tech", "trapmaster", "Special Jawbreaker"},
["01E4"]="TRAPTEAM KNIGHT MARE", --{"470", "d601", "0234", "tech", "trapmaster", "Knockout Jawbreaker"},
["01E5"]="TRAPTEAM BLACKOUT", {"471", "d701", "0030", "tech", "trapmaster", "Gearshift"},
--{"471", "d701", "0234", "tech", "trapmaster", "Special Gearshift"},
{"472", "d801", "0030", "tech", "regular", "Chopper"},
{"473", "d901", "0030", "tech", "regular", "Tread Head"},
{"474", "da01", "0030", "life", "trapmaster", "Bushwhack"},
--{"474", "da01", "0234", "life", "trapmaster", "Special Bushwhack"},
{"475", "db01", "0030", "life", "trapmaster", "Tuff Luck"},
--{"475", "db01", "0234", "life", "trapmaster", "Special Tuff Luck"},
{"476", "dc01", "0030", "life", "regular", "Food Fight"},
{"476", "dc01", "0612", "life", "regular", "LightCore Food Fight"},
--{"476", "dc01", "0030", "life", "regular", "Dark Food Fight"},
--{"476", "dc01", "0030", "life", "regular", "Frosted Food Fight"},
--{"476", "dc01", "0030", "life", "regular", "Instant Food Fight"},
{"477", "dd01", "0030", "life", "regular", "High Five"},
{"478", "de01", "0030", "undead", "trapmaster", "Krypt King"},
{"478", "de01", "0234", "undead", "trapmaster", "Nitro Krypt King"},
{"479", "df01", "0030", "undead", "trapmaster", "Short Cut"},
--{"479", "df01", "0234", "undead", "trapmaster", "Special Short Cut"},
{"480", "e001", "0030", "undead", "regular", "Bat Spin"},
{"481", "e101", "0030", "undead", "regular", "Funny Bone"},
{"481", "e101", "0612", "undead", "regular", "LightCore Funny Bone"},
--{"481", "e101", "0030", "undead", "regular", "Fortune Funny Bone"},
{"482", "e201", "0030", "light", "trapmaster", "Knight light"},
--{"482", "e201", "0234", "light", "trapmaster", "Special Knight light"},
{"483", "e301", "0030", "light", "regular", "Spotlight"},
--{"483", "e301", "0234", "light", "regular", "Special Spotlight"},
{"484", "e401", "0030", "dark", "trapmaster", "Knight Mare"},
--{"484", "e401", "0234", "dark", "trapmaster", "Special Knight Mare"},
{"485", "e501", "0030", "dark", "regular", "Blackout"},
--{"485", "e501", "0234", "dark", "regular", "Special Blackout"},
--[[ -- MINI's
PET {"502", "f601", "0030", "earth", "mini", "Bop"},
--]] {"505", "f901", "0030", "earth", "mini", "Terrabite"},
["01F6"]="PET BOP",
["01F7"]="PET SPRY", {"506", "fa01", "0030", "air", "mini", "Breeze"},
["01F8"]="PET HIJINX", {"508", "fc01", "0030", "air", "mini", "Pet Vac"},
["01F9"]="PET TERRAFIN", --{"508", "fc01", "0030", "air", "mini", "Power Punch Pet Vac"},
["01FA"]="PET BREEZE",
["01FB"]="PET WEERUPTOR", {"507", "fb01", "0030", "fire", "mini", "Weeruptor"},
["01FC"]="PET PET VAC", --{"507", "fb01", "0030", "fire", "mini", "Eggsellent Weeruptor"},
["01FD"]="PET SMALL FRY", {"509", "fd01", "0030", "fire", "mini", "Small Fry"},
["01FE"]="PET DROBIT",
["0202"]="PET GILL GRUNT", {"510", "fe01", "0030", "tech", "mini", "Drobit"},
["0207"]="PET TRIGGER SNAPPY", {"519", "0702", "0030", "tech", "mini", "Trigger Snappy"},
["020E"]="PET WHISPER ELF",
["021C"]="PET BARKLEY", {"526", "0e02", "0030", "life", "mini", "Whisper Elf"},
["021D"]="PET THUMPLING", {"540", "1c02", "0030", "life", "mini", "Barkley"},
["021E"]="PET MINI JINI", --{"540", "1c02", "0030", "life", "mini", "Gnarly Barkley"},
["021F"]="PET EYE SMALL",
{"541", "1d02", "0030", "water", "mini", "Thumpling"},
{"514", "0202", "0030", "water", "mini", "Gill Runt"},
{"542", "1e02", "0030", "magic", "mini", "mini Jini"},
{"503", "f701", "0030", "magic", "mini", "Spry"},
{"504", "f801", "0030", "undead", "mini", "Hijinx"},
{"543", "1f02", "0030", "undead", "mini", "Eye Small"},
{"3000", "b80b", "0030", "air", "mini", "Scratch", "SWAPFORCE"},
{"3001", "b90b", "0030", "air", "SWAPFORCE", "Pop Thorn"},
--{"3001", "b90b", "0030", "air", "SWAPFORCE", "Buttered Pop Thorn"},
{"3002", "ba0b", "0030", "earth", "SWAPFORCE", "Slobber Tooth"},
--{"3002", "ba0b", "0030", "earth", "SWAPFORCE", "Dark Slobber Tooth"},
--{"3002", "ba0b", "0030", "earth", "SWAPFORCE", "Sundae Slobber Tooth"},
{"3003", "bb0b", "0030", "earth", "SWAPFORCE", "Scorp"},
{"3004", "bc0b", "0030", "fire", "SWAPFORCE", "Fryno"},
{"3004", "bc0b", "0138", "fire", "SWAPFORCE", "Hog Wild Fryno"},
--{"3004", "bc0b", "0138", "fire", "SWAPFORCE", "Flip flop Fryno"},
{"3005", "bd0b", "0030", "fire", "SWAPFORCE", "Smolderdash"},
{"3006", "be0b", "0030", "life", "SWAPFORCE", "Bumble Blast"},
--{"3006", "be0b", "0030", "life", "SWAPFORCE", "Jolly Bumble Blast"},
{"3007", "bf0b", "0030", "life", "SWAPFORCE", "Zoo Lou"},
{"3008", "c00b", "0030", "magic", "SWAPFORCE", "Dune Bug"},
{"3009", "c10b", "0030", "magic", "SWAPFORCE", "Star Strike"},
--{"3009", "c10b", "0030", "magic", "SWAPFORCE", "Enchanted Star Strike"},
--{"3009", "c10b", "0030", "magic", "SWAPFORCE", "Mystic Star Strike"},
{"3010", "c20b", "0030", "tech", "SWAPFORCE", "Countdown"},
--{"3010", "c20b", "0030", "tech", "SWAPFORCE", "Kickoff Countdown"},
--{"3010", "c20b", "0030", "tech", "SWAPFORCE", "New Year's Countdown"},
{"3011", "c30b", "0030", "tech", "SWAPFORCE", "Wind Up"},
{"3012", "c40b", "0030", "undead", "SWAPFORCE", "Roller Brawl"},
--{"3012", "c40b", "0030", "undead", "SWAPFORCE", "Snowler Roller Brawl"},
{"3013", "c50b", "0030", "undead", "SWAPFORCE", "Grim Creeper"},
{"3014", "c60b", "0030", "water", "SWAPFORCE", "Rip Tide"},
{"3015", "c70b", "0030", "water", "SWAPFORCE", "Punk Shock"},
--{"", "", "0030", "water", "SWAPFORCE", "Hoot Loop"},
--{"", "", "0030", "water", "SWAPFORCE", "Trap Shadow"},
--{"", "", "0030", "water", "SWAPFORCE", "Wash Buckler"},
--{"", "", "0030", "water", "SWAPFORCE", "Freeze Blade"},
--{"", "", "0030", "fire", "SWAPFORCE", "Magna Charge"},
--{"", "", "0030", "fire", "SWAPFORCE", "Spy Rise"},
--{"", "", "0030", "fire", "SWAPFORCE", "Doom Stone"},
--{"", "", "0030", "fire", "SWAPFORCE", "Rubble Rouser"},
--{"", "", "0030", "fire", "SWAPFORCE", "Blast Zone"}
--{"", "", "0030", "fire", "SWAPFORCE", "Fire Kraken"},
--{"", "", "0030", "fire", "SWAPFORCE", "Rattle Shake"},
--{"", "", "0030", "fire", "SWAPFORCE", "Night Shift"},
--{"", "", "0030", "life", "SWAPFORCE", "Stink Bomb"},
--{"", "", "0030", "life", "SWAPFORCE", "Grilla Drilla"},
--{"", "", "0030", "air", "SWAPFORCE", "Free Ranger"},
--{"", "", "0030", "air", "SWAPFORCE", "Boom Jet"},
--[[
SWAP FORCE
--]]
["0BB8"]="SWAPFORCE SCRATCH",
["0BB9"]="SWAPFORCE POPTHORN",
["0BBA"]="SWAPFORCE SLOBBER TOOTH",
["0BBB"]="SWAPFORCE SCORP",
["0BBC"]="SWAPFORCE HOG WILD FRYNO",
["0BBD"]="SWAPFORCE SMOLDER DASH",
["0BBE"]="SWAPFORCE BUMBLE BLAST",
["0BBF"]="SWAPFORCE ZOO LOU",
["0BC0"]="SWAPFORCE DUNE BUG",
["0BC1"]="SWAPFORCE STAR STRIKE",
["0BC2"]="SWAPFORCE COUNTDOWN",
["0BC3"]="SWAPFORCE WIND UP",
["0BC4"]="SWAPFORCE ROLLER BRAWL",
["0BC5"]="SWAPFORCE GRIM CREEPER",
["0BC6"]="SWAPFORCE RIP TIDE",
["0BC7"]="SWAPFORCE PUNK SHOCK",
} }
return _names
local function find( main, sub)
main = main:lower()
sub = sub:lower()
for k, v in pairs(_names) do
if ( v[2]:lower() == main and v[3]:lower() == sub) then
return v
end
end
return nil
end
local function list()
print ("Type\tSub\tElement\tGame Name")
print (string.rep('=', 54))
for k, v in pairs(_names) do
print(("%s\t%s\t%s\t%-9s\t%s"):format(v[2],v[3],v[4], v[5], v[6] ))
end
end
return {
Find = find,
List = list,
}

View file

@ -192,7 +192,7 @@ end
return { return {
convert_bin_to_html = convert_bin_to_html, convert_bin_to_html = convert_bin_to_html,
convert_eml_to_html = convert_eml_to_html, convert_eml_to_html = convert_eml_to_html,
convert_eml_to_bin = convert_eml_to_bin, convert_eml_to_bin = convert_eml_to_bin,
SaveAsBinary = save_BIN, SaveAsBinary = save_BIN,
SaveAsText = save_TEXT, SaveAsText = save_TEXT,
} }

384
client/lualibs/md5.lua Normal file
View file

@ -0,0 +1,384 @@
local md5 = {
_VERSION = "md5.lua 0.5.0",
_DESCRIPTION = "MD5 computation in Lua (5.1)",
_URL = "https://github.com/kikito/md5.lua",
_LICENSE = [[
MIT LICENSE
Copyright (c) 2013 Enrique García Cota + Adam Baldwin + hanzao + Equi 4 Software
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.
]]
}
-- bit lib implementions
local floor, abs, max = math.floor, math.abs, math.max
local char, byte, format, rep, sub =
string.char, string.byte, string.format, string.rep, string.sub
local function check_int(n)
-- checking not float
if(n - floor(n) > 0) then
error("trying to use bitwise operation on non-integer!")
end
end
local function tbl2number(tbl)
local n = #tbl
local rslt = 0
local power = 1
for i = 1, n do
rslt = rslt + tbl[i]*power
power = power*2
end
return rslt
end
local function expand(tbl_m, tbl_n)
local big = {}
local small = {}
if(#tbl_m > #tbl_n) then
big = tbl_m
small = tbl_n
else
big = tbl_n
small = tbl_m
end
-- expand small
for i = #small + 1, #big do
small[i] = 0
end
end
local to_bits -- needs to be declared before bit_not
local function bit_not(n)
local tbl = to_bits(n)
local size = max(#tbl, 32)
for i = 1, size do
if(tbl[i] == 1) then
tbl[i] = 0
else
tbl[i] = 1
end
end
return tbl2number(tbl)
end
-- defined as local above
to_bits = function (n)
check_int(n)
if(n < 0) then
-- negative
return to_bits(bit_not(abs(n)) + 1)
end
-- to bits table
local tbl = {}
local cnt = 1
while (n > 0) do
local last = math.fmod(n,2)
if(last == 1) then
tbl[cnt] = 1
else
tbl[cnt] = 0
end
n = (n-last)/2
cnt = cnt + 1
end
return tbl
end
local function bit_or(m, n)
local tbl_m = to_bits(m)
local tbl_n = to_bits(n)
expand(tbl_m, tbl_n)
local tbl = {}
local rslt = max(#tbl_m, #tbl_n)
for i = 1, rslt do
if(tbl_m[i]== 0 and tbl_n[i] == 0) then
tbl[i] = 0
else
tbl[i] = 1
end
end
return tbl2number(tbl)
end
local function bit_and(m, n)
local tbl_m = to_bits(m)
local tbl_n = to_bits(n)
expand(tbl_m, tbl_n)
local tbl = {}
local rslt = max(#tbl_m, #tbl_n)
for i = 1, rslt do
if(tbl_m[i]== 0 or tbl_n[i] == 0) then
tbl[i] = 0
else
tbl[i] = 1
end
end
return tbl2number(tbl)
end
local function bit_xor(m, n)
local tbl_m = to_bits(m)
local tbl_n = to_bits(n)
expand(tbl_m, tbl_n)
local tbl = {}
local rslt = max(#tbl_m, #tbl_n)
for i = 1, rslt do
if(tbl_m[i] ~= tbl_n[i]) then
tbl[i] = 1
else
tbl[i] = 0
end
end
return tbl2number(tbl)
end
local function bit_rshift(n, bits)
check_int(n)
local high_bit = 0
if(n < 0) then
-- negative
n = bit_not(abs(n)) + 1
high_bit = 2147483648 -- 0x80000000
end
for i=1, bits do
n = n/2
n = bit_or(floor(n), high_bit)
end
return floor(n)
end
local function bit_lshift(n, bits)
check_int(n)
if(n < 0) then
-- negative
n = bit_not(abs(n)) + 1
end
for i=1, bits do
n = n*2
end
return bit_and(n, 4294967295) -- 0xFFFFFFFF
end
-- convert little-endian 32-bit int to a 4-char string
local function lei2str(i)
local f=function (s) return char( bit_and( bit_rshift(i, s), 255)) end
return f(0)..f(8)..f(16)..f(24)
end
-- convert raw string to big-endian int
local function str2bei(s)
local v=0
for i=1, #s do
v = v * 256 + byte(s, i)
end
return v
end
-- convert raw string to little-endian int
local function str2lei(s)
local v=0
for i = #s,1,-1 do
v = v*256 + byte(s, i)
end
return v
end
-- cut up a string in little-endian ints of given size
local function cut_le_str(s,...)
local o, r = 1, {}
local args = {...}
for i=1, #args do
table.insert(r, str2lei(sub(s, o, o + args[i] - 1)))
o = o + args[i]
end
return r
end
local swap = function (w) return str2bei(lei2str(w)) end
local function hex2binaryaux(hexval)
return char(tonumber(hexval, 16))
end
local function hex2binary(hex)
local result, _ = hex:gsub('..', hex2binaryaux)
return result
end
-- An MD5 mplementation in Lua, requires bitlib (hacked to use LuaBit from above, ugh)
-- 10/02/2001 jcw@equi4.com
local FF = 0xffffffff
local CONSTS = {
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476
}
local f=function (x,y,z) return bit_or(bit_and(x,y),bit_and(-x-1,z)) end
local g=function (x,y,z) return bit_or(bit_and(x,z),bit_and(y,-z-1)) end
local h=function (x,y,z) return bit_xor(x,bit_xor(y,z)) end
local i=function (x,y,z) return bit_xor(y,bit_or(x,-z-1)) end
local z=function (f,a,b,c,d,x,s,ac)
a=bit_and(a+f(b,c,d)+x+ac,FF)
-- be *very* careful that left shift does not cause rounding!
return bit_or(bit_lshift(bit_and(a,bit_rshift(FF,s)),s),bit_rshift(a,32-s))+b
end
local function transform(A,B,C,D,X)
local a,b,c,d=A,B,C,D
local t=CONSTS
a=z(f,a,b,c,d,X[ 0], 7,t[ 1])
d=z(f,d,a,b,c,X[ 1],12,t[ 2])
c=z(f,c,d,a,b,X[ 2],17,t[ 3])
b=z(f,b,c,d,a,X[ 3],22,t[ 4])
a=z(f,a,b,c,d,X[ 4], 7,t[ 5])
d=z(f,d,a,b,c,X[ 5],12,t[ 6])
c=z(f,c,d,a,b,X[ 6],17,t[ 7])
b=z(f,b,c,d,a,X[ 7],22,t[ 8])
a=z(f,a,b,c,d,X[ 8], 7,t[ 9])
d=z(f,d,a,b,c,X[ 9],12,t[10])
c=z(f,c,d,a,b,X[10],17,t[11])
b=z(f,b,c,d,a,X[11],22,t[12])
a=z(f,a,b,c,d,X[12], 7,t[13])
d=z(f,d,a,b,c,X[13],12,t[14])
c=z(f,c,d,a,b,X[14],17,t[15])
b=z(f,b,c,d,a,X[15],22,t[16])
a=z(g,a,b,c,d,X[ 1], 5,t[17])
d=z(g,d,a,b,c,X[ 6], 9,t[18])
c=z(g,c,d,a,b,X[11],14,t[19])
b=z(g,b,c,d,a,X[ 0],20,t[20])
a=z(g,a,b,c,d,X[ 5], 5,t[21])
d=z(g,d,a,b,c,X[10], 9,t[22])
c=z(g,c,d,a,b,X[15],14,t[23])
b=z(g,b,c,d,a,X[ 4],20,t[24])
a=z(g,a,b,c,d,X[ 9], 5,t[25])
d=z(g,d,a,b,c,X[14], 9,t[26])
c=z(g,c,d,a,b,X[ 3],14,t[27])
b=z(g,b,c,d,a,X[ 8],20,t[28])
a=z(g,a,b,c,d,X[13], 5,t[29])
d=z(g,d,a,b,c,X[ 2], 9,t[30])
c=z(g,c,d,a,b,X[ 7],14,t[31])
b=z(g,b,c,d,a,X[12],20,t[32])
a=z(h,a,b,c,d,X[ 5], 4,t[33])
d=z(h,d,a,b,c,X[ 8],11,t[34])
c=z(h,c,d,a,b,X[11],16,t[35])
b=z(h,b,c,d,a,X[14],23,t[36])
a=z(h,a,b,c,d,X[ 1], 4,t[37])
d=z(h,d,a,b,c,X[ 4],11,t[38])
c=z(h,c,d,a,b,X[ 7],16,t[39])
b=z(h,b,c,d,a,X[10],23,t[40])
a=z(h,a,b,c,d,X[13], 4,t[41])
d=z(h,d,a,b,c,X[ 0],11,t[42])
c=z(h,c,d,a,b,X[ 3],16,t[43])
b=z(h,b,c,d,a,X[ 6],23,t[44])
a=z(h,a,b,c,d,X[ 9], 4,t[45])
d=z(h,d,a,b,c,X[12],11,t[46])
c=z(h,c,d,a,b,X[15],16,t[47])
b=z(h,b,c,d,a,X[ 2],23,t[48])
a=z(i,a,b,c,d,X[ 0], 6,t[49])
d=z(i,d,a,b,c,X[ 7],10,t[50])
c=z(i,c,d,a,b,X[14],15,t[51])
b=z(i,b,c,d,a,X[ 5],21,t[52])
a=z(i,a,b,c,d,X[12], 6,t[53])
d=z(i,d,a,b,c,X[ 3],10,t[54])
c=z(i,c,d,a,b,X[10],15,t[55])
b=z(i,b,c,d,a,X[ 1],21,t[56])
a=z(i,a,b,c,d,X[ 8], 6,t[57])
d=z(i,d,a,b,c,X[15],10,t[58])
c=z(i,c,d,a,b,X[ 6],15,t[59])
b=z(i,b,c,d,a,X[13],21,t[60])
a=z(i,a,b,c,d,X[ 4], 6,t[61])
d=z(i,d,a,b,c,X[11],10,t[62])
c=z(i,c,d,a,b,X[ 2],15,t[63])
b=z(i,b,c,d,a,X[ 9],21,t[64])
return A+a,B+b,C+c,D+d
end
----------------------------------------------------------------
function md5.sumhexa(s)
local msgLen = #s
local padLen = 56 - msgLen % 64
if msgLen % 64 > 56 then padLen = padLen + 64 end
if padLen == 0 then padLen = 64 end
s = s .. char(128) .. rep(char(0),padLen-1) .. lei2str(8*msgLen) .. lei2str(0)
assert(#s % 64 == 0)
local t = CONSTS
local a,b,c,d = t[65],t[66],t[67],t[68]
for i=1,#s,64 do
local X = cut_le_str(sub(s,i,i+63),4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4)
assert(#X == 16)
X[0] = table.remove(X,1) -- zero based!
a,b,c,d = transform(a,b,c,d,X)
end
return format("%08x%08x%08x%08x",swap(a),swap(b),swap(c),swap(d))
end
function md5.sum(s)
return hex2binary(md5.sumhexa(s))
end
return md5

View file

@ -2,6 +2,7 @@
local _keys = { local _keys = {
--[[ --[[
These keys are from the pm3 c-codebase. These keys are from the pm3 c-codebase.
@ -157,9 +158,30 @@ local _keys = {
'9de89e070277', '9de89e070277',
'eff603e1efe9', 'eff603e1efe9',
'644672bd4afe', '644672bd4afe',
'b5ff67cba951', 'b5ff67cba951',
}
--[[
hotel system cards,
http://www.proxmark.org/forum/viewtopic.php?id=2430
--]]
'44ab09010845',
'85fed980ea5a',
--[[
VIGIK1
--]]
'314B49474956',
'564c505f4d41',
--[[
BCARD keyB
--]]
'f4a9ef2afc6d',
--[[
--]]
'a9f953def0a3',
}
--- ---
-- The keys above have just been pasted in, for completeness sake. They contain duplicates. -- The keys above have just been pasted in, for completeness sake. They contain duplicates.

View file

@ -0,0 +1,94 @@
--[[
This is an experimental lib.
--]]
local utils = require('utils')
-- LOOKUP Tables
local perm = {}
perm [1]= { 0x0, 0x1, 0x3, 0x2, 0x7, 0x6, 0x4, 0x5, 0xF, 0xE, 0xC, 0xD, 0x8, 0x9, 0xB, 0xA }
perm [2]= { 0x1, 0x0, 0x2, 0x3, 0x6, 0x7, 0x5, 0x4, 0xE, 0xF, 0xD, 0xC, 0x9, 0x8, 0xA, 0xB }
perm [3]= { 0x2, 0x3, 0x1, 0x0, 0x5, 0x4, 0x6, 0x7, 0xD, 0xC, 0xE, 0xF, 0xA, 0xB, 0x9, 0x8 }
perm [4]= { 0x3, 0x2, 0x0, 0x1, 0x4, 0x5, 0x7, 0x6, 0xC, 0xD, 0xF, 0xE, 0xB, 0xA, 0x8, 0x9 }
perm [5]= { 0x4, 0x5, 0x7, 0x6, 0x3, 0x2, 0x0, 0x1, 0xB, 0xA, 0x8, 0x9, 0xC, 0xD, 0xF, 0xE }
perm [6]= { 0x5, 0x4, 0x6, 0x7, 0x2, 0x3, 0x1, 0x0, 0xA, 0xB, 0x9, 0x8, 0xD, 0xC, 0xE, 0xF }
perm [7]= { 0x6, 0x7, 0x5, 0x4, 0x1, 0x0, 0x2, 0x3, 0x9, 0x8, 0xA, 0xB, 0xE, 0xF, 0xD, 0xC }
perm [8]= { 0x7, 0x6, 0x4, 0x5, 0x0, 0x1, 0x3, 0x2, 0x8, 0x9, 0xB, 0xA, 0xF, 0xE, 0xC, 0xD }
perm [9]= { 0x8, 0x9, 0xB, 0xA, 0xF, 0xE, 0xC, 0xD, 0x7, 0x6, 0x4, 0x5, 0x0, 0x1, 0x3, 0x2 }
perm [10]= { 0x9, 0x8, 0xA, 0xB, 0xE, 0xF, 0xD, 0xC, 0x6, 0x7, 0x5, 0x4, 0x1, 0x0, 0x2, 0x3 }
perm [11]= { 0xA, 0xB, 0x9, 0x8, 0xD, 0xC, 0xE, 0xF, 0x5, 0x4, 0x6, 0x7, 0x2, 0x3, 0x1, 0x0 }
perm [12]= { 0xB, 0xA, 0x8, 0x9, 0xC, 0xD, 0xF, 0xE, 0x4, 0x5, 0x7, 0x6, 0x3, 0x2, 0x0, 0x1 }
perm [13]= { 0xC, 0xD, 0xF, 0xE, 0xB, 0xA, 0x8, 0x9, 0x3, 0x2, 0x0, 0x1, 0x4, 0x5, 0x7, 0x6 }
perm [14]= { 0xD, 0xC, 0xE, 0xF, 0xA, 0xB, 0x9, 0x8, 0x2, 0x3, 0x1, 0x0, 0x5, 0x4, 0x6, 0x7 }
perm [15]= { 0xE, 0xF, 0xD, 0xC, 0x9, 0x8, 0xA, 0xB, 0x1, 0x0, 0x2, 0x3, 0x6, 0x7, 0x5, 0x4 }
perm [16]= { 0xF, 0xE, 0xC, 0xD, 0x8, 0x9, 0xB, 0xA, 0x0, 0x1, 0x3, 0x2, 0x7, 0x6, 0x4, 0x5 }
local shifts = {}
shifts[1]= { 0x4, 0x5, 0x7, 0x6, 0x3, 0x2, 0x0, 0x1, 0xB, 0xA, 0x8, 0x9, 0xC, 0xD, 0xF, 0xE }
shifts[2]= { 0x4, 0xB, 0xB, 0x4, 0xB, 0x4, 0x4, 0xB, 0xA, 0x5, 0x5, 0xA, 0x5, 0xA, 0xA, 0x5 }
shifts[3]= { 0xB, 0x6, 0x0, 0xD, 0xD, 0x0, 0x6, 0xB, 0x6, 0xB, 0xD, 0x0, 0x0, 0xD, 0xB, 0x6 }
shifts[4]= { 0xE, 0x5, 0x9, 0x2, 0x0, 0xB, 0x7, 0xC, 0x3, 0x8, 0x4, 0xF, 0xD, 0x6, 0xA, 0x1 }
shifts[5]= { 0x4, 0xE, 0x1, 0xB, 0xF, 0x5, 0xA, 0x0, 0x3, 0x9, 0x6, 0xC, 0x8, 0x2, 0xD, 0x7 }
shifts[6]= { 0xA, 0x4, 0x7, 0x9, 0x0, 0xE, 0xD, 0x3, 0xE, 0x0, 0x3, 0xD, 0x4, 0xA, 0x9, 0x7 }
shifts[7]= { 0xE, 0x6, 0xE, 0x6, 0xF, 0x7, 0xF, 0x7, 0xD, 0x5, 0xD, 0x5, 0xC, 0x4, 0xC, 0x4 }
shifts[8]= { 0x7, 0x1, 0xB, 0xD, 0xE, 0x8, 0x2, 0x4, 0x4, 0x2, 0x8, 0xE, 0xD, 0xB, 0x1, 0x7 }
shifts[9]= { 0xD, 0xB, 0x0, 0x6, 0x6, 0x0, 0xB, 0xD, 0xA, 0xC, 0x7, 0x1, 0x1, 0x7, 0xC, 0xA }
shifts[10]= { 0xe, 0x1, 0x1, 0xe, 0x1, 0xe, 0xe, 0x1, 0x1, 0xe, 0xe, 0x1, 0xe, 0x1, 0x1, 0xe }
local function ApplyPermutationAndShifts( pos, value, nibble)
local shiftbytes = shifts[pos]
local shiftElem = shiftbytes[nibble+1] --one indexed
local shiftOne = shiftbytes[1]
local rs = bit32.bxor(value, bit32.bxor(shiftOne, shiftElem))
return rs
end
local function GetOne( uid, block )
if uid == nil then return nil, 'empty uid string' end
if #uid == 0 then return nil, 'empty uid string' end
if #uid ~= 8 then return nil, 'uid wrong length. Should be 4 hex bytes' end
if type(block) ~= 'number' then return nil, 'block is not number' end
if block > 16 or block < 0 then return nil, 'block is out-of-range' end
local s = ('%s%02X'):format(uid,block)
local nibble1 = tonumber(s:sub(1,1),16) + 1
local permuted = ''
for i = 1, #s do
local el_row = shifts[i]
local el_value = el_row[nibble1]
j = 1
while j <= i do
if i-j > 0 then
local nibble = tonumber(s:sub(j+1,j+1),16)
el_value = ApplyPermutationAndShifts(i-j, el_value, nibble)
end
j = j+1
end
permuted =('%s%X'):format(permuted,el_value)
end
permuted = 'C2'..permuted
local crc64numStr = utils.Crc64(permuted)
local keybytes = utils.ConvertAsciiToBytes(crc64numStr, true)
local key = utils.ConvertBytesToHex(keybytes)
return key:sub(1,12)
end
local PreCalc =
{
GetAll = function(id)
if id == nil then return nil, 'empty string' end
if #id == 0 then return nil, 'empty string' end
if #id ~= 8 then return nil, 'wrong length. Should be 4 hex bytes' end
local list = '4b0b20107ccb'
for i = 1,15 do
local key, err = GetOne(id,i)
if not key then return oops(err) end
list = list..key
end
return list
end,
}
return PreCalc

View file

@ -20,7 +20,9 @@ local ISO14A_COMMAND = {
ISO14A_RAW = 8, ISO14A_RAW = 8,
ISO14A_REQUEST_TRIGGER = 0x10, ISO14A_REQUEST_TRIGGER = 0x10,
ISO14A_APPEND_CRC = 0x20, ISO14A_APPEND_CRC = 0x20,
ISO14A_SET_TIMEOUT = 0x40 ISO14A_SET_TIMEOUT = 0x40,
ISO14A_NO_SELECT = 0x80,
ISO14A_TOPAZMODE = 0x100
} }
local ISO14443a_TYPES = {} local ISO14443a_TYPES = {}

View file

@ -71,8 +71,8 @@ local Utils =
return outResults return outResults
end, end,
------------ CRC-16 ccitt checksums
------------ CRC-16 ccitt checksums
-- Takes a hex string and calculates a crc16 -- Takes a hex string and calculates a crc16
Crc16 = function(s) Crc16 = function(s)
if s == nil then return nil end if s == nil then return nil end
@ -85,7 +85,48 @@ local Utils =
end end
return nil return nil
end, end,
------------ CRC-64 ecma checksums
-- Takes a hex string and calculates a crc64 ecma
Crc64 = function(s)
if s == nil then return nil end
if #s == 0 then return nil end
if type(s) == 'string' then
local utils = require('utils')
local asc = utils.ConvertHexToAscii(s)
local hash = core.crc64(asc)
return hash
end
return nil
end,
------------ SHA1 hash
-- Takes a string and calculates a SHA1 hash
Sha1 = function(s)
if s == nil then return nil end
if #s == 0 then return nil end
if type(s) == 'string' then
local utils = require('utils')
--local asc = utils.ConvertHexToAscii(s)
local hash = core.sha1(s)
return hash
end
return nil
end,
-- Takes a hex string and calculates a SHA1 hash
Sha1Hex = function(s)
if s == nil then return nil end
if #s == 0 then return nil end
if type(s) == 'string' then
local utils = require('utils')
local asc = utils.ConvertHexToAscii(s)
local hash = core.sha1(asc)
return hash
end
return nil
end,
-- input parameter is a string -- input parameter is a string
-- Swaps the endianess and returns a number, -- Swaps the endianess and returns a number,
-- IE: 'cd7a' -> '7acd' -> 0x7acd -- IE: 'cd7a' -> '7acd' -> 0x7acd
@ -135,7 +176,7 @@ local Utils =
while IN>0 do while IN>0 do
I=I+1 I=I+1
IN , D = math.floor(IN/B), math.modf(IN,B)+1 IN , D = math.floor(IN/B), math.modf(IN,B)+1
OUT=string.sub(K,D,D)..OUT OUT = string.sub(K,D,D)..OUT
end end
return OUT return OUT
end, end,
@ -147,7 +188,7 @@ local Utils =
end end
local s={} local s={}
for i = 1, #(bytes) do for i = 1, #(bytes) do
s[i] = string.format("%02X",bytes[i]) s[i] = string.format("%02X",bytes[i])
end end
return table.concat(s) return table.concat(s)
end, end,
@ -171,16 +212,28 @@ local Utils =
end end
return t return t
end, end,
ConvertAsciiToBytes = function(s) ConvertAsciiToBytes = function(s, reverse)
local t={} local t = {}
if s == nil then return t end if s == nil then return t end
if #s == 0 then return t end if #s == 0 then return t end
for k in s:gmatch"(.)" do for k in s:gmatch"(.)" do
table.insert(t, string.byte(k)) table.insert(t, string.byte(k))
end end
return t
if not reverse then
return t
end
local rev = {}
if reverse then
for i = #t, 1,-1 do
table.insert(rev, t[i] )
end
end
return rev
end, end,
ConvertHexToAscii = function(s) ConvertHexToAscii = function(s)
local t={} local t={}
if s == nil then return t end if s == nil then return t end
@ -191,6 +244,30 @@ local Utils =
return table.concat(t) return table.concat(t)
end, end,
Chars2num = function(s)
return (s:byte(1)*16777216)+(s:byte(2)*65536)+(s:byte(3)*256)+(s:byte(4))
end,
-- use length of string to determine 8,16,32,64 bits
bytes_to_int = function(str,endian,signed)
local t={str:byte(1,-1)}
if endian=="big" then --reverse bytes
local tt={}
for k=1,#t do
tt[#t-k+1]=t[k]
end
t=tt
end
local n=0
for k=1,#t do
n=n+t[k]*2^((k-1)*8)
end
if signed then
n = (n > 2^(#t*8-1) -1) and (n - 2^(#t*8)) or n -- if last bit set, negative.
end
return n
end,
-- function convertStringToBytes(str) -- function convertStringToBytes(str)
-- local bytes = {} -- local bytes = {}
-- local strLength = string.len(str) -- local strLength = string.len(str)
@ -237,4 +314,4 @@ local Utils =
-- end -- end
} }
return Utils return Utils

View file

@ -69,7 +69,7 @@ void* nested_worker_thread(void *arg)
int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * resultKey, bool calibrate) int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * resultKey, bool calibrate)
{ {
uint16_t i, len; uint16_t i;
uint32_t uid; uint32_t uid;
UsbCommand resp; UsbCommand resp;
@ -77,31 +77,29 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo
struct Crypto1State *p1, *p2, *p3, *p4; struct Crypto1State *p1, *p2, *p3, *p4;
// flush queue // flush queue
WaitForResponseTimeout(CMD_ACK,NULL,100); WaitForResponseTimeout(CMD_ACK, NULL, 100);
UsbCommand c = {CMD_MIFARE_NESTED, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, calibrate}}; UsbCommand c = {CMD_MIFARE_NESTED, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, calibrate}};
memcpy(c.d.asBytes, key, 6); memcpy(c.d.asBytes, key, 6);
SendCommand(&c); SendCommand(&c);
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
len = resp.arg[1]; return -1;
if (len == 2) { }
memcpy(&uid, resp.d.asBytes, 4);
PrintAndLog("uid:%08x len=%d trgbl=%d trgkey=%x", uid, len, (uint16_t)resp.arg[2] & 0xff, (uint16_t)resp.arg[2] >> 8);
for (i = 0; i < 2; i++) {
statelists[i].blockNo = resp.arg[2] & 0xff;
statelists[i].keyType = (resp.arg[2] >> 8) & 0xff;
statelists[i].uid = uid;
memcpy(&statelists[i].nt, (void *)(resp.d.asBytes + 4 + i * 8 + 0), 4); if (resp.arg[0]) {
memcpy(&statelists[i].ks1, (void *)(resp.d.asBytes + 4 + i * 8 + 4), 4); return resp.arg[0]; // error during nested
} }
}
else { memcpy(&uid, resp.d.asBytes, 4);
PrintAndLog("Got 0 keys from proxmark."); PrintAndLog("uid:%08x trgbl=%d trgkey=%x", uid, (uint16_t)resp.arg[2] & 0xff, (uint16_t)resp.arg[2] >> 8);
return 1;
} for (i = 0; i < 2; i++) {
statelists[i].blockNo = resp.arg[2] & 0xff;
statelists[i].keyType = (resp.arg[2] >> 8) & 0xff;
statelists[i].uid = uid;
memcpy(&statelists[i].nt, (void *)(resp.d.asBytes + 4 + i * 8 + 0), 4);
memcpy(&statelists[i].ks1, (void *)(resp.d.asBytes + 4 + i * 8 + 4), 4);
} }
// calc keys // calc keys
@ -354,10 +352,7 @@ int loadTraceCard(uint8_t *tuid) {
FillFileNameByUID(traceFileName, tuid, ".eml", 7); FillFileNameByUID(traceFileName, tuid, ".eml", 7);
f = fopen(traceFileName, "r"); f = fopen(traceFileName, "r");
if (!f) { if (!f) return 1;
fclose(f);
return 1;
}
blockNum = 0; blockNum = 0;
@ -394,10 +389,7 @@ int saveTraceCard(void) {
if ((!strlen(traceFileName)) || (isTraceCardEmpty())) return 0; if ((!strlen(traceFileName)) || (isTraceCardEmpty())) return 0;
f = fopen(traceFileName, "w+"); f = fopen(traceFileName, "w+");
if ( !f ) { if ( !f ) return 1;
fclose(f);
return 1;
}
for (int i = 0; i < 64; i++) { // blocks for (int i = 0; i < 64; i++) { // blocks
for (int j = 0; j < 16; j++) // bytes for (int j = 0; j < 16; j++) // bytes

View file

@ -24,7 +24,7 @@
#include "ui.h" #include "ui.h"
#include "sleep.h" #include "sleep.h"
#include "cmdparser.h" #include "cmdparser.h"
#include "cmdmain.h" #include "cmdhw.h"
// a global mutex to prevent interlaced printing from different threads // a global mutex to prevent interlaced printing from different threads
pthread_mutex_t print_lock; pthread_mutex_t print_lock;
@ -105,6 +105,8 @@ static void *main_loop(void *targ) {
if (arg->usb_present == 1) { if (arg->usb_present == 1) {
rarg.run = 1; rarg.run = 1;
pthread_create(&reader_thread, NULL, &uart_receiver, &rarg); pthread_create(&reader_thread, NULL, &uart_receiver, &rarg);
// cache Version information now:
CmdVersion(NULL);
} }
FILE *script_file = NULL; FILE *script_file = NULL;

View file

@ -19,6 +19,8 @@
#include "nonce2key/nonce2key.h" #include "nonce2key/nonce2key.h"
#include "../common/iso15693tools.h" #include "../common/iso15693tools.h"
#include "../common/crc16.h" #include "../common/crc16.h"
#include "../common/crc64.h"
#include "../common/sha1.h"
#include "aes.h" #include "aes.h"
/** /**
* The following params expected: * The following params expected:
@ -29,34 +31,34 @@
*/ */
static int l_SendCommand(lua_State *L){ static int l_SendCommand(lua_State *L){
/* /*
* *
The SendCommand (native) expects the following structure: The SendCommand (native) expects the following structure:
typedef struct { typedef struct {
uint64_t cmd; //8 bytes uint64_t cmd; //8 bytes
uint64_t arg[3]; // 8*3 bytes = 24 bytes uint64_t arg[3]; // 8*3 bytes = 24 bytes
union { union {
uint8_t asBytes[USB_CMD_DATA_SIZE]; // 1 byte * 512 = 512 bytes (OR) uint8_t asBytes[USB_CMD_DATA_SIZE]; // 1 byte * 512 = 512 bytes (OR)
uint32_t asDwords[USB_CMD_DATA_SIZE/4]; // 4 byte * 128 = 512 bytes uint32_t asDwords[USB_CMD_DATA_SIZE/4]; // 4 byte * 128 = 512 bytes
} d; } d;
} PACKED UsbCommand; } PACKED UsbCommand;
==> A 544 byte buffer will do. ==> A 544 byte buffer will do.
**/ **/
//Pop cmd //Pop cmd
size_t size; size_t size;
const char *data = luaL_checklstring(L, 1, &size); const char *data = luaL_checklstring(L, 1, &size);
if(size != sizeof(UsbCommand)) if(size != sizeof(UsbCommand))
{ {
printf("Got data size %d, expected %d" , (int) size,(int) sizeof(UsbCommand)); printf("Got data size %d, expected %d" , (int) size,(int) sizeof(UsbCommand));
lua_pushstring(L,"Wrong data size"); lua_pushstring(L,"Wrong data size");
return 1; return 1;
} }
// UsbCommand c = (*data); // UsbCommand c = (*data);
SendCommand((UsbCommand* )data); SendCommand((UsbCommand* )data);
return 0; // no return values return 0; // no return values
} }
/** /**
* @brief The following params expected: * @brief The following params expected:
@ -67,105 +69,105 @@ static int l_SendCommand(lua_State *L){
*/ */
static int l_WaitForResponseTimeout(lua_State *L){ static int l_WaitForResponseTimeout(lua_State *L){
uint32_t cmd = 0; uint32_t cmd = 0;
size_t ms_timeout = -1; size_t ms_timeout = -1;
//Check number of arguments //Check number of arguments
int n = lua_gettop(L); int n = lua_gettop(L);
if(n == 0) if(n == 0)
{ {
//signal error by returning Nil, errorstring //signal error by returning Nil, errorstring
lua_pushnil(L); lua_pushnil(L);
lua_pushstring(L,"You need to supply at least command to wait for"); lua_pushstring(L,"You need to supply at least command to wait for");
return 2; // two return values return 2; // two return values
} }
if(n >= 1) if(n >= 1)
{ {
//pop cmd //pop cmd
cmd = luaL_checkunsigned(L,1); cmd = luaL_checkunsigned(L,1);
} }
if(n >= 2) if(n >= 2)
{ {
//Did the user send a timeout ? //Did the user send a timeout ?
//Check if the current top of stack is an integer //Check if the current top of stack is an integer
ms_timeout = luaL_checkunsigned(L,2); ms_timeout = luaL_checkunsigned(L,2);
//printf("Timeout set to %dms\n" , (int) ms_timeout); //printf("Timeout set to %dms\n" , (int) ms_timeout);
} }
UsbCommand response; UsbCommand response;
if(WaitForResponseTimeout(cmd, &response, ms_timeout)) if(WaitForResponseTimeout(cmd, &response, ms_timeout))
{ {
//Push it as a string //Push it as a string
lua_pushlstring(L,(const char *)&response,sizeof(UsbCommand)); lua_pushlstring(L,(const char *)&response,sizeof(UsbCommand));
return 1;// return 1 to signal one return value return 1;// return 1 to signal one return value
}else{ }else{
//Push a Nil instead //Push a Nil instead
lua_pushnil(L); lua_pushnil(L);
return 1;// one return value return 1;// one return value
} }
} }
static int returnToLuaWithError(lua_State *L, const char* fmt, ...) static int returnToLuaWithError(lua_State *L, const char* fmt, ...)
{ {
char buffer[200]; char buffer[200];
va_list args; va_list args;
va_start(args,fmt); va_start(args,fmt);
vsnprintf(buffer, sizeof(buffer), fmt,args); vsnprintf(buffer, sizeof(buffer), fmt,args);
va_end(args); va_end(args);
lua_pushnil(L); lua_pushnil(L);
lua_pushstring(L,buffer); lua_pushstring(L,buffer);
return 2; return 2;
} }
static int l_nonce2key(lua_State *L){ static int l_nonce2key(lua_State *L){
size_t size; size_t size;
const char *p_uid = luaL_checklstring(L, 1, &size); const char *p_uid = luaL_checklstring(L, 1, &size);
if(size != 4) return returnToLuaWithError(L,"Wrong size of uid, got %d bytes, expected 4", (int) size); if(size != 4) return returnToLuaWithError(L,"Wrong size of uid, got %d bytes, expected 4", (int) size);
const char *p_nt = luaL_checklstring(L, 2, &size); const char *p_nt = luaL_checklstring(L, 2, &size);
if(size != 4) return returnToLuaWithError(L,"Wrong size of nt, got %d bytes, expected 4", (int) size); if(size != 4) return returnToLuaWithError(L,"Wrong size of nt, got %d bytes, expected 4", (int) size);
const char *p_nr = luaL_checklstring(L, 3, &size); const char *p_nr = luaL_checklstring(L, 3, &size);
if(size != 4) return returnToLuaWithError(L,"Wrong size of nr, got %d bytes, expected 4", (int) size); if(size != 4) return returnToLuaWithError(L,"Wrong size of nr, got %d bytes, expected 4", (int) size);
const char *p_par_info = luaL_checklstring(L, 4, &size); const char *p_par_info = luaL_checklstring(L, 4, &size);
if(size != 8) return returnToLuaWithError(L,"Wrong size of par_info, got %d bytes, expected 8", (int) size); if(size != 8) return returnToLuaWithError(L,"Wrong size of par_info, got %d bytes, expected 8", (int) size);
const char *p_pks_info = luaL_checklstring(L, 5, &size); const char *p_pks_info = luaL_checklstring(L, 5, &size);
if(size != 8) return returnToLuaWithError(L,"Wrong size of ks_info, got %d bytes, expected 8", (int) size); if(size != 8) return returnToLuaWithError(L,"Wrong size of ks_info, got %d bytes, expected 8", (int) size);
uint32_t uid = bytes_to_num(( uint8_t *)p_uid,4); uint32_t uid = bytes_to_num(( uint8_t *)p_uid,4);
uint32_t nt = bytes_to_num(( uint8_t *)p_nt,4); uint32_t nt = bytes_to_num(( uint8_t *)p_nt,4);
uint32_t nr = bytes_to_num(( uint8_t*)p_nr,4); uint32_t nr = bytes_to_num(( uint8_t*)p_nr,4);
uint64_t par_info = bytes_to_num(( uint8_t *)p_par_info,8); uint64_t par_info = bytes_to_num(( uint8_t *)p_par_info,8);
uint64_t ks_info = bytes_to_num(( uint8_t *)p_pks_info,8); uint64_t ks_info = bytes_to_num(( uint8_t *)p_pks_info,8);
uint64_t key = 0; uint64_t key = 0;
int retval = nonce2key(uid,nt, nr, par_info,ks_info, &key); int retval = nonce2key(uid,nt, nr, par_info,ks_info, &key);
//Push the retval on the stack //Push the retval on the stack
lua_pushinteger(L,retval); lua_pushinteger(L,retval);
//Push the key onto the stack
uint8_t dest_key[8];
num_to_bytes(key,sizeof(dest_key),dest_key);
//printf("Pushing to lua stack: %012"llx"\n",key); //Push the key onto the stack
lua_pushlstring(L,(const char *) dest_key,sizeof(dest_key)); uint8_t dest_key[8];
num_to_bytes(key,sizeof(dest_key),dest_key);
return 2; //Two return values //printf("Pushing to lua stack: %012"llx"\n",key);
lua_pushlstring(L,(const char *) dest_key,sizeof(dest_key));
return 2; //Two return values
} }
//static int l_PrintAndLog(lua_State *L){ return CmdHF14AMfDump(luaL_checkstring(L, 1));} //static int l_PrintAndLog(lua_State *L){ return CmdHF14AMfDump(luaL_checkstring(L, 1));}
static int l_clearCommandBuffer(lua_State *L){ static int l_clearCommandBuffer(lua_State *L){
clearCommandBuffer(); clearCommandBuffer();
return 0; return 0;
} }
/** /**
* @brief l_foobar is a dummy function to test lua-integration with * @brief l_foobar is a dummy function to test lua-integration with
@ -174,23 +176,23 @@ static int l_clearCommandBuffer(lua_State *L){
*/ */
static int l_foobar(lua_State *L) static int l_foobar(lua_State *L)
{ {
//Check number of arguments //Check number of arguments
int n = lua_gettop(L); int n = lua_gettop(L);
printf("foobar called with %d arguments" , n); printf("foobar called with %d arguments" , n);
lua_settop(L, 0); lua_settop(L, 0);
printf("Arguments discarded, stack now contains %d elements", lua_gettop(L)); printf("Arguments discarded, stack now contains %d elements", lua_gettop(L));
// todo: this is not used, where was it intended for?
// UsbCommand response = {CMD_MIFARE_READBL, {1337, 1338, 1339}};
printf("Now returning a uint64_t as a string");
uint64_t x = 0xDEADBEEF;
uint8_t destination[8];
num_to_bytes(x,sizeof(x),destination);
lua_pushlstring(L,(const char *)&x,sizeof(x));
lua_pushlstring(L,(const char *)destination,sizeof(destination));
return 2; // todo: this is not used, where was it intended for?
// UsbCommand response = {CMD_MIFARE_READBL, {1337, 1338, 1339}};
printf("Now returning a uint64_t as a string");
uint64_t x = 0xDEADBEEF;
uint8_t destination[8];
num_to_bytes(x,sizeof(x),destination);
lua_pushlstring(L,(const char *)&x,sizeof(x));
lua_pushlstring(L,(const char *)destination,sizeof(destination));
return 2;
} }
@ -201,8 +203,8 @@ static int l_foobar(lua_State *L)
*/ */
static int l_ukbhit(lua_State *L) static int l_ukbhit(lua_State *L)
{ {
lua_pushboolean(L,ukbhit() ? true : false); lua_pushboolean(L,ukbhit() ? true : false);
return 1; return 1;
} }
/** /**
* @brief Calls the command line parser to deal with the command. This enables * @brief Calls the command line parser to deal with the command. This enables
@ -212,58 +214,134 @@ static int l_ukbhit(lua_State *L)
*/ */
static int l_CmdConsole(lua_State *L) static int l_CmdConsole(lua_State *L)
{ {
CommandReceived((char *)luaL_checkstring(L, 1)); CommandReceived((char *)luaL_checkstring(L, 1));
return 0; return 0;
} }
static int l_iso15693_crc(lua_State *L) static int l_iso15693_crc(lua_State *L)
{ {
// uint16_t Iso15693Crc(uint8_t *v, int n); // uint16_t Iso15693Crc(uint8_t *v, int n);
size_t size; size_t size;
const char *v = luaL_checklstring(L, 1, &size); const char *v = luaL_checklstring(L, 1, &size);
uint16_t retval = Iso15693Crc((uint8_t *) v, size); uint16_t retval = Iso15693Crc((uint8_t *) v, size);
lua_pushinteger(L, (int) retval); lua_pushinteger(L, (int) retval);
return 1; return 1;
} }
/* /*
Simple AES 128 cbc hook up to OpenSSL. Simple AES 128 cbc hook up to OpenSSL.
params: key, input params: key, input
*/ */
static int l_aes(lua_State *L) static int l_aes128decrypt_cbc(lua_State *L)
{ {
//Check number of arguments //Check number of arguments
int i; int i;
size_t size; size_t size;
const char *p_key = luaL_checklstring(L, 1, &size); const char *p_key = luaL_checklstring(L, 1, &size);
if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size); if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size);
const char *p_encTxt = luaL_checklstring(L, 2, &size);
const char *p_encTxt = luaL_checklstring(L, 2, &size);
unsigned char indata[16] = {0x00}; unsigned char indata[16] = {0x00};
unsigned char outdata[16] = {0x00}; unsigned char outdata[16] = {0x00};
unsigned char aes_key[16] = {0x00}; unsigned char aes_key[16] = {0x00};
unsigned char iv[16] = {0x00}; unsigned char iv[16] = {0x00};
// convert key to bytearray // convert key to bytearray and convert input to bytearray
for (i = 0; i < 32; i += 2) { for (i = 0; i < 32; i += 2) {
sscanf(&p_encTxt[i], "%02x", (unsigned int *)&indata[i / 2]); sscanf(&p_encTxt[i], "%02x", (unsigned int *)&indata[i / 2]);
}
// convert input to bytearray
for (i = 0; i < 32; i += 2) {
sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]); sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]);
} }
//AES_KEY key;
//AES_set_decrypt_key(aes_key, 128, &key);
//AES_cbc_encrypt(indata, outdata, sizeof(indata), &key, iv, AES_DECRYPT);
aes_context ctx; aes_context ctx;
aes_init(&ctx); aes_init(&ctx);
aes_setkey_enc(&ctx,(const unsigned char *)p_key,128); aes_setkey_dec(&ctx, aes_key, 128);
aes_crypt_cbc(&ctx,AES_DECRYPT,sizeof(indata), iv, indata,outdata ); aes_crypt_cbc(&ctx,AES_DECRYPT,sizeof(indata), iv, indata,outdata );
//Push decrypted array as a string //Push decrypted array as a string
lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
return 1;// return 1 to signal one return value
}
static int l_aes128decrypt_ecb(lua_State *L)
{
//Check number of arguments
int i;
size_t size;
const char *p_key = luaL_checklstring(L, 1, &size);
if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size);
const char *p_encTxt = luaL_checklstring(L, 2, &size);
unsigned char indata[16] = {0x00};
unsigned char outdata[16] = {0x00};
unsigned char aes_key[16] = {0x00};
// convert key to bytearray and convert input to bytearray
for (i = 0; i < 32; i += 2) {
sscanf(&p_encTxt[i], "%02x", (unsigned int *)&indata[i / 2]);
sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]);
}
aes_context ctx;
aes_init(&ctx);
aes_setkey_dec(&ctx, aes_key, 128);
aes_crypt_ecb(&ctx, AES_DECRYPT, indata, outdata );
//Push decrypted array as a string
lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
return 1;// return 1 to signal one return value
}
static int l_aes128encrypt_cbc(lua_State *L)
{
//Check number of arguments
int i;
size_t size;
const char *p_key = luaL_checklstring(L, 1, &size);
if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size);
const char *p_txt = luaL_checklstring(L, 2, &size);
unsigned char indata[16] = {0x00};
unsigned char outdata[16] = {0x00};
unsigned char aes_key[16] = {0x00};
unsigned char iv[16] = {0x00};
for (i = 0; i < 32; i += 2) {
sscanf(&p_txt[i], "%02x", (unsigned int *)&indata[i / 2]);
sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]);
}
aes_context ctx;
aes_init(&ctx);
aes_setkey_enc(&ctx, aes_key, 128);
aes_crypt_cbc(&ctx, AES_ENCRYPT, sizeof(indata), iv, indata, outdata );
//Push encrypted array as a string
lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
return 1;// return 1 to signal one return value
}
static int l_aes128encrypt_ecb(lua_State *L)
{
//Check number of arguments
int i;
size_t size;
const char *p_key = luaL_checklstring(L, 1, &size);
if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size);
const char *p_txt = luaL_checklstring(L, 2, &size);
unsigned char indata[16] = {0x00};
unsigned char outdata[16] = {0x00};
unsigned char aes_key[16] = {0x00};
for (i = 0; i < 32; i += 2) {
sscanf(&p_txt[i], "%02x", (unsigned int *)&indata[i / 2]);
sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]);
}
aes_context ctx;
aes_init(&ctx);
aes_setkey_enc(&ctx, aes_key, 128);
aes_crypt_ecb(&ctx, AES_ENCRYPT, indata, outdata );
//Push encrypted array as a string
lua_pushlstring(L,(const char *)&outdata, sizeof(outdata)); lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
return 1;// return 1 to signal one return value return 1;// return 1 to signal one return value
} }
@ -272,10 +350,42 @@ static int l_crc16(lua_State *L)
{ {
size_t size; size_t size;
const char *p_str = luaL_checklstring(L, 1, &size); const char *p_str = luaL_checklstring(L, 1, &size);
uint16_t retval = crc16_ccitt( (uint8_t*) p_str, size); uint16_t retval = crc16_ccitt( (uint8_t*) p_str, size);
lua_pushinteger(L, (int) retval); lua_pushinteger(L, (int) retval);
return 1; return 1;
}
static int l_crc64(lua_State *L)
{
size_t size;
uint64_t crc = 0;
unsigned char outdata[8] = {0x00};
const char *p_str = luaL_checklstring(L, 1, &size);
crc64( (uint8_t*) p_str, size, &crc);
outdata[0] = (uint8_t)(crc >> 56) & 0xff;
outdata[1] = (uint8_t)(crc >> 48) & 0xff;
outdata[2] = (uint8_t)(crc >> 40) & 0xff;
outdata[3] = (uint8_t)(crc >> 32) & 0xff;
outdata[4] = (uint8_t)(crc >> 24) & 0xff;
outdata[5] = (uint8_t)(crc >> 16) & 0xff;
outdata[6] = (uint8_t)(crc >> 8) & 0xff;
outdata[7] = crc & 0xff;
lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
return 1;
}
static int l_sha1(lua_State *L)
{
size_t size;
const char *p_str = luaL_checklstring(L, 1, &size);
unsigned char outdata[20] = {0x00};
sha1( (uint8_t*) p_str, size, outdata);
lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
return 1;
} }
/** /**
@ -288,57 +398,63 @@ static int l_crc16(lua_State *L)
*/ */
int setLuaPath( lua_State* L, const char* path ) int setLuaPath( lua_State* L, const char* path )
{ {
lua_getglobal( L, "package" ); lua_getglobal( L, "package" );
lua_getfield( L, -1, "path" ); // get field "path" from table at top of stack (-1) lua_getfield( L, -1, "path" ); // get field "path" from table at top of stack (-1)
const char* cur_path = lua_tostring( L, -1 ); // grab path string from top of stack const char* cur_path = lua_tostring( L, -1 ); // grab path string from top of stack
int requiredLength = strlen(cur_path)+ strlen(path)+10; //A few bytes too many, whatever we can afford it int requiredLength = strlen(cur_path)+ strlen(path)+10; //A few bytes too many, whatever we can afford it
char * buf = malloc(requiredLength); char * buf = malloc(requiredLength);
snprintf(buf, requiredLength, "%s;%s", cur_path, path); snprintf(buf, requiredLength, "%s;%s", cur_path, path);
lua_pop( L, 1 ); // get rid of the string on the stack we just pushed on line 5 lua_pop( L, 1 ); // get rid of the string on the stack we just pushed on line 5
lua_pushstring( L, buf ); // push the new one lua_pushstring( L, buf ); // push the new one
lua_setfield( L, -2, "path" ); // set the field "path" in table at -2 with value at top of stack lua_setfield( L, -2, "path" ); // set the field "path" in table at -2 with value at top of stack
lua_pop( L, 1 ); // get rid of package table from top of stack lua_pop( L, 1 ); // get rid of package table from top of stack
return 0; // all done! free(buf);
return 0; // all done!
} }
int set_pm3_libraries(lua_State *L) int set_pm3_libraries(lua_State *L)
{ {
static const luaL_Reg libs[] = { static const luaL_Reg libs[] = {
{"SendCommand", l_SendCommand}, {"SendCommand", l_SendCommand},
{"WaitForResponseTimeout", l_WaitForResponseTimeout}, {"WaitForResponseTimeout", l_WaitForResponseTimeout},
{"nonce2key", l_nonce2key}, {"nonce2key", l_nonce2key},
//{"PrintAndLog", l_PrintAndLog}, //{"PrintAndLog", l_PrintAndLog},
{"foobar", l_foobar}, {"foobar", l_foobar},
{"ukbhit", l_ukbhit}, {"ukbhit", l_ukbhit},
{"clearCommandBuffer", l_clearCommandBuffer}, {"clearCommandBuffer", l_clearCommandBuffer},
{"console", l_CmdConsole}, {"console", l_CmdConsole},
{"iso15693_crc", l_iso15693_crc}, {"iso15693_crc", l_iso15693_crc},
{"aes", l_aes}, {"aes128_decrypt", l_aes128decrypt_cbc},
{"aes128_decrypt_ecb", l_aes128decrypt_ecb},
{"aes128_encrypt", l_aes128encrypt_cbc},
{"aes128_encrypt_ecb", l_aes128encrypt_ecb},
{"crc16", l_crc16}, {"crc16", l_crc16},
{NULL, NULL} {"crc64", l_crc64},
}; {"sha1", l_sha1},
{NULL, NULL}
};
lua_pushglobaltable(L); lua_pushglobaltable(L);
// Core library is in this table. Contains ' // Core library is in this table. Contains '
//this is 'pm3' table //this is 'pm3' table
lua_newtable(L); lua_newtable(L);
//Put the function into the hash table. //Put the function into the hash table.
for (int i = 0; libs[i].name; i++) { for (int i = 0; libs[i].name; i++) {
lua_pushcfunction(L, libs[i].func); lua_pushcfunction(L, libs[i].func);
lua_setfield(L, -2, libs[i].name);//set the name, pop stack lua_setfield(L, -2, libs[i].name);//set the name, pop stack
} }
//Name of 'core' //Name of 'core'
lua_setfield(L, -2, "core"); lua_setfield(L, -2, "core");
//-- remove the global environment table from the stack //-- remove the global environment table from the stack
lua_pop(L, 1); lua_pop(L, 1);
//-- Last but not least, add to the LUA_PATH (package.path in lua) //-- Last but not least, add to the LUA_PATH (package.path in lua)
// so we can load libraries from the ./lualib/ - directory // so we can load libraries from the ./lualib/ - directory
setLuaPath(L,"./lualibs/?.lua"); setLuaPath(L,"./lualibs/?.lua");
return 1; return 1;
} }

473
client/scripts/didump.lua Normal file
View file

@ -0,0 +1,473 @@
local cmds = require('commands')
local getopt = require('getopt')
local utils = require('utils')
local lib14a = require('read14a')
example =[[
script run didump
script run didump -k aabbccddeeff
]]
author = "Iceman"
usage = "script run didump -k <key> "
desc = [[
This is a script to dump and decrypt the data of a specific type of Mifare Mini token.
Arguments:
-h : this help
-k <key> : Mifare Key A.
]]
local band=bit32.band
local bor=bit32.bor
local bnot=bit32.bnot
local bxor=bit32.bxor
local lshift=bit32.lshift
local rshift=bit32.rshift
local FOO = 'AF62D2EC0491968CC52A1A7165F865FE'
local BAR = '286329204469736E65792032303133'
local RANDOM = FOO..BAR
local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S");
local TIMEOUT = 2000
local DEBUG = false
local numBlocks = 20
local numSectors = 5
local CHECKSUM_OFFSET = 12; -- +1???
---
-- A debug printout-function
function dbg(args)
if DEBUG then
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
function oops(err)
print("ERROR: ",err)
core.clearCommandBuffer()
end
---
-- Usage help
function help()
print(desc)
print("Example usage")
print(example)
end
---
-- Get checksum,
-- called: data is string (32 hex digits)
-- returns: number
local function getChecksum(data)
local chksum = data:sub(25,32)
return tonumber(chksum,16)
end
---
-- calculate checksum
-- called: data is bytes (24 hex digits)
-- returns: number
local function calculateChecksum(data)
-- Generate table
local _tbl = {}
_tbl[0] = { 0x0 }
_tbl[1] = { 0x77073096 }
_tbl[2] = { 0xEE0E612C }
_tbl[3] = { 0x990951BA }
_tbl[4] = { 0x76DC419 }
_tbl[5] = { 0x706AF48F }
_tbl[6] = { 0xE963A535 }
_tbl[7] = { 0x9E6495A3 }
_tbl[8] = { 0xEDB8832 }
_tbl[9] = { 0x79DCB8A4 }
_tbl[10] = { 0xE0D5E91E }
_tbl[11] = { 0x97D2D988 }
_tbl[12] = { 0x9B64C2B }
_tbl[13] = { 0x7EB17CBD }
_tbl[14] = { 0xE7B82D07 }
_tbl[15] = { 0x90BF1D91 }
_tbl[16] = { 0x1DB71064 }
_tbl[17] = { 0x6AB020F2 }
_tbl[18] = { 0xF3B97148 }
_tbl[19] = { 0x84BE41DE }
_tbl[20] = { 0x1ADAD47D }
_tbl[21] = { 0x6DDDE4EB }
_tbl[22] = { 0xF4D4B551 }
_tbl[23] = { 0x83D385C7 }
_tbl[24] = { 0x136C9856 }
_tbl[25] = { 0x646BA8C0 }
_tbl[26] = { 0xFD62F97A }
_tbl[27] = { 0x8A65C9EC }
_tbl[28] = { 0x14015C4F }
_tbl[29] = { 0x63066CD9 }
_tbl[30] = { 0xFA0F3D63 }
_tbl[31] = { 0x8D080DF5 }
_tbl[32] = { 0x3B6E20C8 }
_tbl[33] = { 0x4C69105E }
_tbl[34] = { 0xD56041E4 }
_tbl[35] = { 0xA2677172 }
_tbl[36] = { 0x3C03E4D1 }
_tbl[37] = { 0x4B04D447 }
_tbl[38] = { 0xD20D85FD }
_tbl[39] = { 0xA50AB56B }
_tbl[40] = { 0x35B5A8FA }
_tbl[41] = { 0x42B2986C }
_tbl[42] = { 0xDBBBC9D6 }
_tbl[43] = { 0xACBCF940 }
_tbl[44] = { 0x32D86CE3 }
_tbl[45] = { 0x45DF5C75 }
_tbl[46] = { 0xDCD60DCF }
_tbl[47] = { 0xABD13D59 }
_tbl[48] = { 0x26D930AC }
_tbl[49] = { 0x51DE003A }
_tbl[50] = { 0xC8D75180 }
_tbl[51] = { 0xBFD06116 }
_tbl[52] = { 0x21B4F4B5 }
_tbl[53] = { 0x56B3C423 }
_tbl[54] = { 0xCFBA9599 }
_tbl[55] = { 0xB8BDA50F }
_tbl[56] = { 0x2802B89E }
_tbl[57] = { 0x5F058808 }
_tbl[58] = { 0xC60CD9B2 }
_tbl[59] = { 0xB10BE924 }
_tbl[60] = { 0x2F6F7C87 }
_tbl[61] = { 0x58684C11 }
_tbl[62] = { 0xC1611DAB }
_tbl[63] = { 0xB6662D3D }
_tbl[64] = { 0x76DC4190 }
_tbl[65] = { 0x1DB7106 }
_tbl[66] = { 0x98D220BC }
_tbl[67] = { 0xEFD5102A }
_tbl[68] = { 0x71B18589 }
_tbl[69] = { 0x6B6B51F }
_tbl[70] = { 0x9FBFE4A5 }
_tbl[71] = { 0xE8B8D433 }
_tbl[72] = { 0x7807C9A2 }
_tbl[73] = { 0xF00F934 }
_tbl[74] = { 0x9609A88E }
_tbl[75] = { 0xE10E9818 }
_tbl[76] = { 0x7F6A0DBB }
_tbl[77] = { 0x86D3D2D }
_tbl[78] = { 0x91646C97 }
_tbl[79] = { 0xE6635C01 }
_tbl[80] = { 0x6B6B51F4 }
_tbl[81] = { 0x1C6C6162 }
_tbl[82] = { 0x856530D8 }
_tbl[83] = { 0xF262004E }
_tbl[84] = { 0x6C0695ED }
_tbl[85] = { 0x1B01A57B }
_tbl[86] = { 0x8208F4C1 }
_tbl[87] = { 0xF50FC457 }
_tbl[88] = { 0x65B0D9C6 }
_tbl[89] = { 0x12B7E950 }
_tbl[90] = { 0x8BBEB8EA }
_tbl[91] = { 0xFCB9887C }
_tbl[92] = { 0x62DD1DDF }
_tbl[93] = { 0x15DA2D49 }
_tbl[94] = { 0x8CD37CF3 }
_tbl[95] = { 0xFBD44C65 }
_tbl[96] = { 0x4DB26158 }
_tbl[97] = { 0x3AB551CE }
_tbl[98] = { 0xA3BC0074 }
_tbl[99] = { 0xD4BB30E2 }
_tbl[100] = { 0x4ADFA541 }
_tbl[101] = { 0x3DD895D7 }
_tbl[102] = { 0xA4D1C46D }
_tbl[103] = { 0xD3D6F4FB }
_tbl[104] = { 0x4369E96A }
_tbl[105] = { 0x346ED9FC }
_tbl[106] = { 0xAD678846 }
_tbl[107] = { 0xDA60B8D0 }
_tbl[108] = { 0x44042D73 }
_tbl[109] = { 0x33031DE5 }
_tbl[110] = { 0xAA0A4C5F }
_tbl[111] = { 0xDD0D7CC9 }
_tbl[112] = { 0x5005713C }
_tbl[113] = { 0x270241AA }
_tbl[114] = { 0xBE0B1010 }
_tbl[115] = { 0xC90C2086 }
_tbl[116] = { 0x5768B525 }
_tbl[117] = { 0x206F85B3 }
_tbl[118] = { 0xB966D409 }
_tbl[119] = { 0xCE61E49F }
_tbl[120] = { 0x5EDEF90E }
_tbl[121] = { 0x29D9C998 }
_tbl[122] = { 0xB0D09822 }
_tbl[123] = { 0xC7D7A8B4 }
_tbl[124] = { 0x59B33D17 }
_tbl[125] = { 0x2EB40D81 }
_tbl[126] = { 0xB7BD5C3B }
_tbl[127] = { 0xC0BA6CAD }
_tbl[128] = { 0xEDB88320 }
_tbl[129] = { 0x9ABFB3B6 }
_tbl[130] = { 0x3B6E20C }
_tbl[131] = { 0x74B1D29A }
_tbl[132] = { 0xEAD54739 }
_tbl[133] = { 0x9DD277AF }
_tbl[134] = { 0x4DB2615 }
_tbl[135] = { 0x73DC1683 }
_tbl[136] = { 0xE3630B12 }
_tbl[137] = { 0x94643B84 }
_tbl[138] = { 0xD6D6A3E }
_tbl[139] = { 0x7A6A5AA8 }
_tbl[140] = { 0xE40ECF0B }
_tbl[141] = { 0x9309FF9D }
_tbl[142] = { 0xA00AE27 }
_tbl[143] = { 0x7D079EB1 }
_tbl[144] = { 0xF00F9344 }
_tbl[145] = { 0x8708A3D2 }
_tbl[146] = { 0x1E01F268 }
_tbl[147] = { 0x6906C2FE }
_tbl[148] = { 0xF762575D }
_tbl[149] = { 0x806567CB }
_tbl[150] = { 0x196C3671 }
_tbl[151] = { 0x6E6B06E7 }
_tbl[152] = { 0xFED41B76 }
_tbl[153] = { 0x89D32BE0 }
_tbl[154] = { 0x10DA7A5A }
_tbl[155] = { 0x67DD4ACC }
_tbl[156] = { 0xF9B9DF6F }
_tbl[157] = { 0x8EBEEFF9 }
_tbl[158] = { 0x17B7BE43 }
_tbl[159] = { 0x60B08ED5 }
_tbl[160] = { 0xD6D6A3E8 }
_tbl[161] = { 0xA1D1937E }
_tbl[162] = { 0x38D8C2C4 }
_tbl[163] = { 0x4FDFF252 }
_tbl[164] = { 0xD1BB67F1 }
_tbl[165] = { 0xA6BC5767 }
_tbl[166] = { 0x3FB506DD }
_tbl[167] = { 0x48B2364B }
_tbl[168] = { 0xD80D2BDA }
_tbl[169] = { 0xAF0A1B4C }
_tbl[170] = { 0x36034AF6 }
_tbl[171] = { 0x41047A60 }
_tbl[172] = { 0xDF60EFC3 }
_tbl[173] = { 0xA867DF55 }
_tbl[174] = { 0x316E8EEF }
_tbl[175] = { 0x4669BE79 }
_tbl[176] = { 0xCB61B38C }
_tbl[177] = { 0xBC66831A }
_tbl[178] = { 0x256FD2A0 }
_tbl[179] = { 0x5268E236 }
_tbl[180] = { 0xCC0C7795 }
_tbl[181] = { 0xBB0B4703 }
_tbl[182] = { 0x220216B9 }
_tbl[183] = { 0x5505262F }
_tbl[184] = { 0xC5BA3BBE }
_tbl[185] = { 0xB2BD0B28 }
_tbl[186] = { 0x2BB45A92 }
_tbl[187] = { 0x5CB36A04 }
_tbl[188] = { 0xC2D7FFA7 }
_tbl[189] = { 0xB5D0CF31 }
_tbl[190] = { 0x2CD99E8B }
_tbl[191] = { 0x5BDEAE1D }
_tbl[192] = { 0x9B64C2B0 }
_tbl[193] = { 0xEC63F226 }
_tbl[194] = { 0x756AA39C }
_tbl[195] = { 0x26D930A }
_tbl[196] = { 0x9C0906A9 }
_tbl[197] = { 0xEB0E363F }
_tbl[198] = { 0x72076785 }
_tbl[199] = { 0x5005713 }
_tbl[200] = { 0x95BF4A82 }
_tbl[201] = { 0xE2B87A14 }
_tbl[202] = { 0x7BB12BAE }
_tbl[203] = { 0xCB61B38 }
_tbl[204] = { 0x92D28E9B }
_tbl[205] = { 0xE5D5BE0D }
_tbl[206] = { 0x7CDCEFB7 }
_tbl[207] = { 0xBDBDF21 }
_tbl[208] = { 0x86D3D2D4 }
_tbl[209] = { 0xF1D4E242 }
_tbl[210] = { 0x68DDB3F8 }
_tbl[211] = { 0x1FDA836E }
_tbl[212] = { 0x81BE16CD }
_tbl[213] = { 0xF6B9265B }
_tbl[214] = { 0x6FB077E1 }
_tbl[215] = { 0x18B74777 }
_tbl[216] = { 0x88085AE6 }
_tbl[217] = { 0xFF0F6A70 }
_tbl[218] = { 0x66063BCA }
_tbl[219] = { 0x11010B5C }
_tbl[220] = { 0x8F659EFF }
_tbl[221] = { 0xF862AE69 }
_tbl[222] = { 0x616BFFD3 }
_tbl[223] = { 0x166CCF45 }
_tbl[224] = { 0xA00AE278 }
_tbl[225] = { 0xD70DD2EE }
_tbl[226] = { 0x4E048354 }
_tbl[227] = { 0x3903B3C2 }
_tbl[228] = { 0xA7672661 }
_tbl[229] = { 0xD06016F7 }
_tbl[230] = { 0x4969474D }
_tbl[231] = { 0x3E6E77DB }
_tbl[232] = { 0xAED16A4A }
_tbl[233] = { 0xD9D65ADC }
_tbl[234] = { 0x40DF0B66 }
_tbl[235] = { 0x37D83BF0 }
_tbl[236] = { 0xA9BCAE53 }
_tbl[237] = { 0xDEBB9EC5 }
_tbl[238] = { 0x47B2CF7F }
_tbl[239] = { 0x30B5FFE9 }
_tbl[240] = { 0xBDBDF21C }
_tbl[241] = { 0xCABAC28A }
_tbl[242] = { 0x53B39330 }
_tbl[243] = { 0x24B4A3A6 }
_tbl[244] = { 0xBAD03605 }
_tbl[245] = { 0xCDD70693 }
_tbl[246] = { 0x54DE5729 }
_tbl[247] = { 0x23D967BF }
_tbl[248] = { 0xB3667A2E }
_tbl[249] = { 0xC4614AB8 }
_tbl[250] = { 0x5D681B02 }
_tbl[251] = { 0x2A6F2B94 }
_tbl[252] = { 0xB40BBE37 }
_tbl[253] = { 0xC30C8EA1 }
_tbl[254] = { 0x5A05DF1B }
_tbl[255] = { 0x2D02EF8D }
-- Calculate it
local ret = 0
for i,item in pairs(data) do
local tmp = band(ret, 0xFF)
local index = band( bxor(tmp, item), 0xFF)
ret = bxor(rshift(ret,8), _tbl[index][1])
end
return ret
end
---
-- update checksum
-- called: data is string, ( >= 24 hex digits )
-- returns: string, (data concat new checksum)
local function updateChecksum(data)
local part = data:sub(1,24)
local chksum = calculateChecksum( utils.ConvertHexToBytes(part))
return string.format("%s%X", part, chksum)
end
---
-- receives the answer from deviceside, used with a readblock command
local function waitCmd()
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
if response then
local count,cmd,arg0 = bin.unpack('LL',response)
if(arg0==1) then
local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
return data:sub(1,32)
else
return nil, "Couldn't read block.."
end
end
return nil, "No response from device"
end
local function selftest()
local testdata = '000F42430D0A14000001D11F'..'5D738517'
local chksum = getChecksum(testdata)
local calc = calculateChecksum( utils.ConvertHexToBytes(testdata:sub(1,24)))
print ('TESTDATA :: '..testdata)
print ('DATA :: '..testdata:sub(1,24))
print (('CHKSUM :: %X'):format(chksum))
print (('CHKSUM CALC :: %X'):format(calc))
print ('UPDATE CHKSUM :: '..updateChecksum(testdata))
end
---
-- The main entry point
-- -d decrypt
-- -e encrypt
-- -v validate
function main(args)
local cmd, result, err, blockNo, keyA
local blocks = {}
local decryptkey = ''
-- Read the parameters
for o, a in getopt.getopt(args, 'hk:') do
if o == "h" then help() return end
if o == "k" then keyA = a end
end
selftest()
local tst2 = '00100100030209094312356432324E34B79A349B'
-- validate input args.
keyA = keyA or '6dd747e86975'
if #(keyA) ~= 12 then
return oops( string.format('Wrong length of write key (was %d) expected 12', #keyA))
end
-- Turn off Debug
local cmdSetDbgOff = "hf mf dbg 0"
core.console( cmdSetDbgOff)
-- GET TAG UID
result, err = lib14a.read1443a(false)
if not result then
return oops(err)
end
core.clearCommandBuffer()
print(result.uid, keyA)
local my = result.uid
if 1 == 1 then
return
end
-- Show tag info
print((' Found tag %s'):format(result.name))
local longrandom = RANDOM..result.uid
local res = utils.Sha1Hex(longrandom)
res = utils.ConvertBytesToHex(utils.ConvertAsciiToBytes(res:sub(1,16)))
decryptkey = utils.SwapEndiannessStr(res:sub(1,8) , 32)
decryptkey = decryptkey..utils.SwapEndiannessStr( res:sub(9,16),32)
decryptkey = decryptkey..utils.SwapEndiannessStr( res:sub(17,24),32)
decryptkey = decryptkey..utils.SwapEndiannessStr( res:sub(25,32),32)
print('Decrypt key::',decryptkey)
print('Reading card data')
print('Raw','Decrypted')
for blockNo = 0, numBlocks-1, 1 do
if core.ukbhit() then
print("aborted by user")
break
end
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blockNo ,arg2 = 0,arg3 = 0, data = keyA}
local err = core.SendCommand(cmd:getBytes())
if err then return oops(err) end
local blockdata, err = waitCmd()
if err then return oops(err) end
if blockNo%4 ~= 3 then
-- blocks with zero not encrypted.
if string.find(blockdata, '^0+$') then
print(blockdata, blockdata)
else
local aes = core.aes128_decrypt_ecb(decryptkey, blockdata)
local bytes = utils.ConvertAsciiToBytes(aes)
local hex = utils.ConvertBytesToHex(bytes)
print(blockdata , hex)
end
elseif blockNo == 0 then
print(blockdata,blockdata)
else
-- Sectorblocks, not encrypted
local sectortrailer = keyA..blockdata:sub(13,20)..keyA
print(sectortrailer, sectortrailer, blockdata:sub(13,20))
end
end
-- checksum fyra sista bytes i varje rad. (kanske inte för s0)
-- s0b1,s1b0,s2b0,s3b0
--
end
main(args)

View file

@ -73,7 +73,8 @@ local function convert_to_emulform(hexdata)
for i = 1, string.len(hexdata),32 do for i = 1, string.len(hexdata),32 do
ascii = ascii ..string.sub(hexdata,i,i+31).."\n" ascii = ascii ..string.sub(hexdata,i,i+31).."\n"
end end
return ascii
return string.sub(ascii,1,-1)
end end
local function main(args) local function main(args)

View file

@ -80,14 +80,14 @@ function GetCardInfo()
core.clearCommandBuffer() core.clearCommandBuffer()
if 0x18 == result.sak then --NXP MIFARE Classic 4k | Plus 4k if 0x18 == result.sak then -- NXP MIFARE Classic 4k | Plus 4k
-- IFARE Classic 4K offers 4096 bytes split into forty sectors, -- IFARE Classic 4K offers 4096 bytes split into forty sectors,
-- of which 32 are same size as in the 1K with eight more that are quadruple size sectors. -- of which 32 are same size as in the 1K with eight more that are quadruple size sectors.
numSectors = 40 numSectors = 40
elseif 0x08 == result.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k elseif 0x08 == result.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k
-- 1K offers 1024 bytes of data storage, split into 16 sector -- 1K offers 1024 bytes of data storage, split into 16 sector
numSectors = 16 numSectors = 16
elseif 0x09 == result.sak then -- NXP MIFARE Mini 0.3k elseif 0x09 == result.sak then -- NXP MIFARE Mini 0.3k
-- MIFARE Classic mini offers 320 bytes split into five sectors. -- MIFARE Classic mini offers 320 bytes split into five sectors.
numSectors = 5 numSectors = 5
elseif 0x10 == result.sak then -- NXP MIFARE Plus 2k elseif 0x10 == result.sak then -- NXP MIFARE Plus 2k

View file

@ -205,7 +205,7 @@ local function main( args)
-- NDEF compliant? -- NDEF compliant?
if b3chars[1] ~= 0xE1 then if b3chars[1] ~= 0xE1 then
return oops("This tag is not NDEF-Complian") return oops("This tag is not NDEF-Compliant")
end end
local ndefVersion = b3chars[2] local ndefVersion = b3chars[2]

View file

@ -95,6 +95,7 @@ end
function test() function test()
local y local y
local block = "00"
for y = 0x0, 0x1d, 0x4 do for y = 0x0, 0x1d, 0x4 do
for _ = 1, #procedurecmds do for _ = 1, #procedurecmds do
local pcmd = procedurecmds[_] local pcmd = procedurecmds[_]
@ -107,7 +108,7 @@ function test()
dbg(('lf t55xx write 0 %s'):format(config)) dbg(('lf t55xx write 0 %s'):format(config))
config = tonumber(config,16) config = tonumber(config,16)
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK, arg1 = config} local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
local err = core.SendCommand(writecmd:getBytes()) local err = core.SendCommand(writecmd:getBytes())
if err then return oops(err) end if err then return oops(err) end
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)

View file

@ -89,6 +89,7 @@ end
function test() function test()
local y local y
local block = "00"
for y = 1, 0x1D, 4 do for y = 1, 0x1D, 4 do
for _ = 1, #procedurecmds do for _ = 1, #procedurecmds do
local pcmd = procedurecmds[_] local pcmd = procedurecmds[_]
@ -98,10 +99,10 @@ function test()
elseif _ == 1 then elseif _ == 1 then
local config = pcmd:format(config1, y, config2) local config = pcmd:format(config1, y, config2)
dbg(('lf t55xx wr 0 %s'):format(config)) dbg(('lf t55xx write 0 %s'):format(config))
config = tonumber(config,16) config = tonumber(config,16)
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK, arg1 = config} local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
local err = core.SendCommand(writecmd:getBytes()) local err = core.SendCommand(writecmd:getBytes())
if err then return oops(err) end if err then return oops(err) end
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)

View file

@ -92,6 +92,7 @@ end
function test(modulation) function test(modulation)
local y local y
local block = "00"
for y = 0x0, 0x1d, 0x4 do for y = 0x0, 0x1d, 0x4 do
for _ = 1, #procedurecmds do for _ = 1, #procedurecmds do
local pcmd = procedurecmds[_] local pcmd = procedurecmds[_]
@ -104,7 +105,7 @@ function test(modulation)
dbg(('lf t55xx write 0 %s'):format(config)) dbg(('lf t55xx write 0 %s'):format(config))
config = tonumber(config,16) config = tonumber(config,16)
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK, arg1 = config} local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
local err = core.SendCommand(writecmd:getBytes()) local err = core.SendCommand(writecmd:getBytes())
if err then return oops(err) end if err then return oops(err) end
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)

View file

@ -108,6 +108,7 @@ end
function test(modulation) function test(modulation)
local bitrate local bitrate
local clockrate local clockrate
local block = "00"
for bitrate = 0x0, 0x1d, 0x4 do for bitrate = 0x0, 0x1d, 0x4 do
for clockrate = 0,8,4 do for clockrate = 0,8,4 do
@ -125,8 +126,8 @@ function test(modulation)
dbg(('lf t55xx write 0 %s'):format(config)) dbg(('lf t55xx write 0 %s'):format(config))
config = tonumber(config,16) config = tonumber(config,16)
local writecommand = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK, arg1 = config ,arg2 = 0, arg3 = 0} local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
local err = core.SendCommand(writecommand:getBytes()) local err = core.SendCommand(writecmd:getBytes())
if err then return oops(err) end if err then return oops(err) end
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
else else

View file

@ -0,0 +1,165 @@
local cmds = require('commands')
local getopt = require('getopt')
local lib14a = require('read14a')
local utils = require('utils')
local pre = require('precalc')
local toys = require('default_toys')
local lsh = bit32.lshift
local rsh = bit32.rshift
local bor = bit32.bor
local band = bit32.band
example =[[
script run tnp3clone
script run tnp3clone -h
script run tnp3clone -l
script run tnp3clone -t aa00 -s 0030
]]
author = "Iceman"
usage = "script run tnp3clone -t <toytype> -s <subtype>"
desc =[[
This script will try making a barebone clone of a tnp3 tag on to a magic generation1 card.
Arguments:
-h : this help
-l : list all known toy tokens
-t <data> : toytype id, 4hex symbols
-s <data> : subtype id, 4hex symbols
For fun, try the following subtype id:
0612 - Lightcore
0118 - Series 1
0138 - Series 2
0234 - Special
023c - Special
0020 - Swapforce
]]
-- This is only meant to be used when errors occur
function oops(err)
print("ERROR: ",err)
end
-- Usage help
function help()
print(desc)
print("Example usage")
print(example)
end
local function waitCmd()
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,2000)
if response then
local count,cmd,arg0 = bin.unpack('LL',response)
if(arg0==1) then
local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
return data:sub(1,32)
else
return nil, "Couldn't read block."
end
end
return nil, "No response from device"
end
local function readblock( blocknum, keyA )
-- Read block 0
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blocknum, arg2 = 0, arg3 = 0, data = keyA}
err = core.SendCommand(cmd:getBytes())
if err then return nil, err end
local block0, err = waitCmd()
if err then return nil, err end
return block0
end
local function readmagicblock( blocknum )
-- Read block 0
local CSETBLOCK_SINGLE_OPERATION = 0x1F
cmd = Command:new{cmd = cmds.CMD_MIFARE_CGETBLOCK, arg1 = CSETBLOCK_SINGLE_OPERATION, arg2 = 0, arg3 = blocknum}
err = core.SendCommand(cmd:getBytes())
if err then return nil, err end
local block0, err = waitCmd()
if err then return nil, err end
return block0
end
local function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
local numBlocks = 64
local cset = 'hf mf csetbl '
local csetuid = 'hf mf csetuid '
local cget = 'hf mf cgetbl '
local empty = '00000000000000000000000000000000'
local AccAndKeyB = '7F078869000000000000'
-- Defaults to Gusto
local toytype = 'C201'
local subtype = '0030'
local DEBUG = true
-- Arguments for the script
for o, a in getopt.getopt(args, 'ht:s:l') do
if o == "h" then return help() end
if o == "t" then toytype = a end
if o == "s" then subtype = a end
if o == "l" then return toys.List() end
end
if #toytype ~= 4 then return oops('Wrong size - toytype. (4hex symbols)') end
if #subtype ~= 4 then return oops('Wrong size - subtype. (4hex symbols)') end
-- look up type, find & validate types
local item = toys.Find( toytype, subtype)
if item then
print( (' Looking up input: Found %s - %s (%s)'):format(item[6],item[5], item[4]) )
else
print('Didn\'t find item type. If you are sure about it, report it in')
end
--15,16
--13-14
-- find tag
result, err = lib14a.read1443a(false)
if not result then return oops(err) end
-- load keys
local akeys = pre.GetAll(result.uid)
local keyA = akeys:sub(1, 12 )
local b0 = readblock(0,keyA)
if not b0 then
print('failed reading block with factorydefault key. Trying chinese magic read.')
b0, err = readmagicblock(0)
if not b0 then
oops(err)
return oops('failed reading block with chinese magic command. quitting...')
end
end
-- wipe card.
local cmd = (csetuid..'%s 0004 08 w'):format(result.uid)
core.console(cmd)
local b1 = toytype..string.rep('00',10)..subtype
local calc = utils.Crc16(b0..b1)
local calcEndian = bor(rsh(calc,8), lsh(band(calc, 0xff), 8))
local cmd = (cset..'1 %s%04x'):format( b1, calcEndian)
core.console(cmd)
local pos, key
for blockNo = 2, numBlocks-1, 1 do
pos = (math.floor( blockNo / 4 ) * 12)+1
key = akeys:sub(pos, pos + 11 )
if blockNo%4 == 3 then
cmd = ('%s %d %s%s'):format(cset,blockNo,key,AccAndKeyB)
core.console(cmd)
end
end
core.clearCommandBuffer()
end
main(args)

View file

@ -5,19 +5,21 @@ local lib14a = require('read14a')
local utils = require('utils') local utils = require('utils')
local md5 = require('md5') local md5 = require('md5')
local dumplib = require('html_dumplib') local dumplib = require('html_dumplib')
local toyNames = require('default_toys') local toys = require('default_toys')
example =[[ example =[[
1. script run tnp3dump script run tnp3dump
2. script run tnp3dump -n script run tnp3dump -n
3. script run tnp3dump -k aabbccddeeff script run tnp3dump -p
4. script run tnp3dump -k aabbccddeeff -n script run tnp3dump -k aabbccddeeff
5. script run tnp3dump -o myfile script run tnp3dump -k aabbccddeeff -n
6. script run tnp3dump -n -o myfile script run tnp3dump -o myfile
7. script run tnp3dump -k aabbccddeeff -n -o myfile script run tnp3dump -n -o myfile
script run tnp3dump -p -o myfile
script run tnp3dump -k aabbccddeeff -n -o myfile
]] ]]
author = "Iceman" author = "Iceman"
usage = "script run tnp3dump -k <key> -n -o <filename>" usage = "script run tnp3dump -k <key> -n -p -o <filename>"
desc =[[ desc =[[
This script will try to dump the contents of a Mifare TNP3xxx card. This script will try to dump the contents of a Mifare TNP3xxx card.
It will need a valid KeyA in order to find the other keys and decode the card. It will need a valid KeyA in order to find the other keys and decode the card.
@ -25,11 +27,10 @@ Arguments:
-h : this help -h : this help
-k <key> : Sector 0 Key A. -k <key> : Sector 0 Key A.
-n : Use the nested cmd to find all keys -n : Use the nested cmd to find all keys
-p : Use the precalc to find all keys
-o : filename for the saved dumps -o : filename for the saved dumps
]] ]]
local RANDOM = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
local HASHCONSTANT = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
local DEBUG = false -- the debug flag local DEBUG = false -- the debug flag
local numBlocks = 64 local numBlocks = 64
@ -93,16 +94,6 @@ local function waitCmd()
return nil, "No response from device" return nil, "No response from device"
end end
local function computeCrc16(s)
local hash = core.crc16(utils.ConvertHexToAscii(s))
return hash
end
local function reverseCrcBytes(crc)
crc2 = crc:sub(3,4)..crc:sub(1,2)
return tonumber(crc2,16)
end
local function main(args) local function main(args)
print( string.rep('--',20) ) print( string.rep('--',20) )
@ -112,18 +103,20 @@ local function main(args)
local cmd local cmd
local err local err
local useNested = false local useNested = false
local usePreCalc = false
local cmdReadBlockString = 'hf mf rdbl %d A %s' local cmdReadBlockString = 'hf mf rdbl %d A %s'
local input = "dumpkeys.bin" local input = "dumpkeys.bin"
local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S"); local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S");
-- Arguments for the script -- Arguments for the script
for o, a in getopt.getopt(args, 'hk:no:') do for o, a in getopt.getopt(args, 'hk:npo:') do
if o == "h" then return help() end if o == "h" then return help() end
if o == "k" then keyA = a end if o == "k" then keyA = a end
if o == "n" then useNested = true end if o == "n" then useNested = true end
if o == "p" then usePreCalc = true end
if o == "o" then outputTemplate = a end if o == "o" then outputTemplate = a end
end end
-- validate input args. -- validate input args.
keyA = keyA or '4b0b20107ccb' keyA = keyA or '4b0b20107ccb'
if #(keyA) ~= 12 then if #(keyA) ~= 12 then
@ -141,30 +134,31 @@ local function main(args)
core.clearCommandBuffer() core.clearCommandBuffer()
if 0x01 ~= result.sak then -- NXP MIFARE TNP3xxx
return oops('This is not a TNP3xxx tag. aborting.')
end
-- Show tag info -- Show tag info
print((' Found tag : %s'):format(result.name)) print((' Found tag %s'):format(result.name))
print(('Using keyA : %s'):format(keyA))
dbg(('Using keyA : %s'):format(keyA))
--Trying to find the other keys --Trying to find the other keys
if useNested then if useNested then
core.console( ('hf mf nested 1 0 A %s d'):format(keyA) ) core.console( ('hf mf nested 1 0 A %s d'):format(keyA) )
end end
core.clearCommandBuffer() core.clearCommandBuffer()
-- Loading keyfile local akeys = ''
print('Loading dumpkeys.bin') if usePreCalc then
local hex, err = utils.ReadDumpFile(input) local pre = require('precalc')
if not hex then akeys = pre.GetAll(result.uid)
return oops(err) else
print('Loading dumpkeys.bin')
local hex, err = utils.ReadDumpFile(input)
if not hex then
return oops(err)
end
akeys = hex:sub(0,12*16)
end end
local akeys = hex:sub(0,12*16)
-- Read block 0 -- Read block 0
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0,arg2 = 0,arg3 = 0, data = keyA} cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0,arg2 = 0,arg3 = 0, data = keyA}
err = core.SendCommand(cmd:getBytes()) err = core.SendCommand(cmd:getBytes())
@ -179,6 +173,8 @@ local function main(args)
local block1, err = waitCmd() local block1, err = waitCmd()
if err then return oops(err) end if err then return oops(err) end
local tmpHash = block0..block1..'%02x'..RANDOM
local key local key
local pos = 0 local pos = 0
local blockNo local blockNo
@ -188,7 +184,7 @@ local function main(args)
core.clearCommandBuffer() core.clearCommandBuffer()
-- main loop -- main loop
io.write('Decrypting blocks > ') io.write('Reading blocks > ')
for blockNo = 0, numBlocks-1, 1 do for blockNo = 0, numBlocks-1, 1 do
if core.ukbhit() then if core.ukbhit() then
@ -204,25 +200,24 @@ local function main(args)
local blockdata, err = waitCmd() local blockdata, err = waitCmd()
if err then return oops(err) end if err then return oops(err) end
if blockNo%4 ~= 3 then if blockNo%4 ~= 3 then
if blockNo < 8 then if blockNo < 8 then
-- Block 0-7 not encrypted -- Block 0-7 not encrypted
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata) blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata)
else else
local base = ('%s%s%02x%s'):format(block0, block1, blockNo, HASHCONSTANT)
local baseStr = utils.ConvertHexToAscii(base)
local md5hash = md5.sumhexa(baseStr)
local aestest = core.aes(md5hash, blockdata)
local hex = utils.ConvertAsciiToBytes(aestest)
hex = utils.ConvertBytesToHex(hex)
-- blocks with zero not encrypted. -- blocks with zero not encrypted.
if string.find(blockdata, '^0+$') then if string.find(blockdata, '^0+$') then
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata) blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata)
else else
local baseStr = utils.ConvertHexToAscii(tmpHash:format(blockNo))
local key = md5.sumhexa(baseStr)
local aestest = core.aes128_decrypt(key, blockdata)
local hex = utils.ConvertAsciiToBytes(aestest)
hex = utils.ConvertBytesToHex(hex)
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,hex) blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,hex)
io.write( blockNo..',') io.write(blockNo..',')
end end
end end
else else
@ -246,31 +241,40 @@ local function main(args)
emldata = emldata..slice..'\n' emldata = emldata..slice..'\n'
for c in (str):gmatch('.') do for c in (str):gmatch('.') do
bindata[#bindata+1] = c bindata[#bindata+1] = c
end end
end end
print( string.rep('--',20) )
local uid = block0:sub(1,8) local uid = block0:sub(1,8)
local itemtype = block1:sub(1,4) local toytype = block1:sub(1,4)
local cardidLsw = block1:sub(9,16)
local cardidMsw = block1:sub(16,24)
local cardid = block1:sub(9,24) local cardid = block1:sub(9,24)
local traptype = block1:sub(25,28) local subtype = block1:sub(25,28)
-- Write dump to files -- Write dump to files
if not DEBUG then if not DEBUG then
local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'_uid_'..uid..'.bin') local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'-'..uid..'.bin')
print(("Wrote a BIN dump to the file %s"):format(foo)) print(("Wrote a BIN dump to: %s"):format(foo))
local bar = dumplib.SaveAsText(emldata, outputTemplate..'_uid_'..uid..'.eml') local bar = dumplib.SaveAsText(emldata, outputTemplate..'-'..uid..'.eml')
print(("Wrote a EML dump to the file %s"):format(bar)) print(("Wrote a EML dump to: %s"):format(bar))
end end
-- Show info
print( string.rep('--',20) )
print( (' ITEM TYPE : 0x%s - %s'):format(itemtype, toyNames[itemtype]) )
print( (' Alter ego / traptype : 0x%s'):format(traptype) )
print( (' UID : 0x%s'):format(uid) )
print( (' CARDID : 0x%s'):format(cardid ) )
print( string.rep('--',20) ) print( string.rep('--',20) )
-- Show info
local item = toys.Find(toytype, subtype)
if item then
print((' ITEM TYPE : %s - %s (%s)'):format(item[6],item[5], item[4]) )
else
print((' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype))
end
print( (' UID : 0x%s'):format(uid) )
print( (' CARDID : 0x%s'):format(cardid ) )
print( string.rep('--',20) )
core.clearCommandBuffer()
end end
main(args) main(args)

View file

@ -4,7 +4,7 @@ local bin = require('bin')
local lib14a = require('read14a') local lib14a = require('read14a')
local utils = require('utils') local utils = require('utils')
local md5 = require('md5') local md5 = require('md5')
local toyNames = require('default_toys') local toys = require('default_toys')
example =[[ example =[[
1. script run tnp3sim 1. script run tnp3sim
@ -23,10 +23,33 @@ Arguments:
-h : this help -h : this help
-m : Maxed out items (experimental) -m : Maxed out items (experimental)
-i : filename for the datadump to read (bin) -i : filename for the datadump to read (bin)
]]
]]
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
local DEBUG = true -- the debug flag local DEBUG = false -- the debug flag
local RANDOM = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
local band = bit32.band
local bor = bit32.bor
local lshift = bit32.lshift
local rshift = bit32.rshift
local byte = string.byte
local char = string.char
local sub = string.sub
local format = string.format
local band = bit32.band
local bor = bit32.bor
local lshift = bit32.lshift
local rshift = bit32.rshift
local byte = string.byte
local char = string.char
local sub = string.sub
local format = string.format
--- ---
-- A debug printout-function -- A debug printout-function
function dbg(args) function dbg(args)
@ -65,7 +88,6 @@ function ExitMsg(msg)
print() print()
end end
local function writedumpfile(infile) local function writedumpfile(infile)
t = infile:read("*all") t = infile:read("*all")
len = string.len(t) len = string.len(t)
@ -187,9 +209,6 @@ local function ValidateCheckSums(blocks)
io.write( ('TYPE 3 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk)) io.write( ('TYPE 3 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk))
end end
local function LoadEmulator(blocks)
local HASHCONSTANT = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
local cmd local cmd
local blockdata local blockdata
for _,b in pairs(blocks) do for _,b in pairs(blocks) do
@ -198,10 +217,10 @@ local function LoadEmulator(blocks)
if _%4 ~= 3 then if _%4 ~= 3 then
if (_ >= 8 and _<=21) or (_ >= 36 and _<=49) then if (_ >= 8 and _<=21) or (_ >= 36 and _<=49) then
local base = ('%s%s%02x%s'):format(blocks[0], blocks[1], _ , HASHCONSTANT) local base = ('%s%s%02x%s'):format(blocks[0], blocks[1], _ , RANDOM)
local baseStr = utils.ConvertHexToAscii(base) local baseStr = utils.ConvertHexToAscii(base)
local key = md5.sumhexa(baseStr) local key = md5.sumhexa(baseStr)
local enc = core.aes(key, blockdata) local enc = core.aes128_encrypt(key, blockdata)
local hex = utils.ConvertAsciiToBytes(enc) local hex = utils.ConvertAsciiToBytes(enc)
hex = utils.ConvertBytesToHex(hex) hex = utils.ConvertBytesToHex(hex)
@ -219,6 +238,102 @@ local function LoadEmulator(blocks)
io.write('\n') io.write('\n')
end end
local function Num2Card(m, l)
local k = {
0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,0x42, 0x43, 0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B,
0x4C, 0x4D, 0x4E, 0x50, 0x51, 0x52, 0x53, 0x54,0x56, 0x57, 0x58, 0x59, 0x5A, 0x00
}
local msw = tonumber(utils.SwapEndiannessStr(m,32),16)
local lsw = tonumber(utils.SwapEndiannessStr(l,32),16)
if msw > 0x17ea1 then
return "too big"
end
if msw == 0x17ea1 and lsw > 0x8931fee8 then
return "out of range"
end
local s = ""
local index
for i = 1,10 do
index, msw, lsw = DivideByK( msw, lsw)
if ( index <= 1 ) then
s = char(k[index]) .. s
else
s = char(k[index-1]) .. s
end
print (index-1, msw, lsw)
end
return s
end
--33LRT-LM9Q9
--7, 122, 3474858630
--20, 4, 1008436634
--7, 0, 627182959
--17, 0, 21626998
--16, 0, 745758
--23, 0, 25715
--21, 0, 886
--16, 0, 30
--1, 0, 1
--1, 0, 0
function DivideByK(msw, lsw)
local lowLSW
local highLSW
local remainder = 0
local RADIX = 29
--local num = 0 | band( rshift(msw,16), 0xffff)
local num = band( rshift(msw, 16), 0xffff)
--highLSW = 0 | lshift( (num / RADIX) , 16)
highLSW = lshift( (num / RADIX) , 16)
remainder = num % RADIX
num = bor( lshift(remainder,16), band(msw, 0xffff))
--highLSW |= num / RADIX
highLSW = highLSW or (num / RADIX)
remainder = num % RADIX
num = bor( lshift(remainder,16), ( band(rshift(lsw,16), 0xffff)))
--lowLSW = 0 | (num / RADIX) << 16
lowLSW = 0 or (lshift( (num / RADIX), 16))
remainder = num % RADIX
num = bor( lshift(remainder,16) , band(lsw, 0xffff) )
lowLSW = bor(lowLSW, (num / RADIX))
remainder = num % RADIX
return remainder, highLSW, lowLSW
-- uint num = 0 | (msw >> 16) & 0xffff;
-- highLSW = 0 | (num / RADIX) << 16;
-- remainder = num % RADIX;
-- num = (remainder << 16) | (msw & 0xffff);
-- highLSW |= num / RADIX;
-- remainder = num % RADIX;
-- num = (remainder << 16) | ((lsw >> 16) & 0xffff);
-- lowLSW = 0 | (num / RADIX) << 16;
-- remainder = num % RADIX;
-- num = (remainder << 16) | (lsw & 0xffff);
-- lowLSW |= num / RADIX;
-- remainder = num % RADIX;
end
local function main(args) local function main(args)
print( string.rep('--',20) ) print( string.rep('--',20) )
@ -241,21 +356,6 @@ local function main(args)
local cmdSetDbgOff = "hf mf dbg 0" local cmdSetDbgOff = "hf mf dbg 0"
core.console( cmdSetDbgOff) core.console( cmdSetDbgOff)
-- if not loadFromDump then
-- -- Look for tag present on reader,
-- result, err = lib14a.read1443a(false)
-- if not result then return oops(err) end
-- core.clearCommandBuffer()
-- if 0x01 ~= result.sak then -- NXP MIFARE TNP3xxx
-- return oops('This is not a TNP3xxx tag. aborting.')
-- end
-- -- Show tag info
-- print((' Found tag : %s'):format(result.name))
-- end
-- Load dump.bin file -- Load dump.bin file
print( (' Load data from %s'):format(inputTemplate)) print( (' Load data from %s'):format(inputTemplate))
hex, err = utils.ReadDumpFile(inputTemplate) hex, err = utils.ReadDumpFile(inputTemplate)
@ -269,7 +369,7 @@ local function main(args)
end end
if DEBUG then if DEBUG then
print('Validating checksums in the loaded datadump') print(' Validating checksums')
ValidateCheckSums(blocks) ValidateCheckSums(blocks)
end end
@ -277,22 +377,44 @@ local function main(args)
print( string.rep('--',20) ) print( string.rep('--',20) )
print(' Gathering info') print(' Gathering info')
local uid = blocks[0]:sub(1,8) local uid = blocks[0]:sub(1,8)
local itemtype = blocks[1]:sub(1,4) local toytype = blocks[1]:sub(1,4)
local cardid = blocks[1]:sub(9,24) local cardidLsw = blocks[1]:sub(9,16)
local cardidMsw = blocks[1]:sub(17,24)
local subtype = blocks[1]:sub(25,28)
-- Show info -- Show info
print( string.rep('--',20) ) print( string.rep('--',20) )
print( (' ITEM TYPE : 0x%s - %s'):format(itemtype, toyNames[itemtype]) )
local item = toys.Find( toytype, subtype)
if item then
local itemStr = ('%s - %s (%s)'):format(item[6],item[5], item[4])
print(' ITEM TYPE : '..itemStr )
else
print( (' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype) )
end
print( (' UID : 0x%s'):format(uid) ) print( (' UID : 0x%s'):format(uid) )
print( (' CARDID : 0x%s'):format(cardid ) ) print( (' CARDID : 0x%s %s [%s]'):format(
cardidMsw,cardidLsw,
--Num2Card(cardidMsw, cardidLsw))
'')
)
print( string.rep('--',20) ) print( string.rep('--',20) )
-- lets do something.
-- -- Experience should be:
local experience = blocks[8]:sub(1,6) local experience = blocks[8]:sub(1,6)
print(('Experience : %d'):format(utils.SwapEndianness(experience,24))) print(('Experience : %d'):format(utils.SwapEndianness(experience,16)))
local money = blocks[8]:sub(7,10) local money = blocks[8]:sub(7,10)
print(('Money : %d'):format(utils.SwapEndianness(money,16))) print(('Money : %d'):format(utils.SwapEndianness(money,16)))
--
-- Sequence number
local seqnum = blocks[8]:sub(18,19)
print(('Sequence number : %d'):format( tonumber(seqnum,16)))
local fairy = blocks[9]:sub(1,8) local fairy = blocks[9]:sub(1,8)
--FD0F = Left, FF0F = Right --FD0F = Left, FF0F = Right
local path = 'not choosen' local path = 'not choosen'
@ -305,6 +427,12 @@ local function main(args)
local hat = blocks[9]:sub(8,11) local hat = blocks[9]:sub(8,11)
print(('Hat : %d'):format(utils.SwapEndianness(hat,16))) print(('Hat : %d'):format(utils.SwapEndianness(hat,16)))
local level = blocks[13]:sub(27,28)
print(('LEVEL : %d'):format( tonumber(level,16)))
--hälsa: 667 029b
--local health = blocks[]:sub();
--print(('Health : %d'):format( tonumber(health,16))
--0x0D 0x29 0x0A 0x02 16-bit hero points value. Maximum 100. --0x0D 0x29 0x0A 0x02 16-bit hero points value. Maximum 100.
local heropoints = blocks[13]:sub(20,23) local heropoints = blocks[13]:sub(20,23)
@ -314,6 +442,11 @@ local function main(args)
local challenges = blocks[16]:sub(25,32) local challenges = blocks[16]:sub(25,32)
print(('Finished hero challenges : %d'):format(utils.SwapEndianness(challenges,32))) print(('Finished hero challenges : %d'):format(utils.SwapEndianness(challenges,32)))
-- Character Name
local name1 = blocks[10]:sub(1,32)
local name2 = blocks[12]:sub(1,32)
print('Custom name : '..utils.ConvertHexToAscii(name1..name2))
if maxed then if maxed then
print('Lets try to max out some values') print('Lets try to max out some values')
-- max out money, experience -- max out money, experience
@ -351,7 +484,7 @@ local function main(args)
err = LoadEmulator(blocks) err = LoadEmulator(blocks)
if err then return oops(err) end if err then return oops(err) end
core.clearCommandBuffer() core.clearCommandBuffer()
print('The simulation is now prepared.\n --> run \"hf mf sim u '..uid..' x\" <--') print('The simulation is now prepared.\n --> run \"hf mf sim u '..uid..'\" <--')
end end
end end
main(args) main(args)

View file

@ -108,11 +108,12 @@ void print_hex(const uint8_t * data, const size_t len)
printf("\n"); printf("\n");
} }
char * sprint_hex(const uint8_t * data, const size_t len) { char *sprint_hex(const uint8_t *data, const size_t len) {
int maxLen = ( len > 1024/3) ? 1024/3 : len; int maxLen = ( len > 1024/3) ? 1024/3 : len;
static char buf[1024]; static char buf[1024];
char * tmp = buf; memset(buf, 0x00, 1024);
char *tmp = buf;
size_t i; size_t i;
for (i=0; i < maxLen; ++i, tmp += 3) for (i=0; i < maxLen; ++i, tmp += 3)
@ -121,19 +122,25 @@ char * sprint_hex(const uint8_t * data, const size_t len) {
return buf; return buf;
} }
char * sprint_bin(const uint8_t * data, const size_t len) { char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t breaks) {
int maxLen = ( len > 1024) ? 1024 : len; int maxLen = ( len > 1020) ? 1020 : len;
static char buf[1024]; static char buf[1024];
char * tmp = buf; memset(buf, 0x00, 1024);
size_t i; char *tmp = buf;
for (i=0; i < maxLen; ++i, ++tmp) for (size_t i=0; i < maxLen; ++i){
sprintf(tmp, "%u", data[i]); sprintf(tmp++, "%u", data[i]);
if (breaks > 0 && !((i+1) % breaks))
sprintf(tmp++, "%s","\n");
}
return buf; return buf;
} }
char *sprint_bin(const uint8_t *data, const size_t len) {
return sprint_bin_break(data, len, 0);
}
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest) void num_to_bytes(uint64_t n, size_t len, uint8_t* dest)
{ {
while (len--) { while (len--) {
@ -153,6 +160,22 @@ uint64_t bytes_to_num(uint8_t* src, size_t len)
return num; return num;
} }
// aa,bb,cc,dd,ee,ff,gg,hh, ii,jj,kk,ll,mm,nn,oo,pp
// to
// hh,gg,ff,ee,dd,cc,bb,aa, pp,oo,nn,mm,ll,kk,jj,ii
// up to 64 bytes or 512 bits
uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize){
static uint8_t buf[64];
memset(buf, 0x00, 64);
uint8_t *tmp = buf;
for (uint8_t block=0; block < (uint8_t)(len/blockSize); block++){
for (size_t i = 0; i < blockSize; i++){
tmp[i+(blockSize*block)] = src[(blockSize-1-i)+(blockSize*block)];
}
}
return tmp;
}
//assumes little endian //assumes little endian
char * printBits(size_t const size, void const * const ptr) char * printBits(size_t const size, void const * const ptr)
{ {
@ -371,7 +394,7 @@ int hextobinstring(char *target, char *source)
// convert binary array of 0x00/0x01 values to hex (safe to do in place as target will always be shorter than source) // convert binary array of 0x00/0x01 values to hex (safe to do in place as target will always be shorter than source)
// return number of bits converted // return number of bits converted
int binarraytohex(char *target, char *source, int length) int binarraytohex(char *target,char *source, int length)
{ {
unsigned char i, x; unsigned char i, x;
int j = length; int j = length;
@ -421,3 +444,12 @@ void wiegand_add_parity(char *target, char *source, char length)
target += length; target += length;
*(target)= GetParity(source + length / 2, ODD, length / 2); *(target)= GetParity(source + length / 2, ODD, length / 2);
} }
void xor(unsigned char *dst, unsigned char *src, size_t len) {
for( ; len > 0; len--,dst++,src++)
*dst ^= *src;
}
int32_t le24toh (uint8_t data[3]) {
return (data[2] << 16) | (data[1] << 8) | data[0];
}

View file

@ -39,10 +39,12 @@ void FillFileNameByUID(char *fileName, uint8_t * uid, char *ext, int byteCount);
void print_hex(const uint8_t * data, const size_t len); void print_hex(const uint8_t * data, const size_t len);
char * sprint_hex(const uint8_t * data, const size_t len); char * sprint_hex(const uint8_t * data, const size_t len);
char * sprint_bin(const uint8_t * data, const size_t len); char * sprint_bin(const uint8_t * data, const size_t len);
char * sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t breaks);
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest); void num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
uint64_t bytes_to_num(uint8_t* src, size_t len); uint64_t bytes_to_num(uint8_t* src, size_t len);
char * printBits(size_t const size, void const * const ptr); char * printBits(size_t const size, void const * const ptr);
uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize);
char param_getchar(const char *line, int paramnum); char param_getchar(const char *line, int paramnum);
uint8_t param_get8(const char *line, int paramnum); uint8_t param_get8(const char *line, int paramnum);
@ -61,3 +63,5 @@ void binarraytobinstring(char *target, char *source, int length);
uint8_t GetParity( char *string, uint8_t type, int length); uint8_t GetParity( char *string, uint8_t type, int length);
void wiegand_add_parity(char *target, char *source, char length); void wiegand_add_parity(char *target, char *source, char length);
void xor(unsigned char *dst, unsigned char *src, size_t len);
int32_t le24toh(uint8_t data[3]);

View file

@ -25,6 +25,7 @@ CC = $(CROSS)gcc
AS = $(CROSS)as AS = $(CROSS)as
LD = $(CROSS)ld LD = $(CROSS)ld
OBJCOPY = $(CROSS)objcopy OBJCOPY = $(CROSS)objcopy
GZIP=gzip
OBJDIR = obj OBJDIR = obj
@ -61,8 +62,8 @@ DETECTED_OS=Windows
endif endif
# Also search prerequisites in the common directory (for usb.c), and the fpga directory (for fpga.bit) # Also search prerequisites in the common directory (for usb.c), the fpga directory (for fpga.bit), and the zlib directory
VPATH = . ../common/ ../fpga/ VPATH = . ../common ../fpga ../zlib
INCLUDES = ../include/proxmark3.h ../include/at91sam7s512.h ../include/config_gpio.h ../include/usb_cmd.h $(APP_INCLUDES) INCLUDES = ../include/proxmark3.h ../include/at91sam7s512.h ../include/config_gpio.h ../include/usb_cmd.h $(APP_INCLUDES)
@ -71,9 +72,9 @@ LDFLAGS = -nostartfiles -nodefaultlibs -Wl,-gc-sections -n
LIBS = -lgcc LIBS = -lgcc
THUMBOBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(THUMBSRC)) THUMBOBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(THUMBSRC)))
ARMOBJ = $(ARMSRC:%.c=$(OBJDIR)/%.o) ARMOBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(ARMSRC)))
ASMOBJ = $(patsubst %.s,$(OBJDIR)/%.o,$(ASMSRC)) ASMOBJ = $(patsubst %.s,$(OBJDIR)/%.o,$(notdir $(ASMSRC)))
VERSIONOBJ = $(OBJDIR)/version.o VERSIONOBJ = $(OBJDIR)/version.o
$(THUMBOBJ): $(OBJDIR)/%.o: %.c $(INCLUDES) $(THUMBOBJ): $(OBJDIR)/%.o: %.c $(INCLUDES)
@ -109,6 +110,7 @@ DEPENDENCY_FILES = $(patsubst %.c,$(OBJDIR)/%.d,$(notdir $(THUMBSRC))) \
$(patsubst %.s,$(OBJDIR)/%.d,$(notdir $(ASMSRC))) $(patsubst %.s,$(OBJDIR)/%.d,$(notdir $(ASMSRC)))
$(DEPENDENCY_FILES): Makefile ../common/Makefile.common $(DEPENDENCY_FILES): Makefile ../common/Makefile.common
$(patsubst %.o,%.d,$(THUMBOBJ) $(ARMOBJ)): $(OBJDIR)/%.d: %.c $(patsubst %.o,%.d,$(THUMBOBJ) $(ARMOBJ)): $(OBJDIR)/%.d: %.c
@$(CC) -MM -MT "$(@) $(@:.d=.o)" $(CFLAGS) $< > $@ @$(CC) -MM -MT "$(@) $(@:.d=.o)" $(CFLAGS) $< > $@
$(patsubst %.o,%.d,$(ASMOBJ)):$(OBJDIR)/%.d: %.s $(patsubst %.o,%.d,$(ASMOBJ)):$(OBJDIR)/%.d: %.s

View file

@ -8,38 +8,54 @@
#include "crc16.h" #include "crc16.h"
unsigned short update_crc16( unsigned short crc, unsigned char c ) unsigned short update_crc16( unsigned short crc, unsigned char c )
{ {
unsigned short i, v, tcrc = 0; unsigned short i, v, tcrc = 0;
v = (crc ^ c) & 0xff; v = (crc ^ c) & 0xff;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
tcrc = ( (tcrc ^ v) & 1 ) ? ( tcrc >> 1 ) ^ 0x8408 : tcrc >> 1; tcrc = ( (tcrc ^ v) & 1 ) ? ( tcrc >> 1 ) ^ 0x8408 : tcrc >> 1;
v >>= 1; v >>= 1;
} }
return ((crc >> 8) ^ tcrc)&0xffff; return ((crc >> 8) ^ tcrc)&0xffff;
} }
uint16_t crc16(uint8_t const *message, int length, uint16_t remainder, uint16_t polynomial) { uint16_t crc16(uint8_t const *message, int length, uint16_t remainder, uint16_t polynomial) {
if (length == 0) if (length == 0) return (~remainder);
return (~remainder);
for (int byte = 0; byte < length; ++byte) {
for (int byte = 0; byte < length; ++byte) { remainder ^= (message[byte] << 8);
remainder ^= (message[byte] << 8); for (uint8_t bit = 8; bit > 0; --bit) {
for (uint8_t bit = 8; bit > 0; --bit) { if (remainder & 0x8000) {
if (remainder & 0x8000) { remainder = (remainder << 1) ^ polynomial;
remainder = (remainder << 1) ^ polynomial; } else {
} else { remainder = (remainder << 1);
remainder = (remainder << 1); }
} }
} }
} return remainder;
return remainder;
} }
uint16_t crc16_ccitt(uint8_t const *message, int length) { uint16_t crc16_ccitt(uint8_t const *message, int length) {
return crc16(message, length, 0xffff, 0x1021); return crc16(message, length, 0xffff, 0x1021);
}
uint16_t crc16_ccitt_kermit(uint8_t const *message, int length) {
return bit_reverse_uint16(crc16(message, length, 0x0000, 0x1021));
}
uint16_t bit_reverse_uint16 (uint16_t value) {
const uint16_t mask0 = 0x5555;
const uint16_t mask1 = 0x3333;
const uint16_t mask2 = 0x0F0F;
const uint16_t mask3 = 0x00FF;
value = (((~mask0) & value) >> 1) | ((mask0 & value) << 1);
value = (((~mask1) & value) >> 2) | ((mask1 & value) << 2);
value = (((~mask2) & value) >> 4) | ((mask2 & value) << 4);
value = (((~mask3) & value) >> 8) | ((mask3 & value) << 8);
return value;
} }

View file

@ -12,4 +12,6 @@
unsigned short update_crc16(unsigned short crc, unsigned char c); unsigned short update_crc16(unsigned short crc, unsigned char c);
uint16_t crc16(uint8_t const *message, int length, uint16_t remainder, uint16_t polynomial); uint16_t crc16(uint8_t const *message, int length, uint16_t remainder, uint16_t polynomial);
uint16_t crc16_ccitt(uint8_t const *message, int length); uint16_t crc16_ccitt(uint8_t const *message, int length);
uint16_t crc16_ccitt_kermit(uint8_t const *message, int length);
uint16_t bit_reverse_uint16 (uint16_t value);
#endif #endif

85
common/crc64.c Normal file
View file

@ -0,0 +1,85 @@
#include <stdint.h>
#include <stddef.h>
#include "crc64.h"
#define CRC64_ISO_PRESET 0xFFFFFFFFFFFFFFFF
#define CRC64_ECMA_PRESET 0x0000000000000000
const uint64_t crc64_table[] = {
0x0000000000000000, 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26, 0xC711223CFA3E5BB5,
0x493366450E42ECDF, 0x0BC387AEA7A8DA4C, 0xCCD2A5925D9681F9, 0x8E224479F47CB76A,
0x9266CC8A1C85D9BE, 0xD0962D61B56FEF2D, 0x17870F5D4F51B498, 0x5577EEB6E6BB820B,
0xDB55AACF12C73561, 0x99A54B24BB2D03F2, 0x5EB4691841135847, 0x1C4488F3E8F96ED4,
0x663D78FF90E185EF, 0x24CD9914390BB37C, 0xE3DCBB28C335E8C9, 0xA12C5AC36ADFDE5A,
0x2F0E1EBA9EA36930, 0x6DFEFF5137495FA3, 0xAAEFDD6DCD770416, 0xE81F3C86649D3285,
0xF45BB4758C645C51, 0xB6AB559E258E6AC2, 0x71BA77A2DFB03177, 0x334A9649765A07E4,
0xBD68D2308226B08E, 0xFF9833DB2BCC861D, 0x388911E7D1F2DDA8, 0x7A79F00C7818EB3B,
0xCC7AF1FF21C30BDE, 0x8E8A101488293D4D, 0x499B3228721766F8, 0x0B6BD3C3DBFD506B,
0x854997BA2F81E701, 0xC7B97651866BD192, 0x00A8546D7C558A27, 0x4258B586D5BFBCB4,
0x5E1C3D753D46D260, 0x1CECDC9E94ACE4F3, 0xDBFDFEA26E92BF46, 0x990D1F49C77889D5,
0x172F5B3033043EBF, 0x55DFBADB9AEE082C, 0x92CE98E760D05399, 0xD03E790CC93A650A,
0xAA478900B1228E31, 0xE8B768EB18C8B8A2, 0x2FA64AD7E2F6E317, 0x6D56AB3C4B1CD584,
0xE374EF45BF6062EE, 0xA1840EAE168A547D, 0x66952C92ECB40FC8, 0x2465CD79455E395B,
0x3821458AADA7578F, 0x7AD1A461044D611C, 0xBDC0865DFE733AA9, 0xFF3067B657990C3A,
0x711223CFA3E5BB50, 0x33E2C2240A0F8DC3, 0xF4F3E018F031D676, 0xB60301F359DBE0E5,
0xDA050215EA6C212F, 0x98F5E3FE438617BC, 0x5FE4C1C2B9B84C09, 0x1D14202910527A9A,
0x93366450E42ECDF0, 0xD1C685BB4DC4FB63, 0x16D7A787B7FAA0D6, 0x5427466C1E109645,
0x4863CE9FF6E9F891, 0x0A932F745F03CE02, 0xCD820D48A53D95B7, 0x8F72ECA30CD7A324,
0x0150A8DAF8AB144E, 0x43A04931514122DD, 0x84B16B0DAB7F7968, 0xC6418AE602954FFB,
0xBC387AEA7A8DA4C0, 0xFEC89B01D3679253, 0x39D9B93D2959C9E6, 0x7B2958D680B3FF75,
0xF50B1CAF74CF481F, 0xB7FBFD44DD257E8C, 0x70EADF78271B2539, 0x321A3E938EF113AA,
0x2E5EB66066087D7E, 0x6CAE578BCFE24BED, 0xABBF75B735DC1058, 0xE94F945C9C3626CB,
0x676DD025684A91A1, 0x259D31CEC1A0A732, 0xE28C13F23B9EFC87, 0xA07CF2199274CA14,
0x167FF3EACBAF2AF1, 0x548F120162451C62, 0x939E303D987B47D7, 0xD16ED1D631917144,
0x5F4C95AFC5EDC62E, 0x1DBC74446C07F0BD, 0xDAAD56789639AB08, 0x985DB7933FD39D9B,
0x84193F60D72AF34F, 0xC6E9DE8B7EC0C5DC, 0x01F8FCB784FE9E69, 0x43081D5C2D14A8FA,
0xCD2A5925D9681F90, 0x8FDAB8CE70822903, 0x48CB9AF28ABC72B6, 0x0A3B7B1923564425,
0x70428B155B4EAF1E, 0x32B26AFEF2A4998D, 0xF5A348C2089AC238, 0xB753A929A170F4AB,
0x3971ED50550C43C1, 0x7B810CBBFCE67552, 0xBC902E8706D82EE7, 0xFE60CF6CAF321874,
0xE224479F47CB76A0, 0xA0D4A674EE214033, 0x67C58448141F1B86, 0x253565A3BDF52D15,
0xAB1721DA49899A7F, 0xE9E7C031E063ACEC, 0x2EF6E20D1A5DF759, 0x6C0603E6B3B7C1CA,
0xF6FAE5C07D3274CD, 0xB40A042BD4D8425E, 0x731B26172EE619EB, 0x31EBC7FC870C2F78,
0xBFC9838573709812, 0xFD39626EDA9AAE81, 0x3A28405220A4F534, 0x78D8A1B9894EC3A7,
0x649C294A61B7AD73, 0x266CC8A1C85D9BE0, 0xE17DEA9D3263C055, 0xA38D0B769B89F6C6,
0x2DAF4F0F6FF541AC, 0x6F5FAEE4C61F773F, 0xA84E8CD83C212C8A, 0xEABE6D3395CB1A19,
0x90C79D3FEDD3F122, 0xD2377CD44439C7B1, 0x15265EE8BE079C04, 0x57D6BF0317EDAA97,
0xD9F4FB7AE3911DFD, 0x9B041A914A7B2B6E, 0x5C1538ADB04570DB, 0x1EE5D94619AF4648,
0x02A151B5F156289C, 0x4051B05E58BC1E0F, 0x87409262A28245BA, 0xC5B073890B687329,
0x4B9237F0FF14C443, 0x0962D61B56FEF2D0, 0xCE73F427ACC0A965, 0x8C8315CC052A9FF6,
0x3A80143F5CF17F13, 0x7870F5D4F51B4980, 0xBF61D7E80F251235, 0xFD913603A6CF24A6,
0x73B3727A52B393CC, 0x31439391FB59A55F, 0xF652B1AD0167FEEA, 0xB4A25046A88DC879,
0xA8E6D8B54074A6AD, 0xEA16395EE99E903E, 0x2D071B6213A0CB8B, 0x6FF7FA89BA4AFD18,
0xE1D5BEF04E364A72, 0xA3255F1BE7DC7CE1, 0x64347D271DE22754, 0x26C49CCCB40811C7,
0x5CBD6CC0CC10FAFC, 0x1E4D8D2B65FACC6F, 0xD95CAF179FC497DA, 0x9BAC4EFC362EA149,
0x158E0A85C2521623, 0x577EEB6E6BB820B0, 0x906FC95291867B05, 0xD29F28B9386C4D96,
0xCEDBA04AD0952342, 0x8C2B41A1797F15D1, 0x4B3A639D83414E64, 0x09CA82762AAB78F7,
0x87E8C60FDED7CF9D, 0xC51827E4773DF90E, 0x020905D88D03A2BB, 0x40F9E43324E99428,
0x2CFFE7D5975E55E2, 0x6E0F063E3EB46371, 0xA91E2402C48A38C4, 0xEBEEC5E96D600E57,
0x65CC8190991CB93D, 0x273C607B30F68FAE, 0xE02D4247CAC8D41B, 0xA2DDA3AC6322E288,
0xBE992B5F8BDB8C5C, 0xFC69CAB42231BACF, 0x3B78E888D80FE17A, 0x7988096371E5D7E9,
0xF7AA4D1A85996083, 0xB55AACF12C735610, 0x724B8ECDD64D0DA5, 0x30BB6F267FA73B36,
0x4AC29F2A07BFD00D, 0x08327EC1AE55E69E, 0xCF235CFD546BBD2B, 0x8DD3BD16FD818BB8,
0x03F1F96F09FD3CD2, 0x41011884A0170A41, 0x86103AB85A2951F4, 0xC4E0DB53F3C36767,
0xD8A453A01B3A09B3, 0x9A54B24BB2D03F20, 0x5D45907748EE6495, 0x1FB5719CE1045206,
0x919735E51578E56C, 0xD367D40EBC92D3FF, 0x1476F63246AC884A, 0x568617D9EF46BED9,
0xE085162AB69D5E3C, 0xA275F7C11F7768AF, 0x6564D5FDE549331A, 0x279434164CA30589,
0xA9B6706FB8DFB2E3, 0xEB46918411358470, 0x2C57B3B8EB0BDFC5, 0x6EA7525342E1E956,
0x72E3DAA0AA188782, 0x30133B4B03F2B111, 0xF7021977F9CCEAA4, 0xB5F2F89C5026DC37,
0x3BD0BCE5A45A6B5D, 0x79205D0E0DB05DCE, 0xBE317F32F78E067B, 0xFCC19ED95E6430E8,
0x86B86ED5267CDBD3, 0xC4488F3E8F96ED40, 0x0359AD0275A8B6F5, 0x41A94CE9DC428066,
0xCF8B0890283E370C, 0x8D7BE97B81D4019F, 0x4A6ACB477BEA5A2A, 0x089A2AACD2006CB9,
0x14DEA25F3AF9026D, 0x562E43B4931334FE, 0x913F6188692D6F4B, 0xD3CF8063C0C759D8,
0x5DEDC41A34BBEEB2, 0x1F1D25F19D51D821, 0xD80C07CD676F8394, 0x9AFCE626CE85B507
};
void crc64 (const uint8_t *data, const size_t len, uint64_t *crc) {
for (size_t i = 0; i < len; i++)
{
//uint8_t tableIndex = (((uint8_t)(*crc >> 56)) ^ data[i]) & 0xff;
uint8_t tableIndex = (((uint8_t)(*crc >> 56)) ^ data[i]) & 0xff;
*crc = crc64_table[tableIndex] ^ (*crc << 8);
}
}
//suint8_t x = (c & 0xFF00000000000000 ) >> 56;

14
common/crc64.h Normal file
View file

@ -0,0 +1,14 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
// CRC64 ECMA
//-----------------------------------------------------------------------------
#ifndef __CRC64_H
#define __CRC64_H
void crc64 (const uint8_t *data, const size_t len, uint64_t *crc) ;
#endif

View file

@ -81,10 +81,8 @@ uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_
// otherwise could be a void with no arguments // otherwise could be a void with no arguments
//set defaults //set defaults
uint32_t i = 0; uint32_t i = 0;
if (BitStream[1]>1){ //allow only 1s and 0s if (BitStream[1]>1) return 0; //allow only 1s and 0s
// PrintAndLog("no data found");
return 0;
}
// 111111111 bit pattern represent start of frame // 111111111 bit pattern represent start of frame
// include 0 in front to help get start pos // include 0 in front to help get start pos
uint8_t preamble[] = {0,1,1,1,1,1,1,1,1,1}; uint8_t preamble[] = {0,1,1,1,1,1,1,1,1,1};
@ -115,216 +113,11 @@ uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_
} }
//by marshmellow //by marshmellow
//takes 3 arguments - clock, invert, maxErr as integers //demodulates strong heavily clipped samples
//attempts to demodulate ask while decoding manchester
//prints binary found and saves in graphbuffer for further commands
int askmandemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr)
{
size_t i;
int start = DetectASKClock(BinStream, *size, clk, 20); //clock default
if (*clk==0 || start < 0) return -3;
if (*invert != 1) *invert=0;
uint8_t initLoopMax = 255;
if (initLoopMax > *size) initLoopMax = *size;
// Detect high and lows
// 25% fuzz in case highs and lows aren't clipped [marshmellow]
int high, low;
if (getHiLo(BinStream, initLoopMax, &high, &low, 75, 75) < 1) return -2; //just noise
// PrintAndLog("DEBUG - valid high: %d - valid low: %d",high,low);
int lastBit = 0; //set first clock check
uint16_t bitnum = 0; //output counter
uint8_t tol = 0; //clock tolerance adjust - waves will be accepted as within the clock if they fall + or - this value + clock from last valid wave
if (*clk <= 32) tol=1; //clock tolerance may not be needed anymore currently set to + or - 1 but could be increased for poor waves or removed entirely
size_t iii = 0;
//if 0 errors allowed then only try first 2 clock cycles as we want a low tolerance
if (!maxErr) initLoopMax = *clk * 2;
uint16_t errCnt = 0, MaxBits = 512;
uint16_t bestStart = start;
uint16_t bestErrCnt = 0;
// PrintAndLog("DEBUG - lastbit - %d",lastBit);
// if best start position not already found by detect clock then
if (start <= 0 || start > initLoopMax){
bestErrCnt = maxErr+1;
// loop to find first wave that works
for (iii=0; iii < initLoopMax; ++iii){
// if no peak skip
if (BinStream[iii] < high && BinStream[iii] > low) continue;
lastBit = iii - *clk;
// loop through to see if this start location works
for (i = iii; i < *size; ++i) {
if ((i-lastBit) > (*clk-tol) && (BinStream[i] >= high || BinStream[i] <= low)) {
lastBit += *clk;
} else if ((i-lastBit) > (*clk+tol)) {
errCnt++;
lastBit += *clk;
}
if ((i-iii) > (MaxBits * *clk) || errCnt > maxErr) break; //got plenty of bits or too many errors
}
//we got more than 64 good bits and not all errors
if ((((i-iii)/ *clk) > (64)) && (errCnt<=maxErr)) {
//possible good read
if (!errCnt || errCnt < bestErrCnt){
bestStart = iii; //set this as new best run
bestErrCnt = errCnt;
if (!errCnt) break; //great read - finish
}
}
errCnt = 0;
}
}
if (bestErrCnt > maxErr){
*invert = bestStart;
*clk = iii;
return -1;
}
//best run is good enough set to best run and set overwrite BinStream
lastBit = bestStart - *clk;
errCnt = 0;
for (i = bestStart; i < *size; ++i) {
if ((BinStream[i] >= high) && ((i-lastBit) > (*clk-tol))){
//high found and we are expecting a bar
lastBit += *clk;
BinStream[bitnum++] = *invert;
} else if ((BinStream[i] <= low) && ((i-lastBit) > (*clk-tol))){
//low found and we are expecting a bar
lastBit += *clk;
BinStream[bitnum++] = *invert ^ 1;
} else if ((i-lastBit)>(*clk+tol)){
//should have hit a high or low based on clock!!
//PrintAndLog("DEBUG - no wave in expected area - location: %d, expected: %d-%d, lastBit: %d - resetting search",i,(lastBit+(clk-((int)(tol)))),(lastBit+(clk+((int)(tol)))),lastBit);
if (bitnum > 0) {
BinStream[bitnum++] = 77;
errCnt++;
}
lastBit += *clk;//skip over error
}
if (bitnum >= MaxBits) break;
}
*size = bitnum;
return bestErrCnt;
}
//by marshmellow
//encode binary data into binary manchester
int ManchesterEncode(uint8_t *BitStream, size_t size)
{
size_t modIdx=20000, i=0;
if (size>modIdx) return -1;
for (size_t idx=0; idx < size; idx++){
BitStream[idx+modIdx++] = BitStream[idx];
BitStream[idx+modIdx++] = BitStream[idx]^1;
}
for (; i<(size*2); i++){
BitStream[i] = BitStream[i+20000];
}
return i;
}
//by marshmellow
//take 10 and 01 and manchester decode
//run through 2 times and take least errCnt
int manrawdecode(uint8_t * BitStream, size_t *size)
{
uint16_t bitnum=0, MaxBits = 512, errCnt = 0;
size_t i, ii;
uint16_t bestErr = 1000, bestRun = 0;
if (size == 0) return -1;
for (ii=0;ii<2;++ii){
for (i=ii; i<*size-2; i+=2)
if (BitStream[i]==BitStream[i+1])
errCnt++;
if (bestErr>errCnt){
bestErr=errCnt;
bestRun=ii;
}
errCnt=0;
}
if (bestErr<20){
for (i=bestRun; i < *size-2; i+=2){
if(BitStream[i] == 1 && (BitStream[i+1] == 0)){
BitStream[bitnum++]=0;
} else if((BitStream[i] == 0) && BitStream[i+1] == 1){
BitStream[bitnum++]=1;
} else {
BitStream[bitnum++]=77;
}
if(bitnum>MaxBits) break;
}
*size=bitnum;
}
return bestErr;
}
//by marshmellow
//take 01 or 10 = 1 and 11 or 00 = 0
//check for phase errors - should never have 111 or 000 should be 01001011 or 10110100 for 1010
//decodes biphase or if inverted it is AKA conditional dephase encoding AKA differential manchester encoding
int BiphaseRawDecode(uint8_t *BitStream, size_t *size, int offset, int invert)
{
uint16_t bitnum = 0;
uint16_t errCnt = 0;
size_t i = offset;
uint16_t MaxBits=512;
//if not enough samples - error
if (*size < 51) return -1;
//check for phase change faults - skip one sample if faulty
uint8_t offsetA = 1, offsetB = 1;
for (; i<48; i+=2){
if (BitStream[i+1]==BitStream[i+2]) offsetA=0;
if (BitStream[i+2]==BitStream[i+3]) offsetB=0;
}
if (!offsetA && offsetB) offset++;
for (i=offset; i<*size-3; i+=2){
//check for phase error
if (BitStream[i+1]==BitStream[i+2]) {
BitStream[bitnum++]=77;
errCnt++;
}
if((BitStream[i]==1 && BitStream[i+1]==0) || (BitStream[i]==0 && BitStream[i+1]==1)){
BitStream[bitnum++]=1^invert;
} else if((BitStream[i]==0 && BitStream[i+1]==0) || (BitStream[i]==1 && BitStream[i+1]==1)){
BitStream[bitnum++]=invert;
} else {
BitStream[bitnum++]=77;
errCnt++;
}
if(bitnum>MaxBits) break;
}
*size=bitnum;
return errCnt;
}
//by marshmellow
void askAmp(uint8_t *BitStream, size_t size)
{
int shift = 127;
int shiftedVal=0;
for(size_t i = 1; i<size; i++){
if (BitStream[i]-BitStream[i-1]>=30) //large jump up
shift=127;
else if(BitStream[i]-BitStream[i-1]<=-20) //large jump down
shift=-127;
shiftedVal=BitStream[i]+shift;
if (shiftedVal>255)
shiftedVal=255;
else if (shiftedVal<0)
shiftedVal=0;
BitStream[i-1] = shiftedVal;
}
return;
}
// demodulates strong heavily clipped samples
int cleanAskRawDemod(uint8_t *BinStream, size_t *size, int clk, int invert, int high, int low) int cleanAskRawDemod(uint8_t *BinStream, size_t *size, int clk, int invert, int high, int low)
{ {
size_t bitCnt=0, smplCnt=0, errCnt=0; size_t bitCnt=0, smplCnt=0, errCnt=0;
uint8_t waveHigh = 0; uint8_t waveHigh = 0;
//PrintAndLog("clk: %d", clk);
for (size_t i=0; i < *size; i++){ for (size_t i=0; i < *size; i++){
if (BinStream[i] >= high && waveHigh){ if (BinStream[i] >= high && waveHigh){
smplCnt++; smplCnt++;
@ -335,7 +128,7 @@ int cleanAskRawDemod(uint8_t *BinStream, size_t *size, int clk, int invert, int
if (smplCnt > clk-(clk/4)-1) { //full clock if (smplCnt > clk-(clk/4)-1) { //full clock
if (smplCnt > clk + (clk/4)+1) { //too many samples if (smplCnt > clk + (clk/4)+1) { //too many samples
errCnt++; errCnt++;
BinStream[bitCnt++]=77; BinStream[bitCnt++]=7;
} else if (waveHigh) { } else if (waveHigh) {
BinStream[bitCnt++] = invert; BinStream[bitCnt++] = invert;
BinStream[bitCnt++] = invert; BinStream[bitCnt++] = invert;
@ -371,111 +164,79 @@ int cleanAskRawDemod(uint8_t *BinStream, size_t *size, int clk, int invert, int
} }
//by marshmellow //by marshmellow
//takes 3 arguments - clock, invert and maxErr as integers void askAmp(uint8_t *BitStream, size_t size)
//attempts to demodulate ask only {
int askrawdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp) for(size_t i = 1; i<size; i++){
if (BitStream[i]-BitStream[i-1]>=30) //large jump up
BitStream[i]=127;
else if(BitStream[i]-BitStream[i-1]<=-20) //large jump down
BitStream[i]=-127;
}
return;
}
//by marshmellow
//attempts to demodulate ask modulations, askType == 0 for ask/raw, askType==1 for ask/manchester
int askdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType)
{ {
if (*size==0) return -1; if (*size==0) return -1;
int start = DetectASKClock(BinStream, *size, clk, 20); //clock default int start = DetectASKClock(BinStream, *size, clk, maxErr); //clock default
if (*clk==0 || start < 0) return -1; if (*clk==0 || start < 0) return -3;
if (*invert != 1) *invert = 0; if (*invert != 1) *invert = 0;
if (amp==1) askAmp(BinStream, *size); if (amp==1) askAmp(BinStream, *size);
uint8_t initLoopMax = 255; uint8_t initLoopMax = 255;
if (initLoopMax > *size) initLoopMax=*size; if (initLoopMax > *size) initLoopMax = *size;
// Detect high and lows // Detect high and lows
//25% clip in case highs and lows aren't clipped [marshmellow] //25% clip in case highs and lows aren't clipped [marshmellow]
int high, low; int high, low;
if (getHiLo(BinStream, initLoopMax, &high, &low, 75, 75) < 1) if (getHiLo(BinStream, initLoopMax, &high, &low, 75, 75) < 1)
return -1; //just noise return -2; //just noise
size_t errCnt = 0;
// if clean clipped waves detected run alternate demod // if clean clipped waves detected run alternate demod
if (DetectCleanAskWave(BinStream, *size, high, low)) if (DetectCleanAskWave(BinStream, *size, high, low)) {
return cleanAskRawDemod(BinStream, size, *clk, *invert, high, low); errCnt = cleanAskRawDemod(BinStream, size, *clk, *invert, high, low);
if (askType) //askman
return manrawdecode(BinStream, size, 0);
else //askraw
return errCnt;
}
int lastBit = 0; //set first clock check - can go negative int lastBit; //set first clock check - can go negative
size_t i, iii = 0; size_t i, bitnum = 0; //output counter
size_t errCnt = 0, bitnum = 0; //output counter
uint8_t midBit = 0; uint8_t midBit = 0;
size_t bestStart = start, bestErrCnt = 0; //(*size/1000); uint8_t tol = 0; //clock tolerance adjust - waves will be accepted as within the clock if they fall + or - this value + clock from last valid wave
if (*clk <= 32) tol = 1; //clock tolerance may not be needed anymore currently set to + or - 1 but could be increased for poor waves or removed entirely
size_t MaxBits = 1024; size_t MaxBits = 1024;
lastBit = start - *clk;
//if 0 errors allowed then only try first 2 clock cycles as we want a low tolerance for (i = start; i < *size; ++i) {
if (!maxErr) initLoopMax = *clk * 2; if (i-lastBit >= *clk-tol){
//if best start not already found by detectclock
if (start <= 0 || start > initLoopMax){
bestErrCnt = maxErr+1;
//PrintAndLog("DEBUG - lastbit - %d",lastBit);
//loop to find first wave that works
for (iii=0; iii < initLoopMax; ++iii){
if ((BinStream[iii] >= high) || (BinStream[iii] <= low)){
lastBit = iii - *clk;
//loop through to see if this start location works
for (i = iii; i < *size; ++i) {
if (i-lastBit > *clk && (BinStream[i] >= high || BinStream[i] <= low)){
lastBit += *clk;
midBit = 0;
} else if (i-lastBit > (*clk/2) && midBit == 0) {
midBit = 1;
} else if ((i-lastBit) > *clk) {
//should have hit a high or low based on clock!!
//PrintAndLog("DEBUG - no wave in expected area - location: %d, expected: %d-%d, lastBit: %d - resetting search",i,(lastBit+(clk-((int)(tol)))),(lastBit+(clk+((int)(tol)))),lastBit);
errCnt++;
lastBit += *clk;//skip over until hit too many errors
if (errCnt > maxErr)
break;
}
if ((i-iii)>(MaxBits * *clk)) break; //got enough bits
}
//we got more than 64 good bits and not all errors
if ((((i-iii)/ *clk) > 64) && (errCnt<=maxErr)) {
//possible good read
if (errCnt==0){
bestStart=iii;
bestErrCnt=errCnt;
break; //great read - finish
}
if (errCnt<bestErrCnt){ //set this as new best run
bestErrCnt=errCnt;
bestStart = iii;
}
}
errCnt=0;
}
}
}
if (bestErrCnt > maxErr){
*invert = bestStart;
*clk = iii;
return -1;
}
//best run is good enough - set to best run and overwrite BinStream
lastBit = bestStart - *clk - 1;
errCnt = 0;
for (i = bestStart; i < *size; ++i) {
if (i - lastBit > *clk){
if (BinStream[i] >= high) { if (BinStream[i] >= high) {
BinStream[bitnum++] = *invert; BinStream[bitnum++] = *invert;
} else if (BinStream[i] <= low) { } else if (BinStream[i] <= low) {
BinStream[bitnum++] = *invert ^ 1; BinStream[bitnum++] = *invert ^ 1;
} else { } else if (i-lastBit >= *clk+tol) {
if (bitnum > 0) { if (bitnum > 0) {
BinStream[bitnum++]=77; BinStream[bitnum++]=7;
errCnt++; errCnt++;
} }
} else { //in tolerance - looking for peak
continue;
} }
midBit = 0; midBit = 0;
lastBit += *clk; lastBit += *clk;
} else if (i-lastBit > (*clk/2) && midBit == 0){ } else if (i-lastBit >= (*clk/2-tol) && !midBit && !askType){
if (BinStream[i] >= high) { if (BinStream[i] >= high) {
BinStream[bitnum++] = *invert; BinStream[bitnum++] = *invert;
} else if (BinStream[i] <= low) { } else if (BinStream[i] <= low) {
BinStream[bitnum++] = *invert ^ 1; BinStream[bitnum++] = *invert ^ 1;
} else { } else if (i-lastBit >= *clk/2+tol) {
BinStream[bitnum] = BinStream[bitnum-1]; BinStream[bitnum] = BinStream[bitnum-1];
bitnum++; bitnum++;
} else { //in tolerance - looking for peak
continue;
} }
midBit = 1; midBit = 1;
} }
@ -485,6 +246,98 @@ int askrawdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int max
return errCnt; return errCnt;
} }
//by marshmellow
//take 10 and 01 and manchester decode
//run through 2 times and take least errCnt
int manrawdecode(uint8_t * BitStream, size_t *size, uint8_t invert)
{
uint16_t bitnum=0, MaxBits = 512, errCnt = 0;
size_t i, ii;
uint16_t bestErr = 1000, bestRun = 0;
if (*size < 16) return -1;
//find correct start position [alignment]
for (ii=0;ii<2;++ii){
for (i=ii; i<*size-3; i+=2)
if (BitStream[i]==BitStream[i+1])
errCnt++;
if (bestErr>errCnt){
bestErr=errCnt;
bestRun=ii;
}
errCnt=0;
}
//decode
for (i=bestRun; i < *size-3; i+=2){
if(BitStream[i] == 1 && (BitStream[i+1] == 0)){
BitStream[bitnum++]=invert;
} else if((BitStream[i] == 0) && BitStream[i+1] == 1){
BitStream[bitnum++]=invert^1;
} else {
BitStream[bitnum++]=7;
}
if(bitnum>MaxBits) break;
}
*size=bitnum;
return bestErr;
}
//by marshmellow
//encode binary data into binary manchester
int ManchesterEncode(uint8_t *BitStream, size_t size)
{
size_t modIdx=20000, i=0;
if (size>modIdx) return -1;
for (size_t idx=0; idx < size; idx++){
BitStream[idx+modIdx++] = BitStream[idx];
BitStream[idx+modIdx++] = BitStream[idx]^1;
}
for (; i<(size*2); i++){
BitStream[i] = BitStream[i+20000];
}
return i;
}
//by marshmellow
//take 01 or 10 = 1 and 11 or 00 = 0
//check for phase errors - should never have 111 or 000 should be 01001011 or 10110100 for 1010
//decodes biphase or if inverted it is AKA conditional dephase encoding AKA differential manchester encoding
int BiphaseRawDecode(uint8_t *BitStream, size_t *size, int offset, int invert)
{
uint16_t bitnum = 0;
uint16_t errCnt = 0;
size_t i = offset;
uint16_t MaxBits=512;
//if not enough samples - error
if (*size < 51) return -1;
//check for phase change faults - skip one sample if faulty
uint8_t offsetA = 1, offsetB = 1;
for (; i<48; i+=2){
if (BitStream[i+1]==BitStream[i+2]) offsetA=0;
if (BitStream[i+2]==BitStream[i+3]) offsetB=0;
}
if (!offsetA && offsetB) offset++;
for (i=offset; i<*size-3; i+=2){
//check for phase error
if (BitStream[i+1]==BitStream[i+2]) {
BitStream[bitnum++]=7;
errCnt++;
}
if((BitStream[i]==1 && BitStream[i+1]==0) || (BitStream[i]==0 && BitStream[i+1]==1)){
BitStream[bitnum++]=1^invert;
} else if((BitStream[i]==0 && BitStream[i+1]==0) || (BitStream[i]==1 && BitStream[i+1]==1)){
BitStream[bitnum++]=invert;
} else {
BitStream[bitnum++]=7;
errCnt++;
}
if(bitnum>MaxBits) break;
}
*size=bitnum;
return errCnt;
}
// by marshmellow
// demod gProxIIDemod // demod gProxIIDemod
// error returns as -x // error returns as -x
// success returns start position in BitStream // success returns start position in BitStream
@ -673,7 +526,7 @@ int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, ui
return (int)startIdx; return (int)startIdx;
} }
uint32_t bytebits_to_byte(uint8_t* src, size_t numbits) uint32_t bytebits_to_byte(uint8_t *src, size_t numbits)
{ {
uint32_t num = 0; uint32_t num = 0;
for(int i = 0 ; i < numbits ; i++) for(int i = 0 ; i < numbits ; i++)
@ -684,6 +537,17 @@ uint32_t bytebits_to_byte(uint8_t* src, size_t numbits)
return num; return num;
} }
//least significant bit first
uint32_t bytebits_to_byteLSBF(uint8_t *src, size_t numbits)
{
uint32_t num = 0;
for(int i = 0 ; i < numbits ; i++)
{
num = (num << 1) | *(src + (numbits-(i+1)));
}
return num;
}
int IOdemodFSK(uint8_t *dest, size_t size) int IOdemodFSK(uint8_t *dest, size_t size)
{ {
if (justNoise(dest, size)) return -1; if (justNoise(dest, size)) return -1;
@ -716,7 +580,7 @@ int IOdemodFSK(uint8_t *dest, size_t size)
// by marshmellow // by marshmellow
// takes a array of binary values, start position, length of bits per parity (includes parity bit), // takes a array of binary values, start position, length of bits per parity (includes parity bit),
// Parity Type (1 for odd 0 for even), and binary Length (length to run) // Parity Type (1 for odd; 0 for even; 2 for just drop it), and binary Length (length to run)
size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen) size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen)
{ {
uint32_t parityWd = 0; uint32_t parityWd = 0;
@ -728,7 +592,9 @@ size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t p
} }
j--; j--;
// if parity fails then return 0 // if parity fails then return 0
if (parityTest(parityWd, pLen, pType) == 0) return -1; if (pType != 2) {
if (parityTest(parityWd, pLen, pType) == 0) return -1;
}
bitCnt+=(pLen-1); bitCnt+=(pLen-1);
parityWd = 0; parityWd = 0;
} }
@ -737,6 +603,21 @@ size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t p
return bitCnt; return bitCnt;
} }
// Ask/Biphase Demod then try to locate an ISO 11784/85 ID
// BitStream must contain previously askrawdemod and biphasedemoded data
int FDXBdemodBI(uint8_t *dest, size_t *size)
{
//make sure buffer has enough data
if (*size < 128) return -1;
size_t startIdx = 0;
uint8_t preamble[] = {0,0,0,0,0,0,0,0,0,0,1};
uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx);
if (errChk == 0) return -2; //preamble not found
return (int)startIdx;
}
// by marshmellow // by marshmellow
// FSK Demod then try to locate an AWID ID // FSK Demod then try to locate an AWID ID
int AWIDdemodFSK(uint8_t *dest, size_t *size) int AWIDdemodFSK(uint8_t *dest, size_t *size)
@ -780,12 +661,13 @@ int PyramiddemodFSK(uint8_t *dest, size_t *size)
return (int)startIdx; return (int)startIdx;
} }
// by marshmellow
uint8_t DetectCleanAskWave(uint8_t dest[], size_t size, int high, int low) // to detect a wave that has heavily clipped (clean) samples
uint8_t DetectCleanAskWave(uint8_t dest[], size_t size, uint8_t high, uint8_t low)
{ {
uint16_t allPeaks=1; uint16_t allPeaks=1;
uint16_t cntPeaks=0; uint16_t cntPeaks=0;
size_t loopEnd = 572; size_t loopEnd = 512+60;
if (loopEnd > size) loopEnd = size; if (loopEnd > size) loopEnd = size;
for (size_t i=60; i<loopEnd; i++){ for (size_t i=60; i<loopEnd; i++){
if (dest[i]>low && dest[i]<high) if (dest[i]>low && dest[i]<high)
@ -801,53 +683,39 @@ uint8_t DetectCleanAskWave(uint8_t dest[], size_t size, int high, int low)
// by marshmellow // by marshmellow
// to help detect clocks on heavily clipped samples // to help detect clocks on heavily clipped samples
// based on counts between zero crossings // based on count of low to low
int DetectStrongAskClock(uint8_t dest[], size_t size) int DetectStrongAskClock(uint8_t dest[], size_t size, uint8_t high, uint8_t low)
{ {
int clk[]={0,8,16,32,40,50,64,100,128}; uint8_t fndClk[] = {8,16,32,40,50,64,128};
size_t idx = 40; size_t startwave;
uint8_t high=0; size_t i = 0;
size_t cnt = 0; size_t minClk = 255;
size_t highCnt = 0; // get to first full low to prime loop and skip incomplete first pulse
size_t highCnt2 = 0; while ((dest[i] < high) && (i < size))
for (;idx < size; idx++){ ++i;
if (dest[idx]>128) { while ((dest[i] > low) && (i < size))
if (!high){ ++i;
high=1;
if (cnt > highCnt){ // loop through all samples
if (highCnt != 0) highCnt2 = highCnt; while (i < size) {
highCnt = cnt; // measure from low to low
} else if (cnt > highCnt2) { while ((dest[i] > low) && (i < size))
highCnt2 = cnt; ++i;
} startwave= i;
cnt=1; while ((dest[i] < high) && (i < size))
} else { ++i;
cnt++; while ((dest[i] > low) && (i < size))
} ++i;
} else if (dest[idx] <= 128){ //get minimum measured distance
if (high) { if (i-startwave < minClk && i < size)
high=0; minClk = i - startwave;
if (cnt > highCnt) {
if (highCnt != 0) highCnt2 = highCnt;
highCnt = cnt;
} else if (cnt > highCnt2) {
highCnt2 = cnt;
}
cnt=1;
} else {
cnt++;
}
}
} }
uint8_t tol; // set clock
for (idx=8; idx>0; idx--){ for (uint8_t clkCnt = 0; clkCnt<7; clkCnt++) {
tol = clk[idx]/8; if (minClk >= fndClk[clkCnt]-(fndClk[clkCnt]/8) && minClk <= fndClk[clkCnt]+1)
if (clk[idx] >= highCnt - tol && clk[idx] <= highCnt + tol) return fndClk[clkCnt];
return clk[idx];
if (clk[idx] >= highCnt2 - tol && clk[idx] <= highCnt2 + tol)
return clk[idx];
} }
return -1; return 0;
} }
// by marshmellow // by marshmellow
@ -856,45 +724,61 @@ int DetectStrongAskClock(uint8_t dest[], size_t size)
// return start index of best starting position for that clock and return clock (by reference) // return start index of best starting position for that clock and return clock (by reference)
int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr) int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr)
{ {
size_t i=0; size_t i=1;
uint8_t clk[]={8,16,32,40,50,64,100,128,255}; uint8_t clk[] = {255,8,16,32,40,50,64,100,128,255};
uint8_t clkEnd = 9;
uint8_t loopCnt = 255; //don't need to loop through entire array... uint8_t loopCnt = 255; //don't need to loop through entire array...
if (size <= loopCnt) return -1; //not enough samples if (size <= loopCnt) return -1; //not enough samples
//if we already have a valid clock quit
//if we already have a valid clock
for (;i<8;++i) uint8_t clockFnd=0;
if (clk[i] == *clock) return 0; for (;i<clkEnd;++i)
if (clk[i] == *clock) clockFnd = i;
//clock found but continue to find best startpos
//get high and low peak //get high and low peak
int peak, low; int peak, low;
if (getHiLo(dest, loopCnt, &peak, &low, 75, 75) < 1) return -1; if (getHiLo(dest, loopCnt, &peak, &low, 75, 75) < 1) return -1;
//test for large clean peaks //test for large clean peaks
if (DetectCleanAskWave(dest, size, peak, low)==1){ if (!clockFnd){
int ans = DetectStrongAskClock(dest, size); if (DetectCleanAskWave(dest, size, peak, low)==1){
for (i=7; i>0; i--){ int ans = DetectStrongAskClock(dest, size, peak, low);
if (clk[i] == ans) { for (i=clkEnd-1; i>0; i--){
*clock = ans; if (clk[i] == ans) {
return 0; *clock = ans;
//clockFnd = i;
return 0; // for strong waves i don't use the 'best start position' yet...
//break; //clock found but continue to find best startpos [not yet]
}
} }
} }
} }
uint8_t ii; uint8_t ii;
uint8_t clkCnt, tol = 0; uint8_t clkCnt, tol = 0;
uint16_t bestErr[]={1000,1000,1000,1000,1000,1000,1000,1000,1000}; uint16_t bestErr[]={1000,1000,1000,1000,1000,1000,1000,1000,1000};
uint8_t bestStart[]={0,0,0,0,0,0,0,0,0}; uint8_t bestStart[]={0,0,0,0,0,0,0,0,0};
size_t errCnt = 0; size_t errCnt = 0;
size_t arrLoc, loopEnd; size_t arrLoc, loopEnd;
if (clockFnd>0) {
clkCnt = clockFnd;
clkEnd = clockFnd+1;
}
else clkCnt=1;
//test each valid clock from smallest to greatest to see which lines up //test each valid clock from smallest to greatest to see which lines up
for(clkCnt=0; clkCnt < 8; clkCnt++){ for(; clkCnt < clkEnd; clkCnt++){
if (clk[clkCnt] == 32){ if (clk[clkCnt] <= 32){
tol=1; tol=1;
}else{ }else{
tol=0; tol=0;
} }
if (!maxErr) loopCnt=clk[clkCnt]*2; //if no errors allowed - keep start within the first clock
if (!maxErr && size > clk[clkCnt]*2 + tol && clk[clkCnt]<128) loopCnt=clk[clkCnt]*2;
bestErr[clkCnt]=1000; bestErr[clkCnt]=1000;
//try lining up the peaks by moving starting point (try first 256) //try lining up the peaks by moving starting point (try first few clocks)
for (ii=0; ii < loopCnt; ii++){ for (ii=0; ii < loopCnt; ii++){
if (dest[ii] < peak && dest[ii] > low) continue; if (dest[ii] < peak && dest[ii] > low) continue;
@ -910,11 +794,11 @@ int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr)
errCnt++; errCnt++;
} }
} }
//if we found no errors then we can stop here //if we found no errors then we can stop here and a low clock (common clocks)
// this is correct one - return this clock // this is correct one - return this clock
//PrintAndLog("DEBUG: clk %d, err %d, ii %d, i %d",clk[clkCnt],errCnt,ii,i); //PrintAndLog("DEBUG: clk %d, err %d, ii %d, i %d",clk[clkCnt],errCnt,ii,i);
if(errCnt==0 && clkCnt<6) { if(errCnt==0 && clkCnt<7) {
*clock = clk[clkCnt]; if (!clockFnd) *clock = clk[clkCnt];
return ii; return ii;
} }
//if we found errors see if it is lowest so far and save it as best run //if we found errors see if it is lowest so far and save it as best run
@ -924,9 +808,9 @@ int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr)
} }
} }
} }
uint8_t iii=0; uint8_t iii;
uint8_t best=0; uint8_t best=0;
for (iii=0; iii<8; ++iii){ for (iii=1; iii<clkEnd; ++iii){
if (bestErr[iii] < bestErr[best]){ if (bestErr[iii] < bestErr[best]){
if (bestErr[iii] == 0) bestErr[iii]=1; if (bestErr[iii] == 0) bestErr[iii]=1;
// current best bit to error ratio vs new bit to error ratio // current best bit to error ratio vs new bit to error ratio
@ -935,8 +819,8 @@ int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr)
} }
} }
} }
if (bestErr[best] > maxErr) return -1; //if (bestErr[best] > maxErr) return -1;
*clock = clk[best]; if (!clockFnd) *clock = clk[best];
return bestStart[best]; return bestStart[best];
} }
@ -1115,7 +999,7 @@ void psk1TOpsk2(uint8_t *BitStream, size_t size)
size_t i=1; size_t i=1;
uint8_t lastBit=BitStream[0]; uint8_t lastBit=BitStream[0];
for (; i<size; i++){ for (; i<size; i++){
if (BitStream[i]==77){ if (BitStream[i]==7){
//ignore errors //ignore errors
} else if (lastBit!=BitStream[i]){ } else if (lastBit!=BitStream[i]){
lastBit=BitStream[i]; lastBit=BitStream[i];
@ -1308,7 +1192,7 @@ int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int maxErr)
if (ignoreCnt == 0){ if (ignoreCnt == 0){
bitHigh = 0; bitHigh = 0;
if (errBitHigh == 1){ if (errBitHigh == 1){
dest[bitnum++] = 77; dest[bitnum++] = 7;
errCnt++; errCnt++;
} }
errBitHigh=0; errBitHigh=0;
@ -1583,7 +1467,7 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert)
//noise after a phase shift - ignore //noise after a phase shift - ignore
} else { //phase shift before supposed to based on clock } else { //phase shift before supposed to based on clock
errCnt++; errCnt++;
dest[numBits++] = 77; dest[numBits++] = 7;
} }
} else if (i+1 > lastClkBit + *clock + tol + fc){ } else if (i+1 > lastClkBit + *clock + tol + fc){
lastClkBit += *clock; //no phase shift but clock bit lastClkBit += *clock; //no phase shift but clock bit

View file

@ -15,34 +15,39 @@
#define LFDEMOD_H__ #define LFDEMOD_H__
#include <stdint.h> #include <stdint.h>
int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr); //generic
uint8_t DetectCleanAskWave(uint8_t dest[], size_t size, int high, int low); int askdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType);
int askmandemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr); int BiphaseRawDecode(uint8_t * BitStream, size_t *size, int offset, int invert);
uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo); uint32_t bytebits_to_byte(uint8_t* src, size_t numbits);
int ManchesterEncode(uint8_t *BitStream, size_t size); uint32_t bytebits_to_byteLSBF(uint8_t* src, size_t numbits);
int manrawdecode(uint8_t *BitStream, size_t *size); uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t fskAdj);
int BiphaseRawDecode(uint8_t * BitStream, size_t *size, int offset, int invert); int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr);
int askrawdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp); uint8_t DetectCleanAskWave(uint8_t dest[], size_t size, uint8_t high, uint8_t low);
uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow);
int DetectNRZClock(uint8_t dest[], size_t size, int clock);
int DetectPSKClock(uint8_t dest[], size_t size, int clock);
int DetectStrongAskClock(uint8_t dest[], size_t size, uint8_t high, uint8_t low);
uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo);
int fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow);
int getHiLo(uint8_t *BitStream, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo);
int ManchesterEncode(uint8_t *BitStream, size_t size);
int manrawdecode(uint8_t *BitStream, size_t *size, uint8_t invert);
int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int maxErr);
uint8_t parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType);
uint8_t preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx);
int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert);
void psk2TOpsk1(uint8_t *BitStream, size_t size);
void psk1TOpsk2(uint8_t *BitStream, size_t size);
size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen);
//tag specific
int FDXBdemodBI(uint8_t *dest, size_t *size);
int AWIDdemodFSK(uint8_t *dest, size_t *size);
int gProxII_Demod(uint8_t BitStream[], size_t *size); int gProxII_Demod(uint8_t BitStream[], size_t *size);
int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo); int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo);
int IOdemodFSK(uint8_t *dest, size_t size); int IOdemodFSK(uint8_t *dest, size_t size);
int fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow);
uint32_t bytebits_to_byte(uint8_t* src, size_t numbits);
int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int maxErr);
void psk1TOpsk2(uint8_t *BitStream, size_t size);
void psk2TOpsk1(uint8_t *BitStream, size_t size);
int DetectNRZClock(uint8_t dest[], size_t size, int clock);
int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert); int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert);
int PyramiddemodFSK(uint8_t *dest, size_t *size); int PyramiddemodFSK(uint8_t *dest, size_t *size);
int AWIDdemodFSK(uint8_t *dest, size_t *size);
size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen);
uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t fskAdj);
uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow);
int getHiLo(uint8_t *BitStream, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo);
int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo); int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo);
uint8_t preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx);
uint8_t parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType);
int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert);
int DetectPSKClock(uint8_t dest[], size_t size, int clock);
#endif #endif

View file

@ -1,4 +1,3 @@
#include <stdio.h>
#include <strings.h> #include <strings.h>
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>

View file

@ -123,9 +123,21 @@ NXP/Philips CUSTOM COMMANDS
#define MIFARE_CMD_RESTORE 0xC2 #define MIFARE_CMD_RESTORE 0xC2
#define MIFARE_CMD_TRANSFER 0xB0 #define MIFARE_CMD_TRANSFER 0xB0
#define MIFARE_ULC_WRITE 0xA0 #define MIFARE_ULC_WRITE 0xA2
//#define MIFARE_ULC__COMP_WRITE 0xA0
#define MIFARE_ULC_AUTH_1 0x1A #define MIFARE_ULC_AUTH_1 0x1A
#define MIFARE_ULC_AUTH_2 0xAF #define MIFARE_ULC_AUTH_2 0xAF
#define MIFARE_ULEV1_AUTH 0x1B
#define MIFARE_ULEV1_VERSION 0x60
#define MIFARE_ULEV1_FASTREAD 0x3A
//#define MIFARE_ULEV1_WRITE 0xA2
//#define MIFARE_ULEV1_COMP_WRITE 0xA0
#define MIFARE_ULEV1_READ_CNT 0x39
#define MIFARE_ULEV1_INCR_CNT 0xA5
#define MIFARE_ULEV1_READSIG 0x3C
#define MIFARE_ULEV1_CHECKTEAR 0x3E
#define MIFARE_ULEV1_VCSL 0x4B
/** /**
06 00 = INITIATE 06 00 = INITIATE

665
common/sha1.c Normal file
View file

@ -0,0 +1,665 @@
/*
* FIPS-180-1 compliant SHA-1 implementation
*
* Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
* This file is part of mbed TLS (https://tls.mbed.org)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* The SHA-1 standard was published by NIST in 1993.
*
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
*/
#if !defined(POLARSSL_CONFIG_FILE)
//#include "polarssl/config.h"
#define POLARSSL_SHA1_C
#else
#include POLARSSL_CONFIG_FILE
#endif
#if defined(POLARSSL_SHA1_C)
#include "sha1.h"
#include <string.h>
#if defined(POLARSSL_FS_IO)
#include <stdio.h>
#endif
#if defined(POLARSSL_SELF_TEST)
#if defined(POLARSSL_PLATFORM_C)
#include "polarssl/platform.h"
#else
#include <stdio.h>
#define polarssl_printf printf
#endif /* POLARSSL_PLATFORM_C */
#endif /* POLARSSL_SELF_TEST */
/* Implementation that should never be optimized out by the compiler */
static void polarssl_zeroize( void *v, size_t n ) {
volatile unsigned char *p = v; while( n-- ) *p++ = 0;
}
#if !defined(POLARSSL_SHA1_ALT)
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
{ \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
}
#endif
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
}
#endif
void sha1_init( sha1_context *ctx )
{
memset( ctx, 0, sizeof( sha1_context ) );
}
void sha1_free( sha1_context *ctx )
{
if( ctx == NULL )
return;
polarssl_zeroize( ctx, sizeof( sha1_context ) );
}
/*
* SHA-1 context setup
*/
void sha1_starts( sha1_context *ctx )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0;
}
void sha1_process( sha1_context *ctx, const unsigned char data[64] )
{
uint32_t temp, W[16], A, B, C, D, E;
GET_UINT32_BE( W[ 0], data, 0 );
GET_UINT32_BE( W[ 1], data, 4 );
GET_UINT32_BE( W[ 2], data, 8 );
GET_UINT32_BE( W[ 3], data, 12 );
GET_UINT32_BE( W[ 4], data, 16 );
GET_UINT32_BE( W[ 5], data, 20 );
GET_UINT32_BE( W[ 6], data, 24 );
GET_UINT32_BE( W[ 7], data, 28 );
GET_UINT32_BE( W[ 8], data, 32 );
GET_UINT32_BE( W[ 9], data, 36 );
GET_UINT32_BE( W[10], data, 40 );
GET_UINT32_BE( W[11], data, 44 );
GET_UINT32_BE( W[12], data, 48 );
GET_UINT32_BE( W[13], data, 52 );
GET_UINT32_BE( W[14], data, 56 );
GET_UINT32_BE( W[15], data, 60 );
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define R(t) \
( \
temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \
W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \
( W[t & 0x0F] = S(temp,1) ) \
)
#define P(a,b,c,d,e,x) \
{ \
e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
#define F(x,y,z) (z ^ (x & (y ^ z)))
#define K 0x5A827999
P( A, B, C, D, E, W[0] );
P( E, A, B, C, D, W[1] );
P( D, E, A, B, C, W[2] );
P( C, D, E, A, B, W[3] );
P( B, C, D, E, A, W[4] );
P( A, B, C, D, E, W[5] );
P( E, A, B, C, D, W[6] );
P( D, E, A, B, C, W[7] );
P( C, D, E, A, B, W[8] );
P( B, C, D, E, A, W[9] );
P( A, B, C, D, E, W[10] );
P( E, A, B, C, D, W[11] );
P( D, E, A, B, C, W[12] );
P( C, D, E, A, B, W[13] );
P( B, C, D, E, A, W[14] );
P( A, B, C, D, E, W[15] );
P( E, A, B, C, D, R(16) );
P( D, E, A, B, C, R(17) );
P( C, D, E, A, B, R(18) );
P( B, C, D, E, A, R(19) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0x6ED9EBA1
P( A, B, C, D, E, R(20) );
P( E, A, B, C, D, R(21) );
P( D, E, A, B, C, R(22) );
P( C, D, E, A, B, R(23) );
P( B, C, D, E, A, R(24) );
P( A, B, C, D, E, R(25) );
P( E, A, B, C, D, R(26) );
P( D, E, A, B, C, R(27) );
P( C, D, E, A, B, R(28) );
P( B, C, D, E, A, R(29) );
P( A, B, C, D, E, R(30) );
P( E, A, B, C, D, R(31) );
P( D, E, A, B, C, R(32) );
P( C, D, E, A, B, R(33) );
P( B, C, D, E, A, R(34) );
P( A, B, C, D, E, R(35) );
P( E, A, B, C, D, R(36) );
P( D, E, A, B, C, R(37) );
P( C, D, E, A, B, R(38) );
P( B, C, D, E, A, R(39) );
#undef K
#undef F
#define F(x,y,z) ((x & y) | (z & (x | y)))
#define K 0x8F1BBCDC
P( A, B, C, D, E, R(40) );
P( E, A, B, C, D, R(41) );
P( D, E, A, B, C, R(42) );
P( C, D, E, A, B, R(43) );
P( B, C, D, E, A, R(44) );
P( A, B, C, D, E, R(45) );
P( E, A, B, C, D, R(46) );
P( D, E, A, B, C, R(47) );
P( C, D, E, A, B, R(48) );
P( B, C, D, E, A, R(49) );
P( A, B, C, D, E, R(50) );
P( E, A, B, C, D, R(51) );
P( D, E, A, B, C, R(52) );
P( C, D, E, A, B, R(53) );
P( B, C, D, E, A, R(54) );
P( A, B, C, D, E, R(55) );
P( E, A, B, C, D, R(56) );
P( D, E, A, B, C, R(57) );
P( C, D, E, A, B, R(58) );
P( B, C, D, E, A, R(59) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0xCA62C1D6
P( A, B, C, D, E, R(60) );
P( E, A, B, C, D, R(61) );
P( D, E, A, B, C, R(62) );
P( C, D, E, A, B, R(63) );
P( B, C, D, E, A, R(64) );
P( A, B, C, D, E, R(65) );
P( E, A, B, C, D, R(66) );
P( D, E, A, B, C, R(67) );
P( C, D, E, A, B, R(68) );
P( B, C, D, E, A, R(69) );
P( A, B, C, D, E, R(70) );
P( E, A, B, C, D, R(71) );
P( D, E, A, B, C, R(72) );
P( C, D, E, A, B, R(73) );
P( B, C, D, E, A, R(74) );
P( A, B, C, D, E, R(75) );
P( E, A, B, C, D, R(76) );
P( D, E, A, B, C, R(77) );
P( C, D, E, A, B, R(78) );
P( B, C, D, E, A, R(79) );
#undef K
#undef F
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
}
/*
* SHA-1 process buffer
*/
void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen )
{
size_t fill;
uint32_t left;
if( ilen == 0 )
return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (uint32_t) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left), input, fill );
sha1_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
sha1_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
memcpy( (void *) (ctx->buffer + left), input, ilen );
}
static const unsigned char sha1_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-1 final digest
*/
void sha1_finish( sha1_context *ctx, unsigned char output[20] )
{
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32_BE( high, msglen, 0 );
PUT_UINT32_BE( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
sha1_update( ctx, sha1_padding, padn );
sha1_update( ctx, msglen, 8 );
PUT_UINT32_BE( ctx->state[0], output, 0 );
PUT_UINT32_BE( ctx->state[1], output, 4 );
PUT_UINT32_BE( ctx->state[2], output, 8 );
PUT_UINT32_BE( ctx->state[3], output, 12 );
PUT_UINT32_BE( ctx->state[4], output, 16 );
}
#endif /* !POLARSSL_SHA1_ALT */
/*
* output = SHA-1( input buffer )
*/
void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] )
{
sha1_context ctx;
sha1_init( &ctx );
sha1_starts( &ctx );
sha1_update( &ctx, input, ilen );
sha1_finish( &ctx, output );
sha1_free( &ctx );
}
#if defined(POLARSSL_FS_IO)
/*
* output = SHA-1( file contents )
*/
int sha1_file( const char *path, unsigned char output[20] )
{
FILE *f;
size_t n;
sha1_context ctx;
unsigned char buf[1024];
if( ( f = fopen( path, "rb" ) ) == NULL )
return( POLARSSL_ERR_SHA1_FILE_IO_ERROR );
sha1_init( &ctx );
sha1_starts( &ctx );
while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
sha1_update( &ctx, buf, n );
sha1_finish( &ctx, output );
sha1_free( &ctx );
if( ferror( f ) != 0 )
{
fclose( f );
return( POLARSSL_ERR_SHA1_FILE_IO_ERROR );
}
fclose( f );
return( 0 );
}
#endif /* POLARSSL_FS_IO */
/*
* SHA-1 HMAC context setup
*/
void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key,
size_t keylen )
{
size_t i;
unsigned char sum[20];
if( keylen > 64 )
{
sha1( key, keylen, sum );
keylen = 20;
key = sum;
}
memset( ctx->ipad, 0x36, 64 );
memset( ctx->opad, 0x5C, 64 );
for( i = 0; i < keylen; i++ )
{
ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
}
sha1_starts( ctx );
sha1_update( ctx, ctx->ipad, 64 );
polarssl_zeroize( sum, sizeof( sum ) );
}
/*
* SHA-1 HMAC process buffer
*/
void sha1_hmac_update( sha1_context *ctx, const unsigned char *input,
size_t ilen )
{
sha1_update( ctx, input, ilen );
}
/*
* SHA-1 HMAC final digest
*/
void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] )
{
unsigned char tmpbuf[20];
sha1_finish( ctx, tmpbuf );
sha1_starts( ctx );
sha1_update( ctx, ctx->opad, 64 );
sha1_update( ctx, tmpbuf, 20 );
sha1_finish( ctx, output );
polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) );
}
/*
* SHA1 HMAC context reset
*/
void sha1_hmac_reset( sha1_context *ctx )
{
sha1_starts( ctx );
sha1_update( ctx, ctx->ipad, 64 );
}
/*
* output = HMAC-SHA-1( hmac key, input buffer )
*/
void sha1_hmac( const unsigned char *key, size_t keylen,
const unsigned char *input, size_t ilen,
unsigned char output[20] )
{
sha1_context ctx;
sha1_init( &ctx );
sha1_hmac_starts( &ctx, key, keylen );
sha1_hmac_update( &ctx, input, ilen );
sha1_hmac_finish( &ctx, output );
sha1_free( &ctx );
}
#if defined(POLARSSL_SELF_TEST)
/*
* FIPS-180-1 test vectors
*/
static const unsigned char sha1_test_buf[3][57] =
{
{ "abc" },
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
{ "" }
};
static const int sha1_test_buflen[3] =
{
3, 56, 1000
};
static const unsigned char sha1_test_sum[3][20] =
{
{ 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D },
{ 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 },
{ 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }
};
/*
* RFC 2202 test vectors
*/
static const unsigned char sha1_hmac_test_key[7][26] =
{
{ "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
"\x0B\x0B\x0B\x0B" },
{ "Jefe" },
{ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
"\xAA\xAA\xAA\xAA" },
{ "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
"\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
{ "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
"\x0C\x0C\x0C\x0C" },
{ "" }, /* 0xAA 80 times */
{ "" }
};
static const int sha1_hmac_test_keylen[7] =
{
20, 4, 20, 25, 20, 80, 80
};
static const unsigned char sha1_hmac_test_buf[7][74] =
{
{ "Hi There" },
{ "what do ya want for nothing?" },
{ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
{ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
{ "Test With Truncation" },
{ "Test Using Larger Than Block-Size Key - Hash Key First" },
{ "Test Using Larger Than Block-Size Key and Larger"
" Than One Block-Size Data" }
};
static const int sha1_hmac_test_buflen[7] =
{
8, 28, 50, 50, 20, 54, 73
};
static const unsigned char sha1_hmac_test_sum[7][20] =
{
{ 0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B,
0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00 },
{ 0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74,
0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79 },
{ 0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3,
0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3 },
{ 0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84,
0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA },
{ 0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2,
0x7B, 0xE1 },
{ 0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70,
0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12 },
{ 0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B,
0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91 }
};
/*
* Checkup routine
*/
int sha1_self_test( int verbose )
{
int i, j, buflen, ret = 0;
unsigned char buf[1024];
unsigned char sha1sum[20];
sha1_context ctx;
sha1_init( &ctx );
/*
* SHA-1
*/
for( i = 0; i < 3; i++ )
{
if( verbose != 0 )
polarssl_printf( " SHA-1 test #%d: ", i + 1 );
sha1_starts( &ctx );
if( i == 2 )
{
memset( buf, 'a', buflen = 1000 );
for( j = 0; j < 1000; j++ )
sha1_update( &ctx, buf, buflen );
}
else
sha1_update( &ctx, sha1_test_buf[i],
sha1_test_buflen[i] );
sha1_finish( &ctx, sha1sum );
if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 )
{
if( verbose != 0 )
polarssl_printf( "failed\n" );
ret = 1;
goto exit;
}
if( verbose != 0 )
polarssl_printf( "passed\n" );
}
if( verbose != 0 )
polarssl_printf( "\n" );
for( i = 0; i < 7; i++ )
{
if( verbose != 0 )
polarssl_printf( " HMAC-SHA-1 test #%d: ", i + 1 );
if( i == 5 || i == 6 )
{
memset( buf, 0xAA, buflen = 80 );
sha1_hmac_starts( &ctx, buf, buflen );
}
else
sha1_hmac_starts( &ctx, sha1_hmac_test_key[i],
sha1_hmac_test_keylen[i] );
sha1_hmac_update( &ctx, sha1_hmac_test_buf[i],
sha1_hmac_test_buflen[i] );
sha1_hmac_finish( &ctx, sha1sum );
buflen = ( i == 4 ) ? 12 : 20;
if( memcmp( sha1sum, sha1_hmac_test_sum[i], buflen ) != 0 )
{
if( verbose != 0 )
polarssl_printf( "failed\n" );
ret = 1;
goto exit;
}
if( verbose != 0 )
polarssl_printf( "passed\n" );
}
if( verbose != 0 )
polarssl_printf( "\n" );
exit:
sha1_free( &ctx );
return( ret );
}
#endif /* POLARSSL_SELF_TEST */
#endif /* POLARSSL_SHA1_C */

213
common/sha1.h Normal file
View file

@ -0,0 +1,213 @@
/**
* \file sha1.h
*
* \brief SHA-1 cryptographic hash function
*
* Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
*
* This file is part of mbed TLS (https://tls.mbed.org)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef POLARSSL_SHA1_H
#define POLARSSL_SHA1_H
#if !defined(POLARSSL_CONFIG_FILE)
//#include "config.h"
/**
* \def POLARSSL_SHA1_C
*
* Enable the SHA1 cryptographic hash algorithm.
*
* Module: library/sha1.c
* Caller: library/md.c
* library/ssl_cli.c
* library/ssl_srv.c
* library/ssl_tls.c
* library/x509write_crt.c
*
* This module is required for SSL/TLS and SHA1-signed certificates.
*/
#define POLARSSL_SHA1_C
#else
#include POLARSSL_CONFIG_FILE
#endif
#include <stddef.h>
#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
#include <basetsd.h>
typedef UINT32 uint32_t;
#else
#include <inttypes.h>
#endif
#define POLARSSL_ERR_SHA1_FILE_IO_ERROR -0x0076 /**< Read/write error in file. */
#if !defined(POLARSSL_SHA1_ALT)
// Regular implementation
//
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief SHA-1 context structure
*/
typedef struct
{
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[5]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
unsigned char ipad[64]; /*!< HMAC: inner padding */
unsigned char opad[64]; /*!< HMAC: outer padding */
}
sha1_context;
/**
* \brief Initialize SHA-1 context
*
* \param ctx SHA-1 context to be initialized
*/
void sha1_init( sha1_context *ctx );
/**
* \brief Clear SHA-1 context
*
* \param ctx SHA-1 context to be cleared
*/
void sha1_free( sha1_context *ctx );
/**
* \brief SHA-1 context setup
*
* \param ctx context to be initialized
*/
void sha1_starts( sha1_context *ctx );
/**
* \brief SHA-1 process buffer
*
* \param ctx SHA-1 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen );
/**
* \brief SHA-1 final digest
*
* \param ctx SHA-1 context
* \param output SHA-1 checksum result
*/
void sha1_finish( sha1_context *ctx, unsigned char output[20] );
/* Internal use */
void sha1_process( sha1_context *ctx, const unsigned char data[64] );
#ifdef __cplusplus
}
#endif
#else /* POLARSSL_SHA1_ALT */
#include "sha1_alt.h"
#endif /* POLARSSL_SHA1_ALT */
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Output = SHA-1( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output SHA-1 checksum result
*/
void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] );
/**
* \brief Output = SHA-1( file contents )
*
* \param path input file name
* \param output SHA-1 checksum result
*
* \return 0 if successful, or POLARSSL_ERR_SHA1_FILE_IO_ERROR
*/
int sha1_file( const char *path, unsigned char output[20] );
/**
* \brief SHA-1 HMAC context setup
*
* \param ctx HMAC context to be initialized
* \param key HMAC secret key
* \param keylen length of the HMAC key
*/
void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key,
size_t keylen );
/**
* \brief SHA-1 HMAC process buffer
*
* \param ctx HMAC context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void sha1_hmac_update( sha1_context *ctx, const unsigned char *input,
size_t ilen );
/**
* \brief SHA-1 HMAC final digest
*
* \param ctx HMAC context
* \param output SHA-1 HMAC checksum result
*/
void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] );
/**
* \brief SHA-1 HMAC context reset
*
* \param ctx HMAC context to be reset
*/
void sha1_hmac_reset( sha1_context *ctx );
/**
* \brief Output = HMAC-SHA-1( hmac key, input buffer )
*
* \param key HMAC secret key
* \param keylen length of the HMAC key
* \param input buffer holding the data
* \param ilen length of the input data
* \param output HMAC-SHA-1 result
*/
void sha1_hmac( const unsigned char *key, size_t keylen,
const unsigned char *input, size_t ilen,
unsigned char output[20] );
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int sha1_self_test( int verbose );
#ifdef __cplusplus
}
#endif
#endif /* sha1.h */

Binary file not shown.

View file

@ -73,9 +73,6 @@ wire hi_read_rx_xcorr_848 = conf_word[0];
// and whether to drive the coil (reader) or just short it (snooper) // and whether to drive the coil (reader) or just short it (snooper)
wire hi_read_rx_xcorr_snoop = conf_word[1]; wire hi_read_rx_xcorr_snoop = conf_word[1];
// Divide the expected subcarrier frequency for hi_read_rx_xcorr by 4
wire hi_read_rx_xcorr_quarter = conf_word[2];
// For the high-frequency simulated tag: what kind of modulation to use. // For the high-frequency simulated tag: what kind of modulation to use.
wire [2:0] hi_simulate_mod_type = conf_word[2:0]; wire [2:0] hi_simulate_mod_type = conf_word[2:0];
@ -102,7 +99,7 @@ hi_read_rx_xcorr hrxc(
hrxc_ssp_frame, hrxc_ssp_din, ssp_dout, hrxc_ssp_clk, hrxc_ssp_frame, hrxc_ssp_din, ssp_dout, hrxc_ssp_clk,
cross_hi, cross_lo, cross_hi, cross_lo,
hrxc_dbg, hrxc_dbg,
hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop, hi_read_rx_xcorr_quarter hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop
); );
hi_simulate hs( hi_simulate hs(

View file

@ -10,7 +10,7 @@ module hi_read_rx_xcorr(
ssp_frame, ssp_din, ssp_dout, ssp_clk, ssp_frame, ssp_din, ssp_dout, ssp_clk,
cross_hi, cross_lo, cross_hi, cross_lo,
dbg, dbg,
xcorr_is_848, snoop, xcorr_quarter_freq xcorr_is_848, snoop
); );
input pck0, ck_1356meg, ck_1356megb; input pck0, ck_1356meg, ck_1356megb;
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
@ -20,58 +20,24 @@ module hi_read_rx_xcorr(
output ssp_frame, ssp_din, ssp_clk; output ssp_frame, ssp_din, ssp_clk;
input cross_hi, cross_lo; input cross_hi, cross_lo;
output dbg; output dbg;
input xcorr_is_848, snoop, xcorr_quarter_freq; input xcorr_is_848, snoop;
// Carrier is steady on through this, unless we're snooping. // Carrier is steady on through this, unless we're snooping.
assign pwr_hi = ck_1356megb & (~snoop); assign pwr_hi = ck_1356megb & (~snoop);
assign pwr_oe1 = 1'b0; assign pwr_oe1 = 1'b0;
assign pwr_oe2 = 1'b0;
assign pwr_oe3 = 1'b0; assign pwr_oe3 = 1'b0;
assign pwr_oe4 = 1'b0; assign pwr_oe4 = 1'b0;
reg ssp_clk; wire adc_clk = ck_1356megb;
reg ssp_frame;
reg fc_div_2; reg fc_div_2;
always @(posedge ck_1356meg) always @(negedge ck_1356megb)
fc_div_2 = ~fc_div_2; fc_div_2 <= fc_div_2 + 1;
reg fc_div_4;
always @(posedge fc_div_2)
fc_div_4 = ~fc_div_4;
reg fc_div_8;
always @(posedge fc_div_4)
fc_div_8 = ~fc_div_8;
reg adc_clk;
always @(xcorr_is_848 or xcorr_quarter_freq or ck_1356meg)
if(~xcorr_quarter_freq)
begin
if(xcorr_is_848)
// The subcarrier frequency is fc/16; we will sample at fc, so that
// means the subcarrier is 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 ...
adc_clk <= ck_1356meg;
else
// The subcarrier frequency is fc/32; we will sample at fc/2, and
// the subcarrier will look identical.
adc_clk <= fc_div_2;
end
else
begin
if(xcorr_is_848)
// The subcarrier frequency is fc/64
adc_clk <= fc_div_4;
else
// The subcarrier frequency is fc/128
adc_clk <= fc_div_8;
end
// When we're a reader, we just need to do the BPSK demod; but when we're an // When we're a reader, we just need to do the BPSK demod; but when we're an
// eavesdropper, we also need to pick out the commands sent by the reader, // eavesdropper, we also need to pick out the commands sent by the reader,
// using AM. Do this the same way that we do it for the simulated tag. // using AM. Do this the same way that we do it for the simulated tag.
reg after_hysteresis, after_hysteresis_prev; reg after_hysteresis, after_hysteresis_prev, after_hysteresis_prev_prev;
reg [11:0] has_been_low_for; reg [11:0] has_been_low_for;
always @(negedge adc_clk) always @(negedge adc_clk)
begin begin
@ -97,12 +63,24 @@ end
// Let us report a correlation every 4 subcarrier cycles, or 4*16 samples, // Let us report a correlation every 4 subcarrier cycles, or 4*16 samples,
// so we need a 6-bit counter. // so we need a 6-bit counter.
reg [5:0] corr_i_cnt; reg [5:0] corr_i_cnt;
reg [5:0] corr_q_cnt;
// And a couple of registers in which to accumulate the correlations. // And a couple of registers in which to accumulate the correlations.
reg signed [15:0] corr_i_accum; // we would add at most 32 times adc_d, the result can be held in 13 bits.
reg signed [15:0] corr_q_accum; // Need one additional bit because it can be negative as well
reg signed [13:0] corr_i_accum;
reg signed [13:0] corr_q_accum;
reg signed [7:0] corr_i_out; reg signed [7:0] corr_i_out;
reg signed [7:0] corr_q_out; reg signed [7:0] corr_q_out;
// clock and frame signal for communication to ARM
reg ssp_clk;
reg ssp_frame;
always @(negedge adc_clk)
begin
if (xcorr_is_848 | fc_div_2)
corr_i_cnt <= corr_i_cnt + 1;
end
// ADC data appears on the rising edge, so sample it on the falling edge // ADC data appears on the rising edge, so sample it on the falling edge
always @(negedge adc_clk) always @(negedge adc_clk)
@ -110,24 +88,24 @@ begin
// These are the correlators: we correlate against in-phase and quadrature // These are the correlators: we correlate against in-phase and quadrature
// versions of our reference signal, and keep the (signed) result to // versions of our reference signal, and keep the (signed) result to
// send out later over the SSP. // send out later over the SSP.
if(corr_i_cnt == 7'd63) if(corr_i_cnt == 6'd0)
begin begin
if(snoop) if(snoop)
begin begin
corr_i_out <= {corr_i_accum[12:6], after_hysteresis_prev}; // Send only 7 most significant bits of tag signal (signed), LSB is reader signal:
corr_q_out <= {corr_q_accum[12:6], after_hysteresis}; corr_i_out <= {corr_i_accum[13:7], after_hysteresis_prev_prev};
corr_q_out <= {corr_q_accum[13:7], after_hysteresis_prev};
after_hysteresis_prev_prev <= after_hysteresis;
end end
else else
begin begin
// Only correlations need to be delivered. // 8 most significant bits of tag signal
corr_i_out <= corr_i_accum[13:6]; corr_i_out <= corr_i_accum[13:6];
corr_q_out <= corr_q_accum[13:6]; corr_q_out <= corr_q_accum[13:6];
end end
corr_i_accum <= adc_d; corr_i_accum <= adc_d;
corr_q_accum <= adc_d; corr_q_accum <= adc_d;
corr_q_cnt <= 4;
corr_i_cnt <= 0;
end end
else else
begin begin
@ -136,18 +114,16 @@ begin
else else
corr_i_accum <= corr_i_accum + adc_d; corr_i_accum <= corr_i_accum + adc_d;
if(corr_q_cnt[3]) if(corr_i_cnt[3] == corr_i_cnt[2]) // phase shifted by pi/2
corr_q_accum <= corr_q_accum - adc_d;
else
corr_q_accum <= corr_q_accum + adc_d; corr_q_accum <= corr_q_accum + adc_d;
else
corr_q_accum <= corr_q_accum - adc_d;
corr_i_cnt <= corr_i_cnt + 1;
corr_q_cnt <= corr_q_cnt + 1;
end end
// The logic in hi_simulate.v reports 4 samples per bit. We report two // The logic in hi_simulate.v reports 4 samples per bit. We report two
// (I, Q) pairs per bit, so we should do 2 samples per pair. // (I, Q) pairs per bit, so we should do 2 samples per pair.
if(corr_i_cnt == 6'd31) if(corr_i_cnt == 6'd32)
after_hysteresis_prev <= after_hysteresis; after_hysteresis_prev <= after_hysteresis;
// Then the result from last time is serialized and send out to the ARM. // Then the result from last time is serialized and send out to the ARM.
@ -168,7 +144,9 @@ begin
end end
end end
if(corr_i_cnt[5:2] == 4'b000 || corr_i_cnt[5:2] == 4'b1000) // set ssp_frame signal for corr_i_cnt = 0..3 and corr_i_cnt = 32..35
// (send two frames with 8 Bits each)
if(corr_i_cnt[5:2] == 4'b0000 || corr_i_cnt[5:2] == 4'b1000)
ssp_frame = 1'b1; ssp_frame = 1'b1;
else else
ssp_frame = 1'b0; ssp_frame = 1'b0;
@ -181,5 +159,6 @@ assign dbg = corr_i_cnt[3];
// Unused. // Unused.
assign pwr_lo = 1'b0; assign pwr_lo = 1'b0;
assign pwr_oe2 = 1'b0;
endmodule endmodule

View file

@ -61,10 +61,6 @@
#define SPI_FPGA_MODE 0 #define SPI_FPGA_MODE 0
#define SPI_LCD_MODE 1 #define SPI_LCD_MODE 1
#define FPGA_BITSTREAM_ERR 0
#define FPGA_BITSTREAM_LF 1
#define FPGA_BITSTREAM_HF 2
#define TRUE 1 #define TRUE 1
#define FALSE 0 #define FALSE 0

View file

@ -100,7 +100,6 @@ typedef struct{
// For the 13.56 MHz tags // For the 13.56 MHz tags
#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300 #define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300
#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443 0x0301
#define CMD_READ_SRI512_TAG 0x0303 #define CMD_READ_SRI512_TAG 0x0303
#define CMD_READ_SRIX4K_TAG 0x0304 #define CMD_READ_SRIX4K_TAG 0x0304
#define CMD_ISO_14443B_COMMAND 0x0305 #define CMD_ISO_14443B_COMMAND 0x0305
@ -118,9 +117,8 @@ typedef struct{
#define CMD_SIMULATE_HITAG 0x0371 #define CMD_SIMULATE_HITAG 0x0371
#define CMD_READER_HITAG 0x0372 #define CMD_READER_HITAG 0x0372
#define CMD_SIMULATE_TAG_HF_LISTEN 0x0380 #define CMD_SIMULATE_TAG_ISO_14443B 0x0381
#define CMD_SIMULATE_TAG_ISO_14443 0x0381 #define CMD_SNOOP_ISO_14443B 0x0382
#define CMD_SNOOP_ISO_14443 0x0382
#define CMD_SNOOP_ISO_14443a 0x0383 #define CMD_SNOOP_ISO_14443a 0x0383
#define CMD_SIMULATE_TAG_ISO_14443a 0x0384 #define CMD_SIMULATE_TAG_ISO_14443a 0x0384
#define CMD_READER_ISO_14443a 0x0385 #define CMD_READER_ISO_14443a 0x0385
@ -128,12 +126,13 @@ typedef struct{
#define CMD_READER_LEGIC_RF 0x0388 #define CMD_READER_LEGIC_RF 0x0388
#define CMD_WRITER_LEGIC_RF 0x0389 #define CMD_WRITER_LEGIC_RF 0x0389
#define CMD_EPA_PACE_COLLECT_NONCE 0x038A #define CMD_EPA_PACE_COLLECT_NONCE 0x038A
#define CMD_EPA_PACE_REPLAY 0x038B
#define CMD_SNOOP_ICLASS 0x0392 #define CMD_SNOOP_ICLASS 0x0392
#define CMD_SIMULATE_TAG_ICLASS 0x0393 #define CMD_SIMULATE_TAG_ICLASS 0x0393
#define CMD_READER_ICLASS 0x0394 #define CMD_READER_ICLASS 0x0394
#define CMD_READER_ICLASS_REPLAY 0x0395 #define CMD_READER_ICLASS_REPLAY 0x0395
#define CMD_ICLASS_ISO14443A_WRITE 0x0397 #define CMD_ICLASS_ISO14443A_WRITE 0x0397
#define CMD_ICLASS_EML_MEMSET 0x0398 #define CMD_ICLASS_EML_MEMSET 0x0398
// For measurements of the antenna tuning // For measurements of the antenna tuning
@ -163,20 +162,21 @@ typedef struct{
#define CMD_MIFARE_NESTED 0x0612 #define CMD_MIFARE_NESTED 0x0612
#define CMD_MIFARE_READBL 0x0620 #define CMD_MIFARE_READBL 0x0620
#define CMD_MIFAREU_READBL 0x0720 #define CMD_MIFAREU_READBL 0x0720
#define CMD_MIFARE_READSC 0x0621 #define CMD_MIFARE_READSC 0x0621
#define CMD_MIFAREU_READCARD 0x0721 #define CMD_MIFAREU_READCARD 0x0721
#define CMD_MIFARE_WRITEBL 0x0622 #define CMD_MIFARE_WRITEBL 0x0622
#define CMD_MIFAREU_WRITEBL 0x0722 #define CMD_MIFAREU_WRITEBL 0x0722
#define CMD_MIFAREU_WRITEBL_COMPAT 0x0723 #define CMD_MIFAREU_WRITEBL_COMPAT 0x0723
#define CMD_MIFARE_CHKKEYS 0x0623 #define CMD_MIFARE_CHKKEYS 0x0623
#define CMD_MIFARE_SNIFFER 0x0630 #define CMD_MIFARE_SNIFFER 0x0630
//ultralightC //ultralightC
#define CMD_MIFAREUC_AUTH1 0x0724 #define CMD_MIFAREUC_AUTH 0x0724
#define CMD_MIFAREUC_AUTH2 0x0725 //0x0725 and 0x0726 no longer used
#define CMD_MIFAREUC_READCARD 0x0726 #define CMD_MIFAREUC_SETPWD 0x0727
// mifare desfire // mifare desfire
#define CMD_MIFARE_DESFIRE_READBL 0x0728 #define CMD_MIFARE_DESFIRE_READBL 0x0728
@ -199,10 +199,11 @@ typedef struct{
//Iclass reader flags //Iclass reader flags
#define FLAG_ICLASS_READER_ONLY_ONCE 0x01 #define FLAG_ICLASS_READER_ONLY_ONCE 0x01
#define FLAG_ICLASS_READER_CC 0x02 #define FLAG_ICLASS_READER_CC 0x02
#define FLAG_ICLASS_READER_CSN 0x04 #define FLAG_ICLASS_READER_CSN 0x04
#define FLAG_ICLASS_READER_CONF 0x08 #define FLAG_ICLASS_READER_CONF 0x08
#define FLAG_ICLASS_READER_AA 0x10 #define FLAG_ICLASS_READER_AA 0x10
#define FLAG_ICLASS_READER_ONE_TRY 0x20

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