mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 13:23:51 -07:00
Merge branch 'master' into GenericTracing
Conflicts: armsrc/iso14443.c armsrc/iso14443a.c client/cmdhf.c client/cmdhf14b.c
This commit is contained in:
commit
7d5ebac993
98 changed files with 444131 additions and 2207 deletions
97
armsrc/BigBuf.c
Normal file
97
armsrc/BigBuf.c
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Jonathan Westhues, Aug 2005
|
||||||
|
// Gerhard de Koning Gans, April 2008, May 2011
|
||||||
|
//
|
||||||
|
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||||
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
|
// the license.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// BigBuf and functions to allocate/free parts of it.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "proxmark3.h"
|
||||||
|
#include "apps.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
|
// BigBuf is the large multi-purpose buffer, typically used to hold A/D samples or traces.
|
||||||
|
// Also used to hold various smaller buffers and the Mifare Emulator Memory.
|
||||||
|
|
||||||
|
// declare it as uint32_t to achieve alignment to 4 Byte boundary
|
||||||
|
static uint32_t BigBuf[BIGBUF_SIZE/sizeof(uint32_t)];
|
||||||
|
|
||||||
|
// High memory mark
|
||||||
|
static uint16_t BigBuf_hi = BIGBUF_SIZE;
|
||||||
|
|
||||||
|
// pointer to the emulator memory.
|
||||||
|
static uint8_t *emulator_memory = NULL;
|
||||||
|
|
||||||
|
// trace related global variables
|
||||||
|
// (only one left). ToDo: make this static as well?
|
||||||
|
uint16_t traceLen = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// get the address of BigBuf
|
||||||
|
uint8_t *BigBuf_get_addr(void)
|
||||||
|
{
|
||||||
|
return (uint8_t *)BigBuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// get the address of the emulator memory. Allocate part of Bigbuf for it, if not yet done
|
||||||
|
uint8_t *BigBuf_get_EM_addr(void)
|
||||||
|
{
|
||||||
|
if (emulator_memory == NULL) { // not yet allocated
|
||||||
|
emulator_memory = BigBuf_malloc(CARD_MEMORY_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return emulator_memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// clear ALL of BigBuf
|
||||||
|
void BigBuf_Clear(void)
|
||||||
|
{
|
||||||
|
memset(BigBuf,0,BIGBUF_SIZE);
|
||||||
|
Dbprintf("Buffer cleared (%i bytes)",BIGBUF_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// allocate a chunk of memory from BigBuf. We allocate high memory first. The unallocated memory
|
||||||
|
// at the beginning of BigBuf is always for traces/samples
|
||||||
|
uint8_t *BigBuf_malloc(uint16_t chunksize)
|
||||||
|
{
|
||||||
|
if (BigBuf_hi - chunksize < 0) {
|
||||||
|
return NULL; // no memory left
|
||||||
|
} else {
|
||||||
|
chunksize = (chunksize + 3) & 0xfffc; // round to next multiple of 4
|
||||||
|
BigBuf_hi -= chunksize; // aligned to 4 Byte boundary
|
||||||
|
return (uint8_t *)BigBuf + BigBuf_hi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// free ALL allocated chunks. The whole BigBuf is available for traces or samples again.
|
||||||
|
void BigBuf_free(void)
|
||||||
|
{
|
||||||
|
BigBuf_hi = BIGBUF_SIZE;
|
||||||
|
emulator_memory = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// free allocated chunks EXCEPT the emulator memory
|
||||||
|
void BigBuf_free_keep_EM(void)
|
||||||
|
{
|
||||||
|
if (emulator_memory != NULL) {
|
||||||
|
BigBuf_hi = emulator_memory - (uint8_t *)BigBuf;
|
||||||
|
} else {
|
||||||
|
BigBuf_hi = BIGBUF_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// return the maximum trace length (i.e. the unallocated size of BigBuf)
|
||||||
|
uint16_t BigBuf_max_traceLen(void)
|
||||||
|
{
|
||||||
|
return BigBuf_hi;
|
||||||
|
}
|
34
armsrc/BigBuf.h
Normal file
34
armsrc/BigBuf.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Jonathan Westhues, Aug 2005
|
||||||
|
// Gerhard de Koning Gans, April 2008, May 2011
|
||||||
|
//
|
||||||
|
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||||
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
|
// the license.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// BigBuf and functions to allocate/free parts of it.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef __BIGBUF_H
|
||||||
|
#define __BIGBUF_H
|
||||||
|
|
||||||
|
|
||||||
|
#define BIGBUF_SIZE 40000
|
||||||
|
#define MAX_FRAME_SIZE 256 // maximum allowed ISO14443 frame
|
||||||
|
#define MAX_PARITY_SIZE ((MAX_FRAME_SIZE + 7) / 8)
|
||||||
|
#define MAX_MIFARE_FRAME_SIZE 18 // biggest Mifare frame is answer to a read (one block = 16 Bytes) + 2 Bytes CRC
|
||||||
|
#define MAX_MIFARE_PARITY_SIZE 3 // need 18 parity bits for the 18 Byte above. 3 Bytes are enough to store these
|
||||||
|
#define CARD_MEMORY_SIZE 4096
|
||||||
|
#define DMA_BUFFER_SIZE 128
|
||||||
|
|
||||||
|
extern uint8_t *BigBuf_get_addr(void);
|
||||||
|
extern uint8_t *BigBuf_get_EM_addr(void);
|
||||||
|
extern uint16_t BigBuf_max_traceLen(void);
|
||||||
|
void BigBuf_Clear(void);
|
||||||
|
extern uint8_t *BigBuf_malloc(uint16_t);
|
||||||
|
extern void BigBuf_free(void);
|
||||||
|
extern void BigBuf_free_keep_EM(void);
|
||||||
|
|
||||||
|
extern uint16_t traceLen;
|
||||||
|
|
||||||
|
#endif /* __BIGBUF_H */
|
|
@ -10,15 +10,16 @@ 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 -fno-strict-aliasing
|
APP_CFLAGS = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG -DWITH_CRC -fno-strict-aliasing
|
||||||
#-DWITH_LCD
|
#-DWITH_LCD
|
||||||
|
|
||||||
#SRC_LCD = fonts.c LCD.c
|
#SRC_LCD = fonts.c LCD.c
|
||||||
SRC_LF = lfops.c hitag2.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 = iso14443.c
|
||||||
SRC_CRAPTO1 = crapto1.c crypto1.c
|
SRC_CRAPTO1 = crapto1.c crypto1.c des.c aes.c
|
||||||
|
SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c
|
||||||
|
|
||||||
THUMBSRC = start.c \
|
THUMBSRC = start.c \
|
||||||
$(SRC_LCD) \
|
$(SRC_LCD) \
|
||||||
|
@ -34,15 +35,14 @@ THUMBSRC = start.c \
|
||||||
# These are to be compiled in ARM mode
|
# These are to be compiled in ARM mode
|
||||||
ARMSRC = fpgaloader.c \
|
ARMSRC = fpgaloader.c \
|
||||||
legicrf.c \
|
legicrf.c \
|
||||||
iso14443crc.c \
|
|
||||||
crc16.c \
|
|
||||||
lfdemod.c \
|
lfdemod.c \
|
||||||
$(SRC_ISO14443a) \
|
$(SRC_ISO14443a) \
|
||||||
$(SRC_ISO14443b) \
|
$(SRC_ISO14443b) \
|
||||||
$(SRC_CRAPTO1) \
|
$(SRC_CRAPTO1) \
|
||||||
|
$(SRC_CRC) \
|
||||||
legic_prng.c \
|
legic_prng.c \
|
||||||
iclass.c \
|
iclass.c \
|
||||||
crc.c
|
BigBuf.c \
|
||||||
|
|
||||||
# stdint.h provided locally until GCC 4.5 becomes C99 compliant
|
# stdint.h provided locally until GCC 4.5 becomes C99 compliant
|
||||||
APP_CFLAGS += -I.
|
APP_CFLAGS += -I.
|
||||||
|
|
1168
armsrc/aes.c
Normal file
1168
armsrc/aes.c
Normal file
File diff suppressed because it is too large
Load diff
30
armsrc/aes.h
Normal file
30
armsrc/aes.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* AES Cryptographic Algorithm Header File. Include this header file in
|
||||||
|
* your source which uses these given APIs. (This source is kept under
|
||||||
|
* public domain)
|
||||||
|
*/
|
||||||
|
|
||||||
|
// AES context structure
|
||||||
|
typedef struct {
|
||||||
|
unsigned int Ek[60];
|
||||||
|
unsigned int Dk[60];
|
||||||
|
unsigned int Iv[4];
|
||||||
|
unsigned char Nr;
|
||||||
|
unsigned char Mode;
|
||||||
|
} AesCtx;
|
||||||
|
|
||||||
|
// key length in bytes
|
||||||
|
#define KEY128 16
|
||||||
|
#define KEY192 24
|
||||||
|
#define KEY256 32
|
||||||
|
// block size in bytes
|
||||||
|
#define BLOCKSZ 16
|
||||||
|
// mode
|
||||||
|
#define EBC 0
|
||||||
|
#define CBC 1
|
||||||
|
|
||||||
|
// AES API function prototype
|
||||||
|
|
||||||
|
int AesCtxIni(AesCtx *pCtx, unsigned char *pIV, unsigned char *pKey, unsigned int KeyLen, unsigned char Mode);
|
||||||
|
int AesEncrypt(AesCtx *pCtx, unsigned char *pData, unsigned char *pCipher, unsigned int DataLen);
|
||||||
|
int AesDecrypt(AesCtx *pCtx, unsigned char *pCipher, unsigned char *pData, unsigned int CipherLen);
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
#include "legicrf.h"
|
#include "legicrf.h"
|
||||||
#include <hitag2.h>
|
#include <hitag2.h>
|
||||||
|
#include "lfsampling.h"
|
||||||
#ifdef WITH_LCD
|
#ifdef WITH_LCD
|
||||||
#include "LCD.h"
|
#include "LCD.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -42,12 +42,6 @@ int ToSendMax;
|
||||||
static int ToSendBit;
|
static int ToSendBit;
|
||||||
struct common_area common_area __attribute__((section(".commonarea")));
|
struct common_area common_area __attribute__((section(".commonarea")));
|
||||||
|
|
||||||
void BufferClear(void)
|
|
||||||
{
|
|
||||||
memset(BigBuf,0,sizeof(BigBuf));
|
|
||||||
Dbprintf("Buffer cleared (%i bytes)",sizeof(BigBuf));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ToSendReset(void)
|
void ToSendReset(void)
|
||||||
{
|
{
|
||||||
ToSendMax = -1;
|
ToSendMax = -1;
|
||||||
|
@ -246,7 +240,10 @@ void MeasureAntennaTuningHf(void)
|
||||||
|
|
||||||
void SimulateTagHfListen(void)
|
void SimulateTagHfListen(void)
|
||||||
{
|
{
|
||||||
uint8_t *dest = (uint8_t *)BigBuf+FREE_BUFFER_OFFSET;
|
// 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;
|
uint8_t v = 0;
|
||||||
int i;
|
int i;
|
||||||
int p = 0;
|
int p = 0;
|
||||||
|
@ -281,7 +278,7 @@ void SimulateTagHfListen(void)
|
||||||
p = 0;
|
p = 0;
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
if(i >= FREE_BUFFER_SIZE) {
|
if(i >= HF_14B_SNOOP_BUFFER_SIZE) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -629,16 +626,17 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
||||||
|
|
||||||
switch(c->cmd) {
|
switch(c->cmd) {
|
||||||
#ifdef WITH_LF
|
#ifdef WITH_LF
|
||||||
|
case CMD_SET_LF_SAMPLING_CONFIG:
|
||||||
|
setSamplingConfig((sample_config *) c->d.asBytes);
|
||||||
|
break;
|
||||||
case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K:
|
case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K:
|
||||||
AcquireRawAdcSamples125k(c->arg[0]);
|
cmd_send(CMD_ACK,SampleLF(),0,0,0,0);
|
||||||
cmd_send(CMD_ACK,0,0,0,0,0);
|
|
||||||
break;
|
break;
|
||||||
case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K:
|
case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K:
|
||||||
ModThenAcquireRawAdcSamples125k(c->arg[0],c->arg[1],c->arg[2],c->d.asBytes);
|
ModThenAcquireRawAdcSamples125k(c->arg[0],c->arg[1],c->arg[2],c->d.asBytes);
|
||||||
break;
|
break;
|
||||||
case CMD_LF_SNOOP_RAW_ADC_SAMPLES:
|
case CMD_LF_SNOOP_RAW_ADC_SAMPLES:
|
||||||
SnoopLFRawAdcSamples(c->arg[0], c->arg[1]);
|
cmd_send(CMD_ACK,SnoopLF(),0,0,0,0);
|
||||||
cmd_send(CMD_ACK,0,0,0,0,0);
|
|
||||||
break;
|
break;
|
||||||
case CMD_HID_DEMOD_FSK:
|
case CMD_HID_DEMOD_FSK:
|
||||||
CmdHIDdemodFSK(c->arg[0], 0, 0, 1);
|
CmdHIDdemodFSK(c->arg[0], 0, 0, 1);
|
||||||
|
@ -801,9 +799,18 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
||||||
case CMD_MIFAREU_READBL:
|
case CMD_MIFAREU_READBL:
|
||||||
MifareUReadBlock(c->arg[0],c->d.asBytes);
|
MifareUReadBlock(c->arg[0],c->d.asBytes);
|
||||||
break;
|
break;
|
||||||
|
case CMD_MIFAREUC_AUTH1:
|
||||||
|
MifareUC_Auth1(c->arg[0],c->d.asBytes);
|
||||||
|
break;
|
||||||
|
case CMD_MIFAREUC_AUTH2:
|
||||||
|
MifareUC_Auth2(c->arg[0],c->d.asBytes);
|
||||||
|
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->d.asBytes);
|
||||||
break;
|
break;
|
||||||
|
case CMD_MIFAREUC_READCARD:
|
||||||
|
MifareUReadCard(c->arg[0], c->arg[1], c->d.asBytes);
|
||||||
|
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);
|
||||||
break;
|
break;
|
||||||
|
@ -858,6 +865,7 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
||||||
case CMD_MIFARE_SNIFFER:
|
case CMD_MIFARE_SNIFFER:
|
||||||
SniffMifare(c->arg[0]);
|
SniffMifare(c->arg[0]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_ICLASS
|
#ifdef WITH_ICLASS
|
||||||
|
@ -881,7 +889,7 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_BUFF_CLEAR:
|
case CMD_BUFF_CLEAR:
|
||||||
BufferClear();
|
BigBuf_Clear();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_MEASURE_ANTENNA_TUNING:
|
case CMD_MEASURE_ANTENNA_TUNING:
|
||||||
|
@ -905,17 +913,18 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
||||||
case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K:
|
case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K:
|
||||||
|
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
|
uint8_t *BigBuf = BigBuf_get_addr();
|
||||||
for(size_t i=0; i<c->arg[1]; i += USB_CMD_DATA_SIZE) {
|
for(size_t i=0; i<c->arg[1]; i += USB_CMD_DATA_SIZE) {
|
||||||
size_t len = MIN((c->arg[1] - i),USB_CMD_DATA_SIZE);
|
size_t len = MIN((c->arg[1] - i),USB_CMD_DATA_SIZE);
|
||||||
cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K,i,len,0,((byte_t*)BigBuf)+c->arg[0]+i,len);
|
cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K,i,len,traceLen,BigBuf+c->arg[0]+i,len);
|
||||||
}
|
}
|
||||||
// Trigger a finish downloading signal with an ACK frame
|
// Trigger a finish downloading signal with an ACK frame
|
||||||
cmd_send(CMD_ACK,0,0,0,0,0);
|
cmd_send(CMD_ACK,1,0,traceLen,getSamplingConfig(),sizeof(sample_config));
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_DOWNLOADED_SIM_SAMPLES_125K: {
|
case CMD_DOWNLOADED_SIM_SAMPLES_125K: {
|
||||||
uint8_t *b = (uint8_t *)BigBuf;
|
uint8_t *b = BigBuf_get_addr();
|
||||||
memcpy(b+c->arg[0], c->d.asBytes, USB_CMD_DATA_SIZE);
|
memcpy(b+c->arg[0], c->d.asBytes, USB_CMD_DATA_SIZE);
|
||||||
cmd_send(CMD_ACK,0,0,0,0,0);
|
cmd_send(CMD_ACK,0,0,0,0,0);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -17,48 +17,10 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "hitag2.h"
|
#include "hitag2.h"
|
||||||
#include "mifare.h"
|
#include "mifare.h"
|
||||||
|
#include "../common/crc32.h"
|
||||||
// The large multi-purpose buffer, typically used to hold A/D samples,
|
#include "BigBuf.h"
|
||||||
// maybe processed in some way.
|
|
||||||
#define BIGBUF_SIZE 40000
|
|
||||||
uint32_t BigBuf[BIGBUF_SIZE / sizeof(uint32_t)];
|
|
||||||
#define TRACE_OFFSET 0
|
|
||||||
#define TRACE_SIZE 3000
|
|
||||||
#define RECV_CMD_OFFSET (TRACE_OFFSET + TRACE_SIZE)
|
|
||||||
#define MAX_FRAME_SIZE 256
|
|
||||||
#define MAX_PARITY_SIZE ((MAX_FRAME_SIZE + 1)/ 8)
|
|
||||||
#define RECV_CMD_PAR_OFFSET (RECV_CMD_OFFSET + MAX_FRAME_SIZE)
|
|
||||||
#define RECV_RESP_OFFSET (RECV_CMD_PAR_OFFSET + MAX_PARITY_SIZE)
|
|
||||||
#define RECV_RESP_PAR_OFFSET (RECV_RESP_OFFSET + MAX_FRAME_SIZE)
|
|
||||||
#define CARD_MEMORY_OFFSET (RECV_RESP_PAR_OFFSET + MAX_PARITY_SIZE)
|
|
||||||
#define CARD_MEMORY_SIZE 4096
|
|
||||||
#define DMA_BUFFER_OFFSET CARD_MEMORY_OFFSET
|
|
||||||
#define DMA_BUFFER_SIZE CARD_MEMORY_SIZE
|
|
||||||
#define FREE_BUFFER_OFFSET (CARD_MEMORY_OFFSET + CARD_MEMORY_SIZE)
|
|
||||||
#define FREE_BUFFER_SIZE (BIGBUF_SIZE - FREE_BUFFER_OFFSET - 1)
|
|
||||||
|
|
||||||
/*
|
|
||||||
The statements above translates into this :
|
|
||||||
BIGBUF_SIZE = 40000
|
|
||||||
TRACE_OFFSET = 0
|
|
||||||
TRACE_SIZE = 3000
|
|
||||||
RECV_CMD_OFFSET = 3000
|
|
||||||
MAX_FRAME_SIZE = 256
|
|
||||||
MAX_PARITY_SIZE = 32
|
|
||||||
RECV_CMD_PAR_OFFSET = 3256
|
|
||||||
RECV_RESP_OFFSET = 3288
|
|
||||||
RECV_RESP_PAR_OFFSET= 3544
|
|
||||||
CARD_MEMORY_OFFSET = 3576
|
|
||||||
CARD_MEMORY_SIZE = 4096
|
|
||||||
DMA_BUFFER_OFFSET = 3576
|
|
||||||
DMA_BUFFER_SIZE = 4096
|
|
||||||
FREE_BUFFER_OFFSET = 7672
|
|
||||||
FREE_BUFFER_SIZE = 32327
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern const uint8_t OddByteParity[256];
|
extern const uint8_t OddByteParity[256];
|
||||||
extern uint8_t *trace; // = (uint8_t *) BigBuf;
|
|
||||||
extern int traceLen; // = 0;
|
|
||||||
extern int rsamples; // = 0;
|
extern int rsamples; // = 0;
|
||||||
extern int tracing; // = TRUE;
|
extern int tracing; // = TRUE;
|
||||||
extern uint8_t trigger;
|
extern uint8_t trigger;
|
||||||
|
@ -81,12 +43,8 @@ int AvgAdc(int ch);
|
||||||
void ToSendStuffBit(int b);
|
void ToSendStuffBit(int b);
|
||||||
void ToSendReset(void);
|
void ToSendReset(void);
|
||||||
void ListenReaderField(int limit);
|
void ListenReaderField(int limit);
|
||||||
void AcquireRawAdcSamples125k(int at134khz);
|
|
||||||
void SnoopLFRawAdcSamples(int divisor, int trigger_threshold);
|
|
||||||
void DoAcquisition125k(int trigger_threshold);
|
|
||||||
extern int ToSendMax;
|
extern int ToSendMax;
|
||||||
extern uint8_t ToSend[];
|
extern uint8_t ToSend[];
|
||||||
extern uint32_t BigBuf[];
|
|
||||||
|
|
||||||
/// fpga.h
|
/// fpga.h
|
||||||
void FpgaSendCommand(uint16_t cmd, uint16_t v);
|
void FpgaSendCommand(uint16_t cmd, uint16_t v);
|
||||||
|
@ -144,6 +102,10 @@ void SetAdcMuxFor(uint32_t whichGpio);
|
||||||
#define FPGA_HF_ISO14443A_READER_MOD (4<<0)
|
#define FPGA_HF_ISO14443A_READER_MOD (4<<0)
|
||||||
|
|
||||||
/// lfops.h
|
/// lfops.h
|
||||||
|
extern uint8_t decimation;
|
||||||
|
extern uint8_t bits_per_sample ;
|
||||||
|
extern bool averaging;
|
||||||
|
|
||||||
void AcquireRawAdcSamples125k(int divisor);
|
void AcquireRawAdcSamples125k(int divisor);
|
||||||
void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,uint8_t *command);
|
void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,uint8_t *command);
|
||||||
void ReadTItag(void);
|
void ReadTItag(void);
|
||||||
|
@ -198,7 +160,9 @@ 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 *datain);
|
||||||
void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain);
|
void MifareUC_Auth1(uint8_t arg0, uint8_t *datain);
|
||||||
|
void MifareUC_Auth2(uint32_t arg0, 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 MifareUWriteBlock(uint8_t arg0,uint8_t *datain);
|
||||||
|
@ -215,6 +179,25 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
||||||
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?
|
||||||
|
|
||||||
|
//desfire
|
||||||
|
void Mifare_DES_Auth1(uint8_t arg0,uint8_t *datain);
|
||||||
|
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
|
||||||
|
|
||||||
|
// mifaredesfire.h
|
||||||
|
bool InitDesfireCard();
|
||||||
|
void MifareSendCommand(uint8_t arg0,uint8_t arg1, uint8_t *datain);
|
||||||
|
void MifareDesfireGetInformation();
|
||||||
|
void MifareDES_Auth1(uint8_t arg0,uint8_t arg1,uint8_t arg2, uint8_t *datain);
|
||||||
|
void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t * datain);
|
||||||
|
int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout);
|
||||||
|
size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout);
|
||||||
|
void OnSuccess();
|
||||||
|
void OnError(uint8_t reason);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// iso15693.h
|
/// iso15693.h
|
||||||
void RecordRawAdcSamplesIso15693(void);
|
void RecordRawAdcSamplesIso15693(void);
|
||||||
void AcquireRawAdcSamplesIso15693(void);
|
void AcquireRawAdcSamplesIso15693(void);
|
||||||
|
|
383
armsrc/des.c
Normal file
383
armsrc/des.c
Normal file
|
@ -0,0 +1,383 @@
|
||||||
|
/* des.c */
|
||||||
|
/*
|
||||||
|
This file is part of the ARM-Crypto-Lib.
|
||||||
|
Copyright (C) 2006-2010 Daniel Otte (daniel.otte@rub.de)
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* \file des.c
|
||||||
|
* \author Daniel Otte
|
||||||
|
* \email daniel.otte@rub.de
|
||||||
|
* \date 2007-06-16
|
||||||
|
* \brief DES and EDE-DES implementation
|
||||||
|
* \license GPLv3 or later
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
const uint8_t sbox[256] = {
|
||||||
|
/* S-box 1 */
|
||||||
|
0xE4, 0xD1, 0x2F, 0xB8, 0x3A, 0x6C, 0x59, 0x07,
|
||||||
|
0x0F, 0x74, 0xE2, 0xD1, 0xA6, 0xCB, 0x95, 0x38,
|
||||||
|
0x41, 0xE8, 0xD6, 0x2B, 0xFC, 0x97, 0x3A, 0x50,
|
||||||
|
0xFC, 0x82, 0x49, 0x17, 0x5B, 0x3E, 0xA0, 0x6D,
|
||||||
|
/* S-box 2 */
|
||||||
|
0xF1, 0x8E, 0x6B, 0x34, 0x97, 0x2D, 0xC0, 0x5A,
|
||||||
|
0x3D, 0x47, 0xF2, 0x8E, 0xC0, 0x1A, 0x69, 0xB5,
|
||||||
|
0x0E, 0x7B, 0xA4, 0xD1, 0x58, 0xC6, 0x93, 0x2F,
|
||||||
|
0xD8, 0xA1, 0x3F, 0x42, 0xB6, 0x7C, 0x05, 0xE9,
|
||||||
|
/* S-box 3 */
|
||||||
|
0xA0, 0x9E, 0x63, 0xF5, 0x1D, 0xC7, 0xB4, 0x28,
|
||||||
|
0xD7, 0x09, 0x34, 0x6A, 0x28, 0x5E, 0xCB, 0xF1,
|
||||||
|
0xD6, 0x49, 0x8F, 0x30, 0xB1, 0x2C, 0x5A, 0xE7,
|
||||||
|
0x1A, 0xD0, 0x69, 0x87, 0x4F, 0xE3, 0xB5, 0x2C,
|
||||||
|
/* S-box 4 */
|
||||||
|
0x7D, 0xE3, 0x06, 0x9A, 0x12, 0x85, 0xBC, 0x4F,
|
||||||
|
0xD8, 0xB5, 0x6F, 0x03, 0x47, 0x2C, 0x1A, 0xE9,
|
||||||
|
0xA6, 0x90, 0xCB, 0x7D, 0xF1, 0x3E, 0x52, 0x84,
|
||||||
|
0x3F, 0x06, 0xA1, 0xD8, 0x94, 0x5B, 0xC7, 0x2E,
|
||||||
|
/* S-box 5 */
|
||||||
|
0x2C, 0x41, 0x7A, 0xB6, 0x85, 0x3F, 0xD0, 0xE9,
|
||||||
|
0xEB, 0x2C, 0x47, 0xD1, 0x50, 0xFA, 0x39, 0x86,
|
||||||
|
0x42, 0x1B, 0xAD, 0x78, 0xF9, 0xC5, 0x63, 0x0E,
|
||||||
|
0xB8, 0xC7, 0x1E, 0x2D, 0x6F, 0x09, 0xA4, 0x53,
|
||||||
|
/* S-box 6 */
|
||||||
|
0xC1, 0xAF, 0x92, 0x68, 0x0D, 0x34, 0xE7, 0x5B,
|
||||||
|
0xAF, 0x42, 0x7C, 0x95, 0x61, 0xDE, 0x0B, 0x38,
|
||||||
|
0x9E, 0xF5, 0x28, 0xC3, 0x70, 0x4A, 0x1D, 0xB6,
|
||||||
|
0x43, 0x2C, 0x95, 0xFA, 0xBE, 0x17, 0x60, 0x8D,
|
||||||
|
/* S-box 7 */
|
||||||
|
0x4B, 0x2E, 0xF0, 0x8D, 0x3C, 0x97, 0x5A, 0x61,
|
||||||
|
0xD0, 0xB7, 0x49, 0x1A, 0xE3, 0x5C, 0x2F, 0x86,
|
||||||
|
0x14, 0xBD, 0xC3, 0x7E, 0xAF, 0x68, 0x05, 0x92,
|
||||||
|
0x6B, 0xD8, 0x14, 0xA7, 0x95, 0x0F, 0xE2, 0x3C,
|
||||||
|
/* S-box 8 */
|
||||||
|
0xD2, 0x84, 0x6F, 0xB1, 0xA9, 0x3E, 0x50, 0xC7,
|
||||||
|
0x1F, 0xD8, 0xA3, 0x74, 0xC5, 0x6B, 0x0E, 0x92,
|
||||||
|
0x7B, 0x41, 0x9C, 0xE2, 0x06, 0xAD, 0xF3, 0x58,
|
||||||
|
0x21, 0xE7, 0x4A, 0x8D, 0xFC, 0x90, 0x35, 0x6B
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t e_permtab[] ={
|
||||||
|
4, 6, /* 4 bytes in 6 bytes out*/
|
||||||
|
32, 1, 2, 3, 4, 5,
|
||||||
|
4, 5, 6, 7, 8, 9,
|
||||||
|
8, 9, 10, 11, 12, 13,
|
||||||
|
12, 13, 14, 15, 16, 17,
|
||||||
|
16, 17, 18, 19, 20, 21,
|
||||||
|
20, 21, 22, 23, 24, 25,
|
||||||
|
24, 25, 26, 27, 28, 29,
|
||||||
|
28, 29, 30, 31, 32, 1
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t p_permtab[] ={
|
||||||
|
4, 4, /* 32 bit -> 32 bit */
|
||||||
|
16, 7, 20, 21,
|
||||||
|
29, 12, 28, 17,
|
||||||
|
1, 15, 23, 26,
|
||||||
|
5, 18, 31, 10,
|
||||||
|
2, 8, 24, 14,
|
||||||
|
32, 27, 3, 9,
|
||||||
|
19, 13, 30, 6,
|
||||||
|
22, 11, 4, 25
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t ip_permtab[] ={
|
||||||
|
8, 8, /* 64 bit -> 64 bit */
|
||||||
|
58, 50, 42, 34, 26, 18, 10, 2,
|
||||||
|
60, 52, 44, 36, 28, 20, 12, 4,
|
||||||
|
62, 54, 46, 38, 30, 22, 14, 6,
|
||||||
|
64, 56, 48, 40, 32, 24, 16, 8,
|
||||||
|
57, 49, 41, 33, 25, 17, 9, 1,
|
||||||
|
59, 51, 43, 35, 27, 19, 11, 3,
|
||||||
|
61, 53, 45, 37, 29, 21, 13, 5,
|
||||||
|
63, 55, 47, 39, 31, 23, 15, 7
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t inv_ip_permtab[] ={
|
||||||
|
8, 8, /* 64 bit -> 64 bit */
|
||||||
|
40, 8, 48, 16, 56, 24, 64, 32,
|
||||||
|
39, 7, 47, 15, 55, 23, 63, 31,
|
||||||
|
38, 6, 46, 14, 54, 22, 62, 30,
|
||||||
|
37, 5, 45, 13, 53, 21, 61, 29,
|
||||||
|
36, 4, 44, 12, 52, 20, 60, 28,
|
||||||
|
35, 3, 43, 11, 51, 19, 59, 27,
|
||||||
|
34, 2, 42, 10, 50, 18, 58, 26,
|
||||||
|
33, 1, 41, 9, 49, 17, 57, 25
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t pc1_permtab[] ={
|
||||||
|
8, 7, /* 64 bit -> 56 bit*/
|
||||||
|
57, 49, 41, 33, 25, 17, 9,
|
||||||
|
1, 58, 50, 42, 34, 26, 18,
|
||||||
|
10, 2, 59, 51, 43, 35, 27,
|
||||||
|
19, 11, 3, 60, 52, 44, 36,
|
||||||
|
63, 55, 47, 39, 31, 23, 15,
|
||||||
|
7, 62, 54, 46, 38, 30, 22,
|
||||||
|
14, 6, 61, 53, 45, 37, 29,
|
||||||
|
21, 13, 5, 28, 20, 12, 4
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t pc2_permtab[] ={
|
||||||
|
7, 6, /* 56 bit -> 48 bit */
|
||||||
|
14, 17, 11, 24, 1, 5,
|
||||||
|
3, 28, 15, 6, 21, 10,
|
||||||
|
23, 19, 12, 4, 26, 8,
|
||||||
|
16, 7, 27, 20, 13, 2,
|
||||||
|
41, 52, 31, 37, 47, 55,
|
||||||
|
30, 40, 51, 45, 33, 48,
|
||||||
|
44, 49, 39, 56, 34, 53,
|
||||||
|
46, 42, 50, 36, 29, 32
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t splitin6bitword_permtab[] = {
|
||||||
|
8, 8, /* 64 bit -> 64 bit */
|
||||||
|
64, 64, 1, 6, 2, 3, 4, 5,
|
||||||
|
64, 64, 7, 12, 8, 9, 10, 11,
|
||||||
|
64, 64, 13, 18, 14, 15, 16, 17,
|
||||||
|
64, 64, 19, 24, 20, 21, 22, 23,
|
||||||
|
64, 64, 25, 30, 26, 27, 28, 29,
|
||||||
|
64, 64, 31, 36, 32, 33, 34, 35,
|
||||||
|
64, 64, 37, 42, 38, 39, 40, 41,
|
||||||
|
64, 64, 43, 48, 44, 45, 46, 47
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t shiftkey_permtab[] = {
|
||||||
|
7, 7, /* 56 bit -> 56 bit */
|
||||||
|
2, 3, 4, 5, 6, 7, 8, 9,
|
||||||
|
10, 11, 12, 13, 14, 15, 16, 17,
|
||||||
|
18, 19, 20, 21, 22, 23, 24, 25,
|
||||||
|
26, 27, 28, 1,
|
||||||
|
30, 31, 32, 33, 34, 35, 36, 37,
|
||||||
|
38, 39, 40, 41, 42, 43, 44, 45,
|
||||||
|
46, 47, 48, 49, 50, 51, 52, 53,
|
||||||
|
54, 55, 56, 29
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t shiftkeyinv_permtab[] = {
|
||||||
|
7, 7,
|
||||||
|
28, 1, 2, 3, 4, 5, 6, 7,
|
||||||
|
8, 9, 10, 11, 12, 13, 14, 15,
|
||||||
|
16, 17, 18, 19, 20, 21, 22, 23,
|
||||||
|
24, 25, 26, 27,
|
||||||
|
56, 29, 30, 31, 32, 33, 34, 35,
|
||||||
|
36, 37, 38, 39, 40, 41, 42, 43,
|
||||||
|
44, 45, 46, 47, 48, 49, 50, 51,
|
||||||
|
52, 53, 54, 55
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
1 0
|
||||||
|
1 0
|
||||||
|
2 1
|
||||||
|
2 1
|
||||||
|
2 1
|
||||||
|
2 1
|
||||||
|
2 1
|
||||||
|
2 1
|
||||||
|
----
|
||||||
|
1 0
|
||||||
|
2 1
|
||||||
|
2 1
|
||||||
|
2 1
|
||||||
|
2 1
|
||||||
|
2 1
|
||||||
|
2 1
|
||||||
|
1 0
|
||||||
|
*/
|
||||||
|
#define ROTTABLE 0x7EFC
|
||||||
|
#define ROTTABLE_INV 0x3F7E
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
void permute(const uint8_t *ptable, const uint8_t *in, uint8_t *out){
|
||||||
|
uint8_t ob; /* in-bytes and out-bytes */
|
||||||
|
uint8_t byte, bit; /* counter for bit and byte */
|
||||||
|
ob = ptable[1];
|
||||||
|
ptable = &(ptable[2]);
|
||||||
|
for(byte=0; byte<ob; ++byte){
|
||||||
|
uint8_t x,t=0;
|
||||||
|
for(bit=0; bit<8; ++bit){
|
||||||
|
x=*ptable++ -1 ;
|
||||||
|
t<<=1;
|
||||||
|
if((in[x/8]) & (0x80>>(x%8)) ){
|
||||||
|
t|=0x01;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out[byte]=t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
void changeendian32(uint32_t * a){
|
||||||
|
*a = (*a & 0x000000FF) << 24 |
|
||||||
|
(*a & 0x0000FF00) << 8 |
|
||||||
|
(*a & 0x00FF0000) >> 8 |
|
||||||
|
(*a & 0xFF000000) >> 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
static inline
|
||||||
|
void shiftkey(uint8_t *key){
|
||||||
|
uint8_t k[7];
|
||||||
|
memcpy(k, key, 7);
|
||||||
|
permute((uint8_t*)shiftkey_permtab, k, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
static inline
|
||||||
|
void shiftkey_inv(uint8_t *key){
|
||||||
|
uint8_t k[7];
|
||||||
|
memcpy(k, key, 7);
|
||||||
|
permute((uint8_t*)shiftkeyinv_permtab, k, key);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
static inline
|
||||||
|
uint64_t splitin6bitwords(uint64_t a){
|
||||||
|
uint64_t ret=0;
|
||||||
|
a &= 0x0000ffffffffffffLL;
|
||||||
|
permute((uint8_t*)splitin6bitword_permtab, (uint8_t*)&a, (uint8_t*)&ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
static inline
|
||||||
|
uint8_t substitute(uint8_t a, uint8_t * sbp){
|
||||||
|
uint8_t x;
|
||||||
|
x = sbp[a>>1];
|
||||||
|
x = (a&1)?x&0x0F:x>>4;
|
||||||
|
return x;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
uint32_t des_f(uint32_t r, uint8_t* kr){
|
||||||
|
uint8_t i;
|
||||||
|
uint32_t t=0,ret;
|
||||||
|
uint64_t data;
|
||||||
|
uint8_t *sbp; /* sboxpointer */
|
||||||
|
permute((uint8_t*)e_permtab, (uint8_t*)&r, (uint8_t*)&data);
|
||||||
|
for(i=0; i<7; ++i)
|
||||||
|
((uint8_t*)&data)[i] ^= kr[i];
|
||||||
|
|
||||||
|
/* Sbox substitution */
|
||||||
|
data = splitin6bitwords(data);
|
||||||
|
sbp=(uint8_t*)sbox;
|
||||||
|
for(i=0; i<8; ++i){
|
||||||
|
uint8_t x;
|
||||||
|
x = substitute(((uint8_t*)&data)[i], sbp);
|
||||||
|
t<<=4;
|
||||||
|
t |= x;
|
||||||
|
sbp += 32;
|
||||||
|
}
|
||||||
|
changeendian32(&t);
|
||||||
|
|
||||||
|
permute((uint8_t*)p_permtab,(uint8_t*)&t, (uint8_t*)&ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
void des_enc(void* out, const void* in, const void* key){
|
||||||
|
#define R *((uint32_t*)&(data[4]))
|
||||||
|
#define L *((uint32_t*)&(data[0]))
|
||||||
|
|
||||||
|
uint8_t data[8],kr[6],k[7];
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
|
permute((uint8_t*)ip_permtab, (uint8_t*)in, data);
|
||||||
|
permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k);
|
||||||
|
for(i=0; i<8; ++i){
|
||||||
|
shiftkey(k);
|
||||||
|
if(ROTTABLE&((1<<((i<<1)+0))) )
|
||||||
|
shiftkey(k);
|
||||||
|
permute((uint8_t*)pc2_permtab, k, kr);
|
||||||
|
L ^= des_f(R, kr);
|
||||||
|
|
||||||
|
shiftkey(k);
|
||||||
|
if(ROTTABLE&((1<<((i<<1)+1))) )
|
||||||
|
shiftkey(k);
|
||||||
|
permute((uint8_t*)pc2_permtab, k, kr);
|
||||||
|
R ^= des_f(L, kr);
|
||||||
|
|
||||||
|
}
|
||||||
|
/* L <-> R*/
|
||||||
|
R ^= L;
|
||||||
|
L ^= R;
|
||||||
|
R ^= L;
|
||||||
|
|
||||||
|
permute((uint8_t*)inv_ip_permtab, data, (uint8_t*)out);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
void des_dec(void* out, const void* in, const uint8_t* key){
|
||||||
|
#define R *((uint32_t*)&(data[4]))
|
||||||
|
#define L *((uint32_t*)&(data[0]))
|
||||||
|
|
||||||
|
uint8_t data[8],kr[6],k[7];
|
||||||
|
int8_t i;
|
||||||
|
permute((uint8_t*)ip_permtab, (uint8_t*)in, data);
|
||||||
|
permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k);
|
||||||
|
for(i=7; i>=0; --i){
|
||||||
|
|
||||||
|
permute((uint8_t*)pc2_permtab, k, kr);
|
||||||
|
L ^= des_f(R, kr);
|
||||||
|
shiftkey_inv(k);
|
||||||
|
if(ROTTABLE&((1<<((i<<1)+1))) ){
|
||||||
|
shiftkey_inv(k);
|
||||||
|
}
|
||||||
|
|
||||||
|
permute((uint8_t*)pc2_permtab, k, kr);
|
||||||
|
R ^= des_f(L, kr);
|
||||||
|
shiftkey_inv(k);
|
||||||
|
if(ROTTABLE&((1<<((i<<1)+0))) ){
|
||||||
|
shiftkey_inv(k);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
/* L <-> R*/
|
||||||
|
R ^= L;
|
||||||
|
L ^= R;
|
||||||
|
R ^= L;
|
||||||
|
|
||||||
|
permute((uint8_t*)inv_ip_permtab, data, (uint8_t*)out);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
void tdes_enc(void* out, void* in, const void* key){
|
||||||
|
des_enc(out, in, (uint8_t*)key + 0);
|
||||||
|
des_dec(out, out, (uint8_t*)key + 8);
|
||||||
|
des_enc(out, out, (uint8_t*)key +16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
void tdes_dec(void* out, void* in, const uint8_t* key){
|
||||||
|
des_dec(out, in, (uint8_t*)key +16);
|
||||||
|
des_enc(out, out, (uint8_t*)key + 8);
|
||||||
|
des_dec(out, out, (uint8_t*)key + 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
|
107
armsrc/des.h
Normal file
107
armsrc/des.h
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
/* des.h */
|
||||||
|
/*
|
||||||
|
This file is part of the ARM-Crypto-Lib.
|
||||||
|
Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* \file des.h
|
||||||
|
* \author Daniel Otte
|
||||||
|
* \date 2007-06-16
|
||||||
|
* \brief des and tdes declarations
|
||||||
|
* \license GPLv3 or later
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef DES_H_
|
||||||
|
#define DES_H_
|
||||||
|
|
||||||
|
/* the FIPS 46-3 (1999-10-25) name for triple DES is triple data encryption algorithm so TDEA.
|
||||||
|
* Also we only implement the three key mode */
|
||||||
|
|
||||||
|
/** \def tdea_enc
|
||||||
|
* \brief defining an alias for void tdes_enc(void* out, const void* in, const void* key)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \def tdea_dec
|
||||||
|
* \brief defining an alias for void tdes_dec(void* out, const void* in, const void* key)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define tdea_enc tdes_enc
|
||||||
|
#define tdea_dec tdes_dec
|
||||||
|
|
||||||
|
/** \fn void des_enc(void* out, const void* in, const void* key)
|
||||||
|
* \brief encrypt a block with DES
|
||||||
|
*
|
||||||
|
* This function encrypts a block of 64 bits (8 bytes) with the DES algorithm.
|
||||||
|
* Key expansion is done automatically. The key is 64 bits long, but note that
|
||||||
|
* only 56 bits are used (the LSB of each byte is dropped). The input and output
|
||||||
|
* blocks may overlap.
|
||||||
|
*
|
||||||
|
* \param out pointer to the block (64 bit = 8 byte) where the ciphertext is written to
|
||||||
|
* \param in pointer to the block (64 bit = 8 byte) where the plaintext is read from
|
||||||
|
* \param key pointer to the key (64 bit = 8 byte)
|
||||||
|
*/
|
||||||
|
void des_enc(void* out, const void* in, const void* key);
|
||||||
|
|
||||||
|
/** \fn void des_dec(void* out, const void* in, const void* key)
|
||||||
|
* \brief decrypt a block with DES
|
||||||
|
*
|
||||||
|
* This function decrypts a block of 64 bits (8 bytes) with the DES algorithm.
|
||||||
|
* Key expansion is done automatically. The key is 64 bits long, but note that
|
||||||
|
* only 56 bits are used (the LSB of each byte is dropped). The input and output
|
||||||
|
* blocks may overlap.
|
||||||
|
*
|
||||||
|
* \param out pointer to the block (64 bit = 8 byte) where the plaintext is written to
|
||||||
|
* \param in pointer to the block (64 bit = 8 byte) where the ciphertext is read from
|
||||||
|
* \param key pointer to the key (64 bit = 8 byte)
|
||||||
|
*/
|
||||||
|
void des_dec(void* out, const void* in, const void* key);
|
||||||
|
|
||||||
|
/** \fn void tdes_enc(void* out, const void* in, const void* key)
|
||||||
|
* \brief encrypt a block with Tripple-DES
|
||||||
|
*
|
||||||
|
* This function encrypts a block of 64 bits (8 bytes) with the Tripple-DES (EDE)
|
||||||
|
* algorithm. Key expansion is done automatically. The key is 192 bits long, but
|
||||||
|
* note that only 178 bits are used (the LSB of each byte is dropped). The input
|
||||||
|
* and output blocks may overlap.
|
||||||
|
*
|
||||||
|
* \param out pointer to the block (64 bit = 8 byte) where the ciphertext is written to
|
||||||
|
* \param in pointer to the block (64 bit = 8 byte) where the plaintext is read from
|
||||||
|
* \param key pointer to the key (192 bit = 24 byte)
|
||||||
|
*/
|
||||||
|
void tdes_enc(void* out, const void* in, const void* key);
|
||||||
|
|
||||||
|
/** \fn void tdes_dec(void* out, const void* in, const void* key)
|
||||||
|
* \brief decrypt a block with Tripple-DES
|
||||||
|
*
|
||||||
|
* This function decrypts a block of 64 bits (8 bytes) with the Tripple-DES (EDE)
|
||||||
|
* algorithm. Key expansion is done automatically. The key is 192 bits long, but
|
||||||
|
* note that only 178 bits are used (the LSB of each byte is dropped). The input
|
||||||
|
* and output blocks may overlap.
|
||||||
|
*
|
||||||
|
* \param out pointer to the block (64 bit = 8 byte) where the plaintext is written to
|
||||||
|
* \param in pointer to the block (64 bit = 8 byte) where the ciphertext is read from
|
||||||
|
* \param key pointer to the key (192 bit = 24 byte)
|
||||||
|
*/
|
||||||
|
void tdes_dec(void* out, const void* in, const void* key);
|
||||||
|
|
||||||
|
#endif /*DES_H_*/
|
||||||
|
|
||||||
|
// Copied from des.h in desfire imp.
|
||||||
|
typedef unsigned long DES_KS[16][2]; /* Single-key DES key schedule */
|
||||||
|
typedef unsigned long DES3_KS[48][2]; /* Triple-DES key schedule */
|
||||||
|
|
||||||
|
|
||||||
|
extern int Asmversion; /* 1 if we're linked with an asm version, 0 if C */
|
112
armsrc/hitag2.c
112
armsrc/hitag2.c
|
@ -24,15 +24,19 @@
|
||||||
|
|
||||||
static bool bQuiet;
|
static bool bQuiet;
|
||||||
|
|
||||||
bool bCrypto;
|
static bool bCrypto;
|
||||||
bool bAuthenticating;
|
static bool bAuthenticating;
|
||||||
bool bPwd;
|
static bool bPwd;
|
||||||
bool bSuccessful;
|
static bool bSuccessful;
|
||||||
|
|
||||||
int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int bReader)
|
|
||||||
|
static int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int bReader)
|
||||||
{
|
{
|
||||||
|
static uint16_t traceLen = 0;
|
||||||
|
uint8_t *trace = BigBuf_get_addr();
|
||||||
|
|
||||||
// Return when trace is full
|
// Return when trace is full
|
||||||
if (traceLen >= TRACE_SIZE) return FALSE;
|
if (traceLen + sizeof(rsamples) + sizeof(dwParity) + sizeof(iBits) + nbytes(iBits) > BigBuf_max_traceLen()) return FALSE;
|
||||||
|
|
||||||
// Trace the random, i'm curious
|
// Trace the random, i'm curious
|
||||||
rsamples += iSamples;
|
rsamples += iSamples;
|
||||||
|
@ -85,21 +89,17 @@ static struct hitag2_tag tag = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
//#define TRACE_LENGTH 3000
|
// ToDo: define a meaningful maximum size for auth_table. The bigger this is, the lower will be the available memory for traces.
|
||||||
//uint8_t *trace = (uint8_t *) BigBuf;
|
// Historically it used to be FREE_BUFFER_SIZE, which was 2744.
|
||||||
//int traceLen = 0;
|
#define AUTH_TABLE_LENGTH 2744
|
||||||
//int rsamples = 0;
|
static byte_t* auth_table;
|
||||||
|
static size_t auth_table_pos = 0;
|
||||||
|
static size_t auth_table_len = AUTH_TABLE_LENGTH;
|
||||||
|
|
||||||
#define AUTH_TABLE_OFFSET FREE_BUFFER_OFFSET
|
static byte_t password[4];
|
||||||
#define AUTH_TABLE_LENGTH FREE_BUFFER_SIZE
|
static byte_t NrAr[8];
|
||||||
byte_t* auth_table = (byte_t *)BigBuf+AUTH_TABLE_OFFSET;
|
static byte_t key[8];
|
||||||
size_t auth_table_pos = 0;
|
static uint64_t cipher_state;
|
||||||
size_t auth_table_len = AUTH_TABLE_LENGTH;
|
|
||||||
|
|
||||||
byte_t password[4];
|
|
||||||
byte_t NrAr[8];
|
|
||||||
byte_t key[8];
|
|
||||||
uint64_t cipher_state;
|
|
||||||
|
|
||||||
/* Following is a modified version of cryptolib.com/ciphers/hitag2/ */
|
/* Following is a modified version of cryptolib.com/ciphers/hitag2/ */
|
||||||
// Software optimized 48-bit Philips/NXP Mifare Hitag2 PCF7936/46/47/52 stream cipher algorithm by I.C. Wiener 2006-2007.
|
// Software optimized 48-bit Philips/NXP Mifare Hitag2 PCF7936/46/47/52 stream cipher algorithm by I.C. Wiener 2006-2007.
|
||||||
|
@ -177,14 +177,14 @@ static u32 _hitag2_byte (u64 * x)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hitag2_reset(void)
|
static int hitag2_reset(void)
|
||||||
{
|
{
|
||||||
tag.state = TAG_STATE_RESET;
|
tag.state = TAG_STATE_RESET;
|
||||||
tag.crypto_active = 0;
|
tag.crypto_active = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hitag2_init(void)
|
static int hitag2_init(void)
|
||||||
{
|
{
|
||||||
// memcpy(&tag, &resetdata, sizeof(tag));
|
// memcpy(&tag, &resetdata, sizeof(tag));
|
||||||
hitag2_reset();
|
hitag2_reset();
|
||||||
|
@ -300,7 +300,8 @@ static void hitag_send_frame(const byte_t* frame, size_t frame_len)
|
||||||
LOW(GPIO_SSC_DOUT);
|
LOW(GPIO_SSC_DOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hitag2_handle_reader_command(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen)
|
|
||||||
|
static void hitag2_handle_reader_command(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen)
|
||||||
{
|
{
|
||||||
byte_t rx_air[HITAG_FRAME_LEN];
|
byte_t rx_air[HITAG_FRAME_LEN];
|
||||||
|
|
||||||
|
@ -457,6 +458,7 @@ static void hitag_reader_send_bit(int bit) {
|
||||||
LED_A_OFF();
|
LED_A_OFF();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void hitag_reader_send_frame(const byte_t* frame, size_t frame_len)
|
static void hitag_reader_send_frame(const byte_t* frame, size_t frame_len)
|
||||||
{
|
{
|
||||||
// Send the content of the frame
|
// Send the content of the frame
|
||||||
|
@ -475,7 +477,7 @@ static void hitag_reader_send_frame(const byte_t* frame, size_t frame_len)
|
||||||
|
|
||||||
size_t blocknr;
|
size_t blocknr;
|
||||||
|
|
||||||
bool hitag2_password(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
|
static bool hitag2_password(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
|
||||||
// Reset the transmission frame length
|
// Reset the transmission frame length
|
||||||
*txlen = 0;
|
*txlen = 0;
|
||||||
|
|
||||||
|
@ -530,7 +532,7 @@ bool hitag2_password(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
|
static bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
|
||||||
// Reset the transmission frame length
|
// Reset the transmission frame length
|
||||||
*txlen = 0;
|
*txlen = 0;
|
||||||
|
|
||||||
|
@ -623,7 +625,7 @@ bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
|
static bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
|
||||||
// Reset the transmission frame length
|
// Reset the transmission frame length
|
||||||
*txlen = 0;
|
*txlen = 0;
|
||||||
|
|
||||||
|
@ -663,7 +665,9 @@ bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txl
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
|
|
||||||
|
static bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
|
||||||
|
|
||||||
// Reset the transmission frame length
|
// Reset the transmission frame length
|
||||||
*txlen = 0;
|
*txlen = 0;
|
||||||
|
|
||||||
|
@ -675,17 +679,17 @@ bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx, size_
|
||||||
if (bCrypto) {
|
if (bCrypto) {
|
||||||
Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed, removed entry!",NrAr[0],NrAr[1],NrAr[2],NrAr[3],NrAr[4],NrAr[5],NrAr[6],NrAr[7]);
|
Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed, removed entry!",NrAr[0],NrAr[1],NrAr[2],NrAr[3],NrAr[4],NrAr[5],NrAr[6],NrAr[7]);
|
||||||
|
|
||||||
// Removing failed entry from authentiations table
|
// Removing failed entry from authentiations table
|
||||||
memcpy(auth_table+auth_table_pos,auth_table+auth_table_pos+8,8);
|
memcpy(auth_table+auth_table_pos,auth_table+auth_table_pos+8,8);
|
||||||
auth_table_len -= 8;
|
auth_table_len -= 8;
|
||||||
|
|
||||||
// Return if we reached the end of the authentiactions table
|
// Return if we reached the end of the authentications table
|
||||||
bCrypto = false;
|
bCrypto = false;
|
||||||
if (auth_table_pos == auth_table_len) {
|
if (auth_table_pos == auth_table_len) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the next authentication attempt in row (at the same position, b/c we removed last failed entry)
|
// Copy the next authentication attempt in row (at the same position, b/c we removed last failed entry)
|
||||||
memcpy(NrAr,auth_table+auth_table_pos,8);
|
memcpy(NrAr,auth_table+auth_table_pos,8);
|
||||||
}
|
}
|
||||||
*txlen = 5;
|
*txlen = 5;
|
||||||
|
@ -718,6 +722,7 @@ bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx, size_
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SnoopHitag(uint32_t type) {
|
void SnoopHitag(uint32_t type) {
|
||||||
int frame_count;
|
int frame_count;
|
||||||
int response;
|
int response;
|
||||||
|
@ -730,14 +735,16 @@ 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;
|
||||||
|
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
|
||||||
iso14a_set_tracing(TRUE);
|
iso14a_set_tracing(TRUE);
|
||||||
iso14a_clear_trace();
|
iso14a_clear_trace();
|
||||||
|
|
||||||
auth_table_len = 0;
|
|
||||||
auth_table_pos = 0;
|
|
||||||
memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
|
|
||||||
|
|
||||||
DbpString("Starting Hitag2 snoop");
|
DbpString("Starting Hitag2 snoop");
|
||||||
LED_D_ON();
|
LED_D_ON();
|
||||||
|
|
||||||
|
@ -760,7 +767,7 @@ void SnoopHitag(uint32_t type) {
|
||||||
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
|
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
|
||||||
AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
|
AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
|
||||||
|
|
||||||
// Disable timer during configuration
|
// Disable timer during configuration
|
||||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
|
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
|
||||||
|
|
||||||
// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
|
// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
|
||||||
|
@ -940,13 +947,17 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
|
||||||
bool bQuitTraceFull = false;
|
bool bQuitTraceFull = false;
|
||||||
bQuiet = false;
|
bQuiet = false;
|
||||||
|
|
||||||
// Clean up trace and prepare it for storing frames
|
|
||||||
iso14a_set_tracing(TRUE);
|
|
||||||
iso14a_clear_trace();
|
|
||||||
auth_table_len = 0;
|
auth_table_len = 0;
|
||||||
auth_table_pos = 0;
|
auth_table_pos = 0;
|
||||||
|
byte_t* auth_table;
|
||||||
|
BigBuf_free();
|
||||||
|
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
|
||||||
|
iso14a_set_tracing(TRUE);
|
||||||
|
iso14a_clear_trace();
|
||||||
|
|
||||||
DbpString("Starting Hitag2 simulation");
|
DbpString("Starting Hitag2 simulation");
|
||||||
LED_D_ON();
|
LED_D_ON();
|
||||||
hitag2_init();
|
hitag2_init();
|
||||||
|
@ -1126,19 +1137,20 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
|
||||||
bool bStop;
|
bool bStop;
|
||||||
bool bQuitTraceFull = false;
|
bool bQuitTraceFull = false;
|
||||||
|
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||||
// Reset the return status
|
// Reset the return status
|
||||||
bSuccessful = false;
|
bSuccessful = false;
|
||||||
|
|
||||||
// Clean up trace and prepare it for storing frames
|
// Clean up trace and prepare it for storing frames
|
||||||
iso14a_set_tracing(TRUE);
|
iso14a_set_tracing(TRUE);
|
||||||
iso14a_clear_trace();
|
iso14a_clear_trace();
|
||||||
|
|
||||||
DbpString("Starting Hitag reader family");
|
DbpString("Starting Hitag reader family");
|
||||||
|
|
||||||
// Check configuration
|
// Check configuration
|
||||||
switch(htf) {
|
switch(htf) {
|
||||||
case RHT2F_PASSWORD: {
|
case RHT2F_PASSWORD: {
|
||||||
Dbprintf("List identifier in password mode");
|
Dbprintf("List identifier in password mode");
|
||||||
memcpy(password,htd->pwd.password,4);
|
memcpy(password,htd->pwd.password,4);
|
||||||
blocknr = 0;
|
blocknr = 0;
|
||||||
bQuitTraceFull = false;
|
bQuitTraceFull = false;
|
||||||
|
@ -1152,7 +1164,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
|
||||||
Dbhexdump(8,NrAr,false);
|
Dbhexdump(8,NrAr,false);
|
||||||
bQuiet = false;
|
bQuiet = false;
|
||||||
bCrypto = false;
|
bCrypto = false;
|
||||||
bAuthenticating = false;
|
bAuthenticating = false;
|
||||||
bQuitTraceFull = true;
|
bQuitTraceFull = true;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -1160,17 +1172,17 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
|
||||||
DbpString("Authenticating using key:");
|
DbpString("Authenticating using key:");
|
||||||
memcpy(key,htd->crypto.key,4); //HACK; 4 or 6?? I read both in the code.
|
memcpy(key,htd->crypto.key,4); //HACK; 4 or 6?? I read both in the code.
|
||||||
Dbhexdump(6,key,false);
|
Dbhexdump(6,key,false);
|
||||||
blocknr = 0;
|
blocknr = 0;
|
||||||
bQuiet = false;
|
bQuiet = false;
|
||||||
bCrypto = false;
|
bCrypto = false;
|
||||||
bAuthenticating = false;
|
bAuthenticating = false;
|
||||||
bQuitTraceFull = true;
|
bQuitTraceFull = true;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case RHT2F_TEST_AUTH_ATTEMPTS: {
|
case RHT2F_TEST_AUTH_ATTEMPTS: {
|
||||||
Dbprintf("Testing %d authentication attempts",(auth_table_len/8));
|
Dbprintf("Testing %d authentication attempts",(auth_table_len/8));
|
||||||
auth_table_pos = 0;
|
auth_table_pos = 0;
|
||||||
memcpy(NrAr,auth_table,8);
|
memcpy(NrAr, auth_table, 8);
|
||||||
bQuitTraceFull = false;
|
bQuitTraceFull = false;
|
||||||
bQuiet = false;
|
bQuiet = false;
|
||||||
bCrypto = false;
|
bCrypto = false;
|
||||||
|
|
|
@ -640,21 +640,25 @@ void RAMFUNC SnoopIClass(void)
|
||||||
// The command (reader -> tag) that we're receiving.
|
// The command (reader -> tag) that we're receiving.
|
||||||
// The length of a received command will in most cases be no more than 18 bytes.
|
// The length of a received command will in most cases be no more than 18 bytes.
|
||||||
// So 32 should be enough!
|
// So 32 should be enough!
|
||||||
uint8_t *readerToTagCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
|
#define ICLASS_BUFFER_SIZE 32
|
||||||
|
uint8_t readerToTagCmd[ICLASS_BUFFER_SIZE];
|
||||||
// The response (tag -> reader) that we're receiving.
|
// The response (tag -> reader) that we're receiving.
|
||||||
uint8_t *tagToReaderResponse = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET);
|
uint8_t tagToReaderResponse[ICLASS_BUFFER_SIZE];
|
||||||
|
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
|
|
||||||
// reset traceLen to 0
|
// free all BigBuf memory
|
||||||
|
BigBuf_free();
|
||||||
|
// The DMA buffer, used to stream samples from the FPGA
|
||||||
|
uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
|
||||||
|
|
||||||
|
// reset traceLen to 0
|
||||||
iso14a_set_tracing(TRUE);
|
iso14a_set_tracing(TRUE);
|
||||||
iso14a_clear_trace();
|
iso14a_clear_trace();
|
||||||
iso14a_set_trigger(FALSE);
|
iso14a_set_trigger(FALSE);
|
||||||
|
|
||||||
// The DMA buffer, used to stream samples from the FPGA
|
int lastRxCounter;
|
||||||
int8_t *dmaBuf = ((int8_t *)BigBuf) + DMA_BUFFER_OFFSET;
|
uint8_t *upTo;
|
||||||
int lastRxCounter;
|
|
||||||
int8_t *upTo;
|
|
||||||
int smpl;
|
int smpl;
|
||||||
int maxBehindBy = 0;
|
int maxBehindBy = 0;
|
||||||
|
|
||||||
|
@ -703,7 +707,7 @@ void RAMFUNC SnoopIClass(void)
|
||||||
(DMA_BUFFER_SIZE-1);
|
(DMA_BUFFER_SIZE-1);
|
||||||
if(behindBy > maxBehindBy) {
|
if(behindBy > maxBehindBy) {
|
||||||
maxBehindBy = behindBy;
|
maxBehindBy = behindBy;
|
||||||
if(behindBy > 400) {
|
if(behindBy > (9 * DMA_BUFFER_SIZE / 10)) {
|
||||||
Dbprintf("blew circular buffer! behindBy=0x%x", behindBy);
|
Dbprintf("blew circular buffer! behindBy=0x%x", behindBy);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -1064,27 +1068,28 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader
|
||||||
int trace_data_size = 0;
|
int trace_data_size = 0;
|
||||||
//uint8_t sof = 0x0f;
|
//uint8_t sof = 0x0f;
|
||||||
|
|
||||||
|
// free eventually allocated BigBuf memory
|
||||||
|
BigBuf_free();
|
||||||
// Respond SOF -- takes 1 bytes
|
// Respond SOF -- takes 1 bytes
|
||||||
uint8_t *resp1 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET);
|
uint8_t *resp1 = BigBuf_malloc(2);
|
||||||
int resp1Len;
|
int resp1Len;
|
||||||
|
|
||||||
// Anticollision CSN (rotated CSN)
|
// Anticollision CSN (rotated CSN)
|
||||||
// 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
|
// 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
|
||||||
uint8_t *resp2 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 2);
|
uint8_t *resp2 = BigBuf_malloc(28);
|
||||||
int resp2Len;
|
int resp2Len;
|
||||||
|
|
||||||
// CSN
|
// CSN
|
||||||
// 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
|
// 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
|
||||||
uint8_t *resp3 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 30);
|
uint8_t *resp3 = BigBuf_malloc(30);
|
||||||
int resp3Len;
|
int resp3Len;
|
||||||
|
|
||||||
// e-Purse
|
// e-Purse
|
||||||
// 18: Takes 2 bytes for SOF/EOF and 8 * 2 = 16 bytes (2 bytes/byte)
|
// 18: Takes 2 bytes for SOF/EOF and 8 * 2 = 16 bytes (2 bytes/bit)
|
||||||
uint8_t *resp4 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 60);
|
uint8_t *resp4 = BigBuf_malloc(20);
|
||||||
int resp4Len;
|
int resp4Len;
|
||||||
|
|
||||||
// + 1720..
|
uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
|
||||||
uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
|
|
||||||
memset(receivedCmd, 0x44, MAX_FRAME_SIZE);
|
memset(receivedCmd, 0x44, MAX_FRAME_SIZE);
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
@ -1529,7 +1534,7 @@ uint8_t handshakeIclassTag(uint8_t *card_data)
|
||||||
static uint8_t identify[] = { 0x0c };
|
static uint8_t identify[] = { 0x0c };
|
||||||
static uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
static uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
static uint8_t readcheck_cc[]= { 0x88, 0x02 };
|
static uint8_t readcheck_cc[]= { 0x88, 0x02 };
|
||||||
uint8_t *resp = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET);
|
uint8_t resp[ICLASS_BUFFER_SIZE];
|
||||||
|
|
||||||
uint8_t read_status = 0;
|
uint8_t read_status = 0;
|
||||||
|
|
||||||
|
@ -1587,7 +1592,7 @@ void ReaderIClass(uint8_t arg0) {
|
||||||
while(!BUTTON_PRESS())
|
while(!BUTTON_PRESS())
|
||||||
{
|
{
|
||||||
|
|
||||||
if(traceLen > TRACE_SIZE) {
|
if(traceLen > BigBuf_max_traceLen()) {
|
||||||
DbpString("Trace full");
|
DbpString("Trace full");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1650,7 +1655,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
|
||||||
int keyaccess;
|
int keyaccess;
|
||||||
} memory;
|
} memory;
|
||||||
|
|
||||||
uint8_t* resp = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET);
|
uint8_t resp[ICLASS_BUFFER_SIZE];
|
||||||
|
|
||||||
setupIclassReader();
|
setupIclassReader();
|
||||||
|
|
||||||
|
@ -1659,7 +1664,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
|
||||||
|
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
if(traceLen > TRACE_SIZE) {
|
if(traceLen > BigBuf_max_traceLen()) {
|
||||||
DbpString("Trace full");
|
DbpString("Trace full");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
1522
armsrc/iso14443.c
1522
armsrc/iso14443.c
File diff suppressed because it is too large
Load diff
|
@ -146,6 +146,7 @@ void iso14a_set_trigger(bool enable) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void iso14a_set_timeout(uint32_t timeout) {
|
void iso14a_set_timeout(uint32_t timeout) {
|
||||||
iso14a_timeout = timeout;
|
iso14a_timeout = timeout;
|
||||||
}
|
}
|
||||||
|
@ -188,7 +189,6 @@ void AppendCrc14443a(uint8_t* data, int len)
|
||||||
ComputeCrc14443(CRC_14443_A,data,len,data+len,data+len+1);
|
ComputeCrc14443(CRC_14443_A,data,len,data+len,data+len+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
// ISO 14443 Type A - Miller decoder
|
// ISO 14443 Type A - Miller decoder
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
@ -526,9 +526,6 @@ void RAMFUNC SnoopIso14443a(uint8_t param) {
|
||||||
// bit 1 - trigger from first reader 7-bit request
|
// bit 1 - trigger from first reader 7-bit request
|
||||||
|
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
// init trace buffer
|
|
||||||
iso14a_clear_trace();
|
|
||||||
iso14a_set_tracing(TRUE);
|
|
||||||
|
|
||||||
// We won't start recording the frames that we acquire until we trigger;
|
// We won't start recording the frames that we acquire until we trigger;
|
||||||
// a good trigger condition to get started is probably when we see a
|
// a good trigger condition to get started is probably when we see a
|
||||||
|
@ -536,22 +533,25 @@ void RAMFUNC SnoopIso14443a(uint8_t param) {
|
||||||
// triggered == FALSE -- to wait first for card
|
// triggered == FALSE -- to wait first for card
|
||||||
bool triggered = !(param & 0x03);
|
bool triggered = !(param & 0x03);
|
||||||
|
|
||||||
|
// Allocate memory from BigBuf for some buffers
|
||||||
|
// free all previous allocations first
|
||||||
|
BigBuf_free();
|
||||||
|
|
||||||
// The command (reader -> tag) that we're receiving.
|
// The command (reader -> tag) that we're receiving.
|
||||||
// The length of a received command will in most cases be no more than 18 bytes.
|
uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
|
||||||
// So 32 should be enough!
|
uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||||
uint8_t *receivedCmd = ((uint8_t *)BigBuf) + RECV_CMD_OFFSET;
|
|
||||||
uint8_t *receivedCmdPar = ((uint8_t *)BigBuf) + RECV_CMD_PAR_OFFSET;
|
|
||||||
|
|
||||||
// The response (tag -> reader) that we're receiving.
|
// The response (tag -> reader) that we're receiving.
|
||||||
uint8_t *receivedResponse = ((uint8_t *)BigBuf) + RECV_RESP_OFFSET;
|
uint8_t *receivedResponse = BigBuf_malloc(MAX_FRAME_SIZE);
|
||||||
uint8_t *receivedResponsePar = ((uint8_t *)BigBuf) + RECV_RESP_PAR_OFFSET;
|
uint8_t *receivedResponsePar = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||||
|
|
||||||
// As we receive stuff, we copy it from receivedCmd or receivedResponse
|
|
||||||
// into trace, along with its length and other annotations.
|
|
||||||
//uint8_t *trace = (uint8_t *)BigBuf;
|
|
||||||
|
|
||||||
// The DMA buffer, used to stream samples from the FPGA
|
// The DMA buffer, used to stream samples from the FPGA
|
||||||
uint8_t *dmaBuf = ((uint8_t *)BigBuf) + DMA_BUFFER_OFFSET;
|
uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
|
||||||
|
|
||||||
|
// init trace buffer
|
||||||
|
iso14a_clear_trace();
|
||||||
|
iso14a_set_tracing(TRUE);
|
||||||
|
|
||||||
uint8_t *data = dmaBuf;
|
uint8_t *data = dmaBuf;
|
||||||
uint8_t previous_data = 0;
|
uint8_t previous_data = 0;
|
||||||
int maxDataLen = 0;
|
int maxDataLen = 0;
|
||||||
|
@ -591,7 +591,7 @@ void RAMFUNC SnoopIso14443a(uint8_t param) {
|
||||||
// test for length of buffer
|
// test for length of buffer
|
||||||
if(dataLen > maxDataLen) {
|
if(dataLen > maxDataLen) {
|
||||||
maxDataLen = dataLen;
|
maxDataLen = dataLen;
|
||||||
if(dataLen > 400) {
|
if(dataLen > (9 * DMA_BUFFER_SIZE / 10)) {
|
||||||
Dbprintf("blew circular buffer! dataLen=%d", dataLen);
|
Dbprintf("blew circular buffer! dataLen=%d", dataLen);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -820,7 +820,7 @@ int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par);
|
||||||
bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity,
|
bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity,
|
||||||
uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity);
|
uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity);
|
||||||
|
|
||||||
static uint8_t* free_buffer_pointer = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET);
|
static uint8_t* free_buffer_pointer;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t* response;
|
uint8_t* response;
|
||||||
|
@ -830,10 +830,6 @@ typedef struct {
|
||||||
uint32_t ProxToAirDuration;
|
uint32_t ProxToAirDuration;
|
||||||
} tag_response_info_t;
|
} tag_response_info_t;
|
||||||
|
|
||||||
void reset_free_buffer() {
|
|
||||||
free_buffer_pointer = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool prepare_tag_modulation(tag_response_info_t* response_info, size_t max_buffer_size) {
|
bool prepare_tag_modulation(tag_response_info_t* response_info, size_t max_buffer_size) {
|
||||||
// Example response, answer to MIFARE Classic read block will be 16 bytes + 2 CRC = 18 bytes
|
// Example response, answer to MIFARE Classic read block will be 16 bytes + 2 CRC = 18 bytes
|
||||||
// This will need the following byte array for a modulation sequence
|
// This will need the following byte array for a modulation sequence
|
||||||
|
@ -846,6 +842,7 @@ bool prepare_tag_modulation(tag_response_info_t* response_info, size_t max_buffe
|
||||||
// 166 bytes, since every bit that needs to be send costs us a byte
|
// 166 bytes, since every bit that needs to be send costs us a byte
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
// Prepare the tag modulation bits from the message
|
// Prepare the tag modulation bits from the message
|
||||||
CodeIso14443aAsTag(response_info->response,response_info->response_n);
|
CodeIso14443aAsTag(response_info->response,response_info->response_n);
|
||||||
|
|
||||||
|
@ -866,15 +863,22 @@ bool prepare_tag_modulation(tag_response_info_t* response_info, size_t max_buffe
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// "precompile" responses. There are 7 predefined responses with a total of 28 bytes data to transmit.
|
||||||
|
// Coded responses need one byte per bit to transfer (data, parity, start, stop, correction)
|
||||||
|
// 28 * 8 data bits, 28 * 1 parity bits, 7 start bits, 7 stop bits, 7 correction bits
|
||||||
|
// -> need 273 bytes buffer
|
||||||
|
#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 273
|
||||||
|
|
||||||
bool prepare_allocated_tag_modulation(tag_response_info_t* response_info) {
|
bool prepare_allocated_tag_modulation(tag_response_info_t* response_info) {
|
||||||
// Retrieve and store the current buffer index
|
// Retrieve and store the current buffer index
|
||||||
response_info->modulation = free_buffer_pointer;
|
response_info->modulation = free_buffer_pointer;
|
||||||
|
|
||||||
// Determine the maximum size we can use from our buffer
|
// Determine the maximum size we can use from our buffer
|
||||||
size_t max_buffer_size = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + FREE_BUFFER_SIZE) - free_buffer_pointer;
|
size_t max_buffer_size = ALLOCATED_TAG_MODULATION_BUFFER_SIZE;
|
||||||
|
|
||||||
// Forward the prepare tag modulation function to the inner function
|
// Forward the prepare tag modulation function to the inner function
|
||||||
if (prepare_tag_modulation(response_info,max_buffer_size)) {
|
if (prepare_tag_modulation(response_info, max_buffer_size)) {
|
||||||
// Update the free buffer offset
|
// Update the free buffer offset
|
||||||
free_buffer_pointer += ToSendMax;
|
free_buffer_pointer += ToSendMax;
|
||||||
return true;
|
return true;
|
||||||
|
@ -889,10 +893,6 @@ bool prepare_allocated_tag_modulation(tag_response_info_t* response_info) {
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
|
void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
|
||||||
{
|
{
|
||||||
// Enable and clear the trace
|
|
||||||
iso14a_clear_trace();
|
|
||||||
iso14a_set_tracing(TRUE);
|
|
||||||
|
|
||||||
uint8_t sak;
|
uint8_t sak;
|
||||||
|
|
||||||
// The first response contains the ATQA (note: bytes are transmitted in reverse order).
|
// The first response contains the ATQA (note: bytes are transmitted in reverse order).
|
||||||
|
@ -936,10 +936,11 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The second response contains the (mandatory) first 24 bits of the UID
|
// The second response contains the (mandatory) first 24 bits of the UID
|
||||||
uint8_t response2[5];
|
uint8_t response2[5] = {0x00};
|
||||||
|
|
||||||
// Check if the uid uses the (optional) part
|
// Check if the uid uses the (optional) part
|
||||||
uint8_t response2a[5];
|
uint8_t response2a[5] = {0x00};
|
||||||
|
|
||||||
if (uid_2nd) {
|
if (uid_2nd) {
|
||||||
response2[0] = 0x88;
|
response2[0] = 0x88;
|
||||||
num_to_bytes(uid_1st,3,response2+1);
|
num_to_bytes(uid_1st,3,response2+1);
|
||||||
|
@ -960,12 +961,12 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
|
||||||
response2[4] = response2[0] ^ response2[1] ^ response2[2] ^ response2[3];
|
response2[4] = response2[0] ^ response2[1] ^ response2[2] ^ response2[3];
|
||||||
|
|
||||||
// Prepare the mandatory SAK (for 4 and 7 byte UID)
|
// Prepare the mandatory SAK (for 4 and 7 byte UID)
|
||||||
uint8_t response3[3];
|
uint8_t response3[3] = {0x00};
|
||||||
response3[0] = sak;
|
response3[0] = sak;
|
||||||
ComputeCrc14443(CRC_14443_A, response3, 1, &response3[1], &response3[2]);
|
ComputeCrc14443(CRC_14443_A, response3, 1, &response3[1], &response3[2]);
|
||||||
|
|
||||||
// Prepare the optional second SAK (for 7 byte UID), drop the cascade bit
|
// Prepare the optional second SAK (for 7 byte UID), drop the cascade bit
|
||||||
uint8_t response3a[3];
|
uint8_t response3a[3] = {0x00};
|
||||||
response3a[0] = sak & 0xFB;
|
response3a[0] = sak & 0xFB;
|
||||||
ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]);
|
ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]);
|
||||||
|
|
||||||
|
@ -1001,8 +1002,16 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
|
||||||
.modulation_n = 0
|
.modulation_n = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
// Reset the offset pointer of the free buffer
|
BigBuf_free_keep_EM();
|
||||||
reset_free_buffer();
|
|
||||||
|
// allocate buffers:
|
||||||
|
uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
|
||||||
|
uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||||
|
free_buffer_pointer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE);
|
||||||
|
|
||||||
|
// clear trace
|
||||||
|
iso14a_clear_trace();
|
||||||
|
iso14a_set_tracing(TRUE);
|
||||||
|
|
||||||
// Prepare the responses of the anticollision phase
|
// Prepare the responses of the anticollision phase
|
||||||
// there will be not enough time to do this at the moment the reader sends it REQA
|
// there will be not enough time to do this at the moment the reader sends it REQA
|
||||||
|
@ -1024,10 +1033,6 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
|
||||||
// We need to listen to the high-frequency, peak-detected path.
|
// We need to listen to the high-frequency, peak-detected path.
|
||||||
iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
|
iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
|
||||||
|
|
||||||
// buffers used on software Uart:
|
|
||||||
uint8_t *receivedCmd = ((uint8_t *)BigBuf) + RECV_CMD_OFFSET;
|
|
||||||
uint8_t *receivedCmdPar = ((uint8_t *)BigBuf) + RECV_CMD_PAR_OFFSET;
|
|
||||||
|
|
||||||
cmdsRecvd = 0;
|
cmdsRecvd = 0;
|
||||||
tag_response_info_t* p_response;
|
tag_response_info_t* p_response;
|
||||||
|
|
||||||
|
@ -1188,6 +1193,7 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
|
||||||
|
|
||||||
Dbprintf("%x %x %x", happened, happened2, cmdsRecvd);
|
Dbprintf("%x %x %x", happened, happened2, cmdsRecvd);
|
||||||
LED_A_OFF();
|
LED_A_OFF();
|
||||||
|
BigBuf_free_keep_EM();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1461,7 +1467,7 @@ static int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen, bool correctionNe
|
||||||
AT91C_BASE_SSC->SSC_THR = SEC_F;
|
AT91C_BASE_SSC->SSC_THR = SEC_F;
|
||||||
|
|
||||||
// send cycle
|
// send cycle
|
||||||
for(; i <= respLen; ) {
|
for(; i < respLen; ) {
|
||||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||||
AT91C_BASE_SSC->SSC_THR = resp[i++];
|
AT91C_BASE_SSC->SSC_THR = resp[i++];
|
||||||
FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
|
@ -1661,8 +1667,8 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u
|
||||||
uint8_t sel_all[] = { 0x93,0x20 };
|
uint8_t sel_all[] = { 0x93,0x20 };
|
||||||
uint8_t sel_uid[] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
|
uint8_t sel_uid[] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
|
||||||
uint8_t rats[] = { 0xE0,0x80,0x00,0x00 }; // FSD=256, FSDI=8, CID=0
|
uint8_t rats[] = { 0xE0,0x80,0x00,0x00 }; // FSD=256, FSDI=8, CID=0
|
||||||
uint8_t *resp = ((uint8_t *)BigBuf) + RECV_RESP_OFFSET;
|
uint8_t resp[MAX_FRAME_SIZE]; // theoretically. A usual RATS will be much smaller
|
||||||
uint8_t *resp_par = ((uint8_t *)BigBuf) + RECV_RESP_PAR_OFFSET;
|
uint8_t resp_par[MAX_PARITY_SIZE];
|
||||||
byte_t uid_resp[4];
|
byte_t uid_resp[4];
|
||||||
size_t uid_resp_len;
|
size_t uid_resp_len;
|
||||||
|
|
||||||
|
@ -1954,8 +1960,11 @@ void ReaderMifare(bool first_try)
|
||||||
uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
|
uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
|
||||||
static uint8_t mf_nr_ar3;
|
static uint8_t mf_nr_ar3;
|
||||||
|
|
||||||
uint8_t* receivedAnswer = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET);
|
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||||
uint8_t* receivedAnswerPar = (((uint8_t *)BigBuf) + RECV_RESP_PAR_OFFSET);
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||||
|
|
||||||
|
// free eventually allocated BigBuf memory. We want all for tracing.
|
||||||
|
BigBuf_free();
|
||||||
|
|
||||||
iso14a_clear_trace();
|
iso14a_clear_trace();
|
||||||
iso14a_set_tracing(TRUE);
|
iso14a_set_tracing(TRUE);
|
||||||
|
@ -2166,10 +2175,10 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
|
||||||
struct Crypto1State *pcs;
|
struct Crypto1State *pcs;
|
||||||
pcs = &mpcs;
|
pcs = &mpcs;
|
||||||
uint32_t numReads = 0;//Counts numer of times reader read a block
|
uint32_t numReads = 0;//Counts numer of times reader read a block
|
||||||
uint8_t* receivedCmd = get_bigbufptr_recvcmdbuf();
|
uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE];
|
||||||
uint8_t* receivedCmd_par = receivedCmd + MAX_FRAME_SIZE;
|
uint8_t receivedCmd_par[MAX_MIFARE_PARITY_SIZE];
|
||||||
uint8_t* response = get_bigbufptr_recvrespbuf();
|
uint8_t response[MAX_MIFARE_FRAME_SIZE];
|
||||||
uint8_t* response_par = response + MAX_FRAME_SIZE;
|
uint8_t response_par[MAX_MIFARE_PARITY_SIZE];
|
||||||
|
|
||||||
uint8_t rATQA[] = {0x04, 0x00}; // Mifare classic 1k 4BUID
|
uint8_t rATQA[] = {0x04, 0x00}; // Mifare classic 1k 4BUID
|
||||||
uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62};
|
uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62};
|
||||||
|
@ -2186,6 +2195,8 @@ 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
|
||||||
iso14a_clear_trace();
|
iso14a_clear_trace();
|
||||||
iso14a_set_tracing(TRUE);
|
iso14a_set_tracing(TRUE);
|
||||||
|
@ -2656,18 +2667,20 @@ void RAMFUNC SniffMifare(uint8_t param) {
|
||||||
// The command (reader -> tag) that we're receiving.
|
// The command (reader -> tag) that we're receiving.
|
||||||
// The length of a received command will in most cases be no more than 18 bytes.
|
// The length of a received command will in most cases be no more than 18 bytes.
|
||||||
// So 32 should be enough!
|
// So 32 should be enough!
|
||||||
uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
|
uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE];
|
||||||
uint8_t *receivedCmdPar = ((uint8_t *)BigBuf) + RECV_CMD_PAR_OFFSET;
|
uint8_t receivedCmdPar[MAX_MIFARE_PARITY_SIZE];
|
||||||
// The response (tag -> reader) that we're receiving.
|
// The response (tag -> reader) that we're receiving.
|
||||||
uint8_t *receivedResponse = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET);
|
uint8_t receivedResponse[MAX_MIFARE_FRAME_SIZE];
|
||||||
uint8_t *receivedResponsePar = ((uint8_t *)BigBuf) + RECV_RESP_PAR_OFFSET;
|
uint8_t receivedResponsePar[MAX_MIFARE_PARITY_SIZE];
|
||||||
|
|
||||||
// As we receive stuff, we copy it from receivedCmd or receivedResponse
|
// As we receive stuff, we copy it from receivedCmd or receivedResponse
|
||||||
// into trace, along with its length and other annotations.
|
// into trace, along with its length and other annotations.
|
||||||
//uint8_t *trace = (uint8_t *)BigBuf;
|
//uint8_t *trace = (uint8_t *)BigBuf;
|
||||||
|
|
||||||
// The DMA buffer, used to stream samples from the FPGA
|
// free eventually allocated BigBuf memory
|
||||||
uint8_t *dmaBuf = ((uint8_t *)BigBuf) + DMA_BUFFER_OFFSET;
|
BigBuf_free();
|
||||||
|
// allocate the DMA buffer, used to stream samples from the FPGA
|
||||||
|
uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
|
||||||
uint8_t *data = dmaBuf;
|
uint8_t *data = dmaBuf;
|
||||||
uint8_t previous_data = 0;
|
uint8_t previous_data = 0;
|
||||||
int maxDataLen = 0;
|
int maxDataLen = 0;
|
||||||
|
@ -2726,7 +2739,7 @@ void RAMFUNC SniffMifare(uint8_t param) {
|
||||||
// test for length of buffer
|
// test for length of buffer
|
||||||
if(dataLen > maxDataLen) { // we are more behind than ever...
|
if(dataLen > maxDataLen) { // we are more behind than ever...
|
||||||
maxDataLen = dataLen;
|
maxDataLen = dataLen;
|
||||||
if(dataLen > 400) {
|
if(dataLen > (9 * DMA_BUFFER_SIZE / 10)) {
|
||||||
Dbprintf("blew circular buffer! dataLen=0x%x", dataLen);
|
Dbprintf("blew circular buffer! dataLen=0x%x", dataLen);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -296,7 +296,7 @@ static void TransmitTo15693Reader(const uint8_t *cmd, int len, int *samples, int
|
||||||
static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed)
|
static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed)
|
||||||
{
|
{
|
||||||
int c = 0;
|
int c = 0;
|
||||||
uint8_t *dest = (uint8_t *)BigBuf;
|
uint8_t *dest = BigBuf_get_addr();
|
||||||
int getNext = 0;
|
int getNext = 0;
|
||||||
|
|
||||||
int8_t prev = 0;
|
int8_t prev = 0;
|
||||||
|
@ -446,7 +446,7 @@ static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *
|
||||||
static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed)
|
static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed)
|
||||||
{
|
{
|
||||||
int c = 0;
|
int c = 0;
|
||||||
uint8_t *dest = (uint8_t *)BigBuf;
|
uint8_t *dest = BigBuf_get_addr();
|
||||||
int getNext = 0;
|
int getNext = 0;
|
||||||
|
|
||||||
int8_t prev = 0;
|
int8_t prev = 0;
|
||||||
|
@ -596,7 +596,7 @@ static void BuildIdentifyRequest(void);
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void AcquireRawAdcSamplesIso15693(void)
|
void AcquireRawAdcSamplesIso15693(void)
|
||||||
{
|
{
|
||||||
uint8_t *dest = (uint8_t *)BigBuf;
|
uint8_t *dest = BigBuf_get_addr();
|
||||||
|
|
||||||
int c = 0;
|
int c = 0;
|
||||||
int getNext = 0;
|
int getNext = 0;
|
||||||
|
@ -678,7 +678,7 @@ void AcquireRawAdcSamplesIso15693(void)
|
||||||
|
|
||||||
void RecordRawAdcSamplesIso15693(void)
|
void RecordRawAdcSamplesIso15693(void)
|
||||||
{
|
{
|
||||||
uint8_t *dest = (uint8_t *)BigBuf;
|
uint8_t *dest = BigBuf_get_addr();
|
||||||
|
|
||||||
int c = 0;
|
int c = 0;
|
||||||
int getNext = 0;
|
int getNext = 0;
|
||||||
|
@ -878,8 +878,8 @@ int SendDataTag(uint8_t *send, int sendlen, int init, int speed, uint8_t **recv)
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
|
|
||||||
int answerLen=0;
|
int answerLen=0;
|
||||||
uint8_t *answer = (((uint8_t *)BigBuf) + 3660);
|
uint8_t *answer = BigBuf_get_addr() + 3660;
|
||||||
if (recv!=NULL) memset(BigBuf + 3660, 0, 100);
|
if (recv != NULL) memset(answer, 0, 100);
|
||||||
|
|
||||||
if (init) Iso15693InitReader();
|
if (init) Iso15693InitReader();
|
||||||
|
|
||||||
|
@ -999,9 +999,9 @@ void ReaderIso15693(uint32_t parameter)
|
||||||
LED_C_OFF();
|
LED_C_OFF();
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
|
|
||||||
uint8_t *answer1 = (((uint8_t *)BigBuf) + 3660); //
|
uint8_t *answer1 = BigBuf_get_addr() + 3660;
|
||||||
uint8_t *answer2 = (((uint8_t *)BigBuf) + 3760);
|
uint8_t *answer2 = BigBuf_get_addr() + 3760;
|
||||||
uint8_t *answer3 = (((uint8_t *)BigBuf) + 3860);
|
uint8_t *answer3 = BigBuf_get_addr() + 3860;
|
||||||
|
|
||||||
int answerLen1 = 0;
|
int answerLen1 = 0;
|
||||||
int answerLen2 = 0;
|
int answerLen2 = 0;
|
||||||
|
@ -1015,7 +1015,7 @@ void ReaderIso15693(uint32_t parameter)
|
||||||
|
|
||||||
|
|
||||||
// Blank arrays
|
// Blank arrays
|
||||||
memset(BigBuf + 3660, 0x00, 300);
|
memset(answer1, 0x00, 300);
|
||||||
|
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
|
|
||||||
|
@ -1111,7 +1111,7 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid)
|
||||||
LED_C_OFF();
|
LED_C_OFF();
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
|
|
||||||
uint8_t *buf = (((uint8_t *)BigBuf) + 3660); //
|
uint8_t *buf = BigBuf_get_addr() + 3660;
|
||||||
|
|
||||||
int answerLen1 = 0;
|
int answerLen1 = 0;
|
||||||
int samples = 0;
|
int samples = 0;
|
||||||
|
@ -1213,7 +1213,7 @@ void BruteforceIso15693Afi(uint32_t speed)
|
||||||
void DirectTag15693Command(uint32_t datalen,uint32_t speed, uint32_t recv, uint8_t data[]) {
|
void DirectTag15693Command(uint32_t datalen,uint32_t speed, uint32_t recv, uint8_t data[]) {
|
||||||
|
|
||||||
int recvlen=0;
|
int recvlen=0;
|
||||||
uint8_t *recvbuf=(uint8_t *)BigBuf;
|
uint8_t *recvbuf = BigBuf_get_addr();
|
||||||
// UsbCommand n;
|
// UsbCommand n;
|
||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
|
|
|
@ -98,13 +98,14 @@ static uint32_t get_key_stream(int skip, int count)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write Time Data into LOG */
|
/* Write Time Data into LOG */
|
||||||
|
uint8_t *BigBuf = BigBuf_get_addr();
|
||||||
if(count == 6) { i = -1; } else { i = legic_read_count; }
|
if(count == 6) { i = -1; } else { i = legic_read_count; }
|
||||||
((uint8_t*)BigBuf)[OFFSET_LOG+128+i] = legic_prng_count();
|
BigBuf[OFFSET_LOG+128+i] = legic_prng_count();
|
||||||
((uint8_t*)BigBuf)[OFFSET_LOG+256+i*4] = (legic_prng_bc >> 0) & 0xff;
|
BigBuf[OFFSET_LOG+256+i*4] = (legic_prng_bc >> 0) & 0xff;
|
||||||
((uint8_t*)BigBuf)[OFFSET_LOG+256+i*4+1] = (legic_prng_bc >> 8) & 0xff;
|
BigBuf[OFFSET_LOG+256+i*4+1] = (legic_prng_bc >> 8) & 0xff;
|
||||||
((uint8_t*)BigBuf)[OFFSET_LOG+256+i*4+2] = (legic_prng_bc >>16) & 0xff;
|
BigBuf[OFFSET_LOG+256+i*4+2] = (legic_prng_bc >>16) & 0xff;
|
||||||
((uint8_t*)BigBuf)[OFFSET_LOG+256+i*4+3] = (legic_prng_bc >>24) & 0xff;
|
BigBuf[OFFSET_LOG+256+i*4+3] = (legic_prng_bc >>24) & 0xff;
|
||||||
((uint8_t*)BigBuf)[OFFSET_LOG+384+i] = count;
|
BigBuf[OFFSET_LOG+384+i] = count;
|
||||||
|
|
||||||
/* Generate KeyStream */
|
/* Generate KeyStream */
|
||||||
for(i=0; i<count; i++) {
|
for(i=0; i<count; i++) {
|
||||||
|
@ -426,6 +427,7 @@ int LegicRfReader(int offset, int bytes) {
|
||||||
|
|
||||||
LegicCommonInit();
|
LegicCommonInit();
|
||||||
|
|
||||||
|
uint8_t *BigBuf = BigBuf_get_addr();
|
||||||
memset(BigBuf, 0, 1024);
|
memset(BigBuf, 0, 1024);
|
||||||
|
|
||||||
DbpString("setting up legic card");
|
DbpString("setting up legic card");
|
||||||
|
@ -465,7 +467,7 @@ int LegicRfReader(int offset, int bytes) {
|
||||||
LED_C_OFF();
|
LED_C_OFF();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
((uint8_t*)BigBuf)[byte_index] = r;
|
BigBuf[byte_index] = r;
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
byte_index++;
|
byte_index++;
|
||||||
if(byte_index & 0x10) LED_C_ON(); else LED_C_OFF();
|
if(byte_index & 0x10) LED_C_ON(); else LED_C_OFF();
|
||||||
|
@ -480,6 +482,7 @@ int LegicRfReader(int offset, int bytes) {
|
||||||
|
|
||||||
void LegicRfWriter(int bytes, int offset) {
|
void LegicRfWriter(int bytes, int offset) {
|
||||||
int byte_index=0, addr_sz=0;
|
int byte_index=0, addr_sz=0;
|
||||||
|
uint8_t *BigBuf = BigBuf_get_addr();
|
||||||
|
|
||||||
LegicCommonInit();
|
LegicCommonInit();
|
||||||
|
|
||||||
|
@ -512,7 +515,7 @@ void LegicRfWriter(int bytes, int offset) {
|
||||||
perform_setup_phase_rwd(SESSION_IV);
|
perform_setup_phase_rwd(SESSION_IV);
|
||||||
legic_prng_forward(2);
|
legic_prng_forward(2);
|
||||||
while(byte_index < bytes) {
|
while(byte_index < bytes) {
|
||||||
int r = legic_write_byte(((uint8_t*)BigBuf)[byte_index+offset], byte_index+offset, addr_sz);
|
int r = legic_write_byte(BigBuf[byte_index+offset], byte_index+offset, addr_sz);
|
||||||
if((r != 0) || BUTTON_PRESS()) {
|
if((r != 0) || BUTTON_PRESS()) {
|
||||||
Dbprintf("operation aborted @ 0x%03.3x", byte_index);
|
Dbprintf("operation aborted @ 0x%03.3x", byte_index);
|
||||||
switch_off_tag_rwd();
|
switch_off_tag_rwd();
|
||||||
|
@ -534,6 +537,8 @@ int timestamp;
|
||||||
/* Handle (whether to respond) a frame in tag mode */
|
/* Handle (whether to respond) a frame in tag mode */
|
||||||
static void frame_handle_tag(struct legic_frame const * const f)
|
static void frame_handle_tag(struct legic_frame const * const f)
|
||||||
{
|
{
|
||||||
|
uint8_t *BigBuf = BigBuf_get_addr();
|
||||||
|
|
||||||
/* First Part of Handshake (IV) */
|
/* First Part of Handshake (IV) */
|
||||||
if(f->bits == 7) {
|
if(f->bits == 7) {
|
||||||
if(f->data == SESSION_IV) {
|
if(f->data == SESSION_IV) {
|
||||||
|
@ -582,9 +587,9 @@ static void frame_handle_tag(struct legic_frame const * const f)
|
||||||
if(legic_state == STATE_CON) {
|
if(legic_state == STATE_CON) {
|
||||||
int key = get_key_stream(-1, 11); //legic_phase_drift, 11);
|
int key = get_key_stream(-1, 11); //legic_phase_drift, 11);
|
||||||
int addr = f->data ^ key; addr = addr >> 1;
|
int addr = f->data ^ key; addr = addr >> 1;
|
||||||
int data = ((uint8_t*)BigBuf)[addr];
|
int data = BigBuf[addr];
|
||||||
int hash = LegicCRC(addr, data, 11) << 8;
|
int hash = LegicCRC(addr, data, 11) << 8;
|
||||||
((uint8_t*)BigBuf)[OFFSET_LOG+legic_read_count] = (uint8_t)addr;
|
BigBuf[OFFSET_LOG+legic_read_count] = (uint8_t)addr;
|
||||||
legic_read_count++;
|
legic_read_count++;
|
||||||
|
|
||||||
//Dbprintf("Data:%03.3x, key:%03.3x, addr: %03.3x, read_c:%u", f->data, key, addr, read_c);
|
//Dbprintf("Data:%03.3x, key:%03.3x, addr: %03.3x, read_c:%u", f->data, key, addr, read_c);
|
||||||
|
@ -619,19 +624,19 @@ static void frame_handle_tag(struct legic_frame const * const f)
|
||||||
int i;
|
int i;
|
||||||
Dbprintf("IV: %03.3x", legic_prng_iv);
|
Dbprintf("IV: %03.3x", legic_prng_iv);
|
||||||
for(i = 0; i<legic_read_count; i++) {
|
for(i = 0; i<legic_read_count; i++) {
|
||||||
Dbprintf("Read Nb: %u, Addr: %u", i, ((uint8_t*)BigBuf)[OFFSET_LOG+i]);
|
Dbprintf("Read Nb: %u, Addr: %u", i, BigBuf[OFFSET_LOG+i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = -1; i<legic_read_count; i++) {
|
for(i = -1; i<legic_read_count; i++) {
|
||||||
uint32_t t;
|
uint32_t t;
|
||||||
t = ((uint8_t*)BigBuf)[OFFSET_LOG+256+i*4];
|
t = BigBuf[OFFSET_LOG+256+i*4];
|
||||||
t |= ((uint8_t*)BigBuf)[OFFSET_LOG+256+i*4+1] << 8;
|
t |= BigBuf[OFFSET_LOG+256+i*4+1] << 8;
|
||||||
t |= ((uint8_t*)BigBuf)[OFFSET_LOG+256+i*4+2] <<16;
|
t |= BigBuf[OFFSET_LOG+256+i*4+2] <<16;
|
||||||
t |= ((uint8_t*)BigBuf)[OFFSET_LOG+256+i*4+3] <<24;
|
t |= BigBuf[OFFSET_LOG+256+i*4+3] <<24;
|
||||||
|
|
||||||
Dbprintf("Cycles: %u, Frame Length: %u, Time: %u",
|
Dbprintf("Cycles: %u, Frame Length: %u, Time: %u",
|
||||||
((uint8_t*)BigBuf)[OFFSET_LOG+128+i],
|
BigBuf[OFFSET_LOG+128+i],
|
||||||
((uint8_t*)BigBuf)[OFFSET_LOG+384+i],
|
BigBuf[OFFSET_LOG+384+i],
|
||||||
t);
|
t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
202
armsrc/lfops.c
202
armsrc/lfops.c
|
@ -15,130 +15,44 @@
|
||||||
#include "crc16.h"
|
#include "crc16.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "lfdemod.h"
|
#include "lfdemod.h"
|
||||||
|
#include "lfsampling.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does the sample acquisition. If threshold is specified, the actual sampling
|
* Function to do a modulation and then get samples.
|
||||||
* is not commenced until the threshold has been reached.
|
* @param delay_off
|
||||||
* @param trigger_threshold - the threshold
|
* @param period_0
|
||||||
* @param silent - is true, now outputs are made. If false, dbprints the status
|
* @param period_1
|
||||||
*/
|
* @param command
|
||||||
void DoAcquisition125k_internal(int trigger_threshold,bool silent)
|
*/
|
||||||
{
|
|
||||||
uint8_t *dest = (uint8_t *)BigBuf;
|
|
||||||
int n = sizeof(BigBuf);
|
|
||||||
int i;
|
|
||||||
|
|
||||||
memset(dest, 0, n);
|
|
||||||
i = 0;
|
|
||||||
for(;;) {
|
|
||||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
|
|
||||||
AT91C_BASE_SSC->SSC_THR = 0x43;
|
|
||||||
LED_D_ON();
|
|
||||||
}
|
|
||||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
|
||||||
dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
|
||||||
LED_D_OFF();
|
|
||||||
if (trigger_threshold != -1 && dest[i] < trigger_threshold)
|
|
||||||
continue;
|
|
||||||
else
|
|
||||||
trigger_threshold = -1;
|
|
||||||
if (++i >= n) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!silent)
|
|
||||||
{
|
|
||||||
Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...",
|
|
||||||
dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Perform sample aquisition.
|
|
||||||
*/
|
|
||||||
void DoAcquisition125k(int trigger_threshold)
|
|
||||||
{
|
|
||||||
DoAcquisition125k_internal(trigger_threshold, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup the FPGA to listen for samples. This method downloads the FPGA bitstream
|
|
||||||
* if not already loaded, sets divisor and starts up the antenna.
|
|
||||||
* @param divisor : 1, 88> 255 or negative ==> 134.8 KHz
|
|
||||||
* 0 or 95 ==> 125 KHz
|
|
||||||
*
|
|
||||||
**/
|
|
||||||
void LFSetupFPGAForADC(int divisor, bool lf_field)
|
|
||||||
{
|
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
|
||||||
if ( (divisor == 1) || (divisor < 0) || (divisor > 255) )
|
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
|
|
||||||
else if (divisor == 0)
|
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
|
||||||
else
|
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor);
|
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | (lf_field ? FPGA_LF_ADC_READER_FIELD : 0));
|
|
||||||
|
|
||||||
// Connect the A/D to the peak-detected low-frequency path.
|
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
|
||||||
// Give it a bit of time for the resonant antenna to settle.
|
|
||||||
SpinDelay(50);
|
|
||||||
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
|
||||||
FpgaSetupSsc();
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Initializes the FPGA, and acquires the samples.
|
|
||||||
**/
|
|
||||||
void AcquireRawAdcSamples125k(int divisor)
|
|
||||||
{
|
|
||||||
LFSetupFPGAForADC(divisor, true);
|
|
||||||
// Now call the acquisition routine
|
|
||||||
DoAcquisition125k_internal(-1,false);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Initializes the FPGA for snoop-mode, and acquires the samples.
|
|
||||||
**/
|
|
||||||
|
|
||||||
void SnoopLFRawAdcSamples(int divisor, int trigger_threshold)
|
|
||||||
{
|
|
||||||
LFSetupFPGAForADC(divisor, false);
|
|
||||||
DoAcquisition125k(trigger_threshold);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModThenAcquireRawAdcSamples125k(int delay_off, int period_0, int period_1, uint8_t *command)
|
void ModThenAcquireRawAdcSamples125k(int delay_off, int period_0, int period_1, uint8_t *command)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Make sure the tag is reset */
|
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
|
||||||
SpinDelay(2500);
|
|
||||||
|
|
||||||
|
|
||||||
int divisor_used = 95; // 125 KHz
|
int divisor_used = 95; // 125 KHz
|
||||||
// see if 'h' was specified
|
// see if 'h' was specified
|
||||||
|
|
||||||
if (command[strlen((char *) command) - 1] == 'h')
|
if (command[strlen((char *) command) - 1] == 'h')
|
||||||
divisor_used = 88; // 134.8 KHz
|
divisor_used = 88; // 134.8 KHz
|
||||||
|
|
||||||
|
sample_config sc = { 0,0,1, divisor_used, 0};
|
||||||
|
setSamplingConfig(&sc);
|
||||||
|
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor_used);
|
/* Make sure the tag is reset */
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||||
// Give it a bit of time for the resonant antenna to settle.
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
SpinDelay(50);
|
SpinDelay(2500);
|
||||||
|
|
||||||
// And a little more time for the tag to fully power up
|
LFSetupFPGAForADC(sc.divisor, 1);
|
||||||
SpinDelay(2000);
|
|
||||||
|
|
||||||
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
// And a little more time for the tag to fully power up
|
||||||
FpgaSetupSsc();
|
SpinDelay(2000);
|
||||||
|
|
||||||
// now modulate the reader field
|
// now modulate the reader field
|
||||||
while(*command != '\0' && *command != ' ') {
|
while(*command != '\0' && *command != ' ') {
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
SpinDelayUs(delay_off);
|
SpinDelayUs(delay_off);
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor_used);
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc.divisor);
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
|
||||||
LED_D_ON();
|
LED_D_ON();
|
||||||
|
@ -150,14 +64,16 @@ void ModThenAcquireRawAdcSamples125k(int delay_off, int period_0, int period_1,
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
SpinDelayUs(delay_off);
|
SpinDelayUs(delay_off);
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor_used);
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc.divisor);
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
|
||||||
|
|
||||||
// now do the read
|
// now do the read
|
||||||
DoAcquisition125k(-1);
|
DoAcquisition_config(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* blank r/w tag data stream
|
/* blank r/w tag data stream
|
||||||
...0000000000000000 01111111
|
...0000000000000000 01111111
|
||||||
1010101010101010101010101010101010101010101010101010101010101010
|
1010101010101010101010101010101010101010101010101010101010101010
|
||||||
|
@ -177,8 +93,8 @@ void ReadTItag(void)
|
||||||
#define FREQLO 123200
|
#define FREQLO 123200
|
||||||
#define FREQHI 134200
|
#define FREQHI 134200
|
||||||
|
|
||||||
signed char *dest = (signed char *)BigBuf;
|
signed char *dest = (signed char *)BigBuf_get_addr();
|
||||||
int n = sizeof(BigBuf);
|
uint16_t n = BigBuf_max_traceLen();
|
||||||
// 128 bit shift register [shift3:shift2:shift1:shift0]
|
// 128 bit shift register [shift3:shift2:shift1:shift0]
|
||||||
uint32_t shift3 = 0, shift2 = 0, shift1 = 0, shift0 = 0;
|
uint32_t shift3 = 0, shift2 = 0, shift1 = 0, shift0 = 0;
|
||||||
|
|
||||||
|
@ -330,7 +246,8 @@ void AcquireTiType(void)
|
||||||
#define TIBUFLEN 1250
|
#define TIBUFLEN 1250
|
||||||
|
|
||||||
// clear buffer
|
// clear buffer
|
||||||
memset(BigBuf,0,sizeof(BigBuf));
|
uint32_t *BigBuf = (uint32_t *)BigBuf_get_addr();
|
||||||
|
memset(BigBuf,0,BigBuf_max_traceLen()/sizeof(uint32_t));
|
||||||
|
|
||||||
// Set up the synchronous serial port
|
// Set up the synchronous serial port
|
||||||
AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DIN;
|
AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DIN;
|
||||||
|
@ -378,7 +295,7 @@ void AcquireTiType(void)
|
||||||
AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT;
|
AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT;
|
||||||
AT91C_BASE_PIOA->PIO_ASR = GPIO_SSC_DIN | GPIO_SSC_DOUT;
|
AT91C_BASE_PIOA->PIO_ASR = GPIO_SSC_DIN | GPIO_SSC_DOUT;
|
||||||
|
|
||||||
char *dest = (char *)BigBuf;
|
char *dest = (char *)BigBuf_get_addr();
|
||||||
n = TIBUFLEN*32;
|
n = TIBUFLEN*32;
|
||||||
// unpack buffer
|
// unpack buffer
|
||||||
for (i=TIBUFLEN-1; i>=0; i--) {
|
for (i=TIBUFLEN-1; i>=0; i--) {
|
||||||
|
@ -467,7 +384,7 @@ void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc)
|
||||||
void SimulateTagLowFrequency(int period, int gap, int ledcontrol)
|
void SimulateTagLowFrequency(int period, int gap, int ledcontrol)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
uint8_t *tab = (uint8_t *)BigBuf;
|
uint8_t *tab = BigBuf_get_addr();
|
||||||
|
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
|
||||||
|
@ -527,7 +444,7 @@ void SimulateTagLowFrequencyBidir(int divisor, int t0)
|
||||||
|
|
||||||
// compose fc/8 fc/10 waveform
|
// compose fc/8 fc/10 waveform
|
||||||
static void fc(int c, int *n) {
|
static void fc(int c, int *n) {
|
||||||
uint8_t *dest = (uint8_t *)BigBuf;
|
uint8_t *dest = BigBuf_get_addr();
|
||||||
int idx;
|
int idx;
|
||||||
|
|
||||||
// for when we want an fc8 pattern every 4 logical bits
|
// for when we want an fc8 pattern every 4 logical bits
|
||||||
|
@ -631,11 +548,11 @@ void CmdHIDsimTAG(int hi, int lo, int ledcontrol)
|
||||||
// loop to get raw HID waveform then FSK demodulate the TAG ID from it
|
// loop to get raw HID waveform then FSK demodulate the TAG ID from it
|
||||||
void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
||||||
{
|
{
|
||||||
uint8_t *dest = (uint8_t *)BigBuf;
|
uint8_t *dest = BigBuf_get_addr();
|
||||||
|
const size_t sizeOfBigBuff = BigBuf_max_traceLen();
|
||||||
size_t size=0; //, found=0;
|
size_t size = 0;
|
||||||
uint32_t hi2=0, hi=0, lo=0;
|
uint32_t hi2=0, hi=0, lo=0;
|
||||||
|
int idx=0;
|
||||||
// Configure to go in 125Khz listen mode
|
// Configure to go in 125Khz listen mode
|
||||||
LFSetupFPGAForADC(95, true);
|
LFSetupFPGAForADC(95, true);
|
||||||
|
|
||||||
|
@ -644,13 +561,12 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
if (ledcontrol) LED_A_ON();
|
if (ledcontrol) LED_A_ON();
|
||||||
|
|
||||||
DoAcquisition125k_internal(-1,true);
|
DoAcquisition_default(-1,true);
|
||||||
// FSK demodulator
|
// FSK demodulator
|
||||||
size = HIDdemodFSK(dest, sizeof(BigBuf), &hi2, &hi, &lo);
|
size = sizeOfBigBuff; //variable size will change after demod so re initialize it before use
|
||||||
|
idx = HIDdemodFSK(dest, &size, &hi2, &hi, &lo);
|
||||||
|
|
||||||
WDT_HIT();
|
if (idx>0 && lo>0){
|
||||||
|
|
||||||
if (size>0 && lo>0){
|
|
||||||
// final loop, go over previously decoded manchester data and decode into usable tag ID
|
// final loop, go over previously decoded manchester data and decode into usable tag ID
|
||||||
// 111000 bit pattern represent start of frame, 01 pattern represents a 1 and 10 represents a 0
|
// 111000 bit pattern represent start of frame, 01 pattern represents a 1 and 10 represents a 0
|
||||||
if (hi2 != 0){ //extra large HID tags
|
if (hi2 != 0){ //extra large HID tags
|
||||||
|
@ -706,6 +622,8 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
||||||
}
|
}
|
||||||
if (findone){
|
if (findone){
|
||||||
if (ledcontrol) LED_A_OFF();
|
if (ledcontrol) LED_A_OFF();
|
||||||
|
*high = hi;
|
||||||
|
*low = lo;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// reset
|
// reset
|
||||||
|
@ -719,9 +637,9 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
||||||
|
|
||||||
void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol)
|
void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol)
|
||||||
{
|
{
|
||||||
uint8_t *dest = (uint8_t *)BigBuf;
|
uint8_t *dest = BigBuf_get_addr();
|
||||||
|
|
||||||
size_t size=0;
|
size_t size=0, idx=0;
|
||||||
int clk=0, invert=0, errCnt=0;
|
int clk=0, invert=0, errCnt=0;
|
||||||
uint64_t lo=0;
|
uint64_t lo=0;
|
||||||
// Configure to go in 125Khz listen mode
|
// Configure to go in 125Khz listen mode
|
||||||
|
@ -732,8 +650,8 @@ void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol)
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
if (ledcontrol) LED_A_ON();
|
if (ledcontrol) LED_A_ON();
|
||||||
|
|
||||||
DoAcquisition125k_internal(-1,true);
|
DoAcquisition_default(-1,true);
|
||||||
size = sizeof(BigBuf);
|
size = BigBuf_max_traceLen();
|
||||||
//Dbprintf("DEBUG: Buffer got");
|
//Dbprintf("DEBUG: Buffer got");
|
||||||
//askdemod and manchester decode
|
//askdemod and manchester decode
|
||||||
errCnt = askmandemod(dest, &size, &clk, &invert);
|
errCnt = askmandemod(dest, &size, &clk, &invert);
|
||||||
|
@ -741,7 +659,7 @@ void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol)
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
if (errCnt>=0){
|
if (errCnt>=0){
|
||||||
lo = Em410xDecode(dest,size);
|
lo = Em410xDecode(dest, &size, &idx);
|
||||||
//Dbprintf("DEBUG: EM GOT");
|
//Dbprintf("DEBUG: EM GOT");
|
||||||
if (lo>0){
|
if (lo>0){
|
||||||
Dbprintf("EM TAG ID: %02x%08x - (%05d_%03d_%08d)",
|
Dbprintf("EM TAG ID: %02x%08x - (%05d_%03d_%08d)",
|
||||||
|
@ -753,6 +671,8 @@ void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol)
|
||||||
}
|
}
|
||||||
if (findone){
|
if (findone){
|
||||||
if (ledcontrol) LED_A_OFF();
|
if (ledcontrol) LED_A_OFF();
|
||||||
|
*high=lo>>32;
|
||||||
|
*low=lo & 0xFFFFFFFF;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else{
|
} else{
|
||||||
|
@ -771,7 +691,7 @@ void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol)
|
||||||
|
|
||||||
void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
||||||
{
|
{
|
||||||
uint8_t *dest = (uint8_t *)BigBuf;
|
uint8_t *dest = BigBuf_get_addr();
|
||||||
int idx=0;
|
int idx=0;
|
||||||
uint32_t code=0, code2=0;
|
uint32_t code=0, code2=0;
|
||||||
uint8_t version=0;
|
uint8_t version=0;
|
||||||
|
@ -783,10 +703,10 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
||||||
while(!BUTTON_PRESS()) {
|
while(!BUTTON_PRESS()) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
if (ledcontrol) LED_A_ON();
|
if (ledcontrol) LED_A_ON();
|
||||||
DoAcquisition125k_internal(-1,true);
|
DoAcquisition_default(-1,true);
|
||||||
//fskdemod and get start index
|
//fskdemod and get start index
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
idx = IOdemodFSK(dest,sizeof(BigBuf));
|
idx = IOdemodFSK(dest, BigBuf_max_traceLen());
|
||||||
if (idx>0){
|
if (idx>0){
|
||||||
//valid tag found
|
//valid tag found
|
||||||
|
|
||||||
|
@ -819,6 +739,8 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
||||||
if (findone){
|
if (findone){
|
||||||
if (ledcontrol) LED_A_OFF();
|
if (ledcontrol) LED_A_OFF();
|
||||||
//LED_A_OFF();
|
//LED_A_OFF();
|
||||||
|
*high=code;
|
||||||
|
*low=code2;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
code=code2=0;
|
code=code2=0;
|
||||||
|
@ -958,11 +880,11 @@ void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t PwdMod
|
||||||
// Read one card block in page 0
|
// Read one card block in page 0
|
||||||
void T55xxReadBlock(uint32_t Block, uint32_t Pwd, uint8_t PwdMode)
|
void T55xxReadBlock(uint32_t Block, uint32_t Pwd, uint8_t PwdMode)
|
||||||
{
|
{
|
||||||
uint8_t *dest = (uint8_t *)BigBuf;
|
uint8_t *dest = BigBuf_get_addr();
|
||||||
//int m=0, i=0; //enio adjustment 12/10/14
|
//int m=0, i=0; //enio adjustment 12/10/14
|
||||||
uint32_t m=0, i=0;
|
uint32_t m=0, i=0;
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||||
m = sizeof(BigBuf);
|
m = BigBuf_max_traceLen();
|
||||||
// Clear destination buffer before sending the command
|
// Clear destination buffer before sending the command
|
||||||
memset(dest, 128, m);
|
memset(dest, 128, m);
|
||||||
// Connect the A/D to the peak-detected low-frequency path.
|
// Connect the A/D to the peak-detected low-frequency path.
|
||||||
|
@ -1023,11 +945,11 @@ void T55xxReadBlock(uint32_t Block, uint32_t Pwd, uint8_t PwdMode)
|
||||||
|
|
||||||
// Read card traceability data (page 1)
|
// Read card traceability data (page 1)
|
||||||
void T55xxReadTrace(void){
|
void T55xxReadTrace(void){
|
||||||
uint8_t *dest = (uint8_t *)BigBuf;
|
uint8_t *dest = BigBuf_get_addr();
|
||||||
int m=0, i=0;
|
int m=0, i=0;
|
||||||
|
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||||
m = sizeof(BigBuf);
|
m = BigBuf_max_traceLen();
|
||||||
// Clear destination buffer before sending the command
|
// Clear destination buffer before sending the command
|
||||||
memset(dest, 128, m);
|
memset(dest, 128, m);
|
||||||
// Connect the A/D to the peak-detected low-frequency path.
|
// Connect the A/D to the peak-detected low-frequency path.
|
||||||
|
@ -1377,8 +1299,8 @@ void CopyIndala224toT55x7(int uid1, int uid2, int uid3, int uid4, int uid5, int
|
||||||
int DemodPCF7931(uint8_t **outBlocks) {
|
int DemodPCF7931(uint8_t **outBlocks) {
|
||||||
uint8_t BitStream[256];
|
uint8_t BitStream[256];
|
||||||
uint8_t Blocks[8][16];
|
uint8_t Blocks[8][16];
|
||||||
uint8_t *GraphBuffer = (uint8_t *)BigBuf;
|
uint8_t *GraphBuffer = BigBuf_get_addr();
|
||||||
int GraphTraceLen = sizeof(BigBuf);
|
int GraphTraceLen = BigBuf_max_traceLen();
|
||||||
int i, j, lastval, bitidx, half_switch;
|
int i, j, lastval, bitidx, half_switch;
|
||||||
int clock = 64;
|
int clock = 64;
|
||||||
int tolerance = clock / 8;
|
int tolerance = clock / 8;
|
||||||
|
@ -1388,7 +1310,9 @@ int DemodPCF7931(uint8_t **outBlocks) {
|
||||||
int lmin=128, lmax=128;
|
int lmin=128, lmax=128;
|
||||||
uint8_t dir;
|
uint8_t dir;
|
||||||
|
|
||||||
AcquireRawAdcSamples125k(0);
|
LFSetupFPGAForADC(95, true);
|
||||||
|
DoAcquisition_default(0, 0);
|
||||||
|
|
||||||
|
|
||||||
lmin = 64;
|
lmin = 64;
|
||||||
lmax = 192;
|
lmax = 192;
|
||||||
|
@ -1795,7 +1719,7 @@ void EM4xLogin(uint32_t Password) {
|
||||||
void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) {
|
void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) {
|
||||||
|
|
||||||
uint8_t fwd_bit_count;
|
uint8_t fwd_bit_count;
|
||||||
uint8_t *dest = (uint8_t *)BigBuf;
|
uint8_t *dest = BigBuf_get_addr();
|
||||||
int m=0, i=0;
|
int m=0, i=0;
|
||||||
|
|
||||||
//If password mode do login
|
//If password mode do login
|
||||||
|
@ -1805,7 +1729,7 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) {
|
||||||
fwd_bit_count = Prepare_Cmd( FWD_CMD_READ );
|
fwd_bit_count = Prepare_Cmd( FWD_CMD_READ );
|
||||||
fwd_bit_count += Prepare_Addr( Address );
|
fwd_bit_count += Prepare_Addr( Address );
|
||||||
|
|
||||||
m = sizeof(BigBuf);
|
m = BigBuf_max_traceLen();
|
||||||
// Clear destination buffer before sending the command
|
// Clear destination buffer before sending the command
|
||||||
memset(dest, 128, m);
|
memset(dest, 128, m);
|
||||||
// Connect the A/D to the peak-detected low-frequency path.
|
// Connect the A/D to the peak-detected low-frequency path.
|
||||||
|
|
252
armsrc/lfsampling.c
Normal file
252
armsrc/lfsampling.c
Normal file
|
@ -0,0 +1,252 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Miscellaneous routines for low frequency sampling.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "proxmark3.h"
|
||||||
|
#include "apps.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
|
#include "lfsampling.h"
|
||||||
|
|
||||||
|
sample_config config = { 1, 8, 1, 88, 0 } ;
|
||||||
|
|
||||||
|
void printConfig()
|
||||||
|
{
|
||||||
|
Dbprintf("Sampling config: ");
|
||||||
|
Dbprintf(" [q] divisor: %d ", config.divisor);
|
||||||
|
Dbprintf(" [b] bps: %d ", config.bits_per_sample);
|
||||||
|
Dbprintf(" [d] decimation: %d ", config.decimation);
|
||||||
|
Dbprintf(" [a] averaging: %d ", config.averaging);
|
||||||
|
Dbprintf(" [t] trigger threshold: %d ", config.trigger_threshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called from the USB-handler to set the sampling configuration
|
||||||
|
* The sampling config is used for std reading and snooping.
|
||||||
|
*
|
||||||
|
* Other functions may read samples and ignore the sampling config,
|
||||||
|
* such as functions to read the UID from a prox tag or similar.
|
||||||
|
*
|
||||||
|
* Values set to '0' implies no change (except for averaging)
|
||||||
|
* @brief setSamplingConfig
|
||||||
|
* @param sc
|
||||||
|
*/
|
||||||
|
void setSamplingConfig(sample_config *sc)
|
||||||
|
{
|
||||||
|
if(sc->divisor != 0) config.divisor = sc->divisor;
|
||||||
|
if(sc->bits_per_sample!= 0) config.bits_per_sample= sc->bits_per_sample;
|
||||||
|
if(sc->decimation!= 0) config.decimation= sc->decimation;
|
||||||
|
if(sc->trigger_threshold != -1) config.trigger_threshold= sc->trigger_threshold;
|
||||||
|
|
||||||
|
config.averaging= sc->averaging;
|
||||||
|
if(config.bits_per_sample > 8) config.bits_per_sample = 8;
|
||||||
|
if(config.decimation < 1) config.decimation = 1;
|
||||||
|
|
||||||
|
printConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
sample_config* getSamplingConfig()
|
||||||
|
{
|
||||||
|
return &config;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t * buffer;
|
||||||
|
uint32_t numbits;
|
||||||
|
uint32_t position;
|
||||||
|
} BitstreamOut;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pushes bit onto the stream
|
||||||
|
* @param stream
|
||||||
|
* @param bit
|
||||||
|
*/
|
||||||
|
void pushBit( BitstreamOut* stream, uint8_t bit)
|
||||||
|
{
|
||||||
|
int bytepos = stream->position >> 3; // divide by 8
|
||||||
|
int bitpos = stream->position & 7;
|
||||||
|
*(stream->buffer+bytepos) |= (bit > 0) << (7 - bitpos);
|
||||||
|
stream->position++;
|
||||||
|
stream->numbits++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup the FPGA to listen for samples. This method downloads the FPGA bitstream
|
||||||
|
* if not already loaded, sets divisor and starts up the antenna.
|
||||||
|
* @param divisor : 1, 88> 255 or negative ==> 134.8 KHz
|
||||||
|
* 0 or 95 ==> 125 KHz
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
void LFSetupFPGAForADC(int divisor, bool lf_field)
|
||||||
|
{
|
||||||
|
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||||
|
if ( (divisor == 1) || (divisor < 0) || (divisor > 255) )
|
||||||
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
|
||||||
|
else if (divisor == 0)
|
||||||
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
||||||
|
else
|
||||||
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor);
|
||||||
|
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | (lf_field ? FPGA_LF_ADC_READER_FIELD : 0));
|
||||||
|
|
||||||
|
// Connect the A/D to the peak-detected low-frequency path.
|
||||||
|
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||||
|
// Give it a bit of time for the resonant antenna to settle.
|
||||||
|
SpinDelay(50);
|
||||||
|
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
||||||
|
FpgaSetupSsc();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the sample acquisition. If threshold is specified, the actual sampling
|
||||||
|
* is not commenced until the threshold has been reached.
|
||||||
|
* This method implements decimation and quantization in order to
|
||||||
|
* be able to provide longer sample traces.
|
||||||
|
* Uses the following global settings:
|
||||||
|
* @param decimation - how much should the signal be decimated. A decimation of N means we keep 1 in N samples, etc.
|
||||||
|
* @param bits_per_sample - bits per sample. Max 8, min 1 bit per sample.
|
||||||
|
* @param averaging If set to true, decimation will use averaging, so that if e.g. decimation is 3, the sample
|
||||||
|
* value that will be used is the average value of the three samples.
|
||||||
|
* @param trigger_threshold - a threshold. The sampling won't commence until this threshold has been reached. Set
|
||||||
|
* to -1 to ignore threshold.
|
||||||
|
* @param silent - is true, now outputs are made. If false, dbprints the status
|
||||||
|
* @return the number of bits occupied by the samples.
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold,bool silent)
|
||||||
|
{
|
||||||
|
//.
|
||||||
|
uint8_t *dest = BigBuf_get_addr();
|
||||||
|
int bufsize = BigBuf_max_traceLen();
|
||||||
|
|
||||||
|
memset(dest, 0, bufsize);
|
||||||
|
|
||||||
|
if(bits_per_sample < 1) bits_per_sample = 1;
|
||||||
|
if(bits_per_sample > 8) bits_per_sample = 8;
|
||||||
|
|
||||||
|
if(decimation < 1) decimation = 1;
|
||||||
|
|
||||||
|
// Use a bit stream to handle the output
|
||||||
|
BitstreamOut data = { dest , 0, 0};
|
||||||
|
int sample_counter = 0;
|
||||||
|
uint8_t sample = 0;
|
||||||
|
//If we want to do averaging
|
||||||
|
uint32_t sample_sum =0 ;
|
||||||
|
uint32_t sample_total_numbers =0 ;
|
||||||
|
uint32_t sample_total_saved =0 ;
|
||||||
|
|
||||||
|
while(!BUTTON_PRESS()) {
|
||||||
|
WDT_HIT();
|
||||||
|
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
|
||||||
|
AT91C_BASE_SSC->SSC_THR = 0x43;
|
||||||
|
LED_D_ON();
|
||||||
|
}
|
||||||
|
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
||||||
|
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
|
LED_D_OFF();
|
||||||
|
if (trigger_threshold > 0 && sample < trigger_threshold)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
trigger_threshold = 0;
|
||||||
|
sample_total_numbers++;
|
||||||
|
|
||||||
|
if(averaging)
|
||||||
|
{
|
||||||
|
sample_sum += sample;
|
||||||
|
}
|
||||||
|
//Check decimation
|
||||||
|
if(decimation > 1)
|
||||||
|
{
|
||||||
|
sample_counter++;
|
||||||
|
if(sample_counter < decimation) continue;
|
||||||
|
sample_counter = 0;
|
||||||
|
}
|
||||||
|
//Averaging
|
||||||
|
if(averaging && decimation > 1) {
|
||||||
|
sample = sample_sum / decimation;
|
||||||
|
sample_sum =0;
|
||||||
|
}
|
||||||
|
//Store the sample
|
||||||
|
sample_total_saved ++;
|
||||||
|
if(bits_per_sample == 8){
|
||||||
|
dest[sample_total_saved-1] = sample;
|
||||||
|
data.numbits = sample_total_saved << 3;//Get the return value correct
|
||||||
|
if(sample_total_saved >= bufsize) break;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
pushBit(&data, sample & 0x80);
|
||||||
|
if(bits_per_sample > 1) pushBit(&data, sample & 0x40);
|
||||||
|
if(bits_per_sample > 2) pushBit(&data, sample & 0x20);
|
||||||
|
if(bits_per_sample > 3) pushBit(&data, sample & 0x10);
|
||||||
|
if(bits_per_sample > 4) pushBit(&data, sample & 0x08);
|
||||||
|
if(bits_per_sample > 5) pushBit(&data, sample & 0x04);
|
||||||
|
if(bits_per_sample > 6) pushBit(&data, sample & 0x02);
|
||||||
|
//Not needed, 8bps is covered above
|
||||||
|
//if(bits_per_sample > 7) pushBit(&data, sample & 0x01);
|
||||||
|
if((data.numbits >> 3) +1 >= bufsize) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!silent)
|
||||||
|
{
|
||||||
|
Dbprintf("Done, saved %d out of %d seen samples at %d bits/sample",sample_total_saved, sample_total_numbers,bits_per_sample);
|
||||||
|
Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...",
|
||||||
|
dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
|
||||||
|
}
|
||||||
|
return data.numbits;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @brief Does sample acquisition, ignoring the config values set in the sample_config.
|
||||||
|
* This method is typically used by tag-specific readers who just wants to read the samples
|
||||||
|
* the normal way
|
||||||
|
* @param trigger_threshold
|
||||||
|
* @param silent
|
||||||
|
* @return number of bits sampled
|
||||||
|
*/
|
||||||
|
uint32_t DoAcquisition_default(int trigger_threshold, bool silent)
|
||||||
|
{
|
||||||
|
return DoAcquisition(1,8,0,trigger_threshold,silent);
|
||||||
|
}
|
||||||
|
uint32_t DoAcquisition_config( bool silent)
|
||||||
|
{
|
||||||
|
return DoAcquisition(config.decimation
|
||||||
|
,config.bits_per_sample
|
||||||
|
,config.averaging
|
||||||
|
,config.trigger_threshold
|
||||||
|
,silent);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ReadLF(bool activeField)
|
||||||
|
{
|
||||||
|
printConfig();
|
||||||
|
LFSetupFPGAForADC(config.divisor, activeField);
|
||||||
|
// Now call the acquisition routine
|
||||||
|
return DoAcquisition_config(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the FPGA for reader-mode (field on), and acquires the samples.
|
||||||
|
* @return number of bits sampled
|
||||||
|
**/
|
||||||
|
uint32_t SampleLF()
|
||||||
|
{
|
||||||
|
return ReadLF(true);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Initializes the FPGA for snoop-mode (field off), and acquires the samples.
|
||||||
|
* @return number of bits sampled
|
||||||
|
**/
|
||||||
|
|
||||||
|
uint32_t SnoopLF()
|
||||||
|
{
|
||||||
|
return ReadLF(false);
|
||||||
|
}
|
59
armsrc/lfsampling.h
Normal file
59
armsrc/lfsampling.h
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#ifndef LFSAMPLING_H
|
||||||
|
#define LFSAMPLING_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the FPGA for reader-mode (field on), and acquires the samples.
|
||||||
|
* @return number of bits sampled
|
||||||
|
**/
|
||||||
|
uint32_t SampleLF();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the FPGA for snoop-mode (field off), and acquires the samples.
|
||||||
|
* @return number of bits sampled
|
||||||
|
**/
|
||||||
|
|
||||||
|
uint32_t SnoopLF();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Does sample acquisition, ignoring the config values set in the sample_config.
|
||||||
|
* This method is typically used by tag-specific readers who just wants to read the samples
|
||||||
|
* the normal way
|
||||||
|
* @param trigger_threshold
|
||||||
|
* @param silent
|
||||||
|
* @return number of bits sampled
|
||||||
|
*/
|
||||||
|
uint32_t DoAcquisition_default(int trigger_threshold, bool silent);
|
||||||
|
/**
|
||||||
|
* @brief Does sample acquisition, using the config values set in the sample_config.
|
||||||
|
* @param trigger_threshold
|
||||||
|
* @param silent
|
||||||
|
* @return number of bits sampled
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint32_t DoAcquisition_config( bool silent);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup the FPGA to listen for samples. This method downloads the FPGA bitstream
|
||||||
|
* if not already loaded, sets divisor and starts up the antenna.
|
||||||
|
* @param divisor : 1, 88> 255 or negative ==> 134.8 KHz
|
||||||
|
* 0 or 95 ==> 125 KHz
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
void LFSetupFPGAForADC(int divisor, bool lf_field);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called from the USB-handler to set the sampling configuration
|
||||||
|
* The sampling config is used for std reading and snooping.
|
||||||
|
*
|
||||||
|
* Other functions may read samples and ignore the sampling config,
|
||||||
|
* such as functions to read the UID from a prox tag or similar.
|
||||||
|
*
|
||||||
|
* Values set to '0' implies no change (except for averaging)
|
||||||
|
* @brief setSamplingConfig
|
||||||
|
* @param sc
|
||||||
|
*/
|
||||||
|
void setSamplingConfig(sample_config *sc);
|
||||||
|
|
||||||
|
sample_config * getSamplingConfig();
|
||||||
|
#endif // LFSAMPLING_H
|
|
@ -17,6 +17,8 @@
|
||||||
#include "apps.h"
|
#include "apps.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
#include "crc.h"
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Select, Authenticate, Read a MIFARE tag.
|
// Select, Authenticate, Read a MIFARE tag.
|
||||||
// read block
|
// read block
|
||||||
|
@ -80,7 +82,71 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
||||||
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16);
|
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16);
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
// Thats it...
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
LEDsoff();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MifareUC_Auth1(uint8_t arg0, uint8_t *datain){
|
||||||
|
|
||||||
|
byte_t isOK = 0;
|
||||||
|
byte_t dataoutbuf[16] = {0x00};
|
||||||
|
uint8_t uid[10] = {0x00};
|
||||||
|
uint32_t cuid;
|
||||||
|
|
||||||
|
LED_A_ON();
|
||||||
|
LED_B_OFF();
|
||||||
|
LED_C_OFF();
|
||||||
|
|
||||||
|
iso14a_clear_trace();
|
||||||
|
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||||
|
|
||||||
|
if(!iso14443a_select_card(uid, NULL, &cuid)) {
|
||||||
|
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||||
|
Dbprintf("Can't select card");
|
||||||
|
//OnError(0);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if(mifare_ultra_auth1(cuid, dataoutbuf)){
|
||||||
|
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||||
|
Dbprintf("Authentication part1: Fail.");
|
||||||
|
//OnError(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isOK = 1;
|
||||||
|
if (MF_DBGLEVEL >= MF_DBG_EXTENDED)
|
||||||
|
DbpString("AUTH 1 FINISHED");
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
}
|
}
|
||||||
|
@ -463,11 +529,13 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
||||||
struct Crypto1State mpcs = {0, 0};
|
struct Crypto1State mpcs = {0, 0};
|
||||||
struct Crypto1State *pcs;
|
struct Crypto1State *pcs;
|
||||||
pcs = &mpcs;
|
pcs = &mpcs;
|
||||||
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||||
|
|
||||||
uint32_t auth1_time, auth2_time;
|
uint32_t auth1_time, auth2_time;
|
||||||
static uint16_t delta_time;
|
static uint16_t delta_time;
|
||||||
|
|
||||||
|
// free eventually allocated BigBuf memory
|
||||||
|
BigBuf_free();
|
||||||
// clear trace
|
// clear trace
|
||||||
iso14a_clear_trace();
|
iso14a_clear_trace();
|
||||||
iso14a_set_tracing(false);
|
iso14a_set_tracing(false);
|
||||||
|
@ -854,8 +922,8 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
||||||
uint8_t d_block[18] = {0x00};
|
uint8_t d_block[18] = {0x00};
|
||||||
uint32_t cuid;
|
uint32_t cuid;
|
||||||
|
|
||||||
uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();
|
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||||
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||||
|
|
||||||
// reset FPGA and LED
|
// reset FPGA and LED
|
||||||
if (workFlags & 0x08) {
|
if (workFlags & 0x08) {
|
||||||
|
@ -973,8 +1041,8 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
||||||
uint8_t data[18] = {0x00};
|
uint8_t data[18] = {0x00};
|
||||||
uint32_t cuid = 0;
|
uint32_t cuid = 0;
|
||||||
|
|
||||||
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||||
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||||
|
|
||||||
if (workFlags & 0x08) {
|
if (workFlags & 0x08) {
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
|
@ -1038,8 +1106,8 @@ void MifareCIdent(){
|
||||||
// variables
|
// variables
|
||||||
byte_t isOK = 1;
|
byte_t isOK = 1;
|
||||||
|
|
||||||
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||||
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||||
|
|
||||||
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
||||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||||
|
@ -1061,3 +1129,58 @@ void MifareCIdent(){
|
||||||
//
|
//
|
||||||
// DESFIRE
|
// DESFIRE
|
||||||
//
|
//
|
||||||
|
|
||||||
|
void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){
|
||||||
|
|
||||||
|
byte_t dataout[11] = {0x00};
|
||||||
|
uint8_t uid[10] = {0x00};
|
||||||
|
uint32_t cuid;
|
||||||
|
|
||||||
|
iso14a_clear_trace();
|
||||||
|
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||||
|
|
||||||
|
int len = iso14443a_select_card(uid, NULL, &cuid);
|
||||||
|
if(!len) {
|
||||||
|
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||||
|
Dbprintf("Can't select card");
|
||||||
|
//OnError(1);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if(mifare_desfire_des_auth1(cuid, dataout)){
|
||||||
|
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||||
|
Dbprintf("Authentication part1: Fail.");
|
||||||
|
//OnError(4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED");
|
||||||
|
|
||||||
|
cmd_send(CMD_ACK,1,cuid,0,dataout, sizeof(dataout));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){
|
||||||
|
|
||||||
|
uint32_t cuid = arg0;
|
||||||
|
uint8_t key[16] = {0x00};
|
||||||
|
byte_t isOK = 0;
|
||||||
|
byte_t dataout[12] = {0x00};
|
||||||
|
|
||||||
|
memcpy(key, datain, 16);
|
||||||
|
|
||||||
|
isOK = mifare_desfire_des_auth2(cuid, key, dataout);
|
||||||
|
|
||||||
|
if( isOK) {
|
||||||
|
if (MF_DBGLEVEL >= MF_DBG_EXTENDED)
|
||||||
|
Dbprintf("Authentication part2: Failed");
|
||||||
|
//OnError(4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MF_DBGLEVEL >= MF_DBG_EXTENDED)
|
||||||
|
DbpString("AUTH 2 FINISHED");
|
||||||
|
|
||||||
|
cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout));
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
LEDsoff();
|
||||||
|
}
|
||||||
|
|
|
@ -13,10 +13,10 @@
|
||||||
|
|
||||||
static int sniffState = SNF_INIT;
|
static int sniffState = SNF_INIT;
|
||||||
static uint8_t sniffUIDType;
|
static uint8_t sniffUIDType;
|
||||||
static uint8_t sniffUID[8];
|
static uint8_t sniffUID[8] = {0x00};
|
||||||
static uint8_t sniffATQA[2];
|
static uint8_t sniffATQA[2] = {0x00};
|
||||||
static uint8_t sniffSAK;
|
static uint8_t sniffSAK;
|
||||||
static uint8_t sniffBuf[16];
|
static uint8_t sniffBuf[16] = {0x00};
|
||||||
static uint32_t timerData = 0;
|
static uint32_t timerData = 0;
|
||||||
|
|
||||||
|
|
||||||
|
@ -151,12 +151,13 @@ bool intMfSniffSend() {
|
||||||
int pckSize = 0;
|
int pckSize = 0;
|
||||||
int pckLen = traceLen;
|
int pckLen = traceLen;
|
||||||
int pckNum = 0;
|
int pckNum = 0;
|
||||||
|
uint8_t *trace = BigBuf_get_addr();
|
||||||
|
|
||||||
FpgaDisableSscDma();
|
FpgaDisableSscDma();
|
||||||
while (pckLen > 0) {
|
while (pckLen > 0) {
|
||||||
pckSize = MIN(USB_CMD_DATA_SIZE, pckLen);
|
pckSize = MIN(USB_CMD_DATA_SIZE, pckLen);
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
cmd_send(CMD_ACK, 1, pckSize, pckNum, trace + traceLen - pckLen, pckSize);
|
cmd_send(CMD_ACK, 1, traceLen, pckSize, trace + traceLen - pckLen, pckSize);
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
pckLen -= pckSize;
|
pckLen -= pckSize;
|
||||||
|
|
|
@ -21,17 +21,6 @@
|
||||||
|
|
||||||
int MF_DBGLEVEL = MF_DBG_ALL;
|
int MF_DBGLEVEL = MF_DBG_ALL;
|
||||||
|
|
||||||
// memory management
|
|
||||||
uint8_t* get_bigbufptr_recvrespbuf(void) {
|
|
||||||
return (((uint8_t *)BigBuf) + RECV_RESP_OFFSET);
|
|
||||||
}
|
|
||||||
uint8_t* get_bigbufptr_recvcmdbuf(void) {
|
|
||||||
return (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
|
|
||||||
}
|
|
||||||
uint8_t* get_bigbufptr_emlcardmem(void) {
|
|
||||||
return (((uint8_t *)BigBuf) + CARD_MEMORY_OFFSET);
|
|
||||||
}
|
|
||||||
|
|
||||||
// crypto1 helpers
|
// crypto1 helpers
|
||||||
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len){
|
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len){
|
||||||
uint8_t bt = 0;
|
uint8_t bt = 0;
|
||||||
|
@ -93,10 +82,30 @@ int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint
|
||||||
AppendCrc14443a(dcmd, 6);
|
AppendCrc14443a(dcmd, 6);
|
||||||
ReaderTransmit(dcmd, sizeof(dcmd), NULL);
|
ReaderTransmit(dcmd, sizeof(dcmd), NULL);
|
||||||
int len = ReaderReceive(answer, answer_parity);
|
int len = ReaderReceive(answer, answer_parity);
|
||||||
if(!len)
|
if(!len) {
|
||||||
{
|
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout.");
|
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout.");
|
||||||
return 2;
|
return 2;
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
uint8_t dcmd[19];
|
||||||
|
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;
|
return len;
|
||||||
}
|
}
|
||||||
|
@ -166,8 +175,8 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
|
||||||
uint32_t nt, ntpp; // Supplied tag nonce
|
uint32_t nt, ntpp; // Supplied tag nonce
|
||||||
|
|
||||||
uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
|
uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
|
||||||
uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();
|
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||||
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||||
|
|
||||||
// Transmit MIFARE_CLASSIC_AUTH
|
// Transmit MIFARE_CLASSIC_AUTH
|
||||||
len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing);
|
len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing);
|
||||||
|
@ -253,8 +262,8 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
|
||||||
int len;
|
int len;
|
||||||
uint8_t bt[2];
|
uint8_t bt[2];
|
||||||
|
|
||||||
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||||
uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||||
|
|
||||||
// command MIFARE_CLASSIC_READBLOCK
|
// command MIFARE_CLASSIC_READBLOCK
|
||||||
len = mifare_sendcmd_short(pcs, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
len = mifare_sendcmd_short(pcs, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
|
@ -278,12 +287,63 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mifare ultralight commands
|
||||||
|
int mifare_ultra_auth1(uint32_t uid, uint8_t *blockData){
|
||||||
|
|
||||||
|
uint16_t len;
|
||||||
|
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||||
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||||
|
|
||||||
|
len = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, 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("Auth1 Resp: %02x%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_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){
|
||||||
|
|
||||||
|
uint16_t len;
|
||||||
|
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)
|
int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
||||||
{
|
{
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
uint8_t bt[2];
|
uint8_t bt[2];
|
||||||
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||||
uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||||
|
|
||||||
|
|
||||||
// command MIFARE_CLASSIC_READBLOCK
|
// command MIFARE_CLASSIC_READBLOCK
|
||||||
|
@ -321,8 +381,8 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
|
||||||
byte_t res;
|
byte_t res;
|
||||||
|
|
||||||
uint8_t d_block[18], d_block_enc[18];
|
uint8_t d_block[18], d_block_enc[18];
|
||||||
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||||
uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||||
|
|
||||||
// command MIFARE_CLASSIC_WRITEBLOCK
|
// command MIFARE_CLASSIC_WRITEBLOCK
|
||||||
len = mifare_sendcmd_short(pcs, 1, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
len = mifare_sendcmd_short(pcs, 1, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
|
@ -364,8 +424,8 @@ int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
uint8_t par[3] = {0}; // enough for 18 parity bits
|
uint8_t par[3] = {0}; // enough for 18 parity bits
|
||||||
uint8_t d_block[18] = {0x00};
|
uint8_t d_block[18] = {0x00};
|
||||||
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||||
uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_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);
|
len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
|
@ -395,8 +455,8 @@ int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *bloc
|
||||||
{
|
{
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
uint8_t d_block[8] = {0x00};
|
uint8_t d_block[8] = {0x00};
|
||||||
uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();
|
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||||
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||||
|
|
||||||
// command MIFARE_CLASSIC_WRITEBLOCK
|
// command MIFARE_CLASSIC_WRITEBLOCK
|
||||||
d_block[0]= blockNo;
|
d_block[0]= blockNo;
|
||||||
|
@ -416,8 +476,8 @@ int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *bloc
|
||||||
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
|
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
|
||||||
{
|
{
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();
|
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||||
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||||
|
|
||||||
len = mifare_sendcmd_short(pcs, pcs == NULL ? false:true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL);
|
len = mifare_sendcmd_short(pcs, pcs == NULL ? false:true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
if (len != 0) {
|
if (len != 0) {
|
||||||
|
@ -432,8 +492,8 @@ int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
|
||||||
int mifare_ultra_halt(uint32_t uid)
|
int mifare_ultra_halt(uint32_t uid)
|
||||||
{
|
{
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();
|
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||||
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_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) {
|
||||||
|
@ -467,22 +527,22 @@ 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 = get_bigbufptr_emlcardmem();
|
uint8_t* emCARD = BigBuf_get_EM_addr();
|
||||||
memcpy(emCARD + blockNum * 16, data, blocksCount * 16);
|
memcpy(emCARD + blockNum * 16, data, blocksCount * 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void emlGetMem(uint8_t *data, int blockNum, int blocksCount) {
|
void emlGetMem(uint8_t *data, int blockNum, int blocksCount) {
|
||||||
uint8_t* emCARD = get_bigbufptr_emlcardmem();
|
uint8_t* emCARD = BigBuf_get_EM_addr();
|
||||||
memcpy(data, emCARD + blockNum * 16, blocksCount * 16);
|
memcpy(data, emCARD + blockNum * 16, blocksCount * 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount) {
|
void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount) {
|
||||||
uint8_t* emCARD = get_bigbufptr_emlcardmem();
|
uint8_t* emCARD = BigBuf_get_EM_addr();
|
||||||
memcpy(data, emCARD + bytePtr, byteCount);
|
memcpy(data, emCARD + bytePtr, byteCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
int emlCheckValBl(int blockNum) {
|
int emlCheckValBl(int blockNum) {
|
||||||
uint8_t* emCARD = get_bigbufptr_emlcardmem();
|
uint8_t* emCARD = BigBuf_get_EM_addr();
|
||||||
uint8_t* data = emCARD + blockNum * 16;
|
uint8_t* data = emCARD + blockNum * 16;
|
||||||
|
|
||||||
if ((data[0] != (data[4] ^ 0xff)) || (data[0] != data[8]) ||
|
if ((data[0] != (data[4] ^ 0xff)) || (data[0] != data[8]) ||
|
||||||
|
@ -497,7 +557,7 @@ int emlCheckValBl(int blockNum) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) {
|
int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) {
|
||||||
uint8_t* emCARD = get_bigbufptr_emlcardmem();
|
uint8_t* emCARD = BigBuf_get_EM_addr();
|
||||||
uint8_t* data = emCARD + blockNum * 16;
|
uint8_t* data = emCARD + blockNum * 16;
|
||||||
|
|
||||||
if (emlCheckValBl(blockNum)) {
|
if (emlCheckValBl(blockNum)) {
|
||||||
|
@ -510,7 +570,7 @@ int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) {
|
int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) {
|
||||||
uint8_t* emCARD = get_bigbufptr_emlcardmem();
|
uint8_t* emCARD = BigBuf_get_EM_addr();
|
||||||
uint8_t* data = emCARD + blockNum * 16;
|
uint8_t* data = emCARD + blockNum * 16;
|
||||||
|
|
||||||
memcpy(data + 0, &blReg, 4);
|
memcpy(data + 0, &blReg, 4);
|
||||||
|
@ -528,7 +588,7 @@ int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) {
|
||||||
|
|
||||||
uint64_t emlGetKey(int sectorNum, int keyType) {
|
uint64_t emlGetKey(int sectorNum, int keyType) {
|
||||||
uint8_t key[6];
|
uint8_t key[6];
|
||||||
uint8_t* emCARD = get_bigbufptr_emlcardmem();
|
uint8_t* emCARD = BigBuf_get_EM_addr();
|
||||||
|
|
||||||
memcpy(key, emCARD + 16 * (FirstBlockOfSector(sectorNum) + NumBlocksPerSector(sectorNum) - 1) + keyType * 10, 6);
|
memcpy(key, emCARD + 16 * (FirstBlockOfSector(sectorNum) + NumBlocksPerSector(sectorNum) - 1) + keyType * 10, 6);
|
||||||
return bytes_to_num(key, 6);
|
return bytes_to_num(key, 6);
|
||||||
|
@ -539,7 +599,7 @@ void emlClearMem(void) {
|
||||||
|
|
||||||
const uint8_t trailer[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x80, 0x69, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
const uint8_t trailer[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x80, 0x69, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||||
const uint8_t uid[] = {0xe6, 0x84, 0x87, 0xf3, 0x16, 0x88, 0x04, 0x00, 0x46, 0x8e, 0x45, 0x55, 0x4d, 0x70, 0x41, 0x04};
|
const uint8_t uid[] = {0xe6, 0x84, 0x87, 0xf3, 0x16, 0x88, 0x04, 0x00, 0x46, 0x8e, 0x45, 0x55, 0x4d, 0x70, 0x41, 0x04};
|
||||||
uint8_t* emCARD = get_bigbufptr_emlcardmem();
|
uint8_t* emCARD = BigBuf_get_EM_addr();
|
||||||
|
|
||||||
memset(emCARD, 0, CARD_MEMORY_SIZE);
|
memset(emCARD, 0, CARD_MEMORY_SIZE);
|
||||||
|
|
||||||
|
@ -552,3 +612,98 @@ void emlClearMem(void) {
|
||||||
emlSetMem((uint8_t *)uid, 0, 1);
|
emlSetMem((uint8_t *)uid, 0, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Mifare desfire commands
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
uint8_t dcmd[5] = {0x00};
|
||||||
|
dcmd[0] = cmd;
|
||||||
|
memcpy(dcmd+1,data,2);
|
||||||
|
AppendCrc14443a(dcmd, 3);
|
||||||
|
|
||||||
|
ReaderTransmit(dcmd, sizeof(dcmd), NULL);
|
||||||
|
int len = ReaderReceive(answer, answer_parity);
|
||||||
|
if(!len) {
|
||||||
|
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||||
|
Dbprintf("Authentication failed. Card timeout.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
uint8_t dcmd[20] = {0x00};
|
||||||
|
dcmd[0] = cmd;
|
||||||
|
memcpy(dcmd+1,data,17);
|
||||||
|
AppendCrc14443a(dcmd, 18);
|
||||||
|
|
||||||
|
ReaderTransmit(dcmd, sizeof(dcmd), NULL);
|
||||||
|
int len = ReaderReceive(answer, answer_parity);
|
||||||
|
if(!len){
|
||||||
|
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||||
|
Dbprintf("Authentication failed. Card timeout.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData){
|
||||||
|
|
||||||
|
int len;
|
||||||
|
// load key, keynumber
|
||||||
|
uint8_t data[2]={0x0a, 0x00};
|
||||||
|
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||||
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||||
|
|
||||||
|
len = mifare_sendcmd_special(NULL, 1, 0x02, data, receivedAnswer,receivedAnswerPar,NULL);
|
||||||
|
if (len == 1) {
|
||||||
|
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||||
|
Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == 12) {
|
||||||
|
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
|
||||||
|
Dbprintf("Auth1 Resp: %02x%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],receivedAnswer[11]);
|
||||||
|
}
|
||||||
|
memcpy(blockData, receivedAnswer, 12);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){
|
||||||
|
|
||||||
|
int len;
|
||||||
|
uint8_t data[17] = {0x00};
|
||||||
|
data[0] = 0xAF;
|
||||||
|
memcpy(data+1,key,16);
|
||||||
|
|
||||||
|
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||||
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||||
|
|
||||||
|
len = mifare_sendcmd_special2(NULL, 1, 0x03, data, receivedAnswer, receivedAnswerPar ,NULL);
|
||||||
|
|
||||||
|
if ((receivedAnswer[0] == 0x03) && (receivedAnswer[1] == 0xae)) {
|
||||||
|
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||||
|
Dbprintf("Auth Error: %02x %02x", receivedAnswer[0], receivedAnswer[1]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == 12){
|
||||||
|
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],receivedAnswer[11]);
|
||||||
|
}
|
||||||
|
memcpy(blockData, receivedAnswer, 12);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
|
@ -53,14 +53,17 @@ 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
|
||||||
uint8_t* mifare_get_bigbufptr(void);
|
|
||||||
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(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_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_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_mfucauth(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_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_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_ultra_auth2(uint32_t cuid, uint8_t *key, uint8_t *blockData);
|
||||||
int mifare_ultra_readblock(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);
|
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
||||||
int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
||||||
|
@ -68,16 +71,17 @@ int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *bloc
|
||||||
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid);
|
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid);
|
||||||
int mifare_ultra_halt(uint32_t uid);
|
int mifare_ultra_halt(uint32_t uid);
|
||||||
|
|
||||||
|
// 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_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_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);
|
||||||
|
|
||||||
// memory management
|
|
||||||
uint8_t* get_bigbufptr_recvrespbuf(void);
|
|
||||||
uint8_t* get_bigbufptr_recvcmdbuf(void);
|
|
||||||
uint8_t* get_bigbufptr_emlcardmem(void);
|
|
||||||
|
|
||||||
// Mifare memory structure
|
// Mifare memory structure
|
||||||
uint8_t NumBlocksPerSector(uint8_t sectorNo);
|
uint8_t NumBlocksPerSector(uint8_t sectorNo);
|
||||||
uint8_t FirstBlockOfSector(uint8_t sectorNo);
|
uint8_t FirstBlockOfSector(uint8_t sectorNo);
|
||||||
|
|
|
@ -12,9 +12,8 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "apps.h"
|
#include "apps.h"
|
||||||
|
#include "BigBuf.h"
|
||||||
|
|
||||||
uint8_t *trace = (uint8_t *) BigBuf+TRACE_OFFSET;
|
|
||||||
int traceLen = 0;
|
|
||||||
int tracing = TRUE;
|
int tracing = TRUE;
|
||||||
|
|
||||||
|
|
||||||
|
@ -439,7 +438,9 @@ void iso14a_set_tracing(bool enable) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_trace() {
|
void clear_trace() {
|
||||||
memset(trace, 0x44, TRACE_SIZE);
|
uint8_t *trace = BigBuf_get_addr();
|
||||||
|
uint16_t max_traceLen = BigBuf_max_traceLen();
|
||||||
|
memset(trace, 0x44, max_traceLen);
|
||||||
traceLen = 0;
|
traceLen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,11 +459,15 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_
|
||||||
{
|
{
|
||||||
if (!tracing) return FALSE;
|
if (!tracing) return FALSE;
|
||||||
|
|
||||||
|
uint8_t *trace = BigBuf_get_addr();
|
||||||
|
|
||||||
uint16_t num_paritybytes = (iLen-1)/8 + 1; // number of valid paritybytes in *parity
|
uint16_t num_paritybytes = (iLen-1)/8 + 1; // number of valid paritybytes in *parity
|
||||||
uint16_t duration = timestamp_end - timestamp_start;
|
uint16_t duration = timestamp_end - timestamp_start;
|
||||||
|
|
||||||
// Return when trace is full
|
// Return when trace is full
|
||||||
if (traceLen + sizeof(iLen) + sizeof(timestamp_start) + sizeof(duration) + num_paritybytes + iLen >= TRACE_SIZE) {
|
uint16_t max_traceLen = BigBuf_max_traceLen();
|
||||||
|
|
||||||
|
if (traceLen + sizeof(iLen) + sizeof(timestamp_start) + sizeof(duration) + num_paritybytes + iLen >= max_traceLen) {
|
||||||
tracing = FALSE; // don't trace any more
|
tracing = FALSE; // don't trace any more
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -504,7 +509,7 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_
|
||||||
}
|
}
|
||||||
traceLen += num_paritybytes;
|
traceLen += num_paritybytes;
|
||||||
|
|
||||||
if(traceLen +4 < TRACE_SIZE)
|
if(traceLen +4 < max_traceLen)
|
||||||
{ //If it hadn't been cleared, for whatever reason..
|
{ //If it hadn't been cleared, for whatever reason..
|
||||||
memset(trace+traceLen,0x44, 4);
|
memset(trace+traceLen,0x44, 4);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <common.h>
|
#include "common.h"
|
||||||
|
|
||||||
#define BYTEx(x, n) (((x) >> (n * 8)) & 0xff )
|
#define BYTEx(x, n) (((x) >> (n * 8)) & 0xff )
|
||||||
|
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd ">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>CFBundleDevelopmentRegion</key> <string>English</string>
|
|
||||||
<key>CFBundleIdentifier</key> <string>org.proxmark</string>
|
|
||||||
<key>CFBundleIconFile</key> <string></string>
|
|
||||||
<key>CFBundleInfoDictionaryVersion</key> <string>6.0</string>
|
|
||||||
<key>CFBundlePackageType</key> <string>KEXT</string>
|
|
||||||
<key>CFBundleSignature</key> <string>????</string>
|
|
||||||
<key>CFBundleVersion</key> <string>1.0.0</string>
|
|
||||||
<key>IOKitPersonalities</key>
|
|
||||||
<dict>
|
|
||||||
<key>Proxmark3</key>
|
|
||||||
<dict>
|
|
||||||
<key>CFBundleIdentifier</key><string>com.apple.kernel.iokit</string>
|
|
||||||
<key>IOClass</key><string>IOService</string>
|
|
||||||
<key>IOProviderClass</key><string>IOUSBInterface</string>
|
|
||||||
<key>bConfigurationValue</key> <integer>1</integer>
|
|
||||||
<key>bInterfaceNumber</key> <integer>0</integer>
|
|
||||||
<key>idProduct</key><integer>19343</integer>
|
|
||||||
<key>idVendor</key><integer>39620</integer>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>OSBundleLibraries</key>
|
|
||||||
<dict>
|
|
||||||
<key>com.apple.iokit.IOUSBFamily</key><string>1.8</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
|
@ -9,7 +9,6 @@ include ../common/Makefile.common
|
||||||
CC=gcc
|
CC=gcc
|
||||||
CXX=g++
|
CXX=g++
|
||||||
#COMMON_FLAGS = -m32
|
#COMMON_FLAGS = -m32
|
||||||
|
|
||||||
VPATH = ../common
|
VPATH = ../common
|
||||||
OBJDIR = obj
|
OBJDIR = obj
|
||||||
|
|
||||||
|
@ -17,7 +16,6 @@ LDLIBS = -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthre
|
||||||
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/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4
|
||||||
LUAPLATFORM = generic
|
LUAPLATFORM = generic
|
||||||
|
|
||||||
ifneq (,$(findstring MINGW,$(platform)))
|
ifneq (,$(findstring MINGW,$(platform)))
|
||||||
CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui
|
CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui
|
||||||
QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4
|
QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4
|
||||||
|
@ -79,6 +77,7 @@ CMDSRCS = nonce2key/crapto1.c\
|
||||||
cmdhflegic.c \
|
cmdhflegic.c \
|
||||||
cmdhficlass.c \
|
cmdhficlass.c \
|
||||||
cmdhfmf.c \
|
cmdhfmf.c \
|
||||||
|
cmdhfmfu.c \
|
||||||
cmdhw.c \
|
cmdhw.c \
|
||||||
cmdlf.c \
|
cmdlf.c \
|
||||||
cmdlfio.c \
|
cmdlfio.c \
|
||||||
|
@ -138,17 +137,6 @@ clean:
|
||||||
tarbin: $(BINS)
|
tarbin: $(BINS)
|
||||||
$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(BINS:%=client/%)
|
$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(BINS:%=client/%)
|
||||||
|
|
||||||
# must be run as root
|
|
||||||
install_kext: Info.plist
|
|
||||||
mkdir -p /System/Library/Extensions/Proxmark3.kext/Contents
|
|
||||||
cp Info.plist /System/Library/Extensions/Proxmark3.kext/Contents
|
|
||||||
chown -R root:wheel /System/Library/Extensions/Proxmark3.kext
|
|
||||||
chmod 755 /System/Library/Extensions/Proxmark3.kext /System/Library/Extensions/Proxmark3.kext/Contents
|
|
||||||
chmod 644 /System/Library/Extensions/Proxmark3.kext/Contents/Info.plist
|
|
||||||
rm -rf /System/Library/Caches/com.apple.kext.caches
|
|
||||||
touch /System/Library/Extensions
|
|
||||||
@echo "*** You may need to reboot for the kext to take effect."
|
|
||||||
|
|
||||||
lua_build:
|
lua_build:
|
||||||
@echo Compiling liblua, using platform $(LUAPLATFORM)
|
@echo Compiling liblua, using platform $(LUAPLATFORM)
|
||||||
cd ../liblua && make $(LUAPLATFORM)
|
cd ../liblua && make $(LUAPLATFORM)
|
||||||
|
|
815
client/cmddata.c
815
client/cmddata.c
File diff suppressed because it is too large
Load diff
|
@ -26,9 +26,12 @@ 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 CmdFSKdemodAWID(const char *Cmd);
|
||||||
int CmdFSKdemod(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 CmdFSKdemodPyramid(const char *Cmd);
|
||||||
int CmdFSKrawdemod(const char *Cmd);
|
int CmdFSKrawdemod(const char *Cmd);
|
||||||
int CmdDetectNRZpskClockRate(const char *Cmd);
|
int CmdDetectNRZpskClockRate(const char *Cmd);
|
||||||
int CmdpskNRZrawDemod(const char *Cmd);
|
int CmdpskNRZrawDemod(const char *Cmd);
|
||||||
|
@ -57,4 +60,6 @@ int CmdIndalaDecode(const char *Cmd);
|
||||||
extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
|
extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
|
||||||
extern int DemodBufferLen;
|
extern int DemodBufferLen;
|
||||||
|
|
||||||
|
#define BIGBUF_SIZE 40000
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "cmdhflegic.h"
|
#include "cmdhflegic.h"
|
||||||
#include "cmdhficlass.h"
|
#include "cmdhficlass.h"
|
||||||
#include "cmdhfmf.h"
|
#include "cmdhfmf.h"
|
||||||
|
#include "cmdhfmfu.h"
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
|
@ -31,8 +32,6 @@ int CmdHFTune(const char *Cmd)
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// for the time being. Need better Bigbuf handling.
|
|
||||||
#define TRACE_SIZE 3000
|
|
||||||
|
|
||||||
//The following data is taken from http://www.proxmark.org/forum/viewtopic.php?pid=13501#p13501
|
//The following data is taken from http://www.proxmark.org/forum/viewtopic.php?pid=13501#p13501
|
||||||
/*
|
/*
|
||||||
|
@ -212,7 +211,7 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
|
||||||
case ISO14443A_CMD_ANTICOLL_OR_SELECT:{
|
case ISO14443A_CMD_ANTICOLL_OR_SELECT:{
|
||||||
// 93 20 = Anticollision (usage: 9320 - answer: 4bytes UID+1byte UID-bytes-xor)
|
// 93 20 = Anticollision (usage: 9320 - answer: 4bytes UID+1byte UID-bytes-xor)
|
||||||
// 93 70 = Select (usage: 9370+5bytes 9320 answer - answer: 1byte SAK)
|
// 93 70 = Select (usage: 9370+5bytes 9320 answer - answer: 1byte SAK)
|
||||||
if(cmd[2] == 0x70)
|
if(cmd[1] == 0x70)
|
||||||
{
|
{
|
||||||
snprintf(exp,size,"SELECT_UID"); break;
|
snprintf(exp,size,"SELECT_UID"); break;
|
||||||
}else
|
}else
|
||||||
|
@ -240,8 +239,8 @@ 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"); break;
|
case MIFARE_AUTH_KEYA: snprintf(exp,size,"AUTH-A(%d)",cmd[1]); break;
|
||||||
case MIFARE_AUTH_KEYB: snprintf(exp,size,"AUTH-B"); break;
|
case MIFARE_AUTH_KEYB: snprintf(exp,size,"AUTH-B(%d)",cmd[1]); break;
|
||||||
case MIFARE_MAGICMODE: snprintf(exp,size,"MAGIC"); break;
|
case MIFARE_MAGICMODE: snprintf(exp,size,"MAGIC"); break;
|
||||||
default: snprintf(exp,size,"?"); break;
|
default: snprintf(exp,size,"?"); break;
|
||||||
}
|
}
|
||||||
|
@ -422,18 +421,18 @@ uint8_t iclass_CRC_check(bool isResponse, uint8_t* data, uint8_t len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, uint8_t protocol, bool showWaitCycles)
|
uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles)
|
||||||
{
|
{
|
||||||
bool isResponse;
|
bool isResponse;
|
||||||
uint16_t duration, data_len,parity_len;
|
uint16_t duration, data_len, parity_len;
|
||||||
|
|
||||||
uint32_t timestamp, first_timestamp, EndOfTransmissionTimestamp;
|
uint32_t timestamp, first_timestamp, EndOfTransmissionTimestamp;
|
||||||
char explanation[30] = {0};
|
char explanation[30] = {0};
|
||||||
|
|
||||||
|
if (tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) > traceLen) return traceLen;
|
||||||
|
|
||||||
first_timestamp = *((uint32_t *)(trace));
|
first_timestamp = *((uint32_t *)(trace));
|
||||||
timestamp = *((uint32_t *)(trace + tracepos));
|
timestamp = *((uint32_t *)(trace + tracepos));
|
||||||
// Break and stick with current result if buffer was not completely full
|
|
||||||
if (timestamp == 0x44444444) return TRACE_SIZE;
|
|
||||||
|
|
||||||
tracepos += 4;
|
tracepos += 4;
|
||||||
duration = *((uint16_t *)(trace + tracepos));
|
duration = *((uint16_t *)(trace + tracepos));
|
||||||
|
@ -449,8 +448,8 @@ uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, uint8_t protocol, boo
|
||||||
}
|
}
|
||||||
parity_len = (data_len-1)/8 + 1;
|
parity_len = (data_len-1)/8 + 1;
|
||||||
|
|
||||||
if (tracepos + data_len + parity_len >= TRACE_SIZE) {
|
if (tracepos + data_len + parity_len > traceLen) {
|
||||||
return TRACE_SIZE;
|
return traceLen;
|
||||||
}
|
}
|
||||||
uint8_t *frame = trace + tracepos;
|
uint8_t *frame = trace + tracepos;
|
||||||
tracepos += data_len;
|
tracepos += data_len;
|
||||||
|
@ -545,6 +544,8 @@ uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, uint8_t protocol, boo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) > traceLen) return traceLen;
|
||||||
|
|
||||||
bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000;
|
bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000;
|
||||||
|
|
||||||
if (showWaitCycles && !isResponse && next_isResponse) {
|
if (showWaitCycles && !isResponse && next_isResponse) {
|
||||||
|
@ -557,9 +558,11 @@ uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, uint8_t protocol, boo
|
||||||
(next_timestamp - EndOfTransmissionTimestamp));
|
(next_timestamp - EndOfTransmissionTimestamp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tracepos;
|
return tracepos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int CmdHFList(const char *Cmd)
|
int CmdHFList(const char *Cmd)
|
||||||
{
|
{
|
||||||
bool showWaitCycles = false;
|
bool showWaitCycles = false;
|
||||||
|
@ -599,12 +602,13 @@ int CmdHFList(const char *Cmd)
|
||||||
|
|
||||||
if (errors) {
|
if (errors) {
|
||||||
PrintAndLog("List protocol data in trace buffer.");
|
PrintAndLog("List protocol data in trace buffer.");
|
||||||
PrintAndLog("Usage: hf list [14a|14b|iclass] [f]");
|
PrintAndLog("Usage: hf list <protocol> [f]");
|
||||||
|
PrintAndLog(" f - show frame delay times as well");
|
||||||
|
PrintAndLog("Supported <protocol> values:");
|
||||||
|
PrintAndLog(" raw - just show raw data without annotations");
|
||||||
PrintAndLog(" 14a - interpret data as iso14443a communications");
|
PrintAndLog(" 14a - interpret data as iso14443a communications");
|
||||||
PrintAndLog(" 14b - interpret data as iso14443b communications");
|
PrintAndLog(" 14b - interpret data as iso14443b communications");
|
||||||
PrintAndLog(" iclass - interpret data as iclass communications");
|
PrintAndLog(" iclass - interpret data as iclass communications");
|
||||||
PrintAndLog(" raw - just show raw data");
|
|
||||||
PrintAndLog(" f - show frame delay times as well");
|
|
||||||
PrintAndLog("");
|
PrintAndLog("");
|
||||||
PrintAndLog("example: hf list 14a f");
|
PrintAndLog("example: hf list 14a f");
|
||||||
PrintAndLog("example: hf list iclass");
|
PrintAndLog("example: hf list iclass");
|
||||||
|
@ -617,11 +621,28 @@ int CmdHFList(const char *Cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t trace[TRACE_SIZE];
|
uint8_t *trace;
|
||||||
uint16_t tracepos = 0;
|
uint16_t tracepos = 0;
|
||||||
GetFromBigBuf(trace, TRACE_SIZE, 0);
|
trace = malloc(USB_CMD_DATA_SIZE);
|
||||||
WaitForResponse(CMD_ACK, NULL);
|
|
||||||
PrintAndLog("Recorded Activity");
|
// Query for the size of the trace
|
||||||
|
UsbCommand response;
|
||||||
|
GetFromBigBuf(trace, USB_CMD_DATA_SIZE, 0);
|
||||||
|
WaitForResponse(CMD_ACK, &response);
|
||||||
|
uint16_t traceLen = response.arg[2];
|
||||||
|
if (traceLen > USB_CMD_DATA_SIZE) {
|
||||||
|
uint8_t *p = realloc(trace, traceLen);
|
||||||
|
if (p == NULL) {
|
||||||
|
PrintAndLog("Cannot allocate memory for trace");
|
||||||
|
free(trace);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
trace = p;
|
||||||
|
GetFromBigBuf(trace, traceLen, 0);
|
||||||
|
WaitForResponse(CMD_ACK, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLog("Recorded Activity (TraceLen = %d bytes)", traceLen);
|
||||||
PrintAndLog("");
|
PrintAndLog("");
|
||||||
PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer");
|
PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer");
|
||||||
PrintAndLog("iso14443a - All times are in carrier periods (1/13.56Mhz)");
|
PrintAndLog("iso14443a - All times are in carrier periods (1/13.56Mhz)");
|
||||||
|
@ -630,10 +651,12 @@ int CmdHFList(const char *Cmd)
|
||||||
PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Annotation |");
|
PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Annotation |");
|
||||||
PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------|-----|--------------------|");
|
PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------|-----|--------------------|");
|
||||||
|
|
||||||
while(tracepos < TRACE_SIZE)
|
while(tracepos < traceLen)
|
||||||
{
|
{
|
||||||
tracepos = printTraceLine(tracepos, trace, protocol, showWaitCycles);
|
tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(trace);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -648,6 +671,7 @@ static command_t CommandTable[] =
|
||||||
{"legic", CmdHFLegic, 0, "{ LEGIC RFIDs... }"},
|
{"legic", CmdHFLegic, 0, "{ LEGIC RFIDs... }"},
|
||||||
{"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"},
|
{"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"},
|
||||||
{"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"},
|
{"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"},
|
||||||
|
{"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"},
|
||||||
{"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}
|
||||||
|
|
|
@ -412,9 +412,9 @@ int CmdHF14ASim(const char *Cmd)
|
||||||
PrintAndLog(" syntax: hf 14a sim <type> <uid>");
|
PrintAndLog(" syntax: hf 14a sim <type> <uid>");
|
||||||
PrintAndLog(" types: 1 = MIFARE Classic");
|
PrintAndLog(" types: 1 = MIFARE Classic");
|
||||||
PrintAndLog(" 2 = MIFARE Ultralight");
|
PrintAndLog(" 2 = MIFARE Ultralight");
|
||||||
PrintAndLog(" 3 = MIFARE DESFIRE");
|
PrintAndLog(" 3 = MIFARE Desfire");
|
||||||
PrintAndLog(" 4 = ISO/IEC 14443-4");
|
PrintAndLog(" 4 = ISO/IEC 14443-4");
|
||||||
PrintAndLog(" 5 = MIFARE TNP3XXX");
|
PrintAndLog(" 5 = MIFARE Tnp3xxx");
|
||||||
PrintAndLog("");
|
PrintAndLog("");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -480,7 +480,8 @@ int CmdHF14ASim(const char *Cmd)
|
||||||
int CmdHF14ASnoop(const char *Cmd) {
|
int CmdHF14ASnoop(const char *Cmd) {
|
||||||
int param = 0;
|
int param = 0;
|
||||||
|
|
||||||
if (param_getchar(Cmd, 0) == 'h') {
|
uint8_t ctmp = param_getchar(Cmd, 0) ;
|
||||||
|
if (ctmp == 'h' || ctmp == 'H') {
|
||||||
PrintAndLog("It get data from the field and saves it into command buffer.");
|
PrintAndLog("It get data from the field and saves it into command buffer.");
|
||||||
PrintAndLog("Buffer accessible from command hf list 14a.");
|
PrintAndLog("Buffer accessible from command hf list 14a.");
|
||||||
PrintAndLog("Usage: hf 14a snoop [c][r]");
|
PrintAndLog("Usage: hf 14a snoop [c][r]");
|
||||||
|
@ -491,7 +492,7 @@ int CmdHF14ASnoop(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
char ctmp = param_getchar(Cmd, i);
|
ctmp = param_getchar(Cmd, i);
|
||||||
if (ctmp == 'c' || ctmp == 'C') param |= 0x01;
|
if (ctmp == 'c' || ctmp == 'C') param |= 0x01;
|
||||||
if (ctmp == 'r' || ctmp == 'R') param |= 0x02;
|
if (ctmp == 'r' || ctmp == 'R') param |= 0x02;
|
||||||
}
|
}
|
||||||
|
@ -670,7 +671,7 @@ static command_t CommandTable[] =
|
||||||
{"list", CmdHF14AList, 0, "[Deprecated] List ISO 14443a history"},
|
{"list", CmdHF14AList, 0, "[Deprecated] List ISO 14443a history"},
|
||||||
{"reader", CmdHF14AReader, 0, "Act like an ISO14443 Type A reader"},
|
{"reader", CmdHF14AReader, 0, "Act like an ISO14443 Type A reader"},
|
||||||
{"cuids", CmdHF14ACUIDs, 0, "<n> Collect n>0 ISO14443 Type A UIDs in one go"},
|
{"cuids", CmdHF14ACUIDs, 0, "<n> Collect n>0 ISO14443 Type A UIDs in one go"},
|
||||||
{"sim", CmdHF14ASim, 0, "<UID> -- Fake ISO 14443a tag"},
|
{"sim", CmdHF14ASim, 0, "<UID> -- Simulate ISO 14443a tag"},
|
||||||
{"snoop", CmdHF14ASnoop, 0, "Eavesdrop ISO 14443 Type A"},
|
{"snoop", CmdHF14ASnoop, 0, "Eavesdrop ISO 14443 Type A"},
|
||||||
{"raw", CmdHF14ACmdRaw, 0, "Send raw hex data to tag"},
|
{"raw", CmdHF14ACmdRaw, 0, "Send raw hex data to tag"},
|
||||||
{NULL, NULL, 0, NULL}
|
{NULL, NULL, 0, NULL}
|
||||||
|
|
|
@ -146,6 +146,7 @@ demodError:
|
||||||
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)
|
int CmdHF14BRead(const char *Cmd)
|
||||||
|
@ -207,7 +208,7 @@ int CmdHF14BCmdRaw (const char *cmd) {
|
||||||
uint8_t power=0;
|
uint8_t power=0;
|
||||||
char buf[5]="";
|
char buf[5]="";
|
||||||
int i=0;
|
int i=0;
|
||||||
uint8_t data[100];
|
uint8_t data[100] = {0x00};
|
||||||
unsigned int datalen=0, temp;
|
unsigned int datalen=0, temp;
|
||||||
char *hexout;
|
char *hexout;
|
||||||
|
|
||||||
|
@ -261,7 +262,7 @@ int CmdHF14BCmdRaw (const char *cmd) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
PrintAndLog("Invalid char on input");
|
PrintAndLog("Invalid char on input");
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
if (datalen == 0)
|
if (datalen == 0)
|
||||||
{
|
{
|
||||||
|
@ -375,7 +376,7 @@ int CmdHF14BWrite( const char *Cmd){
|
||||||
else
|
else
|
||||||
PrintAndLog("[%s] Write block %02X [ %s ]", (isSrix4k)?"SRIX4K":"SRI512", blockno, sprint_hex(data,4) );
|
PrintAndLog("[%s] Write block %02X [ %s ]", (isSrix4k)?"SRIX4K":"SRI512", blockno, sprint_hex(data,4) );
|
||||||
|
|
||||||
sprintf(str, "-c -p 09 %02x %02x%02x%02x%02x", blockno, data[0], data[1], data[2], data[3]);
|
sprintf(str, "-c 09 %02x %02x%02x%02x%02x", blockno, data[0], data[1], data[2], data[3]);
|
||||||
|
|
||||||
CmdHF14BCmdRaw(str);
|
CmdHF14BCmdRaw(str);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
296
client/cmdhfmf.c
296
client/cmdhfmf.c
|
@ -140,117 +140,6 @@ int CmdHF14AMfWrBl(const char *Cmd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdHF14AMfUWrBl(const char *Cmd)
|
|
||||||
{
|
|
||||||
uint8_t blockNo = 0;
|
|
||||||
bool chinese_card=0;
|
|
||||||
uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
||||||
UsbCommand resp;
|
|
||||||
|
|
||||||
if (strlen(Cmd)<3) {
|
|
||||||
PrintAndLog("Usage: hf mf uwrbl <block number> <block data (8 hex symbols)> <w>");
|
|
||||||
PrintAndLog(" sample: hf mf uwrbl 0 01020304");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockNo = param_get8(Cmd, 0);
|
|
||||||
if (param_gethex(Cmd, 1, bldata, 8)) {
|
|
||||||
PrintAndLog("Block data must include 8 HEX symbols");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strchr(Cmd,'w') != 0) {
|
|
||||||
chinese_card=1;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(blockNo){
|
|
||||||
case 0:
|
|
||||||
if (!chinese_card){
|
|
||||||
PrintAndLog("Access Denied");
|
|
||||||
}else{
|
|
||||||
PrintAndLog("--specialblock no:%d", blockNo);
|
|
||||||
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
|
|
||||||
UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
|
|
||||||
memcpy(d.d.asBytes,bldata, 4);
|
|
||||||
SendCommand(&d);
|
|
||||||
|
|
||||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
|
||||||
uint8_t isOK = resp.arg[0] & 0xff;
|
|
||||||
PrintAndLog("isOk:%02x", isOK);
|
|
||||||
} else {
|
|
||||||
PrintAndLog("Command execute timeout");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
if (!chinese_card){
|
|
||||||
PrintAndLog("Access Denied");
|
|
||||||
}else{
|
|
||||||
PrintAndLog("--specialblock no:%d", blockNo);
|
|
||||||
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
|
|
||||||
UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
|
|
||||||
memcpy(d.d.asBytes,bldata, 4);
|
|
||||||
SendCommand(&d);
|
|
||||||
|
|
||||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
|
||||||
uint8_t isOK = resp.arg[0] & 0xff;
|
|
||||||
PrintAndLog("isOk:%02x", isOK);
|
|
||||||
} else {
|
|
||||||
PrintAndLog("Command execute timeout");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
if (!chinese_card){
|
|
||||||
PrintAndLog("Access Denied");
|
|
||||||
}else{
|
|
||||||
PrintAndLog("--specialblock no:%d", blockNo);
|
|
||||||
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
|
|
||||||
UsbCommand c = {CMD_MIFAREU_WRITEBL, {blockNo}};
|
|
||||||
memcpy(c.d.asBytes, bldata, 4);
|
|
||||||
SendCommand(&c);
|
|
||||||
|
|
||||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
|
||||||
uint8_t isOK = resp.arg[0] & 0xff;
|
|
||||||
PrintAndLog("isOk:%02x", isOK);
|
|
||||||
} else {
|
|
||||||
PrintAndLog("Command execute timeout");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
PrintAndLog("--specialblock no:%d", blockNo);
|
|
||||||
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
|
|
||||||
UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
|
|
||||||
memcpy(d.d.asBytes,bldata, 4);
|
|
||||||
SendCommand(&d);
|
|
||||||
|
|
||||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
|
||||||
uint8_t isOK = resp.arg[0] & 0xff;
|
|
||||||
PrintAndLog("isOk:%02x", isOK);
|
|
||||||
} else {
|
|
||||||
PrintAndLog("Command execute timeout");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PrintAndLog("--block no:%d", blockNo);
|
|
||||||
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
|
|
||||||
UsbCommand e = {CMD_MIFAREU_WRITEBL, {blockNo}};
|
|
||||||
memcpy(e.d.asBytes,bldata, 4);
|
|
||||||
SendCommand(&e);
|
|
||||||
|
|
||||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
|
||||||
uint8_t isOK = resp.arg[0] & 0xff;
|
|
||||||
PrintAndLog("isOk:%02x", isOK);
|
|
||||||
} else {
|
|
||||||
PrintAndLog("Command execute timeout");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int CmdHF14AMfRdBl(const char *Cmd)
|
int CmdHF14AMfRdBl(const char *Cmd)
|
||||||
{
|
{
|
||||||
uint8_t blockNo = 0;
|
uint8_t blockNo = 0;
|
||||||
|
@ -299,87 +188,6 @@ int CmdHF14AMfRdBl(const char *Cmd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdHF14AMfURdBl(const char *Cmd)
|
|
||||||
{
|
|
||||||
uint8_t blockNo = 0;
|
|
||||||
|
|
||||||
if (strlen(Cmd)<1) {
|
|
||||||
PrintAndLog("Usage: hf mf urdbl <block number>");
|
|
||||||
PrintAndLog(" sample: hf mf urdbl 0");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockNo = param_get8(Cmd, 0);
|
|
||||||
PrintAndLog("--block no:%d", blockNo);
|
|
||||||
|
|
||||||
UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}};
|
|
||||||
SendCommand(&c);
|
|
||||||
|
|
||||||
UsbCommand resp;
|
|
||||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
|
||||||
uint8_t isOK = resp.arg[0] & 0xff;
|
|
||||||
uint8_t *data = resp.d.asBytes;
|
|
||||||
|
|
||||||
if (isOK)
|
|
||||||
PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 4));
|
|
||||||
else
|
|
||||||
PrintAndLog("isOk:%02x", isOK);
|
|
||||||
} else {
|
|
||||||
PrintAndLog("Command execute timeout");
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int CmdHF14AMfURdCard(const char *Cmd)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
uint8_t sectorNo = 0;
|
|
||||||
uint8_t *lockbytes_t=NULL;
|
|
||||||
uint8_t lockbytes[2]={0,0};
|
|
||||||
bool bit[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
|
||||||
|
|
||||||
uint8_t isOK = 0;
|
|
||||||
uint8_t * data = NULL;
|
|
||||||
|
|
||||||
PrintAndLog("Attempting to Read Ultralight... ");
|
|
||||||
|
|
||||||
UsbCommand c = {CMD_MIFAREU_READCARD, {sectorNo}};
|
|
||||||
SendCommand(&c);
|
|
||||||
|
|
||||||
UsbCommand resp;
|
|
||||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
|
||||||
isOK = resp.arg[0] & 0xff;
|
|
||||||
data = resp.d.asBytes;
|
|
||||||
|
|
||||||
PrintAndLog("isOk:%02x", isOK);
|
|
||||||
if (isOK)
|
|
||||||
{ // bit 0 and 1
|
|
||||||
PrintAndLog("Block %3d:%s ", 0,sprint_hex(data + 0 * 4, 4));
|
|
||||||
PrintAndLog("Block %3d:%s ", 1,sprint_hex(data + 1 * 4, 4));
|
|
||||||
// bit 2
|
|
||||||
//process lock bytes
|
|
||||||
lockbytes_t=data+(2*4);
|
|
||||||
lockbytes[0]=lockbytes_t[2];
|
|
||||||
lockbytes[1]=lockbytes_t[3];
|
|
||||||
for(int j=0; j<16; j++){
|
|
||||||
bit[j]=lockbytes[j/8] & ( 1 <<(7-j%8));
|
|
||||||
}
|
|
||||||
//remaining
|
|
||||||
for (i = 3; i < 16; i++) {
|
|
||||||
int bitnum = (23-i) % 16;
|
|
||||||
PrintAndLog("Block %3d:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[bitnum]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
PrintAndLog("Command execute timeout");
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int CmdHF14AMfRdSc(const char *Cmd)
|
int CmdHF14AMfRdSc(const char *Cmd)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -970,12 +778,14 @@ int CmdHF14AMfNested(const char *Cmd)
|
||||||
int CmdHF14AMfChk(const char *Cmd)
|
int CmdHF14AMfChk(const char *Cmd)
|
||||||
{
|
{
|
||||||
if (strlen(Cmd)<3) {
|
if (strlen(Cmd)<3) {
|
||||||
PrintAndLog("Usage: hf mf chk <block number>|<*card memory> <key type (A/B/?)> [t] [<key (12 hex symbols)>] [<dic (*.dic)>]");
|
PrintAndLog("Usage: hf mf chk <block number>|<*card memory> <key type (A/B/?)> [t|d] [<key (12 hex symbols)>] [<dic (*.dic)>]");
|
||||||
PrintAndLog(" * - all sectors");
|
PrintAndLog(" * - all sectors");
|
||||||
PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K");
|
PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K");
|
||||||
PrintAndLog("d - write keys to binary file\n");
|
PrintAndLog("d - write keys to binary file\n");
|
||||||
|
PrintAndLog("t - write keys to emulator memory");
|
||||||
PrintAndLog(" sample: hf mf chk 0 A 1234567890ab keys.dic");
|
PrintAndLog(" sample: hf mf chk 0 A 1234567890ab keys.dic");
|
||||||
PrintAndLog(" hf mf chk *1 ? t");
|
PrintAndLog(" hf mf chk *1 ? t");
|
||||||
|
PrintAndLog(" hf mf chk *1 ? d");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1202,12 +1012,16 @@ int CmdHF14AMf1kSim(const char *Cmd)
|
||||||
uint8_t exitAfterNReads = 0;
|
uint8_t exitAfterNReads = 0;
|
||||||
uint8_t flags = 0;
|
uint8_t flags = 0;
|
||||||
|
|
||||||
if (param_getchar(Cmd, 0) == 'h') {
|
uint8_t cmdp = param_getchar(Cmd, 0);
|
||||||
|
|
||||||
|
if (cmdp == 'h' || cmdp == 'H') {
|
||||||
PrintAndLog("Usage: hf mf sim u <uid (8 hex symbols)> n <numreads> i x");
|
PrintAndLog("Usage: hf mf sim u <uid (8 hex symbols)> n <numreads> i x");
|
||||||
|
PrintAndLog(" h this help");
|
||||||
PrintAndLog(" u (Optional) UID. If not specified, the UID from emulator memory will be used");
|
PrintAndLog(" u (Optional) UID. If not specified, the UID from emulator memory will be used");
|
||||||
PrintAndLog(" n (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite");
|
PrintAndLog(" n (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite");
|
||||||
PrintAndLog(" i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted");
|
PrintAndLog(" i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted");
|
||||||
PrintAndLog(" x (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)");
|
PrintAndLog(" x (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)");
|
||||||
|
PrintAndLog("");
|
||||||
PrintAndLog(" sample: hf mf sim u 0a0a0a0a ");
|
PrintAndLog(" sample: hf mf sim u 0a0a0a0a ");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1288,7 +1102,7 @@ int CmdHF14AMfDbg(const char *Cmd)
|
||||||
int CmdHF14AMfEGet(const char *Cmd)
|
int CmdHF14AMfEGet(const char *Cmd)
|
||||||
{
|
{
|
||||||
uint8_t blockNo = 0;
|
uint8_t blockNo = 0;
|
||||||
uint8_t data[16];
|
uint8_t data[16] = {0x00};
|
||||||
|
|
||||||
if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {
|
if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {
|
||||||
PrintAndLog("Usage: hf mf eget <block number>");
|
PrintAndLog("Usage: hf mf eget <block number>");
|
||||||
|
@ -1355,14 +1169,11 @@ int CmdHF14AMfELoad(const char *Cmd)
|
||||||
FILE * f;
|
FILE * f;
|
||||||
char filename[FILE_PATH_SIZE];
|
char filename[FILE_PATH_SIZE];
|
||||||
char *fnameptr = filename;
|
char *fnameptr = filename;
|
||||||
char buf[64];
|
char buf[64] = {0x00};
|
||||||
uint8_t buf8[64];
|
uint8_t buf8[64] = {0x00};
|
||||||
int i, len, blockNum, numBlocks;
|
int i, len, blockNum, numBlocks;
|
||||||
int nameParamNo = 1;
|
int nameParamNo = 1;
|
||||||
|
|
||||||
memset(filename, 0, sizeof(filename));
|
|
||||||
memset(buf, 0, sizeof(buf));
|
|
||||||
|
|
||||||
char ctmp = param_getchar(Cmd, 0);
|
char ctmp = param_getchar(Cmd, 0);
|
||||||
|
|
||||||
if ( ctmp == 'h' || ctmp == 0x00) {
|
if ( ctmp == 'h' || ctmp == 0x00) {
|
||||||
|
@ -1432,11 +1243,13 @@ int CmdHF14AMfELoad(const char *Cmd)
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
printf(".");
|
||||||
blockNum++;
|
blockNum++;
|
||||||
|
|
||||||
if (blockNum >= numBlocks) break;
|
if (blockNum >= numBlocks) break;
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
if ((blockNum != numBlocks)) {
|
if ((blockNum != numBlocks)) {
|
||||||
PrintAndLog("File content error. Got %d must be %d blocks.",blockNum, numBlocks);
|
PrintAndLog("File content error. Got %d must be %d blocks.",blockNum, numBlocks);
|
||||||
|
@ -1638,7 +1451,7 @@ int CmdHF14AMfCSetUID(const char *Cmd)
|
||||||
char ctmp = param_getchar(Cmd, 1);
|
char ctmp = param_getchar(Cmd, 1);
|
||||||
if (ctmp == 'w' || ctmp == 'W') wipeCard = 1;
|
if (ctmp == 'w' || ctmp == 'W') wipeCard = 1;
|
||||||
|
|
||||||
PrintAndLog("--wipe card:%02x uid:%s", wipeCard, sprint_hex(uid, 4));
|
PrintAndLog("--wipe card:%s uid:%s", (wipeCard)?"YES":"NO", sprint_hex(uid, 4));
|
||||||
|
|
||||||
res = mfCSetUID(uid, oldUid, wipeCard);
|
res = mfCSetUID(uid, oldUid, wipeCard);
|
||||||
if (res) {
|
if (res) {
|
||||||
|
@ -1653,11 +1466,10 @@ int CmdHF14AMfCSetUID(const char *Cmd)
|
||||||
|
|
||||||
int CmdHF14AMfCSetBlk(const char *Cmd)
|
int CmdHF14AMfCSetBlk(const char *Cmd)
|
||||||
{
|
{
|
||||||
uint8_t uid[8];
|
uint8_t uid[8] = {0x00};
|
||||||
uint8_t memBlock[16];
|
uint8_t memBlock[16] = {0x00};
|
||||||
uint8_t blockNo = 0;
|
uint8_t blockNo = 0;
|
||||||
int res;
|
int res;
|
||||||
memset(memBlock, 0x00, sizeof(memBlock));
|
|
||||||
|
|
||||||
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)>");
|
||||||
|
@ -1682,7 +1494,6 @@ int CmdHF14AMfCSetBlk(const char *Cmd)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLog("UID:%s", sprint_hex(uid, 4));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1697,11 +1508,8 @@ int CmdHF14AMfCLoad(const char *Cmd)
|
||||||
uint8_t fillFromEmulator = 0;
|
uint8_t fillFromEmulator = 0;
|
||||||
int i, len, blockNum, flags;
|
int i, len, blockNum, flags;
|
||||||
|
|
||||||
// memset(filename, 0, sizeof(filename));
|
|
||||||
// memset(buf, 0, sizeof(buf));
|
|
||||||
|
|
||||||
if (param_getchar(Cmd, 0) == 'h' || param_getchar(Cmd, 0)== 0x00) {
|
if (param_getchar(Cmd, 0) == 'h' || param_getchar(Cmd, 0)== 0x00) {
|
||||||
PrintAndLog("It loads magic Chinese card (only works with!!!) from the file `filename.eml`");
|
PrintAndLog("It loads magic Chinese card from the file `filename.eml`");
|
||||||
PrintAndLog("or from emulator memory (option `e`)");
|
PrintAndLog("or from emulator memory (option `e`)");
|
||||||
PrintAndLog("Usage: hf mf cload <file name w/o `.eml`>");
|
PrintAndLog("Usage: hf mf cload <file name w/o `.eml`>");
|
||||||
PrintAndLog(" or: hf mf cload e ");
|
PrintAndLog(" or: hf mf cload e ");
|
||||||
|
@ -1748,7 +1556,9 @@ int CmdHF14AMfCLoad(const char *Cmd)
|
||||||
blockNum = 0;
|
blockNum = 0;
|
||||||
flags = CSETBLOCK_INIT_FIELD + CSETBLOCK_WUPC;
|
flags = CSETBLOCK_INIT_FIELD + CSETBLOCK_WUPC;
|
||||||
while(!feof(f)){
|
while(!feof(f)){
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
if (fgets(buf, sizeof(buf), f) == NULL) {
|
if (fgets(buf, sizeof(buf), f) == NULL) {
|
||||||
PrintAndLog("File reading error.");
|
PrintAndLog("File reading error.");
|
||||||
return 2;
|
return 2;
|
||||||
|
@ -1783,6 +1593,7 @@ int CmdHF14AMfCLoad(const char *Cmd)
|
||||||
PrintAndLog("Loaded from file: %s", filename);
|
PrintAndLog("Loaded from file: %s", filename);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdHF14AMfCGetBlk(const char *Cmd) {
|
int CmdHF14AMfCGetBlk(const char *Cmd) {
|
||||||
|
@ -1814,10 +1625,9 @@ int CmdHF14AMfCGetBlk(const char *Cmd) {
|
||||||
|
|
||||||
|
|
||||||
int CmdHF14AMfCGetSc(const char *Cmd) {
|
int CmdHF14AMfCGetSc(const char *Cmd) {
|
||||||
uint8_t memBlock[16];
|
uint8_t memBlock[16] = {0x00};
|
||||||
uint8_t sectorNo = 0;
|
uint8_t sectorNo = 0;
|
||||||
int i, res, flags;
|
int i, res, flags;
|
||||||
memset(memBlock, 0x00, sizeof(memBlock));
|
|
||||||
|
|
||||||
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>");
|
||||||
|
@ -1955,18 +1765,19 @@ int CmdHF14AMfSniff(const char *Cmd){
|
||||||
int res = 0;
|
int res = 0;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int blockLen = 0;
|
int blockLen = 0;
|
||||||
int num = 0;
|
|
||||||
int pckNum = 0;
|
int pckNum = 0;
|
||||||
|
int num = 0;
|
||||||
uint8_t uid[7];
|
uint8_t uid[7];
|
||||||
uint8_t uid_len;
|
uint8_t uid_len;
|
||||||
uint8_t atqa[2];
|
uint8_t atqa[2] = {0x00};
|
||||||
uint8_t sak;
|
uint8_t sak;
|
||||||
bool isTag;
|
bool isTag;
|
||||||
uint8_t buf[3000];
|
uint8_t *buf = NULL;
|
||||||
uint8_t * bufPtr = buf;
|
uint16_t bufsize = 0;
|
||||||
memset(buf, 0x00, 3000);
|
uint8_t *bufPtr = NULL;
|
||||||
|
|
||||||
if (param_getchar(Cmd, 0) == 'h') {
|
char ctmp = param_getchar(Cmd, 0);
|
||||||
|
if ( ctmp == 'h' || ctmp == 'H' ) {
|
||||||
PrintAndLog("It continuously gets data from the field and saves it to: log, emulator, emulator file.");
|
PrintAndLog("It continuously gets data from the field and saves it to: log, emulator, emulator file.");
|
||||||
PrintAndLog("You can specify:");
|
PrintAndLog("You can specify:");
|
||||||
PrintAndLog(" l - save encrypted sequence to logfile `uid.log`");
|
PrintAndLog(" l - save encrypted sequence to logfile `uid.log`");
|
||||||
|
@ -1979,7 +1790,7 @@ int CmdHF14AMfSniff(const char *Cmd){
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
char ctmp = param_getchar(Cmd, i);
|
ctmp = param_getchar(Cmd, i);
|
||||||
if (ctmp == 'l' || ctmp == 'L') wantLogToFile = true;
|
if (ctmp == 'l' || ctmp == 'L') wantLogToFile = true;
|
||||||
if (ctmp == 'd' || ctmp == 'D') wantDecrypt = true;
|
if (ctmp == 'd' || ctmp == 'D') wantDecrypt = true;
|
||||||
//if (ctmp == 'e' || ctmp == 'E') wantSaveToEml = true; TODO
|
//if (ctmp == 'e' || ctmp == 'E') wantSaveToEml = true; TODO
|
||||||
|
@ -2006,32 +1817,47 @@ int CmdHF14AMfSniff(const char *Cmd){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
if (WaitForResponseTimeout(CMD_ACK,&resp,2000)) {
|
if (WaitForResponseTimeout(CMD_ACK,&resp,2000)) {
|
||||||
res = resp.arg[0] & 0xff;
|
res = resp.arg[0] & 0xff;
|
||||||
len = resp.arg[1];
|
uint16_t traceLen = resp.arg[1];
|
||||||
num = resp.arg[2];
|
len = resp.arg[2];
|
||||||
|
|
||||||
if (res == 0) return 0;
|
if (res == 0) return 0; // we are done
|
||||||
if (res == 1) {
|
|
||||||
if (num ==0) {
|
if (res == 1) { // there is (more) data to be transferred
|
||||||
|
if (pckNum == 0) { // first packet, (re)allocate necessary buffer
|
||||||
|
if (traceLen > bufsize) {
|
||||||
|
uint8_t *p;
|
||||||
|
if (buf == NULL) { // not yet allocated
|
||||||
|
p = malloc(traceLen);
|
||||||
|
} else { // need more memory
|
||||||
|
p = realloc(buf, traceLen);
|
||||||
|
}
|
||||||
|
if (p == NULL) {
|
||||||
|
PrintAndLog("Cannot allocate memory for trace");
|
||||||
|
free(buf);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
buf = p;
|
||||||
|
}
|
||||||
bufPtr = buf;
|
bufPtr = buf;
|
||||||
memset(buf, 0x00, 3000);
|
bufsize = traceLen;
|
||||||
|
memset(buf, 0x00, traceLen);
|
||||||
}
|
}
|
||||||
memcpy(bufPtr, resp.d.asBytes, len);
|
memcpy(bufPtr, resp.d.asBytes, len);
|
||||||
bufPtr += len;
|
bufPtr += len;
|
||||||
pckNum++;
|
pckNum++;
|
||||||
}
|
}
|
||||||
if (res == 2) {
|
|
||||||
|
if (res == 2) { // received all data, start displaying
|
||||||
blockLen = bufPtr - buf;
|
blockLen = bufPtr - buf;
|
||||||
bufPtr = buf;
|
bufPtr = buf;
|
||||||
printf(">\n");
|
printf(">\n");
|
||||||
PrintAndLog("received trace len: %d packages: %d", blockLen, pckNum);
|
PrintAndLog("received trace len: %d packages: %d", blockLen, pckNum);
|
||||||
num = 0;
|
|
||||||
while (bufPtr - buf < blockLen) {
|
while (bufPtr - buf < blockLen) {
|
||||||
bufPtr += 6;
|
bufPtr += 6; // skip (void) timing information
|
||||||
len = *((uint16_t *)bufPtr);
|
len = *((uint16_t *)bufPtr);
|
||||||
|
|
||||||
if(len & 0x8000) {
|
if(len & 0x8000) {
|
||||||
isTag = true;
|
isTag = true;
|
||||||
len &= 0x7fff;
|
len &= 0x7fff;
|
||||||
|
@ -2040,12 +1866,10 @@ int CmdHF14AMfSniff(const char *Cmd){
|
||||||
}
|
}
|
||||||
bufPtr += 2;
|
bufPtr += 2;
|
||||||
if ((len == 14) && (bufPtr[0] == 0xff) && (bufPtr[1] == 0xff) && (bufPtr[12] == 0xff) && (bufPtr[13] == 0xff)) {
|
if ((len == 14) && (bufPtr[0] == 0xff) && (bufPtr[1] == 0xff) && (bufPtr[12] == 0xff) && (bufPtr[13] == 0xff)) {
|
||||||
|
|
||||||
memcpy(uid, bufPtr + 2, 7);
|
memcpy(uid, bufPtr + 2, 7);
|
||||||
memcpy(atqa, bufPtr + 2 + 7, 2);
|
memcpy(atqa, bufPtr + 2 + 7, 2);
|
||||||
uid_len = (atqa[0] & 0xC0) == 0x40 ? 7 : 4;
|
uid_len = (atqa[0] & 0xC0) == 0x40 ? 7 : 4;
|
||||||
sak = bufPtr[11];
|
sak = bufPtr[11];
|
||||||
|
|
||||||
PrintAndLog("tag select uid:%s atqa:0x%02x%02x sak:0x%02x",
|
PrintAndLog("tag select uid:%s atqa:0x%02x%02x sak:0x%02x",
|
||||||
sprint_hex(uid + (7 - uid_len), uid_len),
|
sprint_hex(uid + (7 - uid_len), uid_len),
|
||||||
atqa[1],
|
atqa[1],
|
||||||
|
@ -2063,26 +1887,26 @@ int CmdHF14AMfSniff(const char *Cmd){
|
||||||
AddLogHex(logHexFileName, isTag ? "TAG: ":"RDR: ", bufPtr, len);
|
AddLogHex(logHexFileName, isTag ? "TAG: ":"RDR: ", bufPtr, len);
|
||||||
if (wantDecrypt)
|
if (wantDecrypt)
|
||||||
mfTraceDecode(bufPtr, len, wantSaveToEmlFile);
|
mfTraceDecode(bufPtr, len, wantSaveToEmlFile);
|
||||||
|
num++;
|
||||||
}
|
}
|
||||||
bufPtr += len;
|
bufPtr += len;
|
||||||
bufPtr += ((len-1)/8+1); // ignore parity
|
bufPtr += ((len-1)/8+1); // ignore parity
|
||||||
num++;
|
|
||||||
}
|
}
|
||||||
|
pckNum = 0;
|
||||||
}
|
}
|
||||||
} // resp not NULL
|
} // resp not NULL
|
||||||
} // while (true)
|
} // while (true)
|
||||||
|
|
||||||
|
free(buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static command_t CommandTable[] =
|
static command_t CommandTable[] =
|
||||||
{
|
{
|
||||||
{"help", CmdHelp, 1, "This help"},
|
{"help", CmdHelp, 1, "This help"},
|
||||||
{"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},
|
{"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},
|
||||||
{"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"},
|
{"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"},
|
||||||
{"urdbl", CmdHF14AMfURdBl, 0, "Read MIFARE Ultralight block"},
|
|
||||||
{"urdcard", CmdHF14AMfURdCard, 0,"Read MIFARE Ultralight Card"},
|
|
||||||
{"uwrbl", CmdHF14AMfUWrBl, 0,"Write MIFARE Ultralight block"},
|
|
||||||
{"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"},
|
{"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"},
|
||||||
{"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"},
|
{"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"},
|
||||||
{"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"},
|
{"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"},
|
||||||
|
|
741
client/cmdhfmfu.c
Normal file
741
client/cmdhfmfu.c
Normal file
|
@ -0,0 +1,741 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Ultralight Code (c) 2013,2014 Midnitesnake & Andy Davies of Pentura
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// High frequency MIFARE ULTRALIGHT (C) commands
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//#include <openssl/des.h>
|
||||||
|
#include "loclass/des.h"
|
||||||
|
#include "cmdhfmfu.h"
|
||||||
|
#include "cmdhfmf.h"
|
||||||
|
#include "cmdhf14a.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_ULTRA_BLOCKS 0x0f
|
||||||
|
#define MAX_ULTRAC_BLOCKS 0x2f
|
||||||
|
//#define MAX_ULTRAC_BLOCKS 0x2c
|
||||||
|
|
||||||
|
|
||||||
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
|
int CmdHF14AMfUInfo(const char *Cmd){
|
||||||
|
|
||||||
|
uint8_t datatemp[7] = {0x00};
|
||||||
|
uint8_t isOK = 0;
|
||||||
|
uint8_t *data = NULL;
|
||||||
|
|
||||||
|
UsbCommand c = {CMD_MIFAREU_READCARD, {0, 4}};
|
||||||
|
SendCommand(&c);
|
||||||
|
UsbCommand resp;
|
||||||
|
|
||||||
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||||
|
isOK = resp.arg[0] & 0xff;
|
||||||
|
data = resp.d.asBytes;
|
||||||
|
|
||||||
|
if (!isOK) {
|
||||||
|
PrintAndLog("Error reading from tag");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PrintAndLog("Command execute timed out");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLog("");
|
||||||
|
PrintAndLog("-- Mifare Ultralight / Ultralight-C Tag Information ---------");
|
||||||
|
PrintAndLog("-------------------------------------------------------------");
|
||||||
|
|
||||||
|
// UID
|
||||||
|
memcpy( datatemp, data, 3);
|
||||||
|
memcpy( datatemp+3, data+4, 4);
|
||||||
|
|
||||||
|
PrintAndLog("MANUFACTURER : %s", getTagInfo(datatemp[0]));
|
||||||
|
PrintAndLog(" UID : %s ", sprint_hex(datatemp, 7));
|
||||||
|
// BBC
|
||||||
|
// CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2
|
||||||
|
int crc0 = 0x88 ^ data[0] ^ data[1] ^data[2];
|
||||||
|
if ( data[3] == crc0 )
|
||||||
|
PrintAndLog(" BCC0 : %02x - Ok", data[3]);
|
||||||
|
else
|
||||||
|
PrintAndLog(" BCC0 : %02x - crc should be %02x", data[3], crc0);
|
||||||
|
|
||||||
|
int crc1 = data[4] ^ data[5] ^ data[6] ^data[7];
|
||||||
|
if ( data[8] == crc1 )
|
||||||
|
PrintAndLog(" BCC1 : %02x - Ok", data[8]);
|
||||||
|
else
|
||||||
|
PrintAndLog(" BCC1 : %02x - crc should be %02x", data[8], crc1 );
|
||||||
|
|
||||||
|
PrintAndLog(" Internal : %s ", sprint_hex(data + 9, 1));
|
||||||
|
|
||||||
|
memcpy(datatemp, data+10, 2);
|
||||||
|
PrintAndLog(" Lock : %s - %s", sprint_hex(datatemp, 2),printBits( 2, &datatemp) );
|
||||||
|
PrintAndLog(" OneTimePad : %s ", sprint_hex(data + 3*4, 4));
|
||||||
|
PrintAndLog("");
|
||||||
|
|
||||||
|
int len = CmdHF14AMfucAuth("K 0");
|
||||||
|
// PrintAndLog("CODE: %d",len);
|
||||||
|
|
||||||
|
PrintAndLog("Seems to be a Ultralight %s", (len==0) ? "-C" :"");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Mifare Ultralight Write Single Block
|
||||||
|
//
|
||||||
|
int CmdHF14AMfUWrBl(const char *Cmd){
|
||||||
|
uint8_t blockNo = -1;
|
||||||
|
bool chinese_card = FALSE;
|
||||||
|
uint8_t bldata[16] = {0x00};
|
||||||
|
UsbCommand resp;
|
||||||
|
|
||||||
|
char cmdp = param_getchar(Cmd, 0);
|
||||||
|
if (strlen(Cmd) < 3 || cmdp == 'h' || cmdp == 'H') {
|
||||||
|
PrintAndLog("Usage: hf mfu wrbl <block number> <block data (8 hex symbols)> [w]");
|
||||||
|
PrintAndLog(" [block number]");
|
||||||
|
PrintAndLog(" [block data] - (8 hex symbols)");
|
||||||
|
PrintAndLog(" [w] - Chinese magic ultralight tag");
|
||||||
|
PrintAndLog("");
|
||||||
|
PrintAndLog(" sample: hf mfu wrbl 0 01020304");
|
||||||
|
PrintAndLog("");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockNo = param_get8(Cmd, 0);
|
||||||
|
|
||||||
|
if (blockNo > MAX_ULTRA_BLOCKS){
|
||||||
|
PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (param_gethex(Cmd, 1, bldata, 8)) {
|
||||||
|
PrintAndLog("Block data must include 8 HEX symbols");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strchr(Cmd,'w') != 0 || strchr(Cmd,'W') != 0 ) {
|
||||||
|
chinese_card = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( blockNo <= 3) {
|
||||||
|
if (!chinese_card){
|
||||||
|
PrintAndLog("Access Denied");
|
||||||
|
} else {
|
||||||
|
PrintAndLog("--specialblock no:%02x", blockNo);
|
||||||
|
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
|
||||||
|
UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
|
||||||
|
memcpy(d.d.asBytes,bldata, 4);
|
||||||
|
SendCommand(&d);
|
||||||
|
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||||
|
uint8_t isOK = resp.arg[0] & 0xff;
|
||||||
|
PrintAndLog("isOk:%02x", isOK);
|
||||||
|
} else {
|
||||||
|
PrintAndLog("Command execute timeout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PrintAndLog("--block no:%02x", blockNo);
|
||||||
|
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
|
||||||
|
UsbCommand e = {CMD_MIFAREU_WRITEBL, {blockNo}};
|
||||||
|
memcpy(e.d.asBytes,bldata, 4);
|
||||||
|
SendCommand(&e);
|
||||||
|
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||||
|
uint8_t isOK = resp.arg[0] & 0xff;
|
||||||
|
PrintAndLog("isOk:%02x", isOK);
|
||||||
|
} else {
|
||||||
|
PrintAndLog("Command execute timeout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Mifare Ultralight Read Single Block
|
||||||
|
//
|
||||||
|
int CmdHF14AMfURdBl(const char *Cmd){
|
||||||
|
|
||||||
|
uint8_t blockNo = -1;
|
||||||
|
|
||||||
|
char cmdp = param_getchar(Cmd, 0);
|
||||||
|
|
||||||
|
if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') {
|
||||||
|
PrintAndLog("Usage: hf mfu rdbl <block number>");
|
||||||
|
PrintAndLog(" sample: hfu mfu rdbl 0");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockNo = param_get8(Cmd, 0);
|
||||||
|
|
||||||
|
if (blockNo > MAX_ULTRA_BLOCKS){
|
||||||
|
PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLog("--block no:0x%02X (%d)", (int)blockNo, blockNo);
|
||||||
|
UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}};
|
||||||
|
SendCommand(&c);
|
||||||
|
|
||||||
|
UsbCommand resp;
|
||||||
|
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||||
|
uint8_t isOK = resp.arg[0] & 0xff;
|
||||||
|
uint8_t * data = resp.d.asBytes;
|
||||||
|
|
||||||
|
PrintAndLog("isOk: %02x", isOK);
|
||||||
|
|
||||||
|
if (isOK)
|
||||||
|
PrintAndLog("Data: %s", sprint_hex(data, 4));
|
||||||
|
} else {
|
||||||
|
PrintAndLog("Command execute timeout");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Mifare Ultralight / Ultralight-C; Read and Dump Card Contents
|
||||||
|
//
|
||||||
|
int CmdHF14AMfUDump(const char *Cmd){
|
||||||
|
|
||||||
|
FILE *fout;
|
||||||
|
char filename[FILE_PATH_SIZE] = {0x00};
|
||||||
|
char * fnameptr = filename;
|
||||||
|
|
||||||
|
uint8_t *lockbytes_t = NULL;
|
||||||
|
uint8_t lockbytes[2] = {0x00};
|
||||||
|
|
||||||
|
uint8_t *lockbytes_t2 = NULL;
|
||||||
|
uint8_t lockbytes2[2] = {0x00};
|
||||||
|
|
||||||
|
bool bit[16] = {0x00};
|
||||||
|
bool bit2[16] = {0x00};
|
||||||
|
|
||||||
|
int i;
|
||||||
|
uint8_t BlockNo = 0;
|
||||||
|
int Pages = 16;
|
||||||
|
|
||||||
|
bool tmplockbit = false;
|
||||||
|
uint8_t isOK = 0;
|
||||||
|
uint8_t *data = NULL;
|
||||||
|
|
||||||
|
char cmdp = param_getchar(Cmd, 0);
|
||||||
|
|
||||||
|
if (cmdp == 'h' || cmdp == 'H') {
|
||||||
|
PrintAndLog("Reads all pages from Mifare Ultralight or Ultralight-C tag.");
|
||||||
|
PrintAndLog("It saves binary dump into the file `filename.bin` or `cardUID.bin`");
|
||||||
|
PrintAndLog("Usage: hf mfu dump <c> <filename w/o .bin>");
|
||||||
|
PrintAndLog(" <c> optional cardtype c == Ultralight-C, if not defaults to Ultralight");
|
||||||
|
PrintAndLog(" sample: hf mfu dump");
|
||||||
|
PrintAndLog(" : hf mfu dump myfile");
|
||||||
|
PrintAndLog(" : hf mfu dump c myfile");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// UL or UL-C?
|
||||||
|
Pages = (cmdp == 'c' || cmdp == 'C') ? 44 : 16;
|
||||||
|
|
||||||
|
PrintAndLog("Dumping Ultralight%s Card Data...", (Pages ==16)?"":"-C");
|
||||||
|
|
||||||
|
UsbCommand c = {CMD_MIFAREU_READCARD, {BlockNo,Pages}};
|
||||||
|
SendCommand(&c);
|
||||||
|
UsbCommand resp;
|
||||||
|
|
||||||
|
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||||
|
isOK = resp.arg[0] & 0xff;
|
||||||
|
if (!isOK) {
|
||||||
|
PrintAndLog("Command error");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
data = resp.d.asBytes;
|
||||||
|
} else {
|
||||||
|
PrintAndLog("Command execute timeout");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load lock bytes.
|
||||||
|
int j = 0;
|
||||||
|
|
||||||
|
lockbytes_t = data + 8;
|
||||||
|
lockbytes[0] = lockbytes_t[2];
|
||||||
|
lockbytes[1] = lockbytes_t[3];
|
||||||
|
for(j = 0; j < 16; j++){
|
||||||
|
bit[j] = lockbytes[j/8] & ( 1 <<(7-j%8));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load bottom lockbytes if available
|
||||||
|
if ( Pages == 44 ) {
|
||||||
|
|
||||||
|
lockbytes_t2 = data + (40*4);
|
||||||
|
lockbytes2[0] = lockbytes_t2[2];
|
||||||
|
lockbytes2[1] = lockbytes_t2[3];
|
||||||
|
for (j = 0; j < 16; j++) {
|
||||||
|
bit2[j] = lockbytes2[j/8] & ( 1 <<(7-j%8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < Pages; ++i) {
|
||||||
|
|
||||||
|
if ( i < 3 ) {
|
||||||
|
PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(i){
|
||||||
|
case 3: tmplockbit = bit[4]; break;
|
||||||
|
case 4: tmplockbit = bit[3]; break;
|
||||||
|
case 5: tmplockbit = bit[2]; break;
|
||||||
|
case 6: tmplockbit = bit[1]; break;
|
||||||
|
case 7: tmplockbit = bit[0]; break;
|
||||||
|
case 8: tmplockbit = bit[15]; break;
|
||||||
|
case 9: tmplockbit = bit[14]; break;
|
||||||
|
case 10: tmplockbit = bit[13]; break;
|
||||||
|
case 11: tmplockbit = bit[12]; break;
|
||||||
|
case 12: tmplockbit = bit[11]; break;
|
||||||
|
case 13: tmplockbit = bit[10]; break;
|
||||||
|
case 14: tmplockbit = bit[9]; break;
|
||||||
|
case 15: tmplockbit = bit[8]; break;
|
||||||
|
case 16:
|
||||||
|
case 17:
|
||||||
|
case 18:
|
||||||
|
case 19: tmplockbit = bit2[6]; break;
|
||||||
|
case 20:
|
||||||
|
case 21:
|
||||||
|
case 22:
|
||||||
|
case 23: tmplockbit = bit2[5]; break;
|
||||||
|
case 24:
|
||||||
|
case 25:
|
||||||
|
case 26:
|
||||||
|
case 27: tmplockbit = bit2[4]; break;
|
||||||
|
case 28:
|
||||||
|
case 29:
|
||||||
|
case 30:
|
||||||
|
case 31: tmplockbit = bit2[2]; break;
|
||||||
|
case 32:
|
||||||
|
case 33:
|
||||||
|
case 34:
|
||||||
|
case 35: tmplockbit = bit2[1]; break;
|
||||||
|
case 36:
|
||||||
|
case 37:
|
||||||
|
case 38:
|
||||||
|
case 39: tmplockbit = bit2[0]; break;
|
||||||
|
case 40: tmplockbit = bit2[12]; break;
|
||||||
|
case 41: tmplockbit = bit2[11]; break;
|
||||||
|
case 42: tmplockbit = bit2[10]; break; //auth0
|
||||||
|
case 43: tmplockbit = bit2[9]; break; //auth1
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),tmplockbit);
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = 0;
|
||||||
|
if ( Pages == 16 )
|
||||||
|
len = param_getstr(Cmd,0,filename);
|
||||||
|
else
|
||||||
|
len = param_getstr(Cmd,1,filename);
|
||||||
|
|
||||||
|
if (len > FILE_PATH_SIZE-5) len = FILE_PATH_SIZE-5;
|
||||||
|
|
||||||
|
// user supplied filename?
|
||||||
|
if (len < 1) {
|
||||||
|
|
||||||
|
// UID = data 0-1-2 4-5-6-7 (skips a beat)
|
||||||
|
sprintf(fnameptr,"%02X%02X%02X%02X%02X%02X%02X.bin",
|
||||||
|
data[0],data[1], data[2], data[4],data[5],data[6], data[7]);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
sprintf(fnameptr + len," .bin");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ((fout = fopen(filename,"wb")) == NULL) {
|
||||||
|
PrintAndLog("Could not create file name %s", filename);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
fwrite( data, 1, Pages*4, fout );
|
||||||
|
fclose(fout);
|
||||||
|
|
||||||
|
PrintAndLog("Dumped %d pages, wrote %d bytes to %s", Pages, Pages*4, filename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Needed to Authenticate to Ultralight C tags
|
||||||
|
void rol (uint8_t *data, const size_t len){
|
||||||
|
uint8_t first = data[0];
|
||||||
|
for (size_t i = 0; i < len-1; i++) {
|
||||||
|
data[i] = data[i+1];
|
||||||
|
}
|
||||||
|
data[len-1] = first;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Ultralight C Methods
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//
|
||||||
|
// Ultralight C Authentication Demo {currently uses hard-coded key}
|
||||||
|
//
|
||||||
|
int CmdHF14AMfucAuth(const char *Cmd){
|
||||||
|
|
||||||
|
uint8_t default_keys[5][16] = {
|
||||||
|
{ 0x42,0x52,0x45,0x41,0x4b,0x4d,0x45,0x49,0x46,0x59,0x4f,0x55,0x43,0x41,0x4e,0x21 },// 3des std key
|
||||||
|
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },// all zeroes
|
||||||
|
{ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f },// 0x00-0x0F
|
||||||
|
{ 0x49,0x45,0x4D,0x4B,0x41,0x45,0x52,0x42,0x21,0x4E,0x41,0x43,0x55,0x4F,0x59,0x46 },// NFC-key
|
||||||
|
{ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 } // all ones
|
||||||
|
};
|
||||||
|
|
||||||
|
char cmdp = param_getchar(Cmd, 0);
|
||||||
|
|
||||||
|
uint8_t keyNo = 0;
|
||||||
|
bool errors = false;
|
||||||
|
//Change key to user defined one
|
||||||
|
if (cmdp == 'k' || cmdp == 'K'){
|
||||||
|
keyNo = param_get8(Cmd, 1);
|
||||||
|
if(keyNo >= 4) errors = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdp == 'h' || cmdp == 'H') {
|
||||||
|
errors = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors) {
|
||||||
|
PrintAndLog("Usage: hf mfu cauth k <key number>");
|
||||||
|
PrintAndLog(" 0 (default): 3DES standard key");
|
||||||
|
PrintAndLog(" 1 : all zeros key");
|
||||||
|
PrintAndLog(" 2 : 0x00-0x0F key");
|
||||||
|
PrintAndLog(" 3 : nfc key");
|
||||||
|
PrintAndLog(" 4 : all ones key");
|
||||||
|
PrintAndLog(" sample : hf mfu cauth k");
|
||||||
|
PrintAndLog(" : hf mfu cauth k 3");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t random_a[8] = { 1,1,1,1,1,1,1,1 };
|
||||||
|
//uint8_t enc_random_a[8] = { 0 };
|
||||||
|
uint8_t random_b[8] = { 0 };
|
||||||
|
uint8_t enc_random_b[8] = { 0 };
|
||||||
|
uint8_t random_a_and_b[16] = { 0 };
|
||||||
|
des3_context ctx = { 0 };
|
||||||
|
uint8_t *key = default_keys[keyNo];
|
||||||
|
uint8_t blockNo = 0;
|
||||||
|
uint32_t cuid = 0;
|
||||||
|
|
||||||
|
//Auth1
|
||||||
|
UsbCommand c = {CMD_MIFAREUC_AUTH1, {blockNo}};
|
||||||
|
SendCommand(&c);
|
||||||
|
UsbCommand resp;
|
||||||
|
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||||
|
uint8_t isOK = resp.arg[0] & 0xff;
|
||||||
|
cuid = resp.arg[1];
|
||||||
|
uint8_t * data= resp.d.asBytes;
|
||||||
|
|
||||||
|
if (isOK){
|
||||||
|
PrintAndLog("enc(RndB):%s", sprint_hex(data+1, 8));
|
||||||
|
memcpy(enc_random_b,data+1,8);
|
||||||
|
} else {
|
||||||
|
PrintAndLog("Auth failed");
|
||||||
|
return 2; // auth failed.
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PrintAndLog("Command execute timeout");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t iv[8] = { 0 };
|
||||||
|
// Do we need random ? Right now we use all ones, is that random enough ?
|
||||||
|
// DES_random_key(&RndA);
|
||||||
|
|
||||||
|
PrintAndLog(" RndA :%s",sprint_hex(random_a, 8));
|
||||||
|
PrintAndLog(" e_RndB:%s",sprint_hex(enc_random_b, 8));
|
||||||
|
|
||||||
|
des3_set2key_dec(&ctx, key);
|
||||||
|
|
||||||
|
des3_crypt_cbc(&ctx // des3_context *ctx
|
||||||
|
, DES_DECRYPT // int mode
|
||||||
|
, sizeof(random_b) // size_t length
|
||||||
|
, iv // unsigned char iv[8]
|
||||||
|
, enc_random_b // const unsigned char *input
|
||||||
|
, random_b // unsigned char *output
|
||||||
|
);
|
||||||
|
|
||||||
|
PrintAndLog(" RndB:%s",sprint_hex(random_b, 8));
|
||||||
|
|
||||||
|
rol(random_b,8);
|
||||||
|
memcpy(random_a_and_b ,random_a,8);
|
||||||
|
memcpy(random_a_and_b+8,random_b,8);
|
||||||
|
|
||||||
|
PrintAndLog(" RA+B:%s",sprint_hex(random_a_and_b, 16));
|
||||||
|
|
||||||
|
des3_set2key_enc(&ctx, key);
|
||||||
|
|
||||||
|
des3_crypt_cbc(&ctx // des3_context *ctx
|
||||||
|
, DES_ENCRYPT // int mode
|
||||||
|
, sizeof(random_a_and_b) // size_t length
|
||||||
|
, enc_random_b // unsigned char iv[8]
|
||||||
|
, random_a_and_b // const unsigned char *input
|
||||||
|
, random_a_and_b // unsigned char *output
|
||||||
|
);
|
||||||
|
|
||||||
|
PrintAndLog("enc(RA+B):%s",sprint_hex(random_a_and_b, 16));
|
||||||
|
|
||||||
|
//Auth2
|
||||||
|
UsbCommand d = {CMD_MIFAREUC_AUTH2, {cuid}};
|
||||||
|
memcpy(d.d.asBytes,random_a_and_b, 16);
|
||||||
|
SendCommand(&d);
|
||||||
|
|
||||||
|
UsbCommand respb;
|
||||||
|
if (WaitForResponseTimeout(CMD_ACK,&respb,1500)) {
|
||||||
|
uint8_t isOK = respb.arg[0] & 0xff;
|
||||||
|
uint8_t * data2= respb.d.asBytes;
|
||||||
|
|
||||||
|
if (isOK){
|
||||||
|
PrintAndLog("enc(RndA'):%s", sprint_hex(data2+1, 8));
|
||||||
|
} else {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
PrintAndLog("Command execute timeout");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
A test function to validate that the polarssl-function works the same
|
||||||
|
was as the openssl-implementation.
|
||||||
|
Commented out, since it requires openssl
|
||||||
|
|
||||||
|
int CmdTestDES(const char * cmd)
|
||||||
|
{
|
||||||
|
uint8_t key[16] = {0x00};
|
||||||
|
|
||||||
|
memcpy(key,key3_3des_data,16);
|
||||||
|
DES_cblock RndA, RndB;
|
||||||
|
|
||||||
|
PrintAndLog("----------OpenSSL DES implementation----------");
|
||||||
|
{
|
||||||
|
uint8_t e_RndB[8] = {0x00};
|
||||||
|
unsigned char RndARndB[16] = {0x00};
|
||||||
|
|
||||||
|
DES_cblock iv = { 0 };
|
||||||
|
DES_key_schedule ks1,ks2;
|
||||||
|
DES_cblock key1,key2;
|
||||||
|
|
||||||
|
memcpy(key,key3_3des_data,16);
|
||||||
|
memcpy(key1,key,8);
|
||||||
|
memcpy(key2,key+8,8);
|
||||||
|
|
||||||
|
|
||||||
|
DES_set_key((DES_cblock *)key1,&ks1);
|
||||||
|
DES_set_key((DES_cblock *)key2,&ks2);
|
||||||
|
|
||||||
|
DES_random_key(&RndA);
|
||||||
|
PrintAndLog(" RndA:%s",sprint_hex(RndA, 8));
|
||||||
|
PrintAndLog(" e_RndB:%s",sprint_hex(e_RndB, 8));
|
||||||
|
//void DES_ede2_cbc_encrypt(const unsigned char *input,
|
||||||
|
// unsigned char *output, long length, DES_key_schedule *ks1,
|
||||||
|
// DES_key_schedule *ks2, DES_cblock *ivec, int enc);
|
||||||
|
DES_ede2_cbc_encrypt(e_RndB,RndB,sizeof(e_RndB),&ks1,&ks2,&iv,0);
|
||||||
|
|
||||||
|
PrintAndLog(" RndB:%s",sprint_hex(RndB, 8));
|
||||||
|
rol(RndB,8);
|
||||||
|
memcpy(RndARndB,RndA,8);
|
||||||
|
memcpy(RndARndB+8,RndB,8);
|
||||||
|
PrintAndLog(" RA+B:%s",sprint_hex(RndARndB, 16));
|
||||||
|
DES_ede2_cbc_encrypt(RndARndB,RndARndB,sizeof(RndARndB),&ks1,&ks2,&e_RndB,1);
|
||||||
|
PrintAndLog("enc(RA+B):%s",sprint_hex(RndARndB, 16));
|
||||||
|
|
||||||
|
}
|
||||||
|
PrintAndLog("----------PolarSSL implementation----------");
|
||||||
|
{
|
||||||
|
uint8_t random_a[8] = { 0 };
|
||||||
|
uint8_t enc_random_a[8] = { 0 };
|
||||||
|
uint8_t random_b[8] = { 0 };
|
||||||
|
uint8_t enc_random_b[8] = { 0 };
|
||||||
|
uint8_t random_a_and_b[16] = { 0 };
|
||||||
|
des3_context ctx = { 0 };
|
||||||
|
|
||||||
|
memcpy(random_a, RndA,8);
|
||||||
|
|
||||||
|
uint8_t output[8] = { 0 };
|
||||||
|
uint8_t iv[8] = { 0 };
|
||||||
|
|
||||||
|
PrintAndLog(" RndA :%s",sprint_hex(random_a, 8));
|
||||||
|
PrintAndLog(" e_RndB:%s",sprint_hex(enc_random_b, 8));
|
||||||
|
|
||||||
|
des3_set2key_dec(&ctx, key);
|
||||||
|
|
||||||
|
des3_crypt_cbc(&ctx // des3_context *ctx
|
||||||
|
, DES_DECRYPT // int mode
|
||||||
|
, sizeof(random_b) // size_t length
|
||||||
|
, iv // unsigned char iv[8]
|
||||||
|
, enc_random_b // const unsigned char *input
|
||||||
|
, random_b // unsigned char *output
|
||||||
|
);
|
||||||
|
|
||||||
|
PrintAndLog(" RndB:%s",sprint_hex(random_b, 8));
|
||||||
|
|
||||||
|
rol(random_b,8);
|
||||||
|
memcpy(random_a_and_b ,random_a,8);
|
||||||
|
memcpy(random_a_and_b+8,random_b,8);
|
||||||
|
|
||||||
|
PrintAndLog(" RA+B:%s",sprint_hex(random_a_and_b, 16));
|
||||||
|
|
||||||
|
des3_set2key_enc(&ctx, key);
|
||||||
|
|
||||||
|
des3_crypt_cbc(&ctx // des3_context *ctx
|
||||||
|
, DES_ENCRYPT // int mode
|
||||||
|
, sizeof(random_a_and_b) // size_t length
|
||||||
|
, enc_random_b // unsigned char iv[8]
|
||||||
|
, random_a_and_b // const unsigned char *input
|
||||||
|
, random_a_and_b // unsigned char *output
|
||||||
|
);
|
||||||
|
|
||||||
|
PrintAndLog("enc(RA+B):%s",sprint_hex(random_a_and_b, 16));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
**/
|
||||||
|
//
|
||||||
|
// Ultralight C Read Single Block
|
||||||
|
//
|
||||||
|
int CmdHF14AMfUCRdBl(const char *Cmd)
|
||||||
|
{
|
||||||
|
uint8_t blockNo = -1;
|
||||||
|
char cmdp = param_getchar(Cmd, 0);
|
||||||
|
|
||||||
|
if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') {
|
||||||
|
PrintAndLog("Usage: hf mfu crdbl <block number>");
|
||||||
|
PrintAndLog(" sample: hf mfu crdbl 0");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockNo = param_get8(Cmd, 0);
|
||||||
|
if (blockNo < 0) {
|
||||||
|
PrintAndLog("Wrong block number");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blockNo > MAX_ULTRAC_BLOCKS ){
|
||||||
|
PrintAndLog("Error: Maximum number of readable blocks is 47 for Ultralight-C Cards!");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLog("--block no: 0x%02X (%d)", (int)blockNo, blockNo);
|
||||||
|
|
||||||
|
//Read Block
|
||||||
|
UsbCommand e = {CMD_MIFAREU_READBL, {blockNo}};
|
||||||
|
SendCommand(&e);
|
||||||
|
UsbCommand resp_c;
|
||||||
|
if (WaitForResponseTimeout(CMD_ACK,&resp_c,1500)) {
|
||||||
|
uint8_t isOK = resp_c.arg[0] & 0xff;
|
||||||
|
uint8_t *data = resp_c.d.asBytes;
|
||||||
|
|
||||||
|
PrintAndLog("isOk: %02x", isOK);
|
||||||
|
if (isOK)
|
||||||
|
PrintAndLog("Data: %s", sprint_hex(data, 4));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
PrintAndLog("Command execute timeout");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Mifare Ultralight C Write Single Block
|
||||||
|
//
|
||||||
|
int CmdHF14AMfUCWrBl(const char *Cmd){
|
||||||
|
|
||||||
|
uint8_t blockNo = -1;
|
||||||
|
bool chinese_card = FALSE;
|
||||||
|
uint8_t bldata[16] = {0x00};
|
||||||
|
UsbCommand resp;
|
||||||
|
|
||||||
|
char cmdp = param_getchar(Cmd, 0);
|
||||||
|
|
||||||
|
if (strlen(Cmd) < 3 || cmdp == 'h' || cmdp == 'H') {
|
||||||
|
PrintAndLog("Usage: hf mfu cwrbl <block number> <block data (8 hex symbols)> [w]");
|
||||||
|
PrintAndLog(" [block number]");
|
||||||
|
PrintAndLog(" [block data] - (8 hex symbols)");
|
||||||
|
PrintAndLog(" [w] - Chinese magic ultralight tag");
|
||||||
|
PrintAndLog("");
|
||||||
|
PrintAndLog(" sample: hf mfu cwrbl 0 01020304");
|
||||||
|
PrintAndLog("");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockNo = param_get8(Cmd, 0);
|
||||||
|
if (blockNo > MAX_ULTRAC_BLOCKS ){
|
||||||
|
PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight-C Cards!");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (param_gethex(Cmd, 1, bldata, 8)) {
|
||||||
|
PrintAndLog("Block data must include 8 HEX symbols");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strchr(Cmd,'w') != 0 || strchr(Cmd,'W') != 0 ) {
|
||||||
|
chinese_card = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( blockNo <= 3 ) {
|
||||||
|
if (!chinese_card){
|
||||||
|
PrintAndLog("Access Denied");
|
||||||
|
} else {
|
||||||
|
PrintAndLog("--Special block no: 0x%02x", blockNo);
|
||||||
|
PrintAndLog("--Data: %s", sprint_hex(bldata, 4));
|
||||||
|
UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
|
||||||
|
memcpy(d.d.asBytes,bldata, 4);
|
||||||
|
SendCommand(&d);
|
||||||
|
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||||
|
uint8_t isOK = resp.arg[0] & 0xff;
|
||||||
|
PrintAndLog("isOk:%02x", isOK);
|
||||||
|
} else {
|
||||||
|
PrintAndLog("Command execute timeout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PrintAndLog("--Block no : 0x%02x", blockNo);
|
||||||
|
PrintAndLog("--Data: %s", sprint_hex(bldata, 4));
|
||||||
|
UsbCommand e = {CMD_MIFAREU_WRITEBL, {blockNo}};
|
||||||
|
memcpy(e.d.asBytes,bldata, 4);
|
||||||
|
SendCommand(&e);
|
||||||
|
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||||
|
uint8_t isOK = resp.arg[0] & 0xff;
|
||||||
|
PrintAndLog("isOk : %02x", isOK);
|
||||||
|
} else {
|
||||||
|
PrintAndLog("Command execute timeout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
// Menu Stuff
|
||||||
|
//------------------------------------
|
||||||
|
static command_t CommandTable[] =
|
||||||
|
{
|
||||||
|
{"help", CmdHelp, 1,"This help"},
|
||||||
|
{"dbg", CmdHF14AMfDbg, 0,"Set default debug mode"},
|
||||||
|
{"info", CmdHF14AMfUInfo, 0,"Taginfo"},
|
||||||
|
{"dump", CmdHF14AMfUDump, 0,"Dump MIFARE Ultralight / Ultralight-C tag to binary file"},
|
||||||
|
{"rdbl", CmdHF14AMfURdBl, 0,"Read block - MIFARE Ultralight"},
|
||||||
|
{"wrbl", CmdHF14AMfUWrBl, 0,"Write block - MIFARE Ultralight"},
|
||||||
|
{"crdbl", CmdHF14AMfUCRdBl, 0,"Read block - MIFARE Ultralight C"},
|
||||||
|
{"cwrbl", CmdHF14AMfUCWrBl, 0,"Write MIFARE Ultralight C block"},
|
||||||
|
{"cauth", CmdHF14AMfucAuth, 0,"try a Ultralight C Authentication"},
|
||||||
|
//{"testdes", CmdTestDES , 1, "Test DES"},
|
||||||
|
{NULL, NULL, 0, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
int CmdHFMFUltra(const char *Cmd){
|
||||||
|
WaitForResponseTimeout(CMD_ACK,NULL,100);
|
||||||
|
CmdsParse(CommandTable, Cmd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CmdHelp(const char *Cmd){
|
||||||
|
CmdsHelp(CommandTable);
|
||||||
|
return 0;
|
||||||
|
}
|
19
client/cmdhfmfu.h
Normal file
19
client/cmdhfmfu.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#include "cmdhfmf.h"
|
||||||
|
#include "cmdhf14a.h"
|
||||||
|
|
||||||
|
//standard ultralight
|
||||||
|
int CmdHF14AMfUWrBl(const char *Cmd);
|
||||||
|
int CmdHF14AMfURdBl(const char *Cmd);
|
||||||
|
|
||||||
|
//Crypto Cards
|
||||||
|
int CmdHF14AMfUCRdBl(const char *Cmd);
|
||||||
|
int CmdHF14AMfUCRdCard(const char *Cmd);
|
||||||
|
int CmdHF14AMfucAuth(const char *Cmd);
|
||||||
|
|
||||||
|
//general stuff
|
||||||
|
int CmdHF14AMfUDump(const char *Cmd);
|
||||||
|
void rol (uint8_t *data, const size_t len);
|
||||||
|
|
||||||
|
|
||||||
|
int CmdHFMFUltra(const char *Cmd);
|
||||||
|
int CmdHF14AMfUInfo(const char *Cmd);
|
217
client/cmdlf.c
217
client/cmdlf.c
|
@ -356,24 +356,155 @@ int CmdIndalaClone(const char *Cmd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int usage_lf_read()
|
||||||
|
{
|
||||||
|
PrintAndLog("Usage: lf read");
|
||||||
|
PrintAndLog("Options: ");
|
||||||
|
PrintAndLog(" h This help");
|
||||||
|
PrintAndLog("This function takes no arguments. ");
|
||||||
|
PrintAndLog("Use 'lf config' to set parameters.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int usage_lf_snoop()
|
||||||
|
{
|
||||||
|
PrintAndLog("Usage: lf snoop");
|
||||||
|
PrintAndLog("Options: ");
|
||||||
|
PrintAndLog(" h This help");
|
||||||
|
PrintAndLog("This function takes no arguments. ");
|
||||||
|
PrintAndLog("Use 'lf config' to set parameters.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usage_lf_config()
|
||||||
|
{
|
||||||
|
PrintAndLog("Usage: lf config [H|<divisor>] [b <bps>] [d <decim>] [a 0|1]");
|
||||||
|
PrintAndLog("Options: ");
|
||||||
|
PrintAndLog(" h This help");
|
||||||
|
PrintAndLog(" L Low frequency (125 KHz)");
|
||||||
|
PrintAndLog(" H High frequency (134 KHz)");
|
||||||
|
PrintAndLog(" q <divisor> Manually set divisor. 88-> 134KHz, 95-> 125 Hz");
|
||||||
|
PrintAndLog(" b <bps> Sets resolution of bits per sample. Default (max): 8");
|
||||||
|
PrintAndLog(" d <decim> Sets decimation. A value of N saves only 1 in N samples. Default: 1");
|
||||||
|
PrintAndLog(" a [0|1] Averaging - if set, will average the stored sample value when decimating. Default: 1");
|
||||||
|
PrintAndLog(" t <threshold> Sets trigger threshold. 0 means no threshold");
|
||||||
|
PrintAndLog("Examples:");
|
||||||
|
PrintAndLog(" lf config b 8 L");
|
||||||
|
PrintAndLog(" Samples at 125KHz, 8bps.");
|
||||||
|
PrintAndLog(" lf config H b 4 d 3");
|
||||||
|
PrintAndLog(" Samples at 134KHz, averages three samples into one, stored with ");
|
||||||
|
PrintAndLog(" a resolution of 4 bits per sample.");
|
||||||
|
PrintAndLog(" lf read");
|
||||||
|
PrintAndLog(" Performs a read (active field)");
|
||||||
|
PrintAndLog(" lf snoop");
|
||||||
|
PrintAndLog(" Performs a snoop (no active field)");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CmdLFSetConfig(const char *Cmd)
|
||||||
|
{
|
||||||
|
|
||||||
|
uint8_t divisor = 0;//Frequency divisor
|
||||||
|
uint8_t bps = 0; // Bits per sample
|
||||||
|
uint8_t decimation = 0; //How many to keep
|
||||||
|
bool averaging = 1; // Defaults to true
|
||||||
|
bool errors = FALSE;
|
||||||
|
int trigger_threshold =-1;//Means no change
|
||||||
|
uint8_t unsigned_trigg = 0;
|
||||||
|
|
||||||
|
uint8_t cmdp =0;
|
||||||
|
while(param_getchar(Cmd, cmdp) != 0x00)
|
||||||
|
{
|
||||||
|
PrintAndLog("working %c", param_getchar(Cmd, cmdp));
|
||||||
|
switch(param_getchar(Cmd, cmdp))
|
||||||
|
{
|
||||||
|
case 'h':
|
||||||
|
return usage_lf_config();
|
||||||
|
case 'H':
|
||||||
|
divisor = 88;
|
||||||
|
cmdp++;
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
divisor = 95;
|
||||||
|
cmdp++;
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
errors |= param_getdec(Cmd,cmdp+1,&divisor);
|
||||||
|
cmdp+=2;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
errors |= param_getdec(Cmd,cmdp+1,&unsigned_trigg);
|
||||||
|
cmdp+=2;
|
||||||
|
if(!errors) trigger_threshold = unsigned_trigg;
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
errors |= param_getdec(Cmd,cmdp+1,&bps);
|
||||||
|
cmdp+=2;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
errors |= param_getdec(Cmd,cmdp+1,&decimation);
|
||||||
|
cmdp+=2;
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
averaging = param_getchar(Cmd,cmdp+1) == '1';
|
||||||
|
cmdp+=2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||||
|
errors = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(errors) break;
|
||||||
|
}
|
||||||
|
if(cmdp == 0)
|
||||||
|
{
|
||||||
|
errors = 1;// No args
|
||||||
|
}
|
||||||
|
|
||||||
|
//Validations
|
||||||
|
if(errors)
|
||||||
|
{
|
||||||
|
return usage_lf_config();
|
||||||
|
}
|
||||||
|
//Bps is limited to 8, so fits in lower half of arg1
|
||||||
|
if(bps >> 8) bps = 8;
|
||||||
|
|
||||||
|
sample_config config = {
|
||||||
|
decimation,bps,averaging,divisor,trigger_threshold
|
||||||
|
};
|
||||||
|
//Averaging is a flag on high-bit of arg[1]
|
||||||
|
UsbCommand c = {CMD_SET_LF_SAMPLING_CONFIG};
|
||||||
|
memcpy(c.d.asBytes,&config,sizeof(sample_config));
|
||||||
|
SendCommand(&c);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int CmdLFRead(const char *Cmd)
|
int CmdLFRead(const char *Cmd)
|
||||||
{
|
{
|
||||||
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K};
|
|
||||||
|
|
||||||
// 'h' means higher-low-frequency, 134 kHz
|
uint8_t cmdp =0;
|
||||||
if(*Cmd == 'h') {
|
if(param_getchar(Cmd, cmdp) == 'h')
|
||||||
c.arg[0] = 1;
|
{
|
||||||
} else if (*Cmd == '\0') {
|
return usage_lf_read();
|
||||||
c.arg[0] = 0;
|
}
|
||||||
} else if (sscanf(Cmd, "%"lli, &c.arg[0]) != 1) {
|
//And ship it to device
|
||||||
PrintAndLog("Samples 1: 'lf read'");
|
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K};
|
||||||
PrintAndLog(" 2: 'lf read h'");
|
SendCommand(&c);
|
||||||
PrintAndLog(" 3: 'lf read <divisor>'");
|
WaitForResponse(CMD_ACK,NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
SendCommand(&c);
|
|
||||||
WaitForResponse(CMD_ACK,NULL);
|
int CmdLFSnoop(const char *Cmd)
|
||||||
return 0;
|
{
|
||||||
|
uint8_t cmdp =0;
|
||||||
|
if(param_getchar(Cmd, cmdp) == 'h')
|
||||||
|
{
|
||||||
|
return usage_lf_snoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES};
|
||||||
|
SendCommand(&c);
|
||||||
|
WaitForResponse(CMD_ACK,NULL);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ChkBitstream(const char *str)
|
static void ChkBitstream(const char *str)
|
||||||
|
@ -388,7 +519,7 @@ static void ChkBitstream(const char *str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//appears to attempt to simulate manchester
|
||||||
int CmdLFSim(const char *Cmd)
|
int CmdLFSim(const char *Cmd)
|
||||||
{
|
{
|
||||||
int i,j;
|
int i,j;
|
||||||
|
@ -450,30 +581,6 @@ int CmdLFSimManchester(const char *Cmd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdLFSnoop(const char *Cmd)
|
|
||||||
{
|
|
||||||
UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES};
|
|
||||||
|
|
||||||
// 'h' means higher-low-frequency, 134 kHz
|
|
||||||
c.arg[0] = 0;
|
|
||||||
c.arg[1] = -1;
|
|
||||||
|
|
||||||
if (*Cmd == 'l') {
|
|
||||||
sscanf(Cmd, "l %"lli, &c.arg[1]);
|
|
||||||
} else if(*Cmd == 'h') {
|
|
||||||
c.arg[0] = 1;
|
|
||||||
sscanf(Cmd, "h %"lli, &c.arg[1]);
|
|
||||||
} else if (sscanf(Cmd, "%"lli" %"lli, &c.arg[0], &c.arg[1]) < 1) {
|
|
||||||
PrintAndLog("usage 1: snoop");
|
|
||||||
PrintAndLog(" 2: snoop {l,h} [trigger threshold]");
|
|
||||||
PrintAndLog(" 3: snoop <divisor> [trigger threshold]");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SendCommand(&c);
|
|
||||||
WaitForResponse(CMD_ACK,NULL);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CmdVchDemod(const char *Cmd)
|
int CmdVchDemod(const char *Cmd)
|
||||||
{
|
{
|
||||||
|
@ -575,26 +682,41 @@ int CmdLFfind(const char *Cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLog("NOTE: some demods output possible binary\n if it finds something that looks like a tag");
|
PrintAndLog("NOTE: some demods output possible binary\n if it finds something that looks like a tag");
|
||||||
PrintAndLog("Checking for known tags:");
|
PrintAndLog("\nChecking for known tags:\n");
|
||||||
ans=CmdFSKdemodIO("");
|
ans=CmdFSKdemodIO("");
|
||||||
if (ans>0) {
|
if (ans>0) {
|
||||||
PrintAndLog("Valid IO Prox ID Found!");
|
PrintAndLog("\nValid IO Prox ID Found!");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
ans=CmdFSKdemodPyramid("");
|
||||||
|
if (ans>0) {
|
||||||
|
PrintAndLog("\nValid Pyramid ID Found!");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
ans=CmdFSKdemodParadox("");
|
||||||
|
if (ans>0) {
|
||||||
|
PrintAndLog("\nValid Paradox ID Found!");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
ans=CmdFSKdemodAWID("");
|
||||||
|
if (ans>0) {
|
||||||
|
PrintAndLog("\nValid AWID ID Found!");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
ans=CmdFSKdemodHID("");
|
ans=CmdFSKdemodHID("");
|
||||||
if (ans>0) {
|
if (ans>0) {
|
||||||
PrintAndLog("Valid HID Prox ID Found!");
|
PrintAndLog("\nValid HID Prox ID Found!");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
//add psk and indala
|
//add psk and indala
|
||||||
ans=CmdIndalaDecode("0");
|
ans=CmdIndalaDecode("");
|
||||||
if (ans>0) {
|
if (ans>0) {
|
||||||
PrintAndLog("Valid Indala ID Found!");
|
PrintAndLog("\nValid Indala ID Found!");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
ans=Cmdaskmandemod("");
|
ans=Cmdaskmandemod("");
|
||||||
if (ans>0) {
|
if (ans>0) {
|
||||||
PrintAndLog("Valid EM410x ID Found!");
|
PrintAndLog("\nValid EM410x ID Found!");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
PrintAndLog("No Known Tags Found!\n");
|
PrintAndLog("No Known Tags Found!\n");
|
||||||
|
@ -606,12 +728,13 @@ static command_t CommandTable[] =
|
||||||
{"help", CmdHelp, 1, "This help"},
|
{"help", CmdHelp, 1, "This help"},
|
||||||
{"cmdread", CmdLFCommandRead, 0, "<off period> <'0' period> <'1' period> <command> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"},
|
{"cmdread", CmdLFCommandRead, 0, "<off period> <'0' period> <'1' period> <command> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"},
|
||||||
{"em4x", CmdLFEM4X, 1, "{ EM4X RFIDs... }"},
|
{"em4x", CmdLFEM4X, 1, "{ EM4X RFIDs... }"},
|
||||||
|
{"config", CmdLFSetConfig, 0, "Set config for LF sampling, bit/sample, decimation, frequency"},
|
||||||
{"flexdemod", CmdFlexdemod, 1, "Demodulate samples for FlexPass"},
|
{"flexdemod", CmdFlexdemod, 1, "Demodulate samples for FlexPass"},
|
||||||
{"hid", CmdLFHID, 1, "{ HID RFIDs... }"},
|
{"hid", CmdLFHID, 1, "{ HID RFIDs... }"},
|
||||||
{"io", CmdLFIO, 1, "{ ioProx tags... }"},
|
{"io", CmdLFIO, 1, "{ ioProx tags... }"},
|
||||||
{"indalademod", CmdIndalaDemod, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
|
{"indalademod", CmdIndalaDemod, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
|
||||||
{"indalaclone", CmdIndalaClone, 0, "<UID> ['l']-- Clone Indala to T55x7 (tag must be in antenna)(UID in HEX)(option 'l' for 224 UID"},
|
{"indalaclone", CmdIndalaClone, 0, "<UID> ['l']-- Clone Indala to T55x7 (tag must be in antenna)(UID in HEX)(option 'l' for 224 UID"},
|
||||||
{"read", CmdLFRead, 0, "['h' or <divisor>] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134, alternatively: f=12MHz/(divisor+1))"},
|
{"read", CmdLFRead, 0, "Read 125/134 kHz LF ID-only tag. Do 'lf read h' for help"},
|
||||||
{"search", CmdLFfind, 1, "Read and Search for valid known tag (in offline mode it you can load first then search)"},
|
{"search", CmdLFfind, 1, "Read and Search for valid known tag (in offline mode it you can load first then search)"},
|
||||||
{"sim", CmdLFSim, 0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"},
|
{"sim", CmdLFSim, 0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"},
|
||||||
{"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)"},
|
||||||
|
|
|
@ -29,110 +29,125 @@ size_t nbytes(size_t nbits) {
|
||||||
|
|
||||||
int CmdLFHitagList(const char *Cmd)
|
int CmdLFHitagList(const char *Cmd)
|
||||||
{
|
{
|
||||||
uint8_t got[TRACE_BUFFER_SIZE];
|
uint8_t *got = malloc(USB_CMD_DATA_SIZE);
|
||||||
GetFromBigBuf(got,sizeof(got),0);
|
|
||||||
WaitForResponse(CMD_ACK,NULL);
|
|
||||||
|
|
||||||
PrintAndLog("recorded activity:");
|
// Query for the actual size of the trace
|
||||||
PrintAndLog(" ETU :nbits: who bytes");
|
UsbCommand response;
|
||||||
PrintAndLog("---------+-----+----+-----------");
|
GetFromBigBuf(got, USB_CMD_DATA_SIZE, 0);
|
||||||
|
WaitForResponse(CMD_ACK, &response);
|
||||||
int i = 0;
|
uint16_t traceLen = response.arg[2];
|
||||||
int prev = -1;
|
if (traceLen > USB_CMD_DATA_SIZE) {
|
||||||
int len = strlen(Cmd);
|
uint8_t *p = realloc(got, traceLen);
|
||||||
|
if (p == NULL) {
|
||||||
char filename[FILE_PATH_SIZE] = { 0x00 };
|
PrintAndLog("Cannot allocate memory for trace");
|
||||||
FILE* pf = NULL;
|
free(got);
|
||||||
|
return 2;
|
||||||
if (len > FILE_PATH_SIZE)
|
}
|
||||||
len = FILE_PATH_SIZE;
|
got = p;
|
||||||
memcpy(filename, Cmd, len);
|
GetFromBigBuf(got, traceLen, 0);
|
||||||
|
WaitForResponse(CMD_ACK,NULL);
|
||||||
if (strlen(filename) > 0) {
|
|
||||||
if ((pf = fopen(filename,"wb")) == NULL) {
|
|
||||||
PrintAndLog("Error: Could not open file [%s]",filename);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
PrintAndLog("recorded activity (TraceLen = %d bytes):");
|
||||||
|
PrintAndLog(" ETU :nbits: who bytes");
|
||||||
|
PrintAndLog("---------+-----+----+-----------");
|
||||||
|
|
||||||
if(i >= TRACE_BUFFER_SIZE) { break; }
|
int i = 0;
|
||||||
|
int prev = -1;
|
||||||
|
int len = strlen(Cmd);
|
||||||
|
|
||||||
bool isResponse;
|
char filename[FILE_PATH_SIZE] = { 0x00 };
|
||||||
int timestamp = *((uint32_t *)(got+i));
|
FILE* pf = NULL;
|
||||||
if (timestamp & 0x80000000) {
|
|
||||||
timestamp &= 0x7fffffff;
|
|
||||||
isResponse = 1;
|
|
||||||
} else {
|
|
||||||
isResponse = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int parityBits = *((uint32_t *)(got+i+4));
|
if (len > FILE_PATH_SIZE)
|
||||||
// 4 bytes of additional information...
|
len = FILE_PATH_SIZE;
|
||||||
// maximum of 32 additional parity bit information
|
memcpy(filename, Cmd, len);
|
||||||
//
|
|
||||||
// TODO:
|
|
||||||
// at each quarter bit period we can send power level (16 levels)
|
|
||||||
// or each half bit period in 256 levels.
|
|
||||||
|
|
||||||
int bits = got[i+8];
|
if (strlen(filename) > 0) {
|
||||||
int len = nbytes(got[i+8]);
|
if ((pf = fopen(filename,"wb")) == NULL) {
|
||||||
|
PrintAndLog("Error: Could not open file [%s]",filename);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (len > 100) {
|
for (;;) {
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i + len >= TRACE_BUFFER_SIZE) { break;}
|
|
||||||
|
|
||||||
uint8_t *frame = (got+i+9);
|
if(i > traceLen) { break; }
|
||||||
|
|
||||||
// Break and stick with current result if buffer was not completely full
|
bool isResponse;
|
||||||
if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }
|
int timestamp = *((uint32_t *)(got+i));
|
||||||
|
if (timestamp & 0x80000000) {
|
||||||
|
timestamp &= 0x7fffffff;
|
||||||
|
isResponse = 1;
|
||||||
|
} else {
|
||||||
|
isResponse = 0;
|
||||||
|
}
|
||||||
|
|
||||||
char line[1000] = "";
|
int parityBits = *((uint32_t *)(got+i+4));
|
||||||
int j;
|
// 4 bytes of additional information...
|
||||||
for (j = 0; j < len; j++) {
|
// maximum of 32 additional parity bit information
|
||||||
int oddparity = 0x01;
|
//
|
||||||
int k;
|
// TODO:
|
||||||
|
// at each quarter bit period we can send power level (16 levels)
|
||||||
|
// or each half bit period in 256 levels.
|
||||||
|
|
||||||
for (k=0;k<8;k++) {
|
int bits = got[i+8];
|
||||||
oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
|
int len = nbytes(got[i+8]);
|
||||||
}
|
|
||||||
|
|
||||||
//if((parityBits >> (len - j - 1)) & 0x01) {
|
if (len > 100) {
|
||||||
if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
|
break;
|
||||||
sprintf(line+(j*4), "%02x! ", frame[j]);
|
}
|
||||||
}
|
if (i + len > traceLen) { break;}
|
||||||
else {
|
|
||||||
sprintf(line+(j*4), "%02x ", frame[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PrintAndLog(" +%7d: %3d: %s %s",
|
uint8_t *frame = (got+i+9);
|
||||||
(prev < 0 ? 0 : (timestamp - prev)),
|
|
||||||
bits,
|
|
||||||
(isResponse ? "TAG" : " "),
|
|
||||||
line);
|
|
||||||
|
|
||||||
|
// Break and stick with current result if buffer was not completely full
|
||||||
|
if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }
|
||||||
|
|
||||||
if (pf) {
|
char line[1000] = "";
|
||||||
fprintf(pf," +%7d: %3d: %s %s\n",
|
int j;
|
||||||
(prev < 0 ? 0 : (timestamp - prev)),
|
for (j = 0; j < len; j++) {
|
||||||
bits,
|
int oddparity = 0x01;
|
||||||
(isResponse ? "TAG" : " "),
|
int k;
|
||||||
line);
|
|
||||||
}
|
|
||||||
|
|
||||||
prev = timestamp;
|
for (k=0;k<8;k++) {
|
||||||
i += (len + 9);
|
oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pf) {
|
//if((parityBits >> (len - j - 1)) & 0x01) {
|
||||||
fclose(pf);
|
if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
|
||||||
PrintAndLog("Recorded activity succesfully written to file: %s", filename);
|
sprintf(line+(j*4), "%02x! ", frame[j]);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
sprintf(line+(j*4), "%02x ", frame[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
PrintAndLog(" +%7d: %3d: %s %s",
|
||||||
|
(prev < 0 ? 0 : (timestamp - prev)),
|
||||||
|
bits,
|
||||||
|
(isResponse ? "TAG" : " "),
|
||||||
|
line);
|
||||||
|
|
||||||
|
if (pf) {
|
||||||
|
fprintf(pf," +%7d: %3d: %s %s\n",
|
||||||
|
(prev < 0 ? 0 : (timestamp - prev)),
|
||||||
|
bits,
|
||||||
|
(isResponse ? "TAG" : " "),
|
||||||
|
line);
|
||||||
|
}
|
||||||
|
|
||||||
|
prev = timestamp;
|
||||||
|
i += (len + 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pf) {
|
||||||
|
fclose(pf);
|
||||||
|
PrintAndLog("Recorded activity succesfully written to file: %s", filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(got);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdLFHitagSnoop(const char *Cmd) {
|
int CmdLFHitagSnoop(const char *Cmd) {
|
||||||
|
|
|
@ -273,7 +273,8 @@ int CmdTIWrite(const char *Cmd)
|
||||||
UsbCommand c = {CMD_WRITE_TI_TYPE};
|
UsbCommand c = {CMD_WRITE_TI_TYPE};
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
res = sscanf(Cmd, "0x%"PRIu64"x 0x%"PRIu64"x 0x%"PRIu64"x ", &c.arg[0], &c.arg[1], &c.arg[2]);
|
res = sscanf(Cmd, "%012"llx" %012"llx" %012"llx"", &c.arg[0], &c.arg[1], &c.arg[2]);
|
||||||
|
|
||||||
if (res == 2) c.arg[2]=0;
|
if (res == 2) c.arg[2]=0;
|
||||||
if (res < 2)
|
if (res < 2)
|
||||||
PrintAndLog("Please specify the data as two hex strings, optionally the CRC as a third");
|
PrintAndLog("Please specify the data as two hex strings, optionally the CRC as a third");
|
||||||
|
|
|
@ -188,7 +188,6 @@ void UsbCommandReceived(UsbCommand *UC)
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K: {
|
case CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K: {
|
||||||
sample_buf_len += UC->arg[1];
|
|
||||||
memcpy(sample_buf+(UC->arg[0]),UC->d.asBytes,UC->arg[1]);
|
memcpy(sample_buf+(UC->arg[0]),UC->d.asBytes,UC->arg[1]);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|
|
@ -16,11 +16,9 @@
|
||||||
#include "cmdmain.h"
|
#include "cmdmain.h"
|
||||||
|
|
||||||
uint8_t* sample_buf;
|
uint8_t* sample_buf;
|
||||||
size_t sample_buf_len;
|
|
||||||
|
|
||||||
void GetFromBigBuf(uint8_t *dest, int bytes, int start_index)
|
void GetFromBigBuf(uint8_t *dest, int bytes, int start_index)
|
||||||
{
|
{
|
||||||
sample_buf_len = 0;
|
|
||||||
sample_buf = dest;
|
sample_buf = dest;
|
||||||
UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {start_index, bytes, 0}};
|
UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {start_index, bytes, 0}};
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
|
|
|
@ -13,13 +13,9 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
//trace buffer size as defined in armsrc/apps.h TRACE_SIZE
|
|
||||||
#define TRACE_BUFFER_SIZE 4096
|
|
||||||
#define FILE_PATH_SIZE 1000
|
#define FILE_PATH_SIZE 1000
|
||||||
#define SAMPLE_BUFFER_SIZE 64
|
|
||||||
|
|
||||||
extern uint8_t* sample_buf;
|
extern uint8_t* sample_buf;
|
||||||
extern size_t sample_buf_len;
|
|
||||||
#define arraylen(x) (sizeof(x)/sizeof((x)[0]))
|
#define arraylen(x) (sizeof(x)/sizeof((x)[0]))
|
||||||
|
|
||||||
void GetFromBigBuf(uint8_t *dest, int bytes, int start_index);
|
void GetFromBigBuf(uint8_t *dest, int bytes, int start_index);
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
|
@ -50,7 +51,11 @@ int ClearGraph(int redraw)
|
||||||
|
|
||||||
void setGraphBuf(uint8_t *buff, size_t size)
|
void setGraphBuf(uint8_t *buff, size_t size)
|
||||||
{
|
{
|
||||||
int i=0;
|
if ( buff == NULL ) return;
|
||||||
|
|
||||||
|
uint16_t i = 0;
|
||||||
|
if ( size > MAX_GRAPH_TRACE_LEN )
|
||||||
|
size = MAX_GRAPH_TRACE_LEN;
|
||||||
ClearGraph(0);
|
ClearGraph(0);
|
||||||
for (; i < size; ++i){
|
for (; i < size; ++i){
|
||||||
GraphBuffer[i]=buff[i]-128;
|
GraphBuffer[i]=buff[i]-128;
|
||||||
|
@ -61,6 +66,8 @@ void setGraphBuf(uint8_t *buff, size_t size)
|
||||||
}
|
}
|
||||||
size_t getFromGraphBuf(uint8_t *buff)
|
size_t getFromGraphBuf(uint8_t *buff)
|
||||||
{
|
{
|
||||||
|
if ( buff == NULL ) return 0;
|
||||||
|
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
for (i=0;i<GraphTraceLen;++i){
|
for (i=0;i<GraphTraceLen;++i){
|
||||||
if (GraphBuffer[i]>127) GraphBuffer[i]=127; //trim
|
if (GraphBuffer[i]>127) GraphBuffer[i]=127; //trim
|
||||||
|
@ -69,27 +76,64 @@ size_t getFromGraphBuf(uint8_t *buff)
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Get or auto-detect clock rate
|
// Get or auto-detect clock rate
|
||||||
int GetClock(const char *str, int peak, int verbose)
|
int GetClock(const char *str, int peak, int verbose)
|
||||||
{
|
{
|
||||||
int clock;
|
int clock;
|
||||||
sscanf(str, "%i", &clock);
|
sscanf(str, "%i", &clock);
|
||||||
if (!strcmp(str, ""))
|
if (!strcmp(str, ""))
|
||||||
clock = 0;
|
clock = 0;
|
||||||
|
|
||||||
// Auto-detect clock
|
// Auto-detect clock
|
||||||
if (!clock)
|
if (!clock)
|
||||||
{
|
{
|
||||||
uint8_t grph[MAX_GRAPH_TRACE_LEN]={0};
|
uint8_t grph[MAX_GRAPH_TRACE_LEN]={0};
|
||||||
size_t size = getFromGraphBuf(grph);
|
size_t size = getFromGraphBuf(grph);
|
||||||
clock = DetectASKClock(grph,size,0);
|
if ( size == 0 ) {
|
||||||
|
PrintAndLog("Failed to copy from graphbuffer");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
clock = DetectASKClock(grph,size,0);
|
||||||
// Only print this message if we're not looping something
|
// Only print this message if we're not looping something
|
||||||
if (!verbose){
|
if (!verbose){
|
||||||
PrintAndLog("Auto-detected clock rate: %d", clock);
|
PrintAndLog("Auto-detected clock rate: %d", clock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return clock;
|
||||||
|
}
|
||||||
|
|
||||||
return clock;
|
// A simple test to see if there is any data inside Graphbuffer.
|
||||||
|
bool HasGraphData(){
|
||||||
|
|
||||||
|
if ( GraphTraceLen <= 0) {
|
||||||
|
PrintAndLog("No data available, try reading something first");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect high and lows in Grapbuffer.
|
||||||
|
// Only loops the first 256 values.
|
||||||
|
void DetectHighLowInGraph(int *high, int *low, bool addFuzz) {
|
||||||
|
|
||||||
|
uint8_t loopMax = 255;
|
||||||
|
if ( loopMax > GraphTraceLen)
|
||||||
|
loopMax = GraphTraceLen;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < loopMax; ++i) {
|
||||||
|
if (GraphBuffer[i] > *high)
|
||||||
|
*high = GraphBuffer[i];
|
||||||
|
else if (GraphBuffer[i] < *low)
|
||||||
|
*low = GraphBuffer[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
//12% fuzz in case highs and lows aren't clipped
|
||||||
|
if (addFuzz) {
|
||||||
|
*high = (int)(*high * .88);
|
||||||
|
*low = (int)(*low * .88);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetNRZpskClock(const char *str, int peak, int verbose)
|
int GetNRZpskClock(const char *str, int peak, int verbose)
|
||||||
|
@ -104,6 +148,10 @@ int GetNRZpskClock(const char *str, int peak, int verbose)
|
||||||
{
|
{
|
||||||
uint8_t grph[MAX_GRAPH_TRACE_LEN]={0};
|
uint8_t grph[MAX_GRAPH_TRACE_LEN]={0};
|
||||||
size_t size = getFromGraphBuf(grph);
|
size_t size = getFromGraphBuf(grph);
|
||||||
|
if ( size == 0 ) {
|
||||||
|
PrintAndLog("Failed to copy from graphbuffer");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
clock = DetectpskNRZClock(grph,size,0);
|
clock = DetectpskNRZClock(grph,size,0);
|
||||||
// Only print this message if we're not looping something
|
// Only print this message if we're not looping something
|
||||||
if (!verbose){
|
if (!verbose){
|
||||||
|
|
|
@ -20,8 +20,12 @@ int GetClock(const char *str, int peak, int verbose);
|
||||||
int GetNRZpskClock(const char *str, int peak, int verbose);
|
int GetNRZpskClock(const char *str, int peak, int verbose);
|
||||||
void setGraphBuf(uint8_t *buff, size_t size);
|
void setGraphBuf(uint8_t *buff, size_t size);
|
||||||
|
|
||||||
#define MAX_GRAPH_TRACE_LEN (1024*128)
|
bool HasGraphData();
|
||||||
|
void DetectHighLowInGraph(int *high, int *low, bool addFuzz);
|
||||||
|
|
||||||
|
// Max graph trace len: 40000 (bigbuf) * 8 (at 1 bit per sample)
|
||||||
|
#define MAX_GRAPH_TRACE_LEN (40000 * 8 )
|
||||||
|
|
||||||
extern int GraphBuffer[MAX_GRAPH_TRACE_LEN];
|
extern int GraphBuffer[MAX_GRAPH_TRACE_LEN];
|
||||||
extern int GraphTraceLen;
|
extern int GraphTraceLen;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
50
client/hid-flasher/Info.plist
Normal file
50
client/hid-flasher/Info.plist
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<!-- This is a dummy driver which binds to Proxmark. It -->
|
||||||
|
<!-- contains no actual code; its only purpose is to -->
|
||||||
|
<!-- prevent Apple's USBHID driver from exclusively -->
|
||||||
|
<!-- opening the device. -->
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>English</string>
|
||||||
|
<key>CFBundleIconFile</key>
|
||||||
|
<string></string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>com.proxmark.driver.dummy</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>KEXT</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1.0.0d2</string>
|
||||||
|
<key>IOKitPersonalities</key>
|
||||||
|
<dict>
|
||||||
|
<!-- The Proxmark3 USB interface -->
|
||||||
|
<key>Proxmark3</key>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>com.apple.kpi.iokit</string>
|
||||||
|
<key>IOClass</key>
|
||||||
|
<string>IOService</string>
|
||||||
|
<key>IOProviderClass</key>
|
||||||
|
<string>IOUSBInterface</string>
|
||||||
|
<key>bConfigurationValue</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>bInterfaceNumber</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>idProduct</key>
|
||||||
|
<integer>19343</integer>
|
||||||
|
<key>idVendor</key>
|
||||||
|
<integer>39620</integer>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>OSBundleLibraries</key>
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.iokit.IOUSBFamily</key>
|
||||||
|
<string>1.8</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
48
client/hid-flasher/Makefile
Normal file
48
client/hid-flasher/Makefile
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# 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.
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
include ../../common/Makefile.common
|
||||||
|
|
||||||
|
CC=gcc
|
||||||
|
CXX=g++
|
||||||
|
#COMMON_FLAGS = -m32
|
||||||
|
|
||||||
|
VPATH = ../../common
|
||||||
|
OBJDIR = obj
|
||||||
|
|
||||||
|
LDLIBS = -L/opt/local/lib -L/usr/local/lib -lusb -lreadline -lpthread
|
||||||
|
LDFLAGS = $(COMMON_FLAGS)
|
||||||
|
CFLAGS = -std=gnu99 -I. -I../include -I../common -I/opt/local/include -Wall -Wno-unused-function $(COMMON_FLAGS) -g -O3
|
||||||
|
|
||||||
|
CXXFLAGS =
|
||||||
|
QTLDLIBS =
|
||||||
|
|
||||||
|
RM = rm -f
|
||||||
|
BINS = flasher
|
||||||
|
CLEAN = flasher flasher.exe $(OBJDIR)/*.o *.o
|
||||||
|
|
||||||
|
all: $(BINS)
|
||||||
|
|
||||||
|
flasher: $(OBJDIR)/flash.o $(OBJDIR)/flasher.o $(OBJDIR)/proxusb.o
|
||||||
|
$(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $@
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) $(CLEAN)
|
||||||
|
|
||||||
|
# must be run as root
|
||||||
|
install_kext: Info.plist
|
||||||
|
mkdir -p /System/Library/Extensions/Proxmark3.kext/Contents
|
||||||
|
cp Info.plist /System/Library/Extensions/Proxmark3.kext/Contents
|
||||||
|
chown -R root:wheel /System/Library/Extensions/Proxmark3.kext
|
||||||
|
chmod 755 /System/Library/Extensions/Proxmark3.kext /System/Library/Extensions/Proxmark3.kext/Contents
|
||||||
|
chmod 644 /System/Library/Extensions/Proxmark3.kext/Contents/Info.plist
|
||||||
|
rm -rf /System/Library/Caches/com.apple.kext.caches
|
||||||
|
touch /System/Library/Extensions
|
||||||
|
@echo "*** You may need to reboot for the kext to take effect."
|
||||||
|
|
||||||
|
.PHONY: all clean
|
71
client/hid-flasher/elf.h
Normal file
71
client/hid-flasher/elf.h
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// ELF header
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef __ELF_H__
|
||||||
|
#define __ELF_H__
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t p_type;
|
||||||
|
uint32_t p_offset;
|
||||||
|
uint32_t p_vaddr;
|
||||||
|
uint32_t p_paddr;
|
||||||
|
uint32_t p_filesz;
|
||||||
|
uint32_t p_memsz;
|
||||||
|
uint32_t p_flags;
|
||||||
|
uint32_t p_align;
|
||||||
|
} __attribute__((__packed__)) Elf32_Phdr;
|
||||||
|
|
||||||
|
#define EI_NIDENT 16
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char e_ident[EI_NIDENT];
|
||||||
|
uint16_t e_type;
|
||||||
|
uint16_t e_machine;
|
||||||
|
uint32_t e_version;
|
||||||
|
uint32_t e_entry;
|
||||||
|
uint32_t e_phoff;
|
||||||
|
uint32_t e_shoff;
|
||||||
|
uint32_t e_flags;
|
||||||
|
uint16_t e_ehsize;
|
||||||
|
uint16_t e_phentsize;
|
||||||
|
uint16_t e_phnum;
|
||||||
|
uint16_t e_shentsize;
|
||||||
|
uint16_t e_shnum;
|
||||||
|
uint16_t e_shtrndx;
|
||||||
|
} __attribute__((__packed__)) Elf32_Ehdr;
|
||||||
|
|
||||||
|
#define PT_NULL 0
|
||||||
|
#define PT_LOAD 1
|
||||||
|
#define PT_DYNAMIC 2
|
||||||
|
#define PT_INTERP 3
|
||||||
|
#define PT_NOTE 4
|
||||||
|
#define PT_SHLIB 5
|
||||||
|
#define PT_PHDR 6
|
||||||
|
|
||||||
|
#define ELFCLASS32 1
|
||||||
|
#define ELFCLASS64 2
|
||||||
|
|
||||||
|
#define ELFDATA2LSB 1
|
||||||
|
#define ELFDATA2MSB 2
|
||||||
|
|
||||||
|
#define EV_CURRENT 1
|
||||||
|
|
||||||
|
#define ET_NONE 0
|
||||||
|
#define ET_REL 1
|
||||||
|
#define ET_EXEC 2
|
||||||
|
#define ET_DYN 3
|
||||||
|
#define ET_CORE 4
|
||||||
|
|
||||||
|
#define EM_ARM 0x28
|
||||||
|
|
||||||
|
#define PF_R 4
|
||||||
|
#define PF_W 2
|
||||||
|
#define PF_X 1
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
478
client/hid-flasher/flash.c
Normal file
478
client/hid-flasher/flash.c
Normal file
|
@ -0,0 +1,478 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 2010 Hector Martin "marcan" <marcan@marcansoft.com>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// ELF file flasher
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "sleep.h"
|
||||||
|
#include "proxusb.h"
|
||||||
|
#include "flash.h"
|
||||||
|
#include "elf.h"
|
||||||
|
#include "proxendian.h"
|
||||||
|
|
||||||
|
// FIXME: what the fuckity fuck
|
||||||
|
unsigned int current_command = CMD_UNKNOWN;
|
||||||
|
|
||||||
|
#define FLASH_START 0x100000
|
||||||
|
#define FLASH_SIZE (256*1024)
|
||||||
|
#define FLASH_END (FLASH_START + FLASH_SIZE)
|
||||||
|
#define BOOTLOADER_SIZE 0x2000
|
||||||
|
#define BOOTLOADER_END (FLASH_START + BOOTLOADER_SIZE)
|
||||||
|
|
||||||
|
#define BLOCK_SIZE 0x100
|
||||||
|
|
||||||
|
static const uint8_t elf_ident[] = {
|
||||||
|
0x7f, 'E', 'L', 'F',
|
||||||
|
ELFCLASS32,
|
||||||
|
ELFDATA2LSB,
|
||||||
|
EV_CURRENT
|
||||||
|
};
|
||||||
|
|
||||||
|
// Turn PHDRs into flasher segments, checking for PHDR sanity and merging adjacent
|
||||||
|
// unaligned segments if needed
|
||||||
|
static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, int num_phdrs)
|
||||||
|
{
|
||||||
|
Elf32_Phdr *phdr = phdrs;
|
||||||
|
flash_seg_t *seg;
|
||||||
|
uint32_t last_end = 0;
|
||||||
|
|
||||||
|
ctx->segments = malloc(sizeof(flash_seg_t) * num_phdrs);
|
||||||
|
if (!ctx->segments) {
|
||||||
|
fprintf(stderr, "Out of memory\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ctx->num_segs = 0;
|
||||||
|
seg = ctx->segments;
|
||||||
|
|
||||||
|
fprintf(stderr, "Loading usable ELF segments:\n");
|
||||||
|
for (int i = 0; i < num_phdrs; i++) {
|
||||||
|
if (le32(phdr->p_type) != PT_LOAD) {
|
||||||
|
phdr++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
uint32_t vaddr = le32(phdr->p_vaddr);
|
||||||
|
uint32_t paddr = le32(phdr->p_paddr);
|
||||||
|
uint32_t filesz = le32(phdr->p_filesz);
|
||||||
|
uint32_t memsz = le32(phdr->p_memsz);
|
||||||
|
uint32_t offset = le32(phdr->p_offset);
|
||||||
|
uint32_t flags = le32(phdr->p_flags);
|
||||||
|
if (!filesz) {
|
||||||
|
phdr++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "%d: V 0x%08x P 0x%08x (0x%08x->0x%08x) [%c%c%c] @0x%x\n",
|
||||||
|
i, vaddr, paddr, filesz, memsz,
|
||||||
|
flags & PF_R ? 'R' : ' ',
|
||||||
|
flags & PF_W ? 'W' : ' ',
|
||||||
|
flags & PF_X ? 'X' : ' ',
|
||||||
|
offset);
|
||||||
|
if (filesz != memsz) {
|
||||||
|
fprintf(stderr, "Error: PHDR file size does not equal memory size\n"
|
||||||
|
"(DATA+BSS PHDRs do not make sense on ROM platforms!)\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (paddr < last_end) {
|
||||||
|
fprintf(stderr, "Error: PHDRs not sorted or overlap\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (paddr < FLASH_START || (paddr+filesz) > FLASH_END) {
|
||||||
|
fprintf(stderr, "Error: PHDR is not contained in Flash\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (vaddr >= FLASH_START && vaddr < FLASH_END && (flags & PF_W)) {
|
||||||
|
fprintf(stderr, "Error: Flash VMA segment is writable\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *data;
|
||||||
|
// make extra space if we need to move the data forward
|
||||||
|
data = malloc(filesz + BLOCK_SIZE);
|
||||||
|
if (!data) {
|
||||||
|
fprintf(stderr, "Out of memory\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fseek(fd, offset, SEEK_SET) < 0 || fread(data, 1, filesz, fd) != filesz) {
|
||||||
|
fprintf(stderr, "Error while reading PHDR payload\n");
|
||||||
|
free(data);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t block_offset = paddr & (BLOCK_SIZE-1);
|
||||||
|
if (block_offset) {
|
||||||
|
if (ctx->num_segs) {
|
||||||
|
flash_seg_t *prev_seg = seg - 1;
|
||||||
|
uint32_t this_end = paddr + filesz;
|
||||||
|
uint32_t this_firstblock = paddr & ~(BLOCK_SIZE-1);
|
||||||
|
uint32_t prev_lastblock = (last_end - 1) & ~(BLOCK_SIZE-1);
|
||||||
|
|
||||||
|
if (this_firstblock == prev_lastblock) {
|
||||||
|
uint32_t new_length = this_end - prev_seg->start;
|
||||||
|
uint32_t this_offset = paddr - prev_seg->start;
|
||||||
|
uint32_t hole = this_offset - prev_seg->length;
|
||||||
|
uint8_t *new_data = malloc(new_length);
|
||||||
|
if (!new_data) {
|
||||||
|
fprintf(stderr, "Out of memory\n");
|
||||||
|
free(data);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memset(new_data, 0xff, new_length);
|
||||||
|
memcpy(new_data, prev_seg->data, prev_seg->length);
|
||||||
|
memcpy(new_data + this_offset, data, filesz);
|
||||||
|
fprintf(stderr, "Note: Extending previous segment from 0x%x to 0x%x bytes\n",
|
||||||
|
prev_seg->length, new_length);
|
||||||
|
if (hole)
|
||||||
|
fprintf(stderr, "Note: 0x%x-byte hole created\n", hole);
|
||||||
|
free(data);
|
||||||
|
free(prev_seg->data);
|
||||||
|
prev_seg->data = new_data;
|
||||||
|
prev_seg->length = new_length;
|
||||||
|
last_end = this_end;
|
||||||
|
phdr++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Warning: segment does not begin on a block boundary, will pad\n");
|
||||||
|
memmove(data + block_offset, data, filesz);
|
||||||
|
memset(data, 0xFF, block_offset);
|
||||||
|
filesz += block_offset;
|
||||||
|
paddr -= block_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
seg->data = data;
|
||||||
|
seg->start = paddr;
|
||||||
|
seg->length = filesz;
|
||||||
|
seg++;
|
||||||
|
ctx->num_segs++;
|
||||||
|
|
||||||
|
last_end = paddr + filesz;
|
||||||
|
phdr++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity check segments and check for bootloader writes
|
||||||
|
static int check_segs(flash_file_t *ctx, int can_write_bl) {
|
||||||
|
for (int i = 0; i < ctx->num_segs; i++) {
|
||||||
|
flash_seg_t *seg = &ctx->segments[i];
|
||||||
|
|
||||||
|
if (seg->start & (BLOCK_SIZE-1)) {
|
||||||
|
fprintf(stderr, "Error: Segment is not aligned\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (seg->start < FLASH_START) {
|
||||||
|
fprintf(stderr, "Error: Segment is outside of flash bounds\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (seg->start + seg->length > FLASH_END) {
|
||||||
|
fprintf(stderr, "Error: Segment is outside of flash bounds\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!can_write_bl && seg->start < BOOTLOADER_END) {
|
||||||
|
fprintf(stderr, "Attempted to write bootloader but bootloader writes are not enabled\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load an ELF file and prepare it for flashing
|
||||||
|
int flash_load(flash_file_t *ctx, const char *name, int can_write_bl)
|
||||||
|
{
|
||||||
|
FILE *fd = NULL;
|
||||||
|
Elf32_Ehdr ehdr;
|
||||||
|
Elf32_Phdr *phdrs = NULL;
|
||||||
|
int num_phdrs;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
fd = fopen(name, "rb");
|
||||||
|
if (!fd) {
|
||||||
|
fprintf(stderr, "Could not open file '%s': ", name);
|
||||||
|
perror(NULL);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Loading ELF file '%s'...\n", name);
|
||||||
|
|
||||||
|
if (fread(&ehdr, sizeof(ehdr), 1, fd) != 1) {
|
||||||
|
fprintf(stderr, "Error while reading ELF file header\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (memcmp(ehdr.e_ident, elf_ident, sizeof(elf_ident))
|
||||||
|
|| le32(ehdr.e_version) != 1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Not an ELF file or wrong ELF type\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (le16(ehdr.e_type) != ET_EXEC) {
|
||||||
|
fprintf(stderr, "ELF is not executable\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (le16(ehdr.e_machine) != EM_ARM) {
|
||||||
|
fprintf(stderr, "Wrong ELF architecture\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (!ehdr.e_phnum || !ehdr.e_phoff) {
|
||||||
|
fprintf(stderr, "ELF has no PHDRs\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (le16(ehdr.e_phentsize) != sizeof(Elf32_Phdr)) {
|
||||||
|
// could be a structure padding issue...
|
||||||
|
fprintf(stderr, "Either the ELF file or this code is made of fail\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
num_phdrs = le16(ehdr.e_phnum);
|
||||||
|
|
||||||
|
phdrs = malloc(le16(ehdr.e_phnum) * sizeof(Elf32_Phdr));
|
||||||
|
if (!phdrs) {
|
||||||
|
fprintf(stderr, "Out of memory\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (fseek(fd, le32(ehdr.e_phoff), SEEK_SET) < 0) {
|
||||||
|
fprintf(stderr, "Error while reading ELF PHDRs\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (fread(phdrs, sizeof(Elf32_Phdr), num_phdrs, fd) != num_phdrs) {
|
||||||
|
fprintf(stderr, "Error while reading ELF PHDRs\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = build_segs_from_phdrs(ctx, fd, phdrs, num_phdrs);
|
||||||
|
if (res < 0)
|
||||||
|
goto fail;
|
||||||
|
res = check_segs(ctx, can_write_bl);
|
||||||
|
if (res < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
free(phdrs);
|
||||||
|
fclose(fd);
|
||||||
|
ctx->filename = name;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (phdrs)
|
||||||
|
free(phdrs);
|
||||||
|
if (fd)
|
||||||
|
fclose(fd);
|
||||||
|
flash_free(ctx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the state of the proxmark, backwards compatible
|
||||||
|
static int get_proxmark_state(uint32_t *state)
|
||||||
|
{
|
||||||
|
UsbCommand c;
|
||||||
|
c.cmd = CMD_DEVICE_INFO;
|
||||||
|
SendCommand(&c);
|
||||||
|
|
||||||
|
UsbCommand resp;
|
||||||
|
ReceiveCommand(&resp);
|
||||||
|
|
||||||
|
// Three outcomes:
|
||||||
|
// 1. The old bootrom code will ignore CMD_DEVICE_INFO, but respond with an ACK
|
||||||
|
// 2. The old os code will respond with CMD_DEBUG_PRINT_STRING and "unknown command"
|
||||||
|
// 3. The new bootrom and os codes will respond with CMD_DEVICE_INFO and flags
|
||||||
|
|
||||||
|
switch (resp.cmd) {
|
||||||
|
case CMD_ACK:
|
||||||
|
*state = DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM;
|
||||||
|
break;
|
||||||
|
case CMD_DEBUG_PRINT_STRING:
|
||||||
|
*state = DEVICE_INFO_FLAG_CURRENT_MODE_OS;
|
||||||
|
break;
|
||||||
|
case CMD_DEVICE_INFO:
|
||||||
|
*state = resp.arg[0];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Error: Couldn't get proxmark state, bad response type: 0x%04x\n", resp.cmd);
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enter the bootloader to be able to start flashing
|
||||||
|
static int enter_bootloader(void)
|
||||||
|
{
|
||||||
|
uint32_t state;
|
||||||
|
|
||||||
|
if (get_proxmark_state(&state) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM) {
|
||||||
|
/* Already in flash state, we're done. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state & DEVICE_INFO_FLAG_CURRENT_MODE_OS) {
|
||||||
|
fprintf(stderr,"Entering bootloader...\n");
|
||||||
|
UsbCommand c;
|
||||||
|
memset(&c, 0, sizeof (c));
|
||||||
|
|
||||||
|
if ((state & DEVICE_INFO_FLAG_BOOTROM_PRESENT)
|
||||||
|
&& (state & DEVICE_INFO_FLAG_OSIMAGE_PRESENT))
|
||||||
|
{
|
||||||
|
// New style handover: Send CMD_START_FLASH, which will reset the board
|
||||||
|
// and enter the bootrom on the next boot.
|
||||||
|
c.cmd = CMD_START_FLASH;
|
||||||
|
SendCommand(&c);
|
||||||
|
fprintf(stderr,"(Press and release the button only to abort)\n");
|
||||||
|
} else {
|
||||||
|
// Old style handover: Ask the user to press the button, then reset the board
|
||||||
|
c.cmd = CMD_HARDWARE_RESET;
|
||||||
|
SendCommand(&c);
|
||||||
|
fprintf(stderr,"Press and hold down button NOW if your bootloader requires it.\n");
|
||||||
|
}
|
||||||
|
fprintf(stderr,"Waiting for Proxmark to reappear on USB...");
|
||||||
|
|
||||||
|
CloseProxmark();
|
||||||
|
sleep(1);
|
||||||
|
while (!OpenProxmark(0)) {
|
||||||
|
sleep(1);
|
||||||
|
fprintf(stderr, ".");
|
||||||
|
}
|
||||||
|
fprintf(stderr," Found.\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Error: Unknown Proxmark mode\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wait_for_ack(void)
|
||||||
|
{
|
||||||
|
UsbCommand ack;
|
||||||
|
ReceiveCommand(&ack);
|
||||||
|
if (ack.cmd != CMD_ACK) {
|
||||||
|
printf("Error: Unexpected reply 0x%04x (expected ACK)\n", ack.cmd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go into flashing mode
|
||||||
|
int flash_start_flashing(int enable_bl_writes)
|
||||||
|
{
|
||||||
|
uint32_t state;
|
||||||
|
|
||||||
|
if (enter_bootloader() < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (get_proxmark_state(&state) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (state & DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH) {
|
||||||
|
// This command is stupid. Why the heck does it care which area we're
|
||||||
|
// flashing, as long as it's not the bootloader area? The mind boggles.
|
||||||
|
UsbCommand c = {CMD_START_FLASH};
|
||||||
|
|
||||||
|
if (enable_bl_writes) {
|
||||||
|
c.arg[0] = FLASH_START;
|
||||||
|
c.arg[1] = FLASH_END;
|
||||||
|
c.arg[2] = START_FLASH_MAGIC;
|
||||||
|
} else {
|
||||||
|
c.arg[0] = BOOTLOADER_END;
|
||||||
|
c.arg[1] = FLASH_END;
|
||||||
|
c.arg[2] = 0;
|
||||||
|
}
|
||||||
|
SendCommand(&c);
|
||||||
|
return wait_for_ack();
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Note: Your bootloader does not understand the new START_FLASH command\n");
|
||||||
|
fprintf(stderr, " It is recommended that you update your bootloader\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_block(uint32_t address, uint8_t *data, uint32_t length)
|
||||||
|
{
|
||||||
|
uint8_t block_buf[BLOCK_SIZE];
|
||||||
|
|
||||||
|
memset(block_buf, 0xFF, BLOCK_SIZE);
|
||||||
|
memcpy(block_buf, data, length);
|
||||||
|
|
||||||
|
UsbCommand c = {CMD_SETUP_WRITE};
|
||||||
|
for (int i = 0; i < 240; i += 48) {
|
||||||
|
memcpy(c.d.asBytes, block_buf + i, 48);
|
||||||
|
c.arg[0] = i / 4;
|
||||||
|
SendCommand(&c);
|
||||||
|
if (wait_for_ack() < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
c.cmd = CMD_FINISH_WRITE;
|
||||||
|
c.arg[0] = address;
|
||||||
|
memcpy(c.d.asBytes, block_buf+240, 16);
|
||||||
|
SendCommand(&c);
|
||||||
|
return wait_for_ack();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write a file's segments to Flash
|
||||||
|
int flash_write(flash_file_t *ctx)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Writing segments for file: %s\n", ctx->filename);
|
||||||
|
for (int i = 0; i < ctx->num_segs; i++) {
|
||||||
|
flash_seg_t *seg = &ctx->segments[i];
|
||||||
|
|
||||||
|
uint32_t length = seg->length;
|
||||||
|
uint32_t blocks = (length + BLOCK_SIZE - 1) / BLOCK_SIZE;
|
||||||
|
uint32_t end = seg->start + length;
|
||||||
|
|
||||||
|
fprintf(stderr, " 0x%08x..0x%08x [0x%x / %d blocks]",
|
||||||
|
seg->start, end - 1, length, blocks);
|
||||||
|
|
||||||
|
int block = 0;
|
||||||
|
uint8_t *data = seg->data;
|
||||||
|
uint32_t baddr = seg->start;
|
||||||
|
|
||||||
|
while (length) {
|
||||||
|
uint32_t block_size = length;
|
||||||
|
if (block_size > BLOCK_SIZE)
|
||||||
|
block_size = BLOCK_SIZE;
|
||||||
|
|
||||||
|
if (write_block(baddr, data, block_size) < 0) {
|
||||||
|
fprintf(stderr, " ERROR\n");
|
||||||
|
fprintf(stderr, "Error writing block %d of %d\n", block, blocks);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
data += block_size;
|
||||||
|
baddr += block_size;
|
||||||
|
length -= block_size;
|
||||||
|
block++;
|
||||||
|
fprintf(stderr, ".");
|
||||||
|
}
|
||||||
|
fprintf(stderr, " OK\n");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// free a file context
|
||||||
|
void flash_free(flash_file_t *ctx)
|
||||||
|
{
|
||||||
|
if (!ctx)
|
||||||
|
return;
|
||||||
|
if (ctx->segments) {
|
||||||
|
for (int i = 0; i < ctx->num_segs; i++)
|
||||||
|
free(ctx->segments[i].data);
|
||||||
|
free(ctx->segments);
|
||||||
|
ctx->segments = NULL;
|
||||||
|
ctx->num_segs = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// just reset the unit
|
||||||
|
int flash_stop_flashing(void) {
|
||||||
|
UsbCommand c = {CMD_HARDWARE_RESET};
|
||||||
|
SendCommand(&c);
|
||||||
|
return 0;
|
||||||
|
}
|
35
client/hid-flasher/flash.h
Normal file
35
client/hid-flasher/flash.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Flashing utility functions
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef __FLASH_H__
|
||||||
|
#define __FLASH_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "elf.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *data;
|
||||||
|
uint32_t start;
|
||||||
|
uint32_t length;
|
||||||
|
} flash_seg_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *filename;
|
||||||
|
int can_write_bl;
|
||||||
|
int num_segs;
|
||||||
|
flash_seg_t *segments;
|
||||||
|
} flash_file_t;
|
||||||
|
|
||||||
|
int flash_load(flash_file_t *ctx, const char *name, int can_write_bl);
|
||||||
|
int flash_start_flashing(int enable_bl_writes);
|
||||||
|
int flash_write(flash_file_t *ctx);
|
||||||
|
void flash_free(flash_file_t *ctx);
|
||||||
|
int flash_stop_flashing(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
93
client/hid-flasher/flasher.c
Normal file
93
client/hid-flasher/flasher.c
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Flasher frontend tool
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "sleep.h"
|
||||||
|
#include "proxusb.h"
|
||||||
|
#include "flash.h"
|
||||||
|
|
||||||
|
static void usage(char *argv0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: %s [-b] image.elf [image.elf...]\n\n", argv0);
|
||||||
|
fprintf(stderr, "\t-b\tEnable flashing of bootloader area (DANGEROUS)\n\n");
|
||||||
|
fprintf(stderr, "Example: %s path/to/osimage.elf path/to/fpgaimage.elf\n", argv0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_FILES 4
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int can_write_bl = 0;
|
||||||
|
int num_files = 0;
|
||||||
|
int res;
|
||||||
|
flash_file_t files[MAX_FILES];
|
||||||
|
|
||||||
|
memset(files, 0, sizeof(files));
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
usage(argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < argc; i++) {
|
||||||
|
if (argv[i][0] == '-') {
|
||||||
|
if (!strcmp(argv[i], "-b")) {
|
||||||
|
can_write_bl = 1;
|
||||||
|
} else {
|
||||||
|
usage(argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res = flash_load(&files[num_files], argv[i], can_write_bl);
|
||||||
|
if (res < 0) {
|
||||||
|
fprintf(stderr, "Error while loading %s\n", argv[i]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
num_files++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_init();
|
||||||
|
|
||||||
|
fprintf(stderr, "Waiting for Proxmark to appear on USB...");
|
||||||
|
while (!OpenProxmark(1)) {
|
||||||
|
sleep(1);
|
||||||
|
fprintf(stderr, ".");
|
||||||
|
}
|
||||||
|
fprintf(stderr, " Found.\n");
|
||||||
|
|
||||||
|
res = flash_start_flashing(can_write_bl);
|
||||||
|
if (res < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
fprintf(stderr, "\nFlashing...\n");
|
||||||
|
|
||||||
|
for (int i = 0; i < num_files; i++) {
|
||||||
|
res = flash_write(&files[i]);
|
||||||
|
if (res < 0)
|
||||||
|
return -1;
|
||||||
|
flash_free(&files[i]);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Resetting hardware...\n");
|
||||||
|
|
||||||
|
res = flash_stop_flashing();
|
||||||
|
if (res < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
CloseProxmark();
|
||||||
|
|
||||||
|
fprintf(stderr, "All done.\n\n");
|
||||||
|
fprintf(stderr, "Have a nice day!\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
0
client/hid-flasher/obj/.dummy
Normal file
0
client/hid-flasher/obj/.dummy
Normal file
46
client/hid-flasher/proxendian.h
Normal file
46
client/hid-flasher/proxendian.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 2010 Hector Martin "marcan" <marcan@marcansoft.com>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Endianness convenience functions
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef PROXENDIAN_H__
|
||||||
|
#define PROXENDIAN_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
# define HOST_LITTLE_ENDIAN
|
||||||
|
#else
|
||||||
|
# include <sys/types.h>
|
||||||
|
|
||||||
|
# if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
|
||||||
|
# error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if BYTE_ORDER == LITTLE_ENDIAN
|
||||||
|
# define HOST_LITTLE_ENDIAN
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HOST_LITTLE_ENDIAN
|
||||||
|
# define le16(x) (x)
|
||||||
|
# define le32(x) (x)
|
||||||
|
#else
|
||||||
|
|
||||||
|
static inline uint16_t le16(uint16_t v)
|
||||||
|
{
|
||||||
|
return (v>>8) | (v<<8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t le32(uint32_t v)
|
||||||
|
{
|
||||||
|
return (le16(v)<<16) | (le16(v>>16));
|
||||||
|
}
|
||||||
|
#endif // HOST_LITTLE_ENDIAN
|
||||||
|
|
||||||
|
#endif // PROXENDIAN_H__
|
17
client/hid-flasher/proxmark3.h
Normal file
17
client/hid-flasher/proxmark3.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 2009 Michael Gernoth <michael at gernoth.net>
|
||||||
|
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Main binary
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef PROXMARK3_H__
|
||||||
|
#define PROXMARK3_H__
|
||||||
|
|
||||||
|
#define PROXPROMPT "proxmark3> "
|
||||||
|
|
||||||
|
#endif
|
222
client/hid-flasher/proxusb.c
Normal file
222
client/hid-flasher/proxusb.c
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 2009 Michael Gernoth <michael at gernoth.net>
|
||||||
|
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// USB utilities
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <usb.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "sleep.h"
|
||||||
|
#include "proxusb.h"
|
||||||
|
#include "proxmark3.h"
|
||||||
|
#include "usb_cmd.h"
|
||||||
|
|
||||||
|
// It seems to be missing for mingw
|
||||||
|
#ifndef ETIMEDOUT
|
||||||
|
#define ETIMEDOUT 116
|
||||||
|
#endif
|
||||||
|
|
||||||
|
usb_dev_handle *devh = NULL;
|
||||||
|
static unsigned int claimed_iface = 0;
|
||||||
|
unsigned char return_on_error = 0;
|
||||||
|
unsigned char error_occured = 0;
|
||||||
|
extern unsigned int current_command;
|
||||||
|
|
||||||
|
void SendCommand(UsbCommand *c)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
printf("Sending %d bytes\n", sizeof(UsbCommand));
|
||||||
|
#endif
|
||||||
|
current_command = c->cmd;
|
||||||
|
ret = usb_bulk_write(devh, 0x01, (char*)c, sizeof(UsbCommand), 1000);
|
||||||
|
if (ret<0) {
|
||||||
|
error_occured = 1;
|
||||||
|
if (return_on_error)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fprintf(stderr, "write failed: %s!\nTrying to reopen device...\n",
|
||||||
|
usb_strerror());
|
||||||
|
|
||||||
|
if (devh) {
|
||||||
|
usb_close(devh);
|
||||||
|
devh = NULL;
|
||||||
|
}
|
||||||
|
while(!OpenProxmark(0)) { sleep(1); }
|
||||||
|
printf(PROXPROMPT);
|
||||||
|
fflush(NULL);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReceiveCommandPoll(UsbCommand *c)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
memset(c, 0, sizeof (UsbCommand));
|
||||||
|
ret = usb_bulk_read(devh, 0x82, (char*)c, sizeof(UsbCommand), 500);
|
||||||
|
if (ret<0) {
|
||||||
|
if (ret != -ETIMEDOUT) {
|
||||||
|
error_occured = 1;
|
||||||
|
if (return_on_error)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
fprintf(stderr, "read failed: %s(%d)!\nTrying to reopen device...\n",
|
||||||
|
usb_strerror(), ret);
|
||||||
|
|
||||||
|
if (devh) {
|
||||||
|
usb_close(devh);
|
||||||
|
devh = NULL;
|
||||||
|
}
|
||||||
|
while(!OpenProxmark(0)) { sleep(1); }
|
||||||
|
printf(PROXPROMPT);
|
||||||
|
fflush(NULL);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ret && (ret < sizeof(UsbCommand))) {
|
||||||
|
fprintf(stderr, "Read only %d instead of requested %d bytes!\n",
|
||||||
|
ret, (int)sizeof(UsbCommand));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReceiveCommand(UsbCommand *c)
|
||||||
|
{
|
||||||
|
// printf("%s()\n", __FUNCTION__);
|
||||||
|
int retval = 0;
|
||||||
|
do {
|
||||||
|
retval = ReceiveCommandPoll(c);
|
||||||
|
if (retval != 1) printf("ReceiveCommandPoll returned %d\n", retval);
|
||||||
|
} while(retval<0);
|
||||||
|
// printf("recv %x\n", c->cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_dev_handle* findProxmark(int verbose, unsigned int *iface)
|
||||||
|
{
|
||||||
|
struct usb_bus *busses, *bus;
|
||||||
|
usb_dev_handle *handle = NULL;
|
||||||
|
struct prox_unit units[50];
|
||||||
|
int iUnit = 0;
|
||||||
|
|
||||||
|
usb_find_busses();
|
||||||
|
usb_find_devices();
|
||||||
|
|
||||||
|
busses = usb_get_busses();
|
||||||
|
|
||||||
|
for (bus = busses; bus; bus = bus->next) {
|
||||||
|
struct usb_device *dev;
|
||||||
|
|
||||||
|
for (dev = bus->devices; dev; dev = dev->next) {
|
||||||
|
struct usb_device_descriptor *desc = &(dev->descriptor);
|
||||||
|
|
||||||
|
if ((desc->idProduct == 0x4b8f) && (desc->idVendor == 0x9ac4)) {
|
||||||
|
handle = usb_open(dev);
|
||||||
|
if (!handle) {
|
||||||
|
if (verbose)
|
||||||
|
fprintf(stderr, "open fabiled: %s!\n", usb_strerror());
|
||||||
|
//return NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*iface = dev->config[0].interface[0].altsetting[0].bInterfaceNumber;
|
||||||
|
|
||||||
|
struct prox_unit unit = {handle, {0}};
|
||||||
|
usb_get_string_simple(handle, desc->iSerialNumber, unit.serial_number, sizeof(unit.serial_number));
|
||||||
|
units[iUnit++] = unit;
|
||||||
|
|
||||||
|
//return handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iUnit > 0) {
|
||||||
|
int iSelection = 0;
|
||||||
|
|
||||||
|
fprintf(stdout, "\nConnected units:\n");
|
||||||
|
|
||||||
|
for (int i = 0; i < iUnit; i++) {
|
||||||
|
struct usb_device * dev = usb_device(units[i].handle);
|
||||||
|
fprintf(stdout, "\t%d. SN: %s [%s/%s]\n", i+1, units[i].serial_number, dev->bus->dirname, dev->filename);
|
||||||
|
}
|
||||||
|
if (iUnit > 1) {
|
||||||
|
while (iSelection < 1 || iSelection > iUnit) {
|
||||||
|
fprintf(stdout, "Which unit do you want to connect to? ");
|
||||||
|
fscanf(stdin, "%d", &iSelection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
iSelection = 1;
|
||||||
|
iSelection --;
|
||||||
|
|
||||||
|
for (int i = 0; i < iUnit; i++) {
|
||||||
|
if (iSelection == i) continue;
|
||||||
|
usb_close(units[i].handle);
|
||||||
|
units[i].handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return units[iSelection].handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_dev_handle* OpenProxmark(int verbose)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
usb_dev_handle *handle = NULL;
|
||||||
|
unsigned int iface;
|
||||||
|
|
||||||
|
handle = findProxmark(verbose, &iface);
|
||||||
|
if (!handle)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
/* detach kernel driver first */
|
||||||
|
ret = usb_detach_kernel_driver_np(handle, iface);
|
||||||
|
/* don't complain if no driver attached */
|
||||||
|
if (ret<0 && ret != -61 && verbose)
|
||||||
|
fprintf(stderr, "detach kernel driver failed: (%d) %s!\n", ret, usb_strerror());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Needed for Windows. Optional for Mac OS and Linux
|
||||||
|
ret = usb_set_configuration(handle, 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
if (verbose)
|
||||||
|
fprintf(stderr, "configuration set failed: %s!\n", usb_strerror());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = usb_claim_interface(handle, iface);
|
||||||
|
if (ret < 0) {
|
||||||
|
if (verbose)
|
||||||
|
fprintf(stderr, "claim failed: %s!\n", usb_strerror());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
claimed_iface = iface;
|
||||||
|
devh = handle;
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CloseProxmark(void)
|
||||||
|
{
|
||||||
|
usb_release_interface(devh, claimed_iface);
|
||||||
|
usb_close(devh);
|
||||||
|
devh = NULL;
|
||||||
|
}
|
34
client/hid-flasher/proxusb.h
Normal file
34
client/hid-flasher/proxusb.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// USB utilities
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef PROXUSB_H__
|
||||||
|
#define PROXUSB_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <usb.h>
|
||||||
|
#include "usb_cmd.h"
|
||||||
|
|
||||||
|
extern unsigned char return_on_error;
|
||||||
|
extern unsigned char error_occured;
|
||||||
|
|
||||||
|
void SendCommand(UsbCommand *c);
|
||||||
|
bool ReceiveCommandPoll(UsbCommand *c);
|
||||||
|
void ReceiveCommand(UsbCommand *c);
|
||||||
|
struct usb_dev_handle* FindProxmark(int verbose, unsigned int *iface);
|
||||||
|
struct usb_dev_handle* OpenProxmark(int verbose);
|
||||||
|
void CloseProxmark(void);
|
||||||
|
|
||||||
|
struct prox_unit {
|
||||||
|
usb_dev_handle *handle;
|
||||||
|
char serial_number[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
24
client/hid-flasher/sleep.h
Normal file
24
client/hid-flasher/sleep.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// platform-independant sleep macros
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef SLEEP_H__
|
||||||
|
#define SLEEP_H__
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#define sleep(n) Sleep(1000 * n)
|
||||||
|
#define msleep(n) Sleep(n)
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#define msleep(n) usleep(1000 * n)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
165
client/hid-flasher/usb_cmd.h
Normal file
165
client/hid-flasher/usb_cmd.h
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Jonathan Westhues, Mar 2006
|
||||||
|
// Edits by Gerhard de Koning Gans, Sep 2007
|
||||||
|
//
|
||||||
|
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||||
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
|
// the license.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Definitions for all the types of commands that may be sent over USB; our
|
||||||
|
// own protocol.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef __USB_CMD_H
|
||||||
|
#define __USB_CMD_H
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
typedef DWORD uint32_t;
|
||||||
|
typedef BYTE uint8_t;
|
||||||
|
#define PACKED
|
||||||
|
// stuff
|
||||||
|
#else
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#define PACKED __attribute__((packed))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t cmd;
|
||||||
|
uint32_t arg[3];
|
||||||
|
union {
|
||||||
|
uint8_t asBytes[48];
|
||||||
|
uint32_t asDwords[12];
|
||||||
|
} d;
|
||||||
|
} PACKED UsbCommand;
|
||||||
|
|
||||||
|
// For the bootloader
|
||||||
|
#define CMD_DEVICE_INFO 0x0000
|
||||||
|
#define CMD_SETUP_WRITE 0x0001
|
||||||
|
#define CMD_FINISH_WRITE 0x0003
|
||||||
|
#define CMD_HARDWARE_RESET 0x0004
|
||||||
|
#define CMD_START_FLASH 0x0005
|
||||||
|
#define CMD_NACK 0x00fe
|
||||||
|
#define CMD_ACK 0x00ff
|
||||||
|
|
||||||
|
// For general mucking around
|
||||||
|
#define CMD_DEBUG_PRINT_STRING 0x0100
|
||||||
|
#define CMD_DEBUG_PRINT_INTEGERS 0x0101
|
||||||
|
#define CMD_DEBUG_PRINT_BYTES 0x0102
|
||||||
|
#define CMD_LCD_RESET 0x0103
|
||||||
|
#define CMD_LCD 0x0104
|
||||||
|
#define CMD_BUFF_CLEAR 0x0105
|
||||||
|
#define CMD_READ_MEM 0x0106
|
||||||
|
#define CMD_VERSION 0x0107
|
||||||
|
|
||||||
|
// For low-frequency tags
|
||||||
|
#define CMD_READ_TI_TYPE 0x0202
|
||||||
|
#define CMD_WRITE_TI_TYPE 0x0203
|
||||||
|
#define CMD_DOWNLOADED_RAW_BITS_TI_TYPE 0x0204
|
||||||
|
#define CMD_ACQUIRE_RAW_ADC_SAMPLES_125K 0x0205
|
||||||
|
#define CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K 0x0206
|
||||||
|
#define CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K 0x0207
|
||||||
|
#define CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K 0x0208
|
||||||
|
#define CMD_DOWNLOADED_SIM_SAMPLES_125K 0x0209
|
||||||
|
#define CMD_SIMULATE_TAG_125K 0x020A
|
||||||
|
#define CMD_HID_DEMOD_FSK 0x020B
|
||||||
|
#define CMD_HID_SIM_TAG 0x020C
|
||||||
|
#define CMD_SET_LF_DIVISOR 0x020D
|
||||||
|
#define CMD_LF_SIMULATE_BIDIR 0x020E
|
||||||
|
#define CMD_SET_ADC_MUX 0x020F
|
||||||
|
#define CMD_HID_CLONE_TAG 0x0210
|
||||||
|
#define CMD_EM410X_WRITE_TAG 0x0211
|
||||||
|
#define CMD_INDALA_CLONE_TAG 0x0212
|
||||||
|
// for 224 bits UID
|
||||||
|
#define CMD_INDALA_CLONE_TAG_L 0x0213
|
||||||
|
|
||||||
|
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
|
||||||
|
|
||||||
|
// For the 13.56 MHz tags
|
||||||
|
#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_SRIX4K_TAG 0x0304
|
||||||
|
#define CMD_READER_ISO_15693 0x0310
|
||||||
|
#define CMD_SIMTAG_ISO_15693 0x0311
|
||||||
|
#define CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693 0x0312
|
||||||
|
#define CMD_ISO_15693_COMMAND 0x0313
|
||||||
|
#define CMD_ISO_15693_COMMAND_DONE 0x0314
|
||||||
|
#define CMD_ISO_15693_FIND_AFI 0x0315
|
||||||
|
#define CMD_ISO_15693_DEBUG 0x0316
|
||||||
|
|
||||||
|
// For Hitag2 transponders
|
||||||
|
#define CMD_SNOOP_HITAG 0x0370
|
||||||
|
#define CMD_SIMULATE_HITAG 0x0371
|
||||||
|
#define CMD_READER_HITAG 0x0372
|
||||||
|
|
||||||
|
#define CMD_SIMULATE_TAG_HF_LISTEN 0x0380
|
||||||
|
#define CMD_SIMULATE_TAG_ISO_14443 0x0381
|
||||||
|
#define CMD_SNOOP_ISO_14443 0x0382
|
||||||
|
#define CMD_SNOOP_ISO_14443a 0x0383
|
||||||
|
#define CMD_SIMULATE_TAG_ISO_14443a 0x0384
|
||||||
|
#define CMD_READER_ISO_14443a 0x0385
|
||||||
|
#define CMD_SIMULATE_TAG_LEGIC_RF 0x0387
|
||||||
|
#define CMD_READER_LEGIC_RF 0x0388
|
||||||
|
#define CMD_WRITER_LEGIC_RF 0x0389
|
||||||
|
#define CMD_EPA_PACE_COLLECT_NONCE 0x038A
|
||||||
|
|
||||||
|
#define CMD_SNOOP_ICLASS 0x0392
|
||||||
|
#define CMD_SIMULATE_TAG_ICLASS 0x0393
|
||||||
|
#define CMD_READER_ICLASS 0x0394
|
||||||
|
|
||||||
|
// For measurements of the antenna tuning
|
||||||
|
#define CMD_MEASURE_ANTENNA_TUNING 0x0400
|
||||||
|
#define CMD_MEASURE_ANTENNA_TUNING_HF 0x0401
|
||||||
|
#define CMD_MEASURED_ANTENNA_TUNING 0x0410
|
||||||
|
#define CMD_LISTEN_READER_FIELD 0x0420
|
||||||
|
|
||||||
|
// For direct FPGA control
|
||||||
|
#define CMD_FPGA_MAJOR_MODE_OFF 0x0500
|
||||||
|
|
||||||
|
// For mifare commands
|
||||||
|
#define CMD_MIFARE_SET_DBGMODE 0x0600
|
||||||
|
#define CMD_MIFARE_EML_MEMCLR 0x0601
|
||||||
|
#define CMD_MIFARE_EML_MEMSET 0x0602
|
||||||
|
#define CMD_MIFARE_EML_MEMGET 0x0603
|
||||||
|
#define CMD_MIFARE_EML_CARDLOAD 0x0604
|
||||||
|
#define CMD_MIFARE_EML_CSETBLOCK 0x0605
|
||||||
|
#define CMD_MIFARE_EML_CGETBLOCK 0x0606
|
||||||
|
|
||||||
|
#define CMD_SIMULATE_MIFARE_CARD 0x0610
|
||||||
|
|
||||||
|
#define CMD_READER_MIFARE 0x0611
|
||||||
|
#define CMD_MIFARE_NESTED 0x0612
|
||||||
|
|
||||||
|
#define CMD_MIFARE_READBL 0x0620
|
||||||
|
#define CMD_MIFARE_READSC 0x0621
|
||||||
|
#define CMD_MIFARE_WRITEBL 0x0622
|
||||||
|
#define CMD_MIFARE_CHKKEYS 0x0623
|
||||||
|
|
||||||
|
#define CMD_MIFARE_SNIFFER 0x0630
|
||||||
|
|
||||||
|
#define CMD_UNKNOWN 0xFFFF
|
||||||
|
|
||||||
|
// CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions:
|
||||||
|
/* Whether a bootloader that understands the common_area is present */
|
||||||
|
#define DEVICE_INFO_FLAG_BOOTROM_PRESENT (1<<0)
|
||||||
|
|
||||||
|
/* Whether a osimage that understands the common_area is present */
|
||||||
|
#define DEVICE_INFO_FLAG_OSIMAGE_PRESENT (1<<1)
|
||||||
|
|
||||||
|
/* Set if the bootloader is currently executing */
|
||||||
|
#define DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM (1<<2)
|
||||||
|
|
||||||
|
/* Set if the OS is currently executing */
|
||||||
|
#define DEVICE_INFO_FLAG_CURRENT_MODE_OS (1<<3)
|
||||||
|
|
||||||
|
/* Set if this device understands the extend start flash command */
|
||||||
|
#define DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH (1<<4)
|
||||||
|
|
||||||
|
/* CMD_START_FLASH may have three arguments: start of area to flash,
|
||||||
|
end of area to flash, optional magic.
|
||||||
|
The bootrom will not allow to overwrite itself unless this magic
|
||||||
|
is given as third parameter */
|
||||||
|
|
||||||
|
#define START_FLASH_MAGIC 0x54494f44 // 'DOIT'
|
||||||
|
|
||||||
|
#endif
|
|
@ -28,6 +28,12 @@
|
||||||
#define POLARSSL_DES_H
|
#define POLARSSL_DES_H
|
||||||
|
|
||||||
//#include "config.h"
|
//#include "config.h"
|
||||||
|
/**
|
||||||
|
* \def POLARSSL_CIPHER_MODE_CBC
|
||||||
|
*
|
||||||
|
* Enable Cipher Block Chaining mode (CBC) for symmetric ciphers.
|
||||||
|
*/
|
||||||
|
#define POLARSSL_CIPHER_MODE_CBC
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ local _commands = {
|
||||||
CMD_EM4X_WRITE_WORD = 0x0219,
|
CMD_EM4X_WRITE_WORD = 0x0219,
|
||||||
CMD_IO_DEMOD_FSK = 0x021A,
|
CMD_IO_DEMOD_FSK = 0x021A,
|
||||||
CMD_IO_CLONE_TAG = 0x021B,
|
CMD_IO_CLONE_TAG = 0x021B,
|
||||||
CMD_EM410X_DEMOD = 0x021C,
|
CMD_EM410X_DEMOD = 0x021c,
|
||||||
--/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
|
--/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
|
||||||
|
|
||||||
--// For the 13.56 MHz tags
|
--// For the 13.56 MHz tags
|
||||||
|
|
|
@ -1,63 +1,195 @@
|
||||||
local _names = {
|
local _names = {
|
||||||
--[[
|
--[[
|
||||||
--]]
|
--]]
|
||||||
["0400"]="BASH",
|
["0000"]="WHIRLWIND",
|
||||||
["1600"]="BOOMER" ,
|
|
||||||
["1800"]="CAMO",
|
|
||||||
["3000"]="CHOPCHOP" ,
|
|
||||||
["2000"]="CYNDER",
|
|
||||||
["6400"]="JET-VAC",
|
|
||||||
["6700"]="FLASHWING",
|
|
||||||
["7000"]="TREE REX",
|
|
||||||
["7100"]="LIGHTCORE SHROOMBOOM",
|
|
||||||
["1C00"]="DARK SPYRO",
|
|
||||||
["0600"]="DINORANG" ,
|
|
||||||
["1200"]="DOUBLE TROUBLE" ,
|
|
||||||
["1500"]="DRILLSERGEANT" ,
|
|
||||||
["1400"]="DROBOT",
|
|
||||||
["0900"]="LIGHTCORE ERUPTOR" ,
|
|
||||||
["0B00"]="FLAMESLINGER" ,
|
|
||||||
["1F00"]="GHOST ROASTER",
|
|
||||||
["0E00"]="GILL GRUNT" ,
|
|
||||||
["1D00"]="HEX",
|
|
||||||
["0A00"]="IGNITOR",
|
|
||||||
["0300"]="LIGHTNINGROD",
|
|
||||||
["0700"]="LIGHTCORE PRISM BREAK",
|
|
||||||
["1500"]="SLAMBAM",
|
|
||||||
["0100"]="SONIC BOOM",
|
["0100"]="SONIC BOOM",
|
||||||
|
["0200"]="WARNADO",
|
||||||
|
["0300"]="LIGHTNINGROD",
|
||||||
|
["0400"]="BASH",
|
||||||
|
["0500"]="TERRAFIN",
|
||||||
|
["0600"]="DINORANG" ,
|
||||||
|
["0700"]="LIGHTCORE PRISM BREAK",
|
||||||
|
["0800"]="SUNBURN",
|
||||||
|
["0900"]="LIGHTCORE ERUPTOR",
|
||||||
|
["0A00"]="IGNITOR",
|
||||||
|
["0B00"]="FLAMESLINGER",
|
||||||
|
["0C00"]="ZAP",
|
||||||
|
["0D00"]="WHAM SHELL",
|
||||||
|
["0E00"]="GILL GRUNT",
|
||||||
|
["0F00"]="SLAMBAM",
|
||||||
["1000"]="SPYRO",
|
["1000"]="SPYRO",
|
||||||
|
["1100"]="VOODOOD",
|
||||||
|
["1200"]="DOUBLE TROUBLE",
|
||||||
|
["1300"]="TRIGGER HAPPY",
|
||||||
|
["1400"]="DROBOT",
|
||||||
|
["1500"]="DRILLSERGEANT",
|
||||||
|
["1600"]="BOOMER",
|
||||||
|
["1700"]="WRECKING BALL",
|
||||||
|
["1800"]="CAMO",
|
||||||
|
["1900"]="ZOOK",
|
||||||
["1A00"]="STEALTH ELF",
|
["1A00"]="STEALTH ELF",
|
||||||
["1B00"]="STUMP SMASH",
|
["1B00"]="STUMP SMASH",
|
||||||
["0800"]="SUNBURN",
|
["1D00"]="HEX",
|
||||||
["0500"]="TERRAFIN",
|
["1C00"]="DARK SPYRO",
|
||||||
["1300"]="TRIGGER HAPPY",
|
["1E00"]="CHOPCHOP",
|
||||||
["1100"]="VOODOOD",
|
["1F00"]="GHOST ROASTER",
|
||||||
["0200"]="WARNADO",
|
["2000"]="CYNDER",
|
||||||
["0D00"]="WHAM SHELL",
|
--[[
|
||||||
["0000"]="WHIRLWIND",
|
GIANTS
|
||||||
["1700"]="WRECKING BALL",
|
--]]
|
||||||
["0C00"]="ZAP",
|
["6400"]="GIANT JET-VAC",
|
||||||
["1900"]="ZOOK",
|
["6500"]="GIANT SWARM",
|
||||||
["0300"]="DRAGON",
|
["6600"]="GIANT CRUSHER",
|
||||||
["012D"]="ICE",
|
["6700"]="GIANT FLASHWING",
|
||||||
["012E"]="PIRATE",
|
["6800"]="GIANT HOTHEAD",
|
||||||
["0130"]="PVPUNLOCK",
|
["6900"]="GIANT HOTDOG",
|
||||||
["012F"]="UNDEAD",
|
["6A00"]="GIANT CHILL",
|
||||||
["0200"]="ANVIL" ,
|
["6B00"]="GIANT THUMPBACK",
|
||||||
|
["6C00"]="GIANT POPFIZZ",
|
||||||
|
["6D00"]="GIANT NINJINI",
|
||||||
|
["6E00"]="GIANT BOUNCER",
|
||||||
|
["6F00"]="GIANT SPROCKET",
|
||||||
|
["7000"]="GIANT TREE REX",
|
||||||
|
["7100"]="LIGHTCORE SHROOMBOOM",
|
||||||
|
["7200"]="GIANT EYEBROAWL",
|
||||||
|
["7300"]="GIANT FRIGHTRIDER",
|
||||||
|
|
||||||
|
--[[
|
||||||
|
ITEM
|
||||||
|
--]]
|
||||||
|
["C800"]="ANVIL",
|
||||||
|
["C900"]="SECRET STASH",
|
||||||
|
["CA00"]="REGENERATION",
|
||||||
|
["CD00"]="SHIELD",
|
||||||
["CB00"]="CROSSED SWORDS",
|
["CB00"]="CROSSED SWORDS",
|
||||||
["CC00"]="HOURGLASS",
|
["CC00"]="HOURGLASS",
|
||||||
["CA00"]="REGENERATION",
|
|
||||||
["C900"]="SECRET STASH",
|
|
||||||
["CD00"]="SHIELD",
|
|
||||||
["CF00"]="SPARX",
|
|
||||||
["CE00"]="SPEED BOOTS",
|
["CE00"]="SPEED BOOTS",
|
||||||
|
["CF00"]="SPARX",
|
||||||
|
["D000"]="CANNON",
|
||||||
|
["D100"]="SCORPIONSTRIKER",
|
||||||
|
|
||||||
|
--[[
|
||||||
|
ITEM TRAPS
|
||||||
|
--]]
|
||||||
|
["D200"]="MAGIC TRAP",
|
||||||
|
["D300"]="WATER TRAP",
|
||||||
|
["D400"]="AIR TRAP",
|
||||||
|
["D600"]="TECH TRAP",
|
||||||
|
["D700"]="FIRE TRAP",
|
||||||
|
["D800"]="EARTH TRAP",
|
||||||
|
["D900"]="LIFE TRAP",
|
||||||
|
["DA00"]="DARK TRAP",
|
||||||
|
["DB00"]="LIGHT TRAP",
|
||||||
|
["DC00"]="KAOS TRAP",
|
||||||
|
|
||||||
|
--[[
|
||||||
|
ITEM
|
||||||
|
--]]
|
||||||
|
["E600"]="HAND OF FATE",
|
||||||
|
["E700"]="PIGGYBANK",
|
||||||
|
["E800"]="ROCKET RAM",
|
||||||
|
["E900"]="TIKI SPEAKY",
|
||||||
|
|
||||||
|
|
||||||
|
--[[
|
||||||
|
EXPANSION
|
||||||
|
--]]
|
||||||
|
["012C"]="DRAGON",
|
||||||
|
["012D"]="ICE",
|
||||||
|
["012E"]="PIRATE",
|
||||||
|
["012F"]="UNDEAD",
|
||||||
|
["0130"]="PVPUNLOCK",
|
||||||
|
["0131"]="MIRROR OF MYSTERY",
|
||||||
|
["0132"]="NIGHTMARE EXPRESS",
|
||||||
|
["0133"]="SUNSCRAPER SPIRE",
|
||||||
|
["0134"]="MIDNIGHT MUSEUM",
|
||||||
|
|
||||||
|
--[[
|
||||||
|
LEGENDARY
|
||||||
|
--]]
|
||||||
["0194"]="LEGENDARY BASH",
|
["0194"]="LEGENDARY BASH",
|
||||||
["0430"]="LEGENDARY CHOPCHOP",
|
|
||||||
["01A0"]="LEGENDARY SPYRO",
|
["01A0"]="LEGENDARY SPYRO",
|
||||||
["01A3"]="LEGENDARY TRIGGER HAPPY",
|
["01A3"]="LEGENDARY TRIGGER HAPPY",
|
||||||
["0202"]="PET GILL GRUNT",
|
["01AE"]="LEGENDARY CHOPCHOP",
|
||||||
["020E"]="PET STEALTH ELF",
|
|
||||||
|
--[[
|
||||||
|
TRAPTEAM
|
||||||
|
--]]
|
||||||
|
["01C2"]="TRAPTEAM GUSTO",
|
||||||
|
["01C3"]="TRAPTEAM THUNDERBOLT",
|
||||||
|
["01C4"]="TRAPTEAM FLINGKONG",
|
||||||
|
["01C5"]="TRAPTEAM BLADES",
|
||||||
|
["01C6"]="TRAPTEAM WALLOP",
|
||||||
|
["01C7"]="TRAPTEAM HEADRUSH",
|
||||||
|
["01C8"]="TRAPTEAM FISTBUMP",
|
||||||
|
["01C9"]="TRAPTEAM ROCKYROLL",
|
||||||
|
["01CA"]="TRAPTEAM WILDFIRE",
|
||||||
|
["01CB"]="TRAPTEAM KABOOM",
|
||||||
|
["01CC"]="TRAPTEAM TRAILBLAZER",
|
||||||
|
["01CD"]="TRAPTEAM TORCH",
|
||||||
|
["01CE"]="TRAPTEAM SNAPSHOT",
|
||||||
|
["01CF"]="TRAPTEAM LOBSTAR",
|
||||||
|
["01D0"]="TRAPTEAM FLIPWRECK",
|
||||||
|
["01D1"]="TRAPTEAM ECHO",
|
||||||
|
["01D2"]="TRAPTEAM BLASTERMIND",
|
||||||
|
["01D3"]="TRAPTEAM ENIGMA",
|
||||||
|
["01D4"]="TRAPTEAM DEJAVU",
|
||||||
|
["01D5"]="TRAPTEAM COBRA CADABRA",
|
||||||
|
["01D6"]="TRAPTEAM JAWBREAKER",
|
||||||
|
["01D7"]="TRAPTEAM GEARSHIFT",
|
||||||
|
["01D8"]="TRAPTEAM CHOPPER",
|
||||||
|
["01D9"]="TRAPTEAM TREADHEAD",
|
||||||
|
["01DA"]="TRAPTEAM BUSHWHACK",
|
||||||
|
["01DB"]="TRAPTEAM TUFF LUCK",
|
||||||
|
["01DC"]="TRAPTEAM FOODFIGHT",
|
||||||
|
["01DD"]="TRAPTEAM HIGHFIVE",
|
||||||
|
["01DE"]="TRAPTEAM KRYPTKING",
|
||||||
|
["01DF"]="TRAPTEAM SHORTCUT",
|
||||||
|
["01E0"]="TRAPTEAM BATSPIN",
|
||||||
|
["01E1"]="TRAPTEAM FUNNYBONE",
|
||||||
|
["01E2"]="TRAPTEAM KNIGHTLIGHT",
|
||||||
|
["01E3"]="TRAPTEAM SPOTLIGHT",
|
||||||
|
["01E4"]="TRAPTEAM KNIGHTMARE",
|
||||||
|
["01E5"]="TRAPTEAM BLACKOUT",
|
||||||
|
|
||||||
|
--[[
|
||||||
|
PET
|
||||||
|
--]]
|
||||||
|
["01F6"]="PET BOP",
|
||||||
|
["01F7"]="PET SPRY",
|
||||||
|
["01F8"]="PET HIJINX",
|
||||||
["01F9"]="PET TERRAFIN",
|
["01F9"]="PET TERRAFIN",
|
||||||
|
["01FA"]="PET BREEZE",
|
||||||
|
["01FB"]="PET WEERUPTOR",
|
||||||
|
["01FC"]="PET PETVAC",
|
||||||
|
["01FD"]="PET SMALLFRY",
|
||||||
|
["01FE"]="PET DROBIT",
|
||||||
|
["0202"]="PET GILL GRUNT",
|
||||||
["0207"]="PET TRIGGER HAPPY",
|
["0207"]="PET TRIGGER HAPPY",
|
||||||
|
["020E"]="PET STEALTH ELF",
|
||||||
|
["021C"]="PET BARKLEY",
|
||||||
|
["021D"]="PET THUMPLING",
|
||||||
|
["021E"]="PET MINI JINI",
|
||||||
|
["021F"]="PET EYE SMALL",
|
||||||
|
|
||||||
|
--[[
|
||||||
|
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 ZOOLOU",
|
||||||
|
["0BC0"]="SWAPFORCE DUNE BUG",
|
||||||
|
["0BC1"]="SWAPFORCE STAR STRIKE",
|
||||||
|
["0BC2"]="SWAPFORCE COUNTDOWN",
|
||||||
|
["0BC3"]="SWAPFORCE WINDUP",
|
||||||
|
["0BC4"]="SWAPFORCE ROLLER BRAWL",
|
||||||
|
["0BC5"]="SWAPFORCE GRIM CREEPER",
|
||||||
|
["0BC6"]="SWAPFORCE RIPTIDE",
|
||||||
|
["0BC7"]="SWAPFORCE PUNKSHOCK",
|
||||||
}
|
}
|
||||||
return _names
|
return _names
|
||||||
|
|
|
@ -108,6 +108,24 @@ local Utils =
|
||||||
return retval
|
return retval
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
-- input parameter is a string
|
||||||
|
-- Swaps the endianess and returns a string,
|
||||||
|
-- IE: 'cd7a' -> '7acd' -> 0x7acd
|
||||||
|
SwapEndiannessStr = function(s, len)
|
||||||
|
if s == nil then return nil end
|
||||||
|
if #s == 0 then return '' end
|
||||||
|
if type(s) ~= 'string' then return nil end
|
||||||
|
|
||||||
|
local retval
|
||||||
|
if len == 16 then
|
||||||
|
retval = s:sub(3,4)..s:sub(1,2)
|
||||||
|
elseif len == 24 then
|
||||||
|
retval = s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
|
||||||
|
elseif len == 32 then
|
||||||
|
retval = s:sub(7,8)..s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
|
||||||
|
end
|
||||||
|
return retval
|
||||||
|
end,
|
||||||
------------ CONVERSIONS
|
------------ CONVERSIONS
|
||||||
|
|
||||||
--
|
--
|
||||||
|
@ -116,7 +134,7 @@ local Utils =
|
||||||
local B,K,OUT,I,D=16,"0123456789ABCDEF","",0
|
local B,K,OUT,I,D=16,"0123456789ABCDEF","",0
|
||||||
while IN>0 do
|
while IN>0 do
|
||||||
I=I+1
|
I=I+1
|
||||||
IN,D=math.floor(IN/B),math.mod(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
|
||||||
|
|
|
@ -232,14 +232,27 @@ int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount) {
|
||||||
// "MAGIC" CARD
|
// "MAGIC" CARD
|
||||||
|
|
||||||
int mfCSetUID(uint8_t *uid, uint8_t *oldUID, bool wantWipe) {
|
int mfCSetUID(uint8_t *uid, uint8_t *oldUID, bool wantWipe) {
|
||||||
|
|
||||||
|
uint8_t oldblock0[16] = {0x00};
|
||||||
uint8_t block0[16] = {0x00};
|
uint8_t block0[16] = {0x00};
|
||||||
memcpy(block0, uid, 4);
|
memcpy(block0, uid, 4);
|
||||||
block0[4] = block0[0]^block0[1]^block0[2]^block0[3]; // Mifare UID BCC
|
block0[4] = block0[0]^block0[1]^block0[2]^block0[3]; // Mifare UID BCC
|
||||||
// mifare classic SAK(byte 5) and ATQA(byte 6 and 7)
|
// mifare classic SAK(byte 5) and ATQA(byte 6 and 7)
|
||||||
block0[5] = 0x08;
|
//block0[5] = 0x08;
|
||||||
block0[6] = 0x04;
|
//block0[6] = 0x04;
|
||||||
block0[7] = 0x00;
|
//block0[7] = 0x00;
|
||||||
|
|
||||||
|
block0[5] = 0x01; //sak
|
||||||
|
block0[6] = 0x01;
|
||||||
|
block0[7] = 0x0f;
|
||||||
|
|
||||||
|
int old = mfCGetBlock(0, oldblock0, CSETBLOCK_SINGLE_OPER);
|
||||||
|
if ( old == 0) {
|
||||||
|
memcpy(block0+8, oldblock0+8, 8);
|
||||||
|
PrintAndLog("block 0: %s", sprint_hex(block0,16));
|
||||||
|
} else {
|
||||||
|
PrintAndLog("Couldn't get olddata. Will write over the last bytes of Block 0.");
|
||||||
|
}
|
||||||
return mfCSetBlock(0, block0, oldUID, wantWipe, CSETBLOCK_SINGLE_OPER);
|
return mfCSetBlock(0, block0, oldUID, wantWipe, CSETBLOCK_SINGLE_OPER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,8 +266,10 @@ int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWipe, uin
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||||
isOK = resp.arg[0] & 0xff;
|
isOK = resp.arg[0] & 0xff;
|
||||||
if (uid != NULL) memcpy(uid, resp.d.asBytes, 4);
|
if (uid != NULL)
|
||||||
if (!isOK) return 2;
|
memcpy(uid, resp.d.asBytes, 4);
|
||||||
|
if (!isOK)
|
||||||
|
return 2;
|
||||||
} else {
|
} else {
|
||||||
PrintAndLog("Command execute timeout");
|
PrintAndLog("Command execute timeout");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -286,9 +301,9 @@ int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params) {
|
||||||
static uint8_t trailerAccessBytes[4] = {0x08, 0x77, 0x8F, 0x00};
|
static uint8_t trailerAccessBytes[4] = {0x08, 0x77, 0x8F, 0x00};
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
char logHexFileName[200] = {0x00};
|
char logHexFileName[FILE_PATH_SIZE] = {0x00};
|
||||||
static uint8_t traceCard[4096] = {0x00};
|
static uint8_t traceCard[4096] = {0x00};
|
||||||
static char traceFileName[200] = {0x00};
|
static char traceFileName[FILE_PATH_SIZE] = {0x00};
|
||||||
static int traceState = TRACE_IDLE;
|
static int traceState = TRACE_IDLE;
|
||||||
static uint8_t traceCurBlock = 0;
|
static uint8_t traceCurBlock = 0;
|
||||||
static uint8_t traceCurKey = 0;
|
static uint8_t traceCurKey = 0;
|
||||||
|
@ -323,20 +338,28 @@ int isBlockTrailer(int blockN) {
|
||||||
|
|
||||||
int loadTraceCard(uint8_t *tuid) {
|
int loadTraceCard(uint8_t *tuid) {
|
||||||
FILE * f;
|
FILE * f;
|
||||||
char buf[64];
|
char buf[64] = {0x00};
|
||||||
uint8_t buf8[64];
|
uint8_t buf8[64] = {0x00};
|
||||||
int i, blockNum;
|
int i, blockNum;
|
||||||
|
|
||||||
if (!isTraceCardEmpty()) saveTraceCard();
|
if (!isTraceCardEmpty())
|
||||||
|
saveTraceCard();
|
||||||
|
|
||||||
memset(traceCard, 0x00, 4096);
|
memset(traceCard, 0x00, 4096);
|
||||||
memcpy(traceCard, tuid + 3, 4);
|
memcpy(traceCard, tuid + 3, 4);
|
||||||
|
|
||||||
FillFileNameByUID(traceFileName, tuid, ".eml", 7);
|
FillFileNameByUID(traceFileName, tuid, ".eml", 7);
|
||||||
|
|
||||||
f = fopen(traceFileName, "r");
|
f = fopen(traceFileName, "r");
|
||||||
if (!f) return 1;
|
if (!f) {
|
||||||
|
fclose(f);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
blockNum = 0;
|
blockNum = 0;
|
||||||
|
|
||||||
while(!feof(f)){
|
while(!feof(f)){
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
if (fgets(buf, sizeof(buf), f) == NULL) {
|
if (fgets(buf, sizeof(buf), f) == NULL) {
|
||||||
PrintAndLog("File reading error.");
|
PrintAndLog("File reading error.");
|
||||||
|
@ -368,22 +391,30 @@ 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 ) {
|
||||||
|
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
|
||||||
fprintf(f, "%02x", *(traceCard + i * 16 + j));
|
fprintf(f, "%02x", *(traceCard + i * 16 + j));
|
||||||
fprintf(f,"\n");
|
fprintf(f,"\n");
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mfTraceInit(uint8_t *tuid, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFile) {
|
int mfTraceInit(uint8_t *tuid, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFile) {
|
||||||
|
|
||||||
if (traceCrypto1) crypto1_destroy(traceCrypto1);
|
if (traceCrypto1)
|
||||||
|
crypto1_destroy(traceCrypto1);
|
||||||
|
|
||||||
traceCrypto1 = NULL;
|
traceCrypto1 = NULL;
|
||||||
|
|
||||||
if (wantSaveToEmlFile) loadTraceCard(tuid);
|
if (wantSaveToEmlFile)
|
||||||
|
loadTraceCard(tuid);
|
||||||
|
|
||||||
traceCard[4] = traceCard[0] ^ traceCard[1] ^ traceCard[2] ^ traceCard[3];
|
traceCard[4] = traceCard[0] ^ traceCard[1] ^ traceCard[2] ^ traceCard[3];
|
||||||
traceCard[5] = sak;
|
traceCard[5] = sak;
|
||||||
memcpy(&traceCard[6], atqa, 2);
|
memcpy(&traceCard[6], atqa, 2);
|
||||||
|
|
|
@ -47,7 +47,7 @@ typedef struct {
|
||||||
int foundKey[2];
|
int foundKey[2];
|
||||||
} sector;
|
} sector;
|
||||||
|
|
||||||
extern char logHexFileName[200];
|
extern char logHexFileName[FILE_PATH_SIZE];
|
||||||
|
|
||||||
int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * ResultKeys, bool calibrate);
|
int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * ResultKeys, bool calibrate);
|
||||||
int mfCheckKeys (uint8_t blockNo, uint8_t keyType, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key);
|
int mfCheckKeys (uint8_t blockNo, uint8_t keyType, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key);
|
||||||
|
|
63
client/scripts/remagic.lua
Normal file
63
client/scripts/remagic.lua
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
local getopt = require('getopt')
|
||||||
|
|
||||||
|
example = "script run remagic"
|
||||||
|
author = "Iceman"
|
||||||
|
|
||||||
|
desc =
|
||||||
|
[[
|
||||||
|
This is a script that tries to bring back a chinese magic card (1k generation1)
|
||||||
|
from the dead when it's block 0 has been written with bad values.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
-h this help
|
||||||
|
]]
|
||||||
|
---
|
||||||
|
-- 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)
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Usage help
|
||||||
|
function help()
|
||||||
|
print(desc)
|
||||||
|
print("Example usage")
|
||||||
|
print(example)
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- The main entry point
|
||||||
|
function main(args)
|
||||||
|
|
||||||
|
|
||||||
|
-- Read the parameters
|
||||||
|
for o, a in getopt.getopt(args, 'h') do
|
||||||
|
if o == "h" then help() return end
|
||||||
|
end
|
||||||
|
|
||||||
|
local _cmds = {
|
||||||
|
--[[
|
||||||
|
--]]
|
||||||
|
[0] = "hf 14a raw -p -a -b 7 40",
|
||||||
|
[1] = "hf 14a raw -p -a 43",
|
||||||
|
[2] = "hf 14a raw -c -p -a A000",
|
||||||
|
[3] = "hf 14a raw -c -p -a 01 02 03 04 04 98 02 00 00 00 00 00 00 00 10 01",
|
||||||
|
}
|
||||||
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
|
local i
|
||||||
|
--for _,c in pairs(_cmds) do
|
||||||
|
for i = 0, 3 do
|
||||||
|
print ( _cmds[i] )
|
||||||
|
core.console( _cmds[i] )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
main(args)
|
173
client/scripts/test_t55x7_psk.lua
Normal file
173
client/scripts/test_t55x7_psk.lua
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
local cmds = require('commands')
|
||||||
|
local getopt = require('getopt')
|
||||||
|
local bin = require('bin')
|
||||||
|
local utils = require('utils')
|
||||||
|
local dumplib = require('html_dumplib')
|
||||||
|
|
||||||
|
example =[[
|
||||||
|
1. script run tracetest
|
||||||
|
2. script run tracetest -o
|
||||||
|
|
||||||
|
]]
|
||||||
|
author = "Iceman"
|
||||||
|
usage = "script run test_t55x7_psk -o <filename>"
|
||||||
|
desc =[[
|
||||||
|
This script will program a T55x7 TAG with the configuration: block 0x00 data 0x00088040
|
||||||
|
The outlined procedure is as following:
|
||||||
|
|
||||||
|
"lf t55xx write 0 00088040"
|
||||||
|
"lf read"
|
||||||
|
"data samples"
|
||||||
|
"data pskdet"
|
||||||
|
"data psknrz"
|
||||||
|
"data pskindala"
|
||||||
|
"data psknrzraw"
|
||||||
|
|
||||||
|
Loop OUTER:
|
||||||
|
change the configuretion block 0 with:
|
||||||
|
-xxxx8xxx = PSK RF/2 with Manchester modulation
|
||||||
|
-xxxx1xxx = PSK RF/2 with PSK1 modulation (phase change when input changes)
|
||||||
|
-xxxx2xxx = PSK RF/2 with PSk2 modulation (phase change on bitclk if input high)
|
||||||
|
-xxxx3xxx = PSK RF/2 with PSk3 modulation (phase change on rising edge of input)
|
||||||
|
Loop INNER
|
||||||
|
for each outer configuration, also do
|
||||||
|
XXXXX0XX = PSK RF/2
|
||||||
|
XXXXX4XX = PSK RF/4
|
||||||
|
XXXXX8XX = PSK RF/8
|
||||||
|
|
||||||
|
In all 12 individual test for the PSK demod
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
-h : this help
|
||||||
|
-o : logfile name
|
||||||
|
]]
|
||||||
|
|
||||||
|
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
||||||
|
local DEBUG = true -- the debug flag
|
||||||
|
|
||||||
|
--BLOCK 0 = 00088040
|
||||||
|
local config1 = '0008'
|
||||||
|
local config2 = '40'
|
||||||
|
|
||||||
|
local procedurecmds = {
|
||||||
|
[1] = '%s%s%s%s',
|
||||||
|
[2] = 'lf read',
|
||||||
|
--[3] = '',
|
||||||
|
[3] = 'data samples',
|
||||||
|
[4] = 'data pskdetectclock',
|
||||||
|
[5] = 'data psknrzrawdemod',
|
||||||
|
[6] = 'data pskindalademod',
|
||||||
|
}
|
||||||
|
|
||||||
|
---
|
||||||
|
-- A debug printout-function
|
||||||
|
function dbg(args)
|
||||||
|
if not DEBUG then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(args) == "table" then
|
||||||
|
local i = 1
|
||||||
|
while args[i] do
|
||||||
|
dbg(args[i])
|
||||||
|
i = i+1
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print("###", args)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- This is only meant to be used when errors occur
|
||||||
|
function oops(err)
|
||||||
|
print("ERROR: ",err)
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- Usage help
|
||||||
|
function help()
|
||||||
|
print(desc)
|
||||||
|
print("Example usage")
|
||||||
|
print(example)
|
||||||
|
end
|
||||||
|
--
|
||||||
|
-- Exit message
|
||||||
|
function ExitMsg(msg)
|
||||||
|
print( string.rep('--',20) )
|
||||||
|
print( string.rep('--',20) )
|
||||||
|
print(msg)
|
||||||
|
print()
|
||||||
|
end
|
||||||
|
|
||||||
|
function pskTest(modulation)
|
||||||
|
local y
|
||||||
|
for y = 0, 8, 4 do
|
||||||
|
for _ = 1, #procedurecmds do
|
||||||
|
local cmd = procedurecmds[_]
|
||||||
|
|
||||||
|
if #cmd == 0 then
|
||||||
|
|
||||||
|
elseif _ == 1 then
|
||||||
|
|
||||||
|
dbg("Writing to T55x7 TAG")
|
||||||
|
|
||||||
|
local configdata = cmd:format( config1, modulation , y, config2)
|
||||||
|
|
||||||
|
dbg( configdata)
|
||||||
|
|
||||||
|
local writecommand = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK, arg1 = configdata ,arg2 = 0, arg3 = 0}
|
||||||
|
local err = core.SendCommand(writecommand:getBytes())
|
||||||
|
if err then return oops(err) end
|
||||||
|
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
|
||||||
|
|
||||||
|
if response then
|
||||||
|
local count,cmd,arg0 = bin.unpack('LL',response)
|
||||||
|
if(arg0==1) then
|
||||||
|
dbg("Writing success")
|
||||||
|
else
|
||||||
|
return nil, "Couldn't read block.."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
dbg(cmd)
|
||||||
|
core.console( cmd )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
core.clearCommandBuffer()
|
||||||
|
end
|
||||||
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local function main(args)
|
||||||
|
|
||||||
|
print( string.rep('--',20) )
|
||||||
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
|
local outputTemplate = os.date("testpsk_%Y-%m-%d_%H%M%S")
|
||||||
|
|
||||||
|
-- Arguments for the script
|
||||||
|
for o, arg in getopt.getopt(args, 'ho:') do
|
||||||
|
if o == "h" then return help() end
|
||||||
|
if o == "o" then outputTemplate = arg end
|
||||||
|
end
|
||||||
|
|
||||||
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
|
pskTest(1)
|
||||||
|
pskTest(2)
|
||||||
|
pskTest(3)
|
||||||
|
pskTest(8)
|
||||||
|
|
||||||
|
print( string.rep('--',20) )
|
||||||
|
end
|
||||||
|
main(args)
|
||||||
|
|
||||||
|
-- Where it iterates over
|
||||||
|
-- xxxx8xxx = PSK RF/2 with Manchester modulation
|
||||||
|
-- xxxx1xxx = PSK RF/2 with PSK1 modulation (phase change when input changes)
|
||||||
|
-- xxxx2xxx = PSK RF/2 with PSk2 modulation (phase change on bitclk if input high)
|
||||||
|
-- xxxx3xxx = PSK RF/2 with PSk3 modulation (phase change on rising edge of input)
|
||||||
|
|
||||||
|
-- XXXXX0XX = PSK RF/2
|
||||||
|
-- XXXXX4XX = PSK RF/4
|
||||||
|
-- XXXXX8XX = PSK RF/8
|
|
@ -249,23 +249,27 @@ local function main(args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Write dump to files
|
|
||||||
if not DEBUG then
|
|
||||||
local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'.bin')
|
|
||||||
print(("Wrote a BIN dump to the file %s"):format(foo))
|
|
||||||
local bar = dumplib.SaveAsText(emldata, outputTemplate..'.eml')
|
|
||||||
print(("Wrote a EML dump to the file %s"):format(bar))
|
|
||||||
end
|
|
||||||
|
|
||||||
local uid = block0:sub(1,8)
|
local uid = block0:sub(1,8)
|
||||||
local itemtype = block1:sub(1,4)
|
local itemtype = block1:sub(1,4)
|
||||||
local cardid = block1:sub(9,24)
|
local cardid = block1:sub(9,24)
|
||||||
|
local traptype = block1:sub(25,28)
|
||||||
|
|
||||||
|
-- Write dump to files
|
||||||
|
if not DEBUG then
|
||||||
|
local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'_uid_'..uid..'.bin')
|
||||||
|
print(("Wrote a BIN dump to the file %s"):format(foo))
|
||||||
|
local bar = dumplib.SaveAsText(emldata, outputTemplate..'_uid_'..uid..'.eml')
|
||||||
|
print(("Wrote a EML dump to the file %s"):format(bar))
|
||||||
|
end
|
||||||
|
|
||||||
-- Show info
|
-- Show info
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
print( (' ITEM TYPE : 0x%s - %s'):format(itemtype, toyNames[itemtype]) )
|
print( (' ITEM TYPE : 0x%s - %s'):format(itemtype, toyNames[itemtype]) )
|
||||||
print( (' UID : 0x%s'):format(uid) )
|
print( (' Alter ego / traptype : 0x%s'):format(traptype) )
|
||||||
print( (' CARDID : 0x%s'):format(cardid ) )
|
print( (' UID : 0x%s'):format(uid) )
|
||||||
|
print( (' CARDID : 0x%s'):format(cardid ) )
|
||||||
|
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -241,18 +241,20 @@ local function main(args)
|
||||||
local cmdSetDbgOff = "hf mf dbg 0"
|
local cmdSetDbgOff = "hf mf dbg 0"
|
||||||
core.console( cmdSetDbgOff)
|
core.console( cmdSetDbgOff)
|
||||||
|
|
||||||
-- Look for tag present on reader,
|
-- if not loadFromDump then
|
||||||
result, err = lib14a.read1443a(false)
|
-- -- Look for tag present on reader,
|
||||||
if not result then return oops(err) end
|
-- result, err = lib14a.read1443a(false)
|
||||||
|
-- if not result then return oops(err) end
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
-- core.clearCommandBuffer()
|
||||||
|
|
||||||
if 0x01 ~= result.sak then -- NXP MIFARE TNP3xxx
|
-- if 0x01 ~= result.sak then -- NXP MIFARE TNP3xxx
|
||||||
return oops('This is not a TNP3xxx tag. aborting.')
|
-- return oops('This is not a TNP3xxx tag. aborting.')
|
||||||
end
|
-- end
|
||||||
|
|
||||||
-- Show tag info
|
-- -- Show tag info
|
||||||
print((' Found tag : %s'):format(result.name))
|
-- 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))
|
||||||
|
@ -349,7 +351,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 5 '..uid..'\" <--')
|
print('The simulation is now prepared.\n --> run \"hf mf sim u '..uid..' x\" <--')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
main(args)
|
main(args)
|
132
client/scripts/tracetest.lua
Normal file
132
client/scripts/tracetest.lua
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
local cmds = require('commands')
|
||||||
|
local getopt = require('getopt')
|
||||||
|
local bin = require('bin')
|
||||||
|
local utils = require('utils')
|
||||||
|
local dumplib = require('html_dumplib')
|
||||||
|
|
||||||
|
example =[[
|
||||||
|
1. script run tracetest
|
||||||
|
2. script run tracetest -o
|
||||||
|
|
||||||
|
]]
|
||||||
|
author = "Iceman"
|
||||||
|
usage = "script run tracetest -o <filename>"
|
||||||
|
desc =[[
|
||||||
|
This script will load several traces files in ../traces/ folder and do
|
||||||
|
"data load"
|
||||||
|
"lf search"
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
-h : this help
|
||||||
|
-o : logfile name
|
||||||
|
]]
|
||||||
|
|
||||||
|
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
||||||
|
local DEBUG = true -- the debug flag
|
||||||
|
---
|
||||||
|
-- A debug printout-function
|
||||||
|
function dbg(args)
|
||||||
|
if not DEBUG then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(args) == "table" then
|
||||||
|
local i = 1
|
||||||
|
while result[i] do
|
||||||
|
dbg(result[i])
|
||||||
|
i = i+1
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print("###", args)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- This is only meant to be used when errors occur
|
||||||
|
function oops(err)
|
||||||
|
print("ERROR: ",err)
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- Usage help
|
||||||
|
function help()
|
||||||
|
print(desc)
|
||||||
|
print("Example usage")
|
||||||
|
print(example)
|
||||||
|
end
|
||||||
|
--
|
||||||
|
-- Exit message
|
||||||
|
function ExitMsg(msg)
|
||||||
|
print( string.rep('--',20) )
|
||||||
|
print( string.rep('--',20) )
|
||||||
|
print(msg)
|
||||||
|
print()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function main(args)
|
||||||
|
|
||||||
|
print( string.rep('--',20) )
|
||||||
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
|
local cmdDataLoad = 'data load %s';
|
||||||
|
local tracesEM = "find '../traces/' -iname 'em*.pm3' -type f"
|
||||||
|
local tracesMOD = "find '../traces/' -iname 'm*.pm3' -type f"
|
||||||
|
|
||||||
|
local outputTemplate = os.date("testtest_%Y-%m-%d_%H%M%S")
|
||||||
|
|
||||||
|
-- Arguments for the script
|
||||||
|
for o, arg in getopt.getopt(args, 'ho:') do
|
||||||
|
if o == "h" then return help() end
|
||||||
|
if o == "o" then outputTemplate = arg end
|
||||||
|
end
|
||||||
|
|
||||||
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
|
local files = {}
|
||||||
|
|
||||||
|
-- Find a set of traces staring with EM
|
||||||
|
local p = assert( io.popen(tracesEM))
|
||||||
|
for file in p:lines() do
|
||||||
|
table.insert(files, file)
|
||||||
|
end
|
||||||
|
p.close();
|
||||||
|
|
||||||
|
-- Find a set of traces staring with MOD
|
||||||
|
p = assert( io.popen(tracesMOD) )
|
||||||
|
for file in p:lines() do
|
||||||
|
table.insert(files, file)
|
||||||
|
end
|
||||||
|
p.close();
|
||||||
|
|
||||||
|
local cmdLFSEARCH = "lf search 1"
|
||||||
|
|
||||||
|
-- main loop
|
||||||
|
io.write('Starting to test traces > ')
|
||||||
|
for _,file in pairs(files) do
|
||||||
|
|
||||||
|
local x = "data load "..file
|
||||||
|
dbg(x)
|
||||||
|
core.console(x)
|
||||||
|
|
||||||
|
dbg(cmdLFSEARCH)
|
||||||
|
core.console(cmdLFSEARCH)
|
||||||
|
|
||||||
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
|
if core.ukbhit() then
|
||||||
|
print("aborted by user")
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
io.write('\n')
|
||||||
|
|
||||||
|
-- Write dump to files
|
||||||
|
if not DEBUG then
|
||||||
|
local bar = dumplib.SaveAsText(emldata, outputTemplate..'.txt')
|
||||||
|
print(("Wrote output to: %s"):format(bar))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Show info
|
||||||
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
|
end
|
||||||
|
main(args)
|
|
@ -213,6 +213,7 @@ int param_getptr(const char *line, int *bg, int *en, int paramnum)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char param_getchar(const char *line, int paramnum)
|
char param_getchar(const char *line, int paramnum)
|
||||||
{
|
{
|
||||||
int bg, en;
|
int bg, en;
|
||||||
|
@ -227,6 +228,36 @@ uint8_t param_get8(const char *line, int paramnum)
|
||||||
return param_get8ex(line, paramnum, 10, 0);
|
return param_get8ex(line, paramnum, 10, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads a decimal integer (actually, 0-254, not 255)
|
||||||
|
* @param line
|
||||||
|
* @param paramnum
|
||||||
|
* @return -1 if error
|
||||||
|
*/
|
||||||
|
uint8_t param_getdec(const char *line, int paramnum, uint8_t *destination)
|
||||||
|
{
|
||||||
|
uint8_t val = param_get8ex(line, paramnum, 255, 10);
|
||||||
|
printf("read %i", (int8_t ) val);
|
||||||
|
if( (int8_t) val == -1) return 1;
|
||||||
|
(*destination) = val;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @brief Checks if param is decimal
|
||||||
|
* @param line
|
||||||
|
* @param paramnum
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
uint8_t param_isdec(const char *line, int paramnum)
|
||||||
|
{
|
||||||
|
int bg, en;
|
||||||
|
//TODO, check more thorougly
|
||||||
|
if (!param_getptr(line, &bg, &en, paramnum)) return 1;
|
||||||
|
// return strtoul(&line[bg], NULL, 10) & 0xff;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base)
|
uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base)
|
||||||
{
|
{
|
||||||
int bg, en;
|
int bg, en;
|
||||||
|
|
|
@ -49,6 +49,8 @@ uint8_t param_get8(const char *line, int paramnum);
|
||||||
uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base);
|
uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base);
|
||||||
uint32_t param_get32ex(const char *line, int paramnum, int deflt, int base);
|
uint32_t param_get32ex(const char *line, int paramnum, int deflt, int base);
|
||||||
uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base);
|
uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base);
|
||||||
|
uint8_t param_getdec(const char *line, int paramnum, uint8_t *destination);
|
||||||
|
uint8_t param_isdec(const char *line, int paramnum);
|
||||||
int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt);
|
int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt);
|
||||||
int param_getstr(const char *line, int paramnum, char * str);
|
int param_getstr(const char *line, int paramnum, char * str);
|
||||||
|
|
||||||
|
|
|
@ -33,8 +33,8 @@
|
||||||
#ifndef _PROXMARK_CMD_H_
|
#ifndef _PROXMARK_CMD_H_
|
||||||
#define _PROXMARK_CMD_H_
|
#define _PROXMARK_CMD_H_
|
||||||
|
|
||||||
#include <common.h>
|
#include "common.h"
|
||||||
#include <usb_cmd.h>
|
#include "usb_cmd.h"
|
||||||
#include "usb_cdc.h"
|
#include "usb_cdc.h"
|
||||||
|
|
||||||
bool cmd_receive(UsbCommand* cmd);
|
bool cmd_receive(UsbCommand* cmd);
|
||||||
|
|
955
common/lfdemod.c
955
common/lfdemod.c
File diff suppressed because it is too large
Load diff
|
@ -4,7 +4,11 @@
|
||||||
// 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.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Low frequency commands
|
// Low frequency demod related commands
|
||||||
|
// marshmellow
|
||||||
|
// note that many of these demods are not the slickest code and they often rely
|
||||||
|
// on peaks and clock instead of converting to clean signal.
|
||||||
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#ifndef LFDEMOD_H__
|
#ifndef LFDEMOD_H__
|
||||||
|
@ -13,17 +17,29 @@
|
||||||
|
|
||||||
int DetectASKClock(uint8_t dest[], size_t size, int clock);
|
int DetectASKClock(uint8_t dest[], size_t size, int clock);
|
||||||
int askmandemod(uint8_t *BinStream, size_t *size, int *clk, int *invert);
|
int askmandemod(uint8_t *BinStream, size_t *size, int *clk, int *invert);
|
||||||
uint64_t Em410xDecode(uint8_t *BitStream,size_t size);
|
uint64_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx);
|
||||||
|
int ManchesterEncode(uint8_t *BitStream, size_t size);
|
||||||
int manrawdecode(uint8_t *BitStream, size_t *size);
|
int manrawdecode(uint8_t *BitStream, size_t *size);
|
||||||
int BiphaseRawDecode(uint8_t * BitStream, size_t *size, int offset);
|
int BiphaseRawDecode(uint8_t * BitStream, size_t *size, int offset, int invert);
|
||||||
int askrawdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert);
|
int askrawdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert);
|
||||||
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);
|
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);
|
uint32_t bytebits_to_byte(uint8_t* src, size_t numbits);
|
||||||
int pskNRZrawDemod(uint8_t *dest, size_t *size, int *clk, int *invert);
|
int pskNRZrawDemod(uint8_t *dest, size_t *size, int *clk, int *invert);
|
||||||
|
void psk1TOpsk2(uint8_t *BitStream, size_t size);
|
||||||
int DetectpskNRZClock(uint8_t dest[], size_t size, int clock);
|
int DetectpskNRZClock(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);
|
||||||
void pskCleanWave(uint8_t *bitStream, size_t size);
|
void pskCleanWave(uint8_t *bitStream, 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 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);
|
||||||
|
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);
|
||||||
|
uint8_t justNoise(uint8_t *BitStream, size_t size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -370,7 +370,7 @@ uint32_t usb_write(const byte_t* data, const size_t len) {
|
||||||
//* \fn AT91F_USB_SendData
|
//* \fn AT91F_USB_SendData
|
||||||
//* \brief Send Data through the control endpoint
|
//* \brief Send Data through the control endpoint
|
||||||
//*----------------------------------------------------------------------------
|
//*----------------------------------------------------------------------------
|
||||||
unsigned int csrTab[100];
|
unsigned int csrTab[100] = {0x00};
|
||||||
unsigned char csrIdx = 0;
|
unsigned char csrIdx = 0;
|
||||||
|
|
||||||
static void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) {
|
static void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) {
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#ifndef _USB_CDC_H_
|
#ifndef _USB_CDC_H_
|
||||||
#define _USB_CDC_H_
|
#define _USB_CDC_H_
|
||||||
|
|
||||||
#include <common.h>
|
#include "common.h"
|
||||||
|
|
||||||
void usb_disable();
|
void usb_disable();
|
||||||
void usb_enable();
|
void usb_enable();
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
typedef enum {
|
typedef enum {
|
||||||
RHT2F_PASSWORD = 21,
|
RHT2F_PASSWORD = 21,
|
||||||
RHT2F_AUTHENTICATE = 22,
|
RHT2F_AUTHENTICATE = 22,
|
||||||
RHT2F_CRYPTO = 23,
|
RHT2F_CRYPTO = 23,
|
||||||
RHT2F_TEST_AUTH_ATTEMPTS = 25,
|
RHT2F_TEST_AUTH_ATTEMPTS = 25,
|
||||||
} hitag_function;
|
} hitag_function;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -33,7 +33,7 @@ typedef struct {
|
||||||
typedef union {
|
typedef union {
|
||||||
rht2d_password pwd;
|
rht2d_password pwd;
|
||||||
rht2d_authenticate auth;
|
rht2d_authenticate auth;
|
||||||
rht2d_crypto crypto;
|
rht2d_crypto crypto;
|
||||||
} hitag_data;
|
} hitag_data;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -33,6 +33,14 @@ typedef struct {
|
||||||
uint32_t asDwords[USB_CMD_DATA_SIZE/4];
|
uint32_t asDwords[USB_CMD_DATA_SIZE/4];
|
||||||
} d;
|
} d;
|
||||||
} PACKED UsbCommand;
|
} PACKED UsbCommand;
|
||||||
|
// A struct used to send sample-configs over USB
|
||||||
|
typedef struct{
|
||||||
|
uint8_t decimation;
|
||||||
|
uint8_t bits_per_sample;
|
||||||
|
bool averaging;
|
||||||
|
int divisor;
|
||||||
|
int trigger_threshold;
|
||||||
|
} sample_config;
|
||||||
|
|
||||||
// For the bootloader
|
// For the bootloader
|
||||||
#define CMD_DEVICE_INFO 0x0000
|
#define CMD_DEVICE_INFO 0x0000
|
||||||
|
@ -82,6 +90,8 @@ typedef struct {
|
||||||
#define CMD_IO_DEMOD_FSK 0x021A
|
#define CMD_IO_DEMOD_FSK 0x021A
|
||||||
#define CMD_IO_CLONE_TAG 0x021B
|
#define CMD_IO_CLONE_TAG 0x021B
|
||||||
#define CMD_EM410X_DEMOD 0x021c
|
#define CMD_EM410X_DEMOD 0x021c
|
||||||
|
// Sampling configuration for LF reader/snooper
|
||||||
|
#define CMD_SET_LF_SAMPLING_CONFIG 0x021d
|
||||||
|
|
||||||
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
|
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
|
||||||
|
|
||||||
|
@ -187,6 +197,7 @@ typedef struct {
|
||||||
#define FLAG_ICLASS_READER_ONLY_ONCE 0x01
|
#define FLAG_ICLASS_READER_ONLY_ONCE 0x01
|
||||||
#define FLAG_ICLASS_READER_GET_CC 0x02
|
#define FLAG_ICLASS_READER_GET_CC 0x02
|
||||||
|
|
||||||
|
|
||||||
// CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions:
|
// CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions:
|
||||||
/* Whether a bootloader that understands the common_area is present */
|
/* Whether a bootloader that understands the common_area is present */
|
||||||
#define DEVICE_INFO_FLAG_BOOTROM_PRESENT (1<<0)
|
#define DEVICE_INFO_FLAG_BOOTROM_PRESENT (1<<0)
|
||||||
|
|
20000
traces/AWID-15-259.pm3
Normal file
20000
traces/AWID-15-259.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/HID-weak-fob-11647.pm3
Normal file
20000
traces/HID-weak-fob-11647.pm3
Normal file
File diff suppressed because it is too large
Load diff
16000
traces/Paradox-96_40426-APJN08.pm3
Normal file
16000
traces/Paradox-96_40426-APJN08.pm3
Normal file
File diff suppressed because it is too large
Load diff
|
@ -22,3 +22,5 @@ EM4102-Fob.pm3: (ID: 0400193cbe)
|
||||||
ioprox-XSF-01-3B-44725.pm3: IO Prox FSK RF/64 ID in name
|
ioprox-XSF-01-3B-44725.pm3: IO Prox FSK RF/64 ID in name
|
||||||
ioprox-XSF-01-BE-03011.pm3: IO Prox FSK RF/64 ID in name
|
ioprox-XSF-01-BE-03011.pm3: IO Prox FSK RF/64 ID in name
|
||||||
indala-504278295.pm3: PSK 26 bit indala
|
indala-504278295.pm3: PSK 26 bit indala
|
||||||
|
AWID-15-259.pm3: AWID FSK RF/50 FC: 15 Card: 259
|
||||||
|
HID-weak-fob-11647.pm3: HID 32bit Prox Card#: 11647. very weak tag/read but just readable.
|
20000
traces/modulation-ask-biph-50.pm3
Normal file
20000
traces/modulation-ask-biph-50.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-ask-man-100.pm3
Normal file
20000
traces/modulation-ask-man-100.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-ask-man-128.pm3
Normal file
20000
traces/modulation-ask-man-128.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-ask-man-16.pm3
Normal file
20000
traces/modulation-ask-man-16.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-ask-man-32.pm3
Normal file
20000
traces/modulation-ask-man-32.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-ask-man-40.pm3
Normal file
20000
traces/modulation-ask-man-40.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-ask-man-8.pm3
Normal file
20000
traces/modulation-ask-man-8.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-direct-32.pm3
Normal file
20000
traces/modulation-direct-32.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-direct-40.pm3
Normal file
20000
traces/modulation-direct-40.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-direct-50.pm3
Normal file
20000
traces/modulation-direct-50.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-fsk1-50.pm3
Normal file
20000
traces/modulation-fsk1-50.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-fsk1a-50.pm3
Normal file
20000
traces/modulation-fsk1a-50.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-fsk2-50.pm3
Normal file
20000
traces/modulation-fsk2-50.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-fsk2a-40.pm3
Normal file
20000
traces/modulation-fsk2a-40.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-fsk2a-50.pm3
Normal file
20000
traces/modulation-fsk2a-50.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-psk1-32-4.pm3
Normal file
20000
traces/modulation-psk1-32-4.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-psk1-64-8.pm3
Normal file
20000
traces/modulation-psk1-64-8.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-psk2-32-2.pm3
Normal file
20000
traces/modulation-psk2-32-2.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-psk3-32-8.pm3
Normal file
20000
traces/modulation-psk3-32-8.pm3
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue