Merge branch 'master' into GenericTracing

Conflicts:
	armsrc/iso14443.c
	armsrc/iso14443a.c
	client/cmdhf.c
	client/cmdhf14b.c
This commit is contained in:
Martin Holst Swende 2015-02-06 08:41:02 +01:00
commit 7d5ebac993
98 changed files with 444131 additions and 2207 deletions

97
armsrc/BigBuf.c Normal file
View 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
View 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 */

View file

@ -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

File diff suppressed because it is too large Load diff

30
armsrc/aes.h Normal file
View 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);

View file

@ -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;

View file

@ -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
View 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
View 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 */

View file

@ -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;
@ -679,7 +683,7 @@ bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx, size_
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;
@ -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();
@ -940,12 +947,16 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
bool bQuitTraceFull = false; bool bQuitTraceFull = false;
bQuiet = false; bQuiet = false;
auth_table_len = 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);
// 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 simulation"); DbpString("Starting Hitag2 simulation");
LED_D_ON(); LED_D_ON();
@ -1133,6 +1144,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
// 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

View file

@ -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);
// 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 // 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
int8_t *dmaBuf = ((int8_t *)BigBuf) + DMA_BUFFER_OFFSET;
int lastRxCounter; int lastRxCounter;
int8_t *upTo; uint8_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;
} }

View file

@ -339,10 +339,10 @@ void SimulateIso14443Tag(void)
uint8_t *resp; uint8_t *resp;
int respLen; int respLen;
uint8_t *resp1 = (((uint8_t *)BigBuf) + 800); uint8_t *resp1 = BigBuf_get_addr() + 800;
int resp1Len; int resp1Len;
uint8_t *receivedCmd = (uint8_t *)BigBuf; uint8_t *receivedCmd = BigBuf_get_addr();
int len; int len;
int i; int i;
@ -616,26 +616,31 @@ static RAMFUNC int Handle14443SamplesDemod(int ci, int cq)
if (Demod.state == DEMOD_UNSYNCD) LED_C_OFF(); // Not synchronized... if (Demod.state == DEMOD_UNSYNCD) LED_C_OFF(); // Not synchronized...
return FALSE; return FALSE;
} }
static void DemodReset() static void DemodReset()
{ {
// Clear out the state of the "UART" that receives from the tag. // Clear out the state of the "UART" that receives from the tag.
Demod.output = ((uint8_t *)BigBuf) + RECV_RESP_OFFSET;
Demod.len = 0; Demod.len = 0;
Demod.state = DEMOD_UNSYNCD; Demod.state = DEMOD_UNSYNCD;
memset(Demod.output, 0x00, MAX_FRAME_SIZE); memset(Demod.output, 0x00, MAX_FRAME_SIZE);
}
static void DemodInit(uint8_t *data)
{
Demod.output = data;
DemodReset();
} }
static void UartReset() static void UartReset()
{ {
// And the UART that receives from the reader
Uart.output = ((uint8_t *)BigBuf) + RECV_CMD_OFFSET;
Uart.byteCntMax = MAX_FRAME_SIZE; Uart.byteCntMax = MAX_FRAME_SIZE;
Uart.state = STATE_UNSYNCD; Uart.state = STATE_UNSYNCD;
Uart.byteCnt = 0; Uart.byteCnt = 0;
Uart.bitCnt = 0; Uart.bitCnt = 0;
} }
static void UartInit(uint8_t *data)
{
Uart.output = data;
UartReset();
}
/* /*
* Demodulate the samples we received from the tag, also log to tracebuffer * Demodulate the samples we received from the tag, also log to tracebuffer
@ -647,21 +652,31 @@ static void GetSamplesFor14443Demod(int weTx, int n, int quiet)
{ {
int max = 0; int max = 0;
int gotFrame = FALSE; int gotFrame = FALSE;
int lastRxCounter, ci, cq, samples = 0;
int lastRxCounter; // Allocate memory from BigBuf for some buffers
// free all previous allocations first
BigBuf_free();
int ci, cq; // The command (reader -> tag) that we're receiving.
uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
int samples = 0; // The response (tag -> reader) that we're receiving.
uint8_t *receivedResponse = BigBuf_malloc(MAX_FRAME_SIZE);
DemodReset();
UartReset();
// The DMA buffer, used to stream samples from the FPGA // The DMA buffer, used to stream samples from the FPGA
int8_t *dmaBuf = ((int8_t *)BigBuf) + DMA_BUFFER_OFFSET; uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
int8_t *upTo= dmaBuf;
// Set up the demodulator for tag -> reader responses.
DemodInit(receivedResponse);
// Set up the demodulator for the reader -> tag commands
UartInit(receivedCmd);
// Setup and start DMA.
FpgaSetupSscDma(dmaBuf, DMA_BUFFER_SIZE);
uint8_t *upTo= dmaBuf;
lastRxCounter = DMA_BUFFER_SIZE; lastRxCounter = DMA_BUFFER_SIZE;
FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE);
// Signal field is ON with the appropriate LED: // Signal field is ON with the appropriate LED:
if (weTx) LED_D_ON(); else LED_D_OFF(); if (weTx) LED_D_ON(); else LED_D_OFF();
@ -1043,14 +1058,15 @@ void RAMFUNC SnoopIso14443(void)
int triggered = TRUE; int triggered = TRUE;
FpgaDownloadAndGo(FPGA_BITSTREAM_HF); FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
BigBuf_free();
clear_trace(); clear_trace();
set_tracing(TRUE); set_tracing(TRUE);
// The DMA buffer, used to stream samples from the FPGA. // The DMA buffer, used to stream samples from the FPGA
int8_t *dmaBuf = ((int8_t *)BigBuf) + DMA_BUFFER_OFFSET; uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
int lastRxCounter; int lastRxCounter;
int8_t *upTo; uint8_t *upTo;
int ci, cq; int ci, cq;
int maxBehindBy = 0; int maxBehindBy = 0;
@ -1058,12 +1074,12 @@ void RAMFUNC SnoopIso14443(void)
// information in the trace buffer. // information in the trace buffer.
int samples = 0; int samples = 0;
DemodReset(); DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
UartReset(); UartInit(BigBuf_malloc(MAX_FRAME_SIZE));
// Print some debug information about the buffer sizes // Print some debug information about the buffer sizes
Dbprintf("Snooping buffers initialized:"); Dbprintf("Snooping buffers initialized:");
Dbprintf(" Trace: %i bytes", TRACE_SIZE); Dbprintf(" Trace: %i bytes", BigBuf_max_traceLen());
Dbprintf(" Reader -> tag: %i bytes", MAX_FRAME_SIZE); Dbprintf(" Reader -> tag: %i bytes", MAX_FRAME_SIZE);
Dbprintf(" tag -> Reader: %i bytes", MAX_FRAME_SIZE); Dbprintf(" tag -> Reader: %i bytes", MAX_FRAME_SIZE);
Dbprintf(" DMA: %i bytes", DMA_BUFFER_SIZE); Dbprintf(" DMA: %i bytes", DMA_BUFFER_SIZE);
@ -1091,7 +1107,7 @@ void RAMFUNC SnoopIso14443(void)
(DMA_BUFFER_SIZE-1); (DMA_BUFFER_SIZE-1);
if(behindBy > maxBehindBy) { if(behindBy > maxBehindBy) {
maxBehindBy = behindBy; maxBehindBy = behindBy;
if(behindBy > (DMA_BUFFER_SIZE-2)) { // TODO: understand whether we can increase/decrease as we want or not? if(behindBy > (9*DMA_BUFFER_SIZE/10)) { // TODO: understand whether we can increase/decrease as we want or not?
Dbprintf("blew circular buffer! behindBy=0x%x", behindBy); Dbprintf("blew circular buffer! behindBy=0x%x", behindBy);
break; break;
} }

View file

@ -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,12 +863,19 @@ 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)) {
@ -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;
} }

View file

@ -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) {

View file

@ -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);
} }
} }

View file

@ -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);
LFSetupFPGAForADC(sc.divisor, 1);
// And a little more time for the tag to fully power up // And a little more time for the tag to fully power up
SpinDelay(2000); SpinDelay(2000);
// Now set up the SSC to get the ADC samples that are now streaming at us.
FpgaSetupSsc();
// 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
View 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
View 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

View file

@ -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();
}

View file

@ -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;

View file

@ -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,14 +82,34 @@ 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; 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;
}
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)
{ {
uint8_t dcmd[4], ecmd[4]; uint8_t dcmd[4], ecmd[4];
@ -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;
}

View file

@ -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);

View file

@ -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);
} }

View file

@ -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 )

View file

@ -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>

View file

@ -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)

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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,7 +421,7 @@ 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;
@ -430,10 +429,10 @@ uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, uint8_t protocol, boo
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);
// 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); WaitForResponse(CMD_ACK, NULL);
PrintAndLog("Recorded Activity"); }
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}

View file

@ -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}

View file

@ -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;

View file

@ -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
@ -2009,29 +1820,44 @@ int CmdHF14AMfSniff(const char *Cmd){
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
View 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
View 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);

View file

@ -356,21 +356,152 @@ int CmdIndalaClone(const char *Cmd)
return 0; return 0;
} }
int CmdLFRead(const char *Cmd) int usage_lf_read()
{ {
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K}; PrintAndLog("Usage: lf read");
PrintAndLog("Options: ");
// 'h' means higher-low-frequency, 134 kHz PrintAndLog(" h This help");
if(*Cmd == 'h') { PrintAndLog("This function takes no arguments. ");
c.arg[0] = 1; PrintAndLog("Use 'lf config' to set parameters.");
} else if (*Cmd == '\0') {
c.arg[0] = 0;
} else if (sscanf(Cmd, "%"lli, &c.arg[0]) != 1) {
PrintAndLog("Samples 1: 'lf read'");
PrintAndLog(" 2: 'lf read h'");
PrintAndLog(" 3: 'lf read <divisor>'");
return 0; 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)
{
uint8_t cmdp =0;
if(param_getchar(Cmd, cmdp) == 'h')
{
return usage_lf_read();
}
//And ship it to device
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K};
SendCommand(&c);
WaitForResponse(CMD_ACK,NULL);
return 0;
}
int CmdLFSnoop(const char *Cmd)
{
uint8_t cmdp =0;
if(param_getchar(Cmd, cmdp) == 'h')
{
return usage_lf_snoop();
}
UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES};
SendCommand(&c); SendCommand(&c);
WaitForResponse(CMD_ACK,NULL); WaitForResponse(CMD_ACK,NULL);
return 0; return 0;
@ -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)"},

View file

@ -29,11 +29,26 @@ 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
UsbCommand response;
GetFromBigBuf(got, 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(got, traceLen);
if (p == NULL) {
PrintAndLog("Cannot allocate memory for trace");
free(got);
return 2;
}
got = p;
GetFromBigBuf(got, traceLen, 0);
WaitForResponse(CMD_ACK,NULL);
}
PrintAndLog("recorded activity (TraceLen = %d bytes):");
PrintAndLog(" ETU :nbits: who bytes"); PrintAndLog(" ETU :nbits: who bytes");
PrintAndLog("---------+-----+----+-----------"); PrintAndLog("---------+-----+----+-----------");
@ -57,7 +72,7 @@ int CmdLFHitagList(const char *Cmd)
for (;;) { for (;;) {
if(i >= TRACE_BUFFER_SIZE) { break; } if(i > traceLen) { break; }
bool isResponse; bool isResponse;
int timestamp = *((uint32_t *)(got+i)); int timestamp = *((uint32_t *)(got+i));
@ -82,7 +97,7 @@ int CmdLFHitagList(const char *Cmd)
if (len > 100) { if (len > 100) {
break; break;
} }
if (i + len >= TRACE_BUFFER_SIZE) { break;} if (i + len > traceLen) { break;}
uint8_t *frame = (got+i+9); uint8_t *frame = (got+i+9);
@ -114,7 +129,6 @@ int CmdLFHitagList(const char *Cmd)
(isResponse ? "TAG" : " "), (isResponse ? "TAG" : " "),
line); line);
if (pf) { if (pf) {
fprintf(pf," +%7d: %3d: %s %s\n", fprintf(pf," +%7d: %3d: %s %s\n",
(prev < 0 ? 0 : (timestamp - prev)), (prev < 0 ? 0 : (timestamp - prev)),
@ -132,6 +146,7 @@ int CmdLFHitagList(const char *Cmd)
PrintAndLog("Recorded activity succesfully written to file: %s", filename); PrintAndLog("Recorded activity succesfully written to file: %s", filename);
} }
free(got);
return 0; return 0;
} }

View file

@ -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");

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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,6 +76,8 @@ 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)
{ {
@ -82,16 +91,51 @@ int GetClock(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 = DetectASKClock(grph,size,0); 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)
{ {
int clock; int clock;
@ -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){

View file

@ -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

View 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>

View 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
View 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
View 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;
}

View 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

View 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;
}

View file

View 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__

View 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

View 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;
}

View 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

View 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

View 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

View file

@ -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>

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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);

View 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)

View 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

View file

@ -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( (' Alter ego / traptype : 0x%s'):format(traptype) )
print( (' UID : 0x%s'):format(uid) ) print( (' UID : 0x%s'):format(uid) )
print( (' CARDID : 0x%s'):format(cardid ) ) print( (' CARDID : 0x%s'):format(cardid ) )
print( string.rep('--',20) ) print( string.rep('--',20) )
end end

View file

@ -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)

View 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)

View file

@ -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;

View file

@ -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);

View file

@ -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);

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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) {

View file

@ -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();

View file

@ -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

File diff suppressed because it is too large Load diff

20000
traces/HID-weak-fob-11647.pm3 Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -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.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

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

File diff suppressed because it is too large Load diff

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

File diff suppressed because it is too large Load diff

20000
traces/modulation-fsk2a-50.pm3 Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff