mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 10:37:23 -07:00
Merge branch 'master' of https://github.com/Proxmark/proxmark3
Conflicts: armsrc/Makefile armsrc/appmain.c armsrc/apps.h armsrc/epa.c armsrc/iclass.c armsrc/iso14443a.c armsrc/iso14443a.h armsrc/iso15693.c armsrc/lfops.c armsrc/mifarecmd.c armsrc/mifareutil.c armsrc/mifareutil.h armsrc/string.h armsrc/util.h bootrom/bootrom.c client/Makefile client/cmddata.c client/cmddata.h client/cmdhf.c client/cmdhf14a.c client/cmdhf14b.c client/cmdhf15.c client/cmdhficlass.c client/cmdhfmf.c client/cmdhfmfu.c client/cmdlf.c client/cmdlfem4x.c client/cmdlfhid.c client/cmdlfhitag.c client/cmdlfio.c client/cmdmain.c client/data.h client/flash.c client/graph.c client/graph.h client/loclass/elite_crack.c client/loclass/fileutils.c client/lualibs/commands.lua client/lualibs/html_dumplib.lua client/lualibs/mf_default_keys.lua client/lualibs/utils.lua client/mifarehost.c client/nonce2key/crapto1.c client/proxmark3.c client/scripting.c client/scripts/tnp3dump.lua client/scripts/tnp3sim.lua client/scripts/tracetest.lua common/Makefile.common common/cmd.c common/cmd.h common/lfdemod.c common/lfdemod.h common/usb_cdc.c common/usb_cdc.h include/usb_cmd.h
This commit is contained in:
commit
64d1b4efc9
104 changed files with 462574 additions and 5340 deletions
97
armsrc/BigBuf.c
Normal file
97
armsrc/BigBuf.c
Normal file
|
@ -0,0 +1,97 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Jonathan Westhues, Aug 2005
|
||||
// Gerhard de Koning Gans, April 2008, May 2011
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// BigBuf and functions to allocate/free parts of it.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <stdint.h>
|
||||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "string.h"
|
||||
|
||||
// BigBuf is the large multi-purpose buffer, typically used to hold A/D samples or traces.
|
||||
// Also used to hold various smaller buffers and the Mifare Emulator Memory.
|
||||
|
||||
// declare it as uint32_t to achieve alignment to 4 Byte boundary
|
||||
static uint32_t BigBuf[BIGBUF_SIZE/sizeof(uint32_t)];
|
||||
|
||||
// High memory mark
|
||||
static uint16_t BigBuf_hi = BIGBUF_SIZE;
|
||||
|
||||
// pointer to the emulator memory.
|
||||
static uint8_t *emulator_memory = NULL;
|
||||
|
||||
// trace related global variables
|
||||
// (only one left). ToDo: make this static as well?
|
||||
uint16_t traceLen = 0;
|
||||
|
||||
|
||||
// get the address of BigBuf
|
||||
uint8_t *BigBuf_get_addr(void)
|
||||
{
|
||||
return (uint8_t *)BigBuf;
|
||||
}
|
||||
|
||||
|
||||
// get the address of the emulator memory. Allocate part of Bigbuf for it, if not yet done
|
||||
uint8_t *BigBuf_get_EM_addr(void)
|
||||
{
|
||||
if (emulator_memory == NULL) { // not yet allocated
|
||||
emulator_memory = BigBuf_malloc(CARD_MEMORY_SIZE);
|
||||
}
|
||||
|
||||
return emulator_memory;
|
||||
}
|
||||
|
||||
|
||||
// clear ALL of BigBuf
|
||||
void BigBuf_Clear(void)
|
||||
{
|
||||
memset(BigBuf,0,BIGBUF_SIZE);
|
||||
Dbprintf("Buffer cleared (%i bytes)",BIGBUF_SIZE);
|
||||
}
|
||||
|
||||
|
||||
// allocate a chunk of memory from BigBuf. We allocate high memory first. The unallocated memory
|
||||
// at the beginning of BigBuf is always for traces/samples
|
||||
uint8_t *BigBuf_malloc(uint16_t chunksize)
|
||||
{
|
||||
if (BigBuf_hi - chunksize < 0) {
|
||||
return NULL; // no memory left
|
||||
} else {
|
||||
chunksize = (chunksize + 3) & 0xfffc; // round to next multiple of 4
|
||||
BigBuf_hi -= chunksize; // aligned to 4 Byte boundary
|
||||
return (uint8_t *)BigBuf + BigBuf_hi;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// free ALL allocated chunks. The whole BigBuf is available for traces or samples again.
|
||||
void BigBuf_free(void)
|
||||
{
|
||||
BigBuf_hi = BIGBUF_SIZE;
|
||||
emulator_memory = NULL;
|
||||
}
|
||||
|
||||
|
||||
// free allocated chunks EXCEPT the emulator memory
|
||||
void BigBuf_free_keep_EM(void)
|
||||
{
|
||||
if (emulator_memory != NULL) {
|
||||
BigBuf_hi = emulator_memory - (uint8_t *)BigBuf;
|
||||
} else {
|
||||
BigBuf_hi = BIGBUF_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// return the maximum trace length (i.e. the unallocated size of BigBuf)
|
||||
uint16_t BigBuf_max_traceLen(void)
|
||||
{
|
||||
return BigBuf_hi;
|
||||
}
|
34
armsrc/BigBuf.h
Normal file
34
armsrc/BigBuf.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Jonathan Westhues, Aug 2005
|
||||
// Gerhard de Koning Gans, April 2008, May 2011
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// BigBuf and functions to allocate/free parts of it.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __BIGBUF_H
|
||||
#define __BIGBUF_H
|
||||
|
||||
|
||||
#define BIGBUF_SIZE 40000
|
||||
#define MAX_FRAME_SIZE 256 // maximum allowed ISO14443 frame
|
||||
#define MAX_PARITY_SIZE ((MAX_FRAME_SIZE + 7) / 8)
|
||||
#define MAX_MIFARE_FRAME_SIZE 18 // biggest Mifare frame is answer to a read (one block = 16 Bytes) + 2 Bytes CRC
|
||||
#define MAX_MIFARE_PARITY_SIZE 3 // need 18 parity bits for the 18 Byte above. 3 Bytes are enough to store these
|
||||
#define CARD_MEMORY_SIZE 4096
|
||||
#define DMA_BUFFER_SIZE 128
|
||||
|
||||
extern uint8_t *BigBuf_get_addr(void);
|
||||
extern uint8_t *BigBuf_get_EM_addr(void);
|
||||
extern uint16_t BigBuf_max_traceLen(void);
|
||||
void BigBuf_Clear(void);
|
||||
extern uint8_t *BigBuf_malloc(uint16_t);
|
||||
extern void BigBuf_free(void);
|
||||
extern void BigBuf_free_keep_EM(void);
|
||||
|
||||
extern uint16_t traceLen;
|
||||
|
||||
#endif /* __BIGBUF_H */
|
|
@ -16,9 +16,9 @@ APP_CFLAGS = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_
|
|||
#SRC_LCD = fonts.c LCD.c
|
||||
SRC_LF = lfops.c hitag2.c
|
||||
SRC_ISO15693 = iso15693.c iso15693tools.c
|
||||
SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c
|
||||
SRC_ISO14443b = iso14443.c
|
||||
SRC_CRAPTO1 = crapto1.c crypto1.c des.c aes.c desfire_key.c desfire_crypto.c mifaredesfire.c
|
||||
SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c
|
||||
SRC_ISO14443b = iso14443.c
|
||||
SRC_CRAPTO1 = crapto1.c crypto1.c des.c aes.c
|
||||
SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c
|
||||
|
||||
THUMBSRC = start.c \
|
||||
|
@ -41,7 +41,8 @@ ARMSRC = fpgaloader.c \
|
|||
$(SRC_CRAPTO1) \
|
||||
$(SRC_CRC) \
|
||||
legic_prng.c \
|
||||
iclass.c
|
||||
iclass.c \
|
||||
BigBuf.c \
|
||||
|
||||
|
||||
# stdint.h provided locally until GCC 4.5 becomes C99 compliant
|
||||
|
|
|
@ -36,18 +36,12 @@
|
|||
// is the order in which they go out on the wire.
|
||||
//=============================================================================
|
||||
|
||||
#define TOSEND_BUFFER_SIZE (9*MAX_FRAME_SIZE + 1 + 1 + 2) // 8 data bits and 1 parity bit per payload byte, 1 correction bit, 1 SOC bit, 2 EOC bits
|
||||
#define TOSEND_BUFFER_SIZE (9*MAX_FRAME_SIZE + 1 + 1 + 2) // 8 data bits and 1 parity bit per payload byte, 1 correction bit, 1 SOC bit, 2 EOC bits
|
||||
uint8_t ToSend[TOSEND_BUFFER_SIZE];
|
||||
int ToSendMax;
|
||||
static int ToSendBit;
|
||||
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)
|
||||
{
|
||||
ToSendMax = -1;
|
||||
|
@ -68,7 +62,7 @@ void ToSendStuffBit(int b)
|
|||
|
||||
ToSendBit++;
|
||||
|
||||
if(ToSendMax >= sizeof(ToSend)) {
|
||||
if(ToSendMax >= sizeof(ToSend)) {
|
||||
ToSendBit = 0;
|
||||
DbpString("ToSendStuffBit overflowed!");
|
||||
}
|
||||
|
@ -246,7 +240,10 @@ void MeasureAntennaTuningHf(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;
|
||||
int i;
|
||||
int p = 0;
|
||||
|
@ -281,7 +278,7 @@ void SimulateTagHfListen(void)
|
|||
p = 0;
|
||||
i++;
|
||||
|
||||
if(i >= FREE_BUFFER_SIZE) {
|
||||
if(i >= HF_14B_SNOOP_BUFFER_SIZE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -811,11 +808,11 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
|||
MifareUC_Auth2(c->arg[0],c->d.asBytes);
|
||||
break;
|
||||
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;
|
||||
case CMD_MIFAREUC_READCARD:
|
||||
MifareUReadCard(c->arg[0],c->arg[1],c->d.asBytes);
|
||||
break;
|
||||
MifareUReadCard(c->arg[0], c->arg[1], c->d.asBytes);
|
||||
break;
|
||||
case CMD_MIFARE_READSC:
|
||||
MifareReadSector(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
|
||||
break;
|
||||
|
@ -870,27 +867,6 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
|||
case CMD_MIFARE_SNIFFER:
|
||||
SniffMifare(c->arg[0]);
|
||||
break;
|
||||
|
||||
// mifare desfire
|
||||
case CMD_MIFARE_DESFIRE_READBL:
|
||||
break;
|
||||
case CMD_MIFARE_DESFIRE_WRITEBL:
|
||||
break;
|
||||
case CMD_MIFARE_DESFIRE_AUTH1:
|
||||
MifareDES_Auth1(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
|
||||
break;
|
||||
case CMD_MIFARE_DESFIRE_AUTH2:
|
||||
//MifareDES_Auth2(c->arg[0],c->d.asBytes);
|
||||
break;
|
||||
// case CMD_MIFARE_DES_READER:
|
||||
// ReaderMifareDES(c->arg[0], c->arg[1], c->d.asBytes);
|
||||
//break;
|
||||
case CMD_MIFARE_DESFIRE_INFO:
|
||||
MifareDesfireGetInformation();
|
||||
break;
|
||||
case CMD_MIFARE_DESFIRE:
|
||||
MifareSendCommand(c->arg[0], c->arg[1], c->d.asBytes);
|
||||
break;
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -915,7 +891,7 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
|||
break;
|
||||
|
||||
case CMD_BUFF_CLEAR:
|
||||
BufferClear();
|
||||
BigBuf_Clear();
|
||||
break;
|
||||
|
||||
case CMD_MEASURE_ANTENNA_TUNING:
|
||||
|
@ -939,17 +915,18 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
|||
case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K:
|
||||
|
||||
LED_B_ON();
|
||||
uint8_t *BigBuf = BigBuf_get_addr();
|
||||
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);
|
||||
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
|
||||
cmd_send(CMD_ACK,0,0,0,0,0);
|
||||
cmd_send(CMD_ACK,0,0,traceLen,0,0);
|
||||
LED_B_OFF();
|
||||
break;
|
||||
|
||||
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);
|
||||
cmd_send(CMD_ACK,0,0,0,0,0);
|
||||
break;
|
||||
|
|
|
@ -18,40 +18,10 @@
|
|||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include "../include/common.h"
|
||||
#include "../include/hitag2.h"
|
||||
#include "../include/mifare.h"
|
||||
|
||||
//#include <openssl/des.h>
|
||||
//#include <openssl/aes.h>
|
||||
//#include "des.h"
|
||||
//#include "aes.h"
|
||||
#include "../common/desfire.h"
|
||||
#include "../common/crc32.h"
|
||||
|
||||
// The large multi-purpose buffer, typically used to hold A/D samples,
|
||||
// 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)
|
||||
#include "BigBuf.h"
|
||||
|
||||
extern const uint8_t OddByteParity[256];
|
||||
extern uint8_t *trace; // = (uint8_t *) BigBuf;
|
||||
extern int traceLen; // = 0;
|
||||
extern int rsamples; // = 0;
|
||||
extern int tracing; // = TRUE;
|
||||
extern uint8_t trigger;
|
||||
|
@ -82,7 +52,6 @@ void DoAcquisition125k();
|
|||
|
||||
extern int ToSendMax;
|
||||
extern uint8_t ToSend[];
|
||||
extern uint32_t BigBuf[];
|
||||
|
||||
/// fpga.h
|
||||
void FpgaSendCommand(uint16_t cmd, uint16_t v);
|
||||
|
@ -130,6 +99,8 @@ void SetAdcMuxFor(uint32_t whichGpio);
|
|||
#define FPGA_HF_SIMULATOR_MODULATE_BPSK (1<<0)
|
||||
#define FPGA_HF_SIMULATOR_MODULATE_212K (2<<0)
|
||||
#define FPGA_HF_SIMULATOR_MODULATE_424K (4<<0)
|
||||
#define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 0x5//101
|
||||
|
||||
// Options for ISO14443A
|
||||
#define FPGA_HF_ISO14443A_SNIFFER (0<<0)
|
||||
#define FPGA_HF_ISO14443A_TAGSIM_LISTEN (1<<0)
|
||||
|
@ -181,7 +152,7 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data);
|
|||
void ReaderIso14443a(UsbCommand * c);
|
||||
// Also used in iclass.c
|
||||
bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t len, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag);
|
||||
void GetParity(const uint8_t * pbtCmd, uint16_t len, uint8_t *parity);
|
||||
void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *parity);
|
||||
void iso14a_set_trigger(bool enable);
|
||||
void iso14a_clear_trace();
|
||||
void iso14a_set_tracing(bool enable);
|
||||
|
@ -231,17 +202,6 @@ void OnError(uint8_t reason);
|
|||
|
||||
|
||||
|
||||
// desfire_crypto.h
|
||||
void *mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes, off_t offset, int communication_settings);
|
||||
void *mifare_cryto_postprocess_data (desfiretag_t tag, void *data, ssize_t *nbytes, int communication_settings);
|
||||
void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size);
|
||||
void mifare_cypher_blocks_chained (desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation);
|
||||
size_t key_block_size (const desfirekey_t key);
|
||||
size_t padded_data_length (const size_t nbytes, const size_t block_size);
|
||||
size_t maced_data_length (const desfirekey_t key, const size_t nbytes);
|
||||
size_t enciphered_data_length (const desfiretag_t tag, const size_t nbytes, int communication_settings);
|
||||
void cmac_generate_subkeys (desfirekey_t key);
|
||||
void cmac (const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac);
|
||||
|
||||
|
||||
/// iso15693.h
|
||||
|
|
|
@ -435,6 +435,8 @@ int EPA_Setup()
|
|||
|
||||
iso14a_set_timeout(10500);
|
||||
|
||||
iso14a_set_timeout(10500);
|
||||
|
||||
// select the card
|
||||
return_code = iso14443a_select_card(uid, &card_select_info, NULL);
|
||||
if (return_code != 1) {
|
||||
|
|
116
armsrc/hitag2.c
116
armsrc/hitag2.c
|
@ -24,15 +24,19 @@
|
|||
|
||||
static bool bQuiet;
|
||||
|
||||
bool bCrypto;
|
||||
bool bAuthenticating;
|
||||
bool bPwd;
|
||||
bool bSuccessful;
|
||||
static bool bCrypto;
|
||||
static bool bAuthenticating;
|
||||
static bool bPwd;
|
||||
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
|
||||
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
|
||||
rsamples += iSamples;
|
||||
|
@ -85,21 +89,17 @@ static struct hitag2_tag tag = {
|
|||
},
|
||||
};
|
||||
|
||||
//#define TRACE_LENGTH 3000
|
||||
//uint8_t *trace = (uint8_t *) BigBuf;
|
||||
//int traceLen = 0;
|
||||
//int rsamples = 0;
|
||||
// ToDo: define a meaningful maximum size for auth_table. The bigger this is, the lower will be the available memory for traces.
|
||||
// Historically it used to be FREE_BUFFER_SIZE, which was 2744.
|
||||
#define AUTH_TABLE_LENGTH 2744
|
||||
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
|
||||
#define AUTH_TABLE_LENGTH FREE_BUFFER_SIZE
|
||||
byte_t* auth_table = (byte_t *)BigBuf+AUTH_TABLE_OFFSET;
|
||||
size_t auth_table_pos = 0;
|
||||
size_t auth_table_len = AUTH_TABLE_LENGTH;
|
||||
|
||||
byte_t password[4];
|
||||
byte_t NrAr[8];
|
||||
byte_t key[8];
|
||||
uint64_t cipher_state;
|
||||
static byte_t password[4];
|
||||
static byte_t NrAr[8];
|
||||
static byte_t key[8];
|
||||
static uint64_t cipher_state;
|
||||
|
||||
/* 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.
|
||||
|
@ -177,14 +177,14 @@ static u32 _hitag2_byte (u64 * x)
|
|||
return c;
|
||||
}
|
||||
|
||||
int hitag2_reset(void)
|
||||
static int hitag2_reset(void)
|
||||
{
|
||||
tag.state = TAG_STATE_RESET;
|
||||
tag.crypto_active = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hitag2_init(void)
|
||||
static int hitag2_init(void)
|
||||
{
|
||||
// memcpy(&tag, &resetdata, sizeof(tag));
|
||||
hitag2_reset();
|
||||
|
@ -300,7 +300,8 @@ static void hitag_send_frame(const byte_t* frame, size_t frame_len)
|
|||
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];
|
||||
|
||||
|
@ -457,6 +458,7 @@ static void hitag_reader_send_bit(int bit) {
|
|||
LED_A_OFF();
|
||||
}
|
||||
|
||||
|
||||
static void hitag_reader_send_frame(const byte_t* frame, size_t frame_len)
|
||||
{
|
||||
// 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;
|
||||
|
||||
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
|
||||
*txlen = 0;
|
||||
|
||||
|
@ -530,7 +532,7 @@ bool hitag2_password(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen)
|
|||
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
|
||||
*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
|
||||
*txlen = 0;
|
||||
|
||||
|
@ -663,7 +665,9 @@ bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txl
|
|||
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
|
||||
*txlen = 0;
|
||||
|
||||
|
@ -675,17 +679,17 @@ bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx, size_
|
|||
if (bCrypto) {
|
||||
Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed, removed entry!",NrAr[0],NrAr[1],NrAr[2],NrAr[3],NrAr[4],NrAr[5],NrAr[6],NrAr[7]);
|
||||
|
||||
// Removing failed entry from authentiations table
|
||||
memcpy(auth_table+auth_table_pos,auth_table+auth_table_pos+8,8);
|
||||
auth_table_len -= 8;
|
||||
// Removing failed entry from authentiations table
|
||||
memcpy(auth_table+auth_table_pos,auth_table+auth_table_pos+8,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;
|
||||
if (auth_table_pos == auth_table_len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy the next authentication attempt in row (at the same position, b/c we removed last failed entry)
|
||||
|
||||
// Copy the next authentication attempt in row (at the same position, b/c we removed last failed entry)
|
||||
memcpy(NrAr,auth_table+auth_table_pos,8);
|
||||
}
|
||||
*txlen = 5;
|
||||
|
@ -718,6 +722,7 @@ bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx, size_
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SnoopHitag(uint32_t type) {
|
||||
int frame_count;
|
||||
int response;
|
||||
|
@ -730,13 +735,15 @@ void SnoopHitag(uint32_t type) {
|
|||
byte_t rx[HITAG_FRAME_LEN];
|
||||
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
|
||||
iso14a_set_tracing(TRUE);
|
||||
iso14a_clear_trace();
|
||||
|
||||
auth_table_len = 0;
|
||||
auth_table_pos = 0;
|
||||
memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
|
||||
|
||||
DbpString("Starting Hitag2 snoop");
|
||||
LED_D_ON();
|
||||
|
@ -760,7 +767,7 @@ void SnoopHitag(uint32_t type) {
|
|||
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
|
||||
AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
|
||||
|
||||
// Disable timer during configuration
|
||||
// Disable timer during configuration
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
|
||||
|
||||
// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
|
||||
|
@ -940,13 +947,17 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
|
|||
bool bQuitTraceFull = false;
|
||||
bQuiet = false;
|
||||
|
||||
// Clean up trace and prepare it for storing frames
|
||||
iso14a_set_tracing(TRUE);
|
||||
iso14a_clear_trace();
|
||||
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
|
||||
iso14a_set_tracing(TRUE);
|
||||
iso14a_clear_trace();
|
||||
|
||||
DbpString("Starting Hitag2 simulation");
|
||||
LED_D_ON();
|
||||
hitag2_init();
|
||||
|
@ -1126,21 +1137,22 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
|
|||
bool bStop;
|
||||
bool bQuitTraceFull = false;
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
// Reset the return status
|
||||
bSuccessful = false;
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
// Reset the return status
|
||||
bSuccessful = false;
|
||||
|
||||
// Clean up trace and prepare it for storing frames
|
||||
iso14a_set_tracing(TRUE);
|
||||
iso14a_clear_trace();
|
||||
iso14a_set_tracing(TRUE);
|
||||
iso14a_clear_trace();
|
||||
|
||||
DbpString("Starting Hitag reader family");
|
||||
|
||||
// Check configuration
|
||||
switch(htf) {
|
||||
case RHT2F_PASSWORD: {
|
||||
Dbprintf("List identifier in password mode");
|
||||
Dbprintf("List identifier in password mode");
|
||||
memcpy(password,htd->pwd.password,4);
|
||||
blocknr = 0;
|
||||
blocknr = 0;
|
||||
bQuitTraceFull = false;
|
||||
bQuiet = false;
|
||||
bPwd = false;
|
||||
|
@ -1152,7 +1164,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
|
|||
Dbhexdump(8,NrAr,false);
|
||||
bQuiet = false;
|
||||
bCrypto = false;
|
||||
bAuthenticating = false;
|
||||
bAuthenticating = false;
|
||||
bQuitTraceFull = true;
|
||||
} break;
|
||||
|
||||
|
@ -1160,17 +1172,17 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
|
|||
DbpString("Authenticating using key:");
|
||||
memcpy(key,htd->crypto.key,4); //HACK; 4 or 6?? I read both in the code.
|
||||
Dbhexdump(6,key,false);
|
||||
blocknr = 0;
|
||||
blocknr = 0;
|
||||
bQuiet = false;
|
||||
bCrypto = false;
|
||||
bAuthenticating = false;
|
||||
bAuthenticating = false;
|
||||
bQuitTraceFull = true;
|
||||
} break;
|
||||
|
||||
case RHT2F_TEST_AUTH_ATTEMPTS: {
|
||||
Dbprintf("Testing %d authentication attempts",(auth_table_len/8));
|
||||
auth_table_pos = 0;
|
||||
memcpy(NrAr,auth_table,8);
|
||||
memcpy(NrAr, auth_table, 8);
|
||||
bQuitTraceFull = false;
|
||||
bQuiet = false;
|
||||
bCrypto = false;
|
||||
|
|
288
armsrc/iclass.c
288
armsrc/iclass.c
|
@ -435,7 +435,7 @@ static RAMFUNC int ManchesterDecoding(int v)
|
|||
else {
|
||||
modulation = bit & Demod.syncBit;
|
||||
modulation |= ((bit << 1) ^ ((Demod.buffer & 0x08) >> 3)) & Demod.syncBit;
|
||||
|
||||
|
||||
Demod.samples += 4;
|
||||
|
||||
if(Demod.posCount==0) {
|
||||
|
@ -642,21 +642,25 @@ void RAMFUNC SnoopIClass(void)
|
|||
// The command (reader -> tag) that we're receiving.
|
||||
// The length of a received command will in most cases be no more than 18 bytes.
|
||||
// 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.
|
||||
uint8_t *tagToReaderResponse = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET);
|
||||
|
||||
uint8_t tagToReaderResponse[ICLASS_BUFFER_SIZE];
|
||||
|
||||
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
|
||||
iso14a_set_tracing(TRUE);
|
||||
iso14a_clear_trace();
|
||||
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;
|
||||
int8_t *upTo;
|
||||
uint8_t *upTo;
|
||||
int smpl;
|
||||
int maxBehindBy = 0;
|
||||
|
||||
|
@ -689,7 +693,8 @@ void RAMFUNC SnoopIClass(void)
|
|||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
uint32_t time_0 = GetCountSspClk();
|
||||
|
||||
uint32_t time_start = 0;
|
||||
uint32_t time_stop = 0;
|
||||
|
||||
int div = 0;
|
||||
//int div2 = 0;
|
||||
|
@ -704,7 +709,7 @@ void RAMFUNC SnoopIClass(void)
|
|||
(DMA_BUFFER_SIZE-1);
|
||||
if(behindBy > maxBehindBy) {
|
||||
maxBehindBy = behindBy;
|
||||
if(behindBy > 400) {
|
||||
if(behindBy > (9 * DMA_BUFFER_SIZE / 10)) {
|
||||
Dbprintf("blew circular buffer! behindBy=0x%x", behindBy);
|
||||
goto done;
|
||||
}
|
||||
|
@ -740,14 +745,15 @@ void RAMFUNC SnoopIClass(void)
|
|||
smpl = decbyter;
|
||||
if(OutOfNDecoding((smpl & 0xF0) >> 4)) {
|
||||
rsamples = samples - Uart.samples;
|
||||
time_stop = (GetCountSspClk()-time_0) << 4;
|
||||
LED_C_ON();
|
||||
|
||||
//if(!LogTrace(Uart.output,Uart.byteCnt, rsamples, Uart.parityBits,TRUE)) break;
|
||||
//if(!LogTrace(NULL, 0, Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, 0, TRUE)) break;
|
||||
if(tracing) {
|
||||
if(tracing) {
|
||||
uint8_t parity[MAX_PARITY_SIZE];
|
||||
GetParity(Uart.output, Uart.byteCnt, parity);
|
||||
LogTrace(Uart.output,Uart.byteCnt, (GetCountSspClk()-time_0) << 4, (GetCountSspClk()-time_0) << 4, parity, TRUE);
|
||||
LogTrace(Uart.output,Uart.byteCnt, time_start, time_stop, parity, TRUE);
|
||||
}
|
||||
|
||||
|
||||
|
@ -758,6 +764,8 @@ void RAMFUNC SnoopIClass(void)
|
|||
Demod.state = DEMOD_UNSYNCD;
|
||||
LED_B_OFF();
|
||||
Uart.byteCnt = 0;
|
||||
}else{
|
||||
time_start = (GetCountSspClk()-time_0) << 4;
|
||||
}
|
||||
decbyter = 0;
|
||||
}
|
||||
|
@ -765,21 +773,24 @@ void RAMFUNC SnoopIClass(void)
|
|||
if(div > 3) {
|
||||
smpl = decbyte;
|
||||
if(ManchesterDecoding(smpl & 0x0F)) {
|
||||
time_stop = (GetCountSspClk()-time_0) << 4;
|
||||
|
||||
rsamples = samples - Demod.samples;
|
||||
LED_B_ON();
|
||||
|
||||
if(tracing) {
|
||||
if(tracing) {
|
||||
uint8_t parity[MAX_PARITY_SIZE];
|
||||
GetParity(Demod.output, Demod.len, parity);
|
||||
LogTrace(Demod.output, Demod.len, (GetCountSspClk()-time_0) << 4, (GetCountSspClk()-time_0) << 4, parity, FALSE);
|
||||
LogTrace(Demod.output, Demod.len, time_start, time_stop, parity, FALSE);
|
||||
}
|
||||
|
||||
|
||||
// And ready to receive another response.
|
||||
memset(&Demod, 0, sizeof(Demod));
|
||||
Demod.output = tagToReaderResponse;
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
LED_C_OFF();
|
||||
}else{
|
||||
time_start = (GetCountSspClk()-time_0) << 4;
|
||||
}
|
||||
|
||||
div = 0;
|
||||
|
@ -852,57 +863,93 @@ static int GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen)
|
|||
}
|
||||
}
|
||||
|
||||
static uint8_t encode4Bits(const uint8_t b)
|
||||
{
|
||||
uint8_t c = b & 0xF;
|
||||
// OTA, the least significant bits first
|
||||
// The columns are
|
||||
// 1 - Bit value to send
|
||||
// 2 - Reversed (big-endian)
|
||||
// 3 - Encoded
|
||||
// 4 - Hex values
|
||||
|
||||
switch(c){
|
||||
// 1 2 3 4
|
||||
case 15: return 0x55; // 1111 -> 1111 -> 01010101 -> 0x55
|
||||
case 14: return 0x95; // 1110 -> 0111 -> 10010101 -> 0x95
|
||||
case 13: return 0x65; // 1101 -> 1011 -> 01100101 -> 0x65
|
||||
case 12: return 0xa5; // 1100 -> 0011 -> 10100101 -> 0xa5
|
||||
case 11: return 0x59; // 1011 -> 1101 -> 01011001 -> 0x59
|
||||
case 10: return 0x99; // 1010 -> 0101 -> 10011001 -> 0x99
|
||||
case 9: return 0x69; // 1001 -> 1001 -> 01101001 -> 0x69
|
||||
case 8: return 0xa9; // 1000 -> 0001 -> 10101001 -> 0xa9
|
||||
case 7: return 0x56; // 0111 -> 1110 -> 01010110 -> 0x56
|
||||
case 6: return 0x96; // 0110 -> 0110 -> 10010110 -> 0x96
|
||||
case 5: return 0x66; // 0101 -> 1010 -> 01100110 -> 0x66
|
||||
case 4: return 0xa6; // 0100 -> 0010 -> 10100110 -> 0xa6
|
||||
case 3: return 0x5a; // 0011 -> 1100 -> 01011010 -> 0x5a
|
||||
case 2: return 0x9a; // 0010 -> 0100 -> 10011010 -> 0x9a
|
||||
case 1: return 0x6a; // 0001 -> 1000 -> 01101010 -> 0x6a
|
||||
default: return 0xaa; // 0000 -> 0000 -> 10101010 -> 0xaa
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Prepare tag messages
|
||||
//-----------------------------------------------------------------------------
|
||||
static void CodeIClassTagAnswer(const uint8_t *cmd, int len)
|
||||
{
|
||||
//So far a dummy implementation, not used
|
||||
//int lastProxToAirDuration =0;
|
||||
|
||||
/*
|
||||
* SOF comprises 3 parts;
|
||||
* * An unmodulated time of 56.64 us
|
||||
* * 24 pulses of 423.75 KHz (fc/32)
|
||||
* * A logic 1, which starts with an unmodulated time of 18.88us
|
||||
* followed by 8 pulses of 423.75kHz (fc/32)
|
||||
*
|
||||
*
|
||||
* EOF comprises 3 parts:
|
||||
* - A logic 0 (which starts with 8 pulses of fc/32 followed by an unmodulated
|
||||
* time of 18.88us.
|
||||
* - 24 pulses of fc/32
|
||||
* - An unmodulated time of 56.64 us
|
||||
*
|
||||
*
|
||||
* A logic 0 starts with 8 pulses of fc/32
|
||||
* followed by an unmodulated time of 256/fc (~18,88us).
|
||||
*
|
||||
* A logic 0 starts with unmodulated time of 256/fc (~18,88us) followed by
|
||||
* 8 pulses of fc/32 (also 18.88us)
|
||||
*
|
||||
* The mode FPGA_HF_SIMULATOR_MODULATE_424K_8BIT which we use to simulate tag,
|
||||
* works like this.
|
||||
* - A 1-bit input to the FPGA becomes 8 pulses on 423.5kHz (fc/32) (18.88us).
|
||||
* - A 0-bit inptu to the FPGA becomes an unmodulated time of 18.88us
|
||||
*
|
||||
* In this mode the SOF can be written as 00011101 = 0x1D
|
||||
* The EOF can be written as 10111000 = 0xb8
|
||||
* A logic 1 is 01
|
||||
* A logic 0 is 10
|
||||
*
|
||||
* */
|
||||
|
||||
int i;
|
||||
|
||||
ToSendReset();
|
||||
|
||||
// Send SOF
|
||||
ToSend[++ToSendMax] = 0x00;
|
||||
ToSend[++ToSendMax] = 0x00;
|
||||
ToSend[++ToSendMax] = 0x00;
|
||||
ToSend[++ToSendMax] = 0xff;//Proxtoair duration starts here
|
||||
ToSend[++ToSendMax] = 0xff;
|
||||
ToSend[++ToSendMax] = 0xff;
|
||||
ToSend[++ToSendMax] = 0x00;
|
||||
ToSend[++ToSendMax] = 0xff;
|
||||
ToSend[++ToSendMax] = 0x1D;
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
int j;
|
||||
uint8_t b = cmd[i];
|
||||
|
||||
// Data bits
|
||||
for(j = 0; j < 8; j++) {
|
||||
if(b & 1) {
|
||||
ToSend[++ToSendMax] = 0x00;
|
||||
ToSend[++ToSendMax] = 0xff;
|
||||
} else {
|
||||
ToSend[++ToSendMax] = 0xff;
|
||||
ToSend[++ToSendMax] = 0x00;
|
||||
ToSend[++ToSendMax] = encode4Bits(b & 0xF); //Least significant half
|
||||
ToSend[++ToSendMax] = encode4Bits((b >>4) & 0xF);//Most significant half
|
||||
}
|
||||
b >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Send EOF
|
||||
ToSend[++ToSendMax] = 0xff;
|
||||
ToSend[++ToSendMax] = 0x00;
|
||||
ToSend[++ToSendMax] = 0xff;
|
||||
ToSend[++ToSendMax] = 0xff;
|
||||
ToSend[++ToSendMax] = 0xff;
|
||||
ToSend[++ToSendMax] = 0x00;
|
||||
ToSend[++ToSendMax] = 0x00;
|
||||
ToSend[++ToSendMax] = 0x00;
|
||||
|
||||
ToSend[++ToSendMax] = 0xB8;
|
||||
//lastProxToAirDuration = 8*ToSendMax - 3*8 - 3*8;//Not counting zeroes in the beginning or end
|
||||
|
||||
// Convert from last byte pos to length
|
||||
ToSendMax++;
|
||||
}
|
||||
|
@ -915,21 +962,13 @@ static void CodeIClassTagSOF()
|
|||
|
||||
ToSendReset();
|
||||
// Send SOF
|
||||
ToSend[++ToSendMax] = 0x00;
|
||||
ToSend[++ToSendMax] = 0x00;
|
||||
ToSend[++ToSendMax] = 0x00;
|
||||
ToSend[++ToSendMax] = 0xff;
|
||||
ToSend[++ToSendMax] = 0xff;
|
||||
ToSend[++ToSendMax] = 0xff;
|
||||
ToSend[++ToSendMax] = 0x00;
|
||||
ToSend[++ToSendMax] = 0xff;
|
||||
|
||||
ToSend[++ToSendMax] = 0x1D;
|
||||
// lastProxToAirDuration = 8*ToSendMax - 3*8;//Not counting zeroes in the beginning
|
||||
|
||||
|
||||
// Convert from last byte pos to length
|
||||
ToSendMax++;
|
||||
}
|
||||
|
||||
int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader_mac_buf);
|
||||
/**
|
||||
* @brief SimulateIClass simulates an iClass card.
|
||||
|
@ -965,7 +1004,7 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
|
|||
else if(simType == 2)
|
||||
{
|
||||
|
||||
uint8_t mac_responses[64] = { 0 };
|
||||
uint8_t mac_responses[USB_CMD_DATA_SIZE] = { 0 };
|
||||
Dbprintf("Going into attack mode, %d CSNS sent", numberOfCSNS);
|
||||
// In this mode, a number of csns are within datain. We'll simulate each one, one at a time
|
||||
// in order to collect MAC's from the reader. This can later be used in an offlne-attack
|
||||
|
@ -978,6 +1017,7 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
|
|||
memcpy(csn_crc, datain+(i*8), 8);
|
||||
if(doIClassSimulation(csn_crc,1,mac_responses+i*8))
|
||||
{
|
||||
cmd_send(CMD_ACK,CMD_SIMULATE_TAG_ICLASS,i,0,mac_responses,i*8);
|
||||
return; // Button pressed
|
||||
}
|
||||
}
|
||||
|
@ -999,7 +1039,9 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
|
|||
*/
|
||||
int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader_mac_buf)
|
||||
{
|
||||
|
||||
// CSN followed by two CRC bytes
|
||||
uint8_t response1[] = { 0x0F} ;
|
||||
uint8_t response2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t response3[] = { 0,0,0,0,0,0,0,0,0,0};
|
||||
memcpy(response3,csn,sizeof(response3));
|
||||
|
@ -1022,33 +1064,34 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader
|
|||
// Reader 81 anticoll. CSN
|
||||
// Tag CSN
|
||||
|
||||
uint8_t *resp;
|
||||
int respLen;
|
||||
uint8_t* respdata = NULL;
|
||||
int respsize = 0;
|
||||
uint8_t sof = 0x0f;
|
||||
uint8_t *modulated_response;
|
||||
int modulated_response_size;
|
||||
uint8_t* trace_data = NULL;
|
||||
int trace_data_size = 0;
|
||||
//uint8_t sof = 0x0f;
|
||||
|
||||
// Respond SOF -- takes 8 bytes
|
||||
uint8_t *resp1 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET);
|
||||
// free eventually allocated BigBuf memory
|
||||
BigBuf_free();
|
||||
// Respond SOF -- takes 1 bytes
|
||||
uint8_t *resp1 = BigBuf_malloc(2);
|
||||
int resp1Len;
|
||||
|
||||
// Anticollision CSN (rotated CSN)
|
||||
// 176: Takes 16 bytes for SOF/EOF and 10 * 16 = 160 bytes (2 bytes/bit)
|
||||
uint8_t *resp2 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 10);
|
||||
// 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
|
||||
uint8_t *resp2 = BigBuf_malloc(28);
|
||||
int resp2Len;
|
||||
|
||||
// CSN
|
||||
// 176: Takes 16 bytes for SOF/EOF and 10 * 16 = 160 bytes (2 bytes/bit)
|
||||
uint8_t *resp3 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 190);
|
||||
// 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
|
||||
uint8_t *resp3 = BigBuf_malloc(30);
|
||||
int resp3Len;
|
||||
|
||||
// e-Purse
|
||||
// 144: Takes 16 bytes for SOF/EOF and 8 * 16 = 128 bytes (2 bytes/bit)
|
||||
uint8_t *resp4 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 370);
|
||||
// 18: Takes 2 bytes for SOF/EOF and 8 * 2 = 16 bytes (2 bytes/bit)
|
||||
uint8_t *resp4 = BigBuf_malloc(20);
|
||||
int resp4Len;
|
||||
|
||||
// + 1720..
|
||||
uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
|
||||
uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
|
||||
memset(receivedCmd, 0x44, MAX_FRAME_SIZE);
|
||||
int len;
|
||||
|
||||
|
@ -1091,11 +1134,6 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader
|
|||
LED_A_ON();
|
||||
bool buttonPressed = false;
|
||||
|
||||
/** Hack for testing
|
||||
memcpy(reader_mac_buf,csn,8);
|
||||
exitLoop = true;
|
||||
end hack **/
|
||||
|
||||
while(!exitLoop) {
|
||||
|
||||
LED_B_OFF();
|
||||
|
@ -1114,35 +1152,35 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader
|
|||
// Okay, look at the command now.
|
||||
if(receivedCmd[0] == 0x0a ) {
|
||||
// Reader in anticollission phase
|
||||
resp = resp1; respLen = resp1Len; //order = 1;
|
||||
respdata = &sof;
|
||||
respsize = sizeof(sof);
|
||||
modulated_response = resp1; modulated_response_size = resp1Len; //order = 1;
|
||||
trace_data = response1;
|
||||
trace_data_size = sizeof(response1);
|
||||
} else if(receivedCmd[0] == 0x0c) {
|
||||
// Reader asks for anticollission CSN
|
||||
resp = resp2; respLen = resp2Len; //order = 2;
|
||||
respdata = response2;
|
||||
respsize = sizeof(response2);
|
||||
modulated_response = resp2; modulated_response_size = resp2Len; //order = 2;
|
||||
trace_data = response2;
|
||||
trace_data_size = sizeof(response2);
|
||||
//DbpString("Reader requests anticollission CSN:");
|
||||
} else if(receivedCmd[0] == 0x81) {
|
||||
// Reader selects anticollission CSN.
|
||||
// Tag sends the corresponding real CSN
|
||||
resp = resp3; respLen = resp3Len; //order = 3;
|
||||
respdata = response3;
|
||||
respsize = sizeof(response3);
|
||||
modulated_response = resp3; modulated_response_size = resp3Len; //order = 3;
|
||||
trace_data = response3;
|
||||
trace_data_size = sizeof(response3);
|
||||
//DbpString("Reader selects anticollission CSN:");
|
||||
} else if(receivedCmd[0] == 0x88) {
|
||||
// Read e-purse (88 02)
|
||||
resp = resp4; respLen = resp4Len; //order = 4;
|
||||
respdata = response4;
|
||||
respsize = sizeof(response4);
|
||||
modulated_response = resp4; modulated_response_size = resp4Len; //order = 4;
|
||||
trace_data = response4;
|
||||
trace_data_size = sizeof(response4);
|
||||
LED_B_ON();
|
||||
} else if(receivedCmd[0] == 0x05) {
|
||||
// Reader random and reader MAC!!!
|
||||
// Do not respond
|
||||
// We do not know what to answer, so lets keep quiet
|
||||
resp = resp1; respLen = 0; //order = 5;
|
||||
respdata = NULL;
|
||||
respsize = 0;
|
||||
modulated_response = resp1; modulated_response_size = 0; //order = 5;
|
||||
trace_data = NULL;
|
||||
trace_data_size = 0;
|
||||
if (breakAfterMacReceived){
|
||||
// dbprintf:ing ...
|
||||
Dbprintf("CSN: %02x %02x %02x %02x %02x %02x %02x %02x"
|
||||
|
@ -1159,9 +1197,9 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader
|
|||
}
|
||||
} else if(receivedCmd[0] == 0x00 && len == 1) {
|
||||
// Reader ends the session
|
||||
resp = resp1; respLen = 0; //order = 0;
|
||||
respdata = NULL;
|
||||
respsize = 0;
|
||||
modulated_response = resp1; modulated_response_size = 0; //order = 0;
|
||||
trace_data = NULL;
|
||||
trace_data_size = 0;
|
||||
} else {
|
||||
//#db# Unknown command received from reader (len=5): 26 1 0 f6 a 44 44 44 44
|
||||
// Never seen this command before
|
||||
|
@ -1171,9 +1209,9 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader
|
|||
receivedCmd[3], receivedCmd[4], receivedCmd[5],
|
||||
receivedCmd[6], receivedCmd[7], receivedCmd[8]);
|
||||
// Do not respond
|
||||
resp = resp1; respLen = 0; //order = 0;
|
||||
respdata = NULL;
|
||||
respsize = 0;
|
||||
modulated_response = resp1; modulated_response_size = 0; //order = 0;
|
||||
trace_data = NULL;
|
||||
trace_data_size = 0;
|
||||
}
|
||||
|
||||
if(cmdsRecvd > 100) {
|
||||
|
@ -1183,9 +1221,11 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader
|
|||
else {
|
||||
cmdsRecvd++;
|
||||
}
|
||||
|
||||
if(respLen > 0) {
|
||||
SendIClassAnswer(resp, respLen, 21);
|
||||
/**
|
||||
A legit tag has about 380us delay between reader EOT and tag SOF.
|
||||
**/
|
||||
if(modulated_response_size > 0) {
|
||||
SendIClassAnswer(modulated_response, modulated_response_size, 1);
|
||||
t2r_time = GetCountSspClk();
|
||||
}
|
||||
|
||||
|
@ -1194,9 +1234,9 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader
|
|||
GetParity(receivedCmd, len, parity);
|
||||
LogTrace(receivedCmd,len, (r2t_time-time_0)<< 4, (r2t_time-time_0) << 4, parity, TRUE);
|
||||
|
||||
if (respdata != NULL) {
|
||||
GetParity(respdata, respsize, parity);
|
||||
LogTrace(respdata, respsize, (t2r_time-time_0) << 4, (t2r_time-time_0) << 4, parity, FALSE);
|
||||
if (trace_data != NULL) {
|
||||
GetParity(trace_data, trace_data_size, parity);
|
||||
LogTrace(trace_data, trace_data_size, (t2r_time-time_0) << 4, (t2r_time-time_0) << 4, parity, FALSE);
|
||||
}
|
||||
if(!tracing) {
|
||||
DbpString("Trace full");
|
||||
|
@ -1210,6 +1250,8 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader
|
|||
//Dbprintf("%x", cmdsRecvd);
|
||||
LED_A_OFF();
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
|
||||
if(buttonPressed)
|
||||
{
|
||||
DbpString("Button pressed");
|
||||
|
@ -1222,7 +1264,8 @@ static int SendIClassAnswer(uint8_t *resp, int respLen, int delay)
|
|||
int i = 0, d=0;//, u = 0, d = 0;
|
||||
uint8_t b = 0;
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR|FPGA_HF_SIMULATOR_MODULATE_424K);
|
||||
//FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR|FPGA_HF_SIMULATOR_MODULATE_424K);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR|FPGA_HF_SIMULATOR_MODULATE_424K_8BIT);
|
||||
|
||||
AT91C_BASE_SSC->SSC_THR = 0x00;
|
||||
FpgaSetupSsc();
|
||||
|
@ -1246,7 +1289,8 @@ static int SendIClassAnswer(uint8_t *resp, int respLen, int delay)
|
|||
AT91C_BASE_SSC->SSC_THR = b;
|
||||
}
|
||||
|
||||
if (i > respLen +4) break;
|
||||
// if (i > respLen +4) break;
|
||||
if (i > respLen +1) break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1267,7 +1311,7 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int
|
|||
if (wait)
|
||||
{
|
||||
if(*wait < 10) *wait = 10;
|
||||
|
||||
|
||||
for(c = 0; c < *wait;) {
|
||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||
AT91C_BASE_SSC->SSC_THR = 0x00; // For exact timing!
|
||||
|
@ -1373,7 +1417,7 @@ void ReaderTransmitIClass(uint8_t* frame, int len)
|
|||
LED_A_ON();
|
||||
|
||||
// Store reader command in buffer
|
||||
if (tracing) {
|
||||
if (tracing) {
|
||||
uint8_t par[MAX_PARITY_SIZE];
|
||||
GetParity(frame, len, par);
|
||||
LogTrace(frame, len, rsamples, rsamples, par, TRUE);
|
||||
|
@ -1433,10 +1477,10 @@ int ReaderReceiveIClass(uint8_t* receivedAnswer)
|
|||
int samples = 0;
|
||||
if (!GetIClassAnswer(receivedAnswer,160,&samples,0)) return FALSE;
|
||||
rsamples += samples;
|
||||
if (tracing){
|
||||
uint8_t parity[MAX_PARITY_SIZE];
|
||||
GetParity(receivedAnswer, Demod.len, parity);
|
||||
LogTrace(receivedAnswer,Demod.len,rsamples,rsamples,parity,FALSE);
|
||||
if (tracing) {
|
||||
uint8_t parity[MAX_PARITY_SIZE];
|
||||
GetParity(receivedAnswer, Demod.len, parity);
|
||||
LogTrace(receivedAnswer,Demod.len,rsamples,rsamples,parity,FALSE);
|
||||
}
|
||||
if(samples == 0) return FALSE;
|
||||
return Demod.len;
|
||||
|
@ -1492,7 +1536,7 @@ uint8_t handshakeIclassTag(uint8_t *card_data)
|
|||
static uint8_t identify[] = { 0x0c };
|
||||
static uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
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;
|
||||
|
||||
|
@ -1539,7 +1583,7 @@ void ReaderIClass(uint8_t arg0) {
|
|||
|
||||
uint8_t card_data[24]={0};
|
||||
uint8_t last_csn[8]={0};
|
||||
|
||||
|
||||
int read_status= 0;
|
||||
bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE;
|
||||
bool get_cc = arg0 & FLAG_ICLASS_READER_GET_CC;
|
||||
|
@ -1550,11 +1594,11 @@ void ReaderIClass(uint8_t arg0) {
|
|||
while(!BUTTON_PRESS())
|
||||
{
|
||||
|
||||
if(traceLen > TRACE_SIZE) {
|
||||
if(traceLen > BigBuf_max_traceLen()) {
|
||||
DbpString("Trace full");
|
||||
break;
|
||||
}
|
||||
WDT_HIT();
|
||||
WDT_HIT();
|
||||
|
||||
read_status = handshakeIclassTag(card_data);
|
||||
|
||||
|
@ -1579,7 +1623,7 @@ void ReaderIClass(uint8_t arg0) {
|
|||
}
|
||||
//If 'get_cc' was specified and we didn't get a CC, we'll just keep trying...
|
||||
}
|
||||
LED_B_OFF();
|
||||
LED_B_OFF();
|
||||
}
|
||||
cmd_send(CMD_ACK,0,0,0,card_data, 0);
|
||||
LED_A_OFF();
|
||||
|
@ -1613,16 +1657,16 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
|
|||
int keyaccess;
|
||||
} memory;
|
||||
|
||||
uint8_t* resp = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET);
|
||||
|
||||
uint8_t resp[ICLASS_BUFFER_SIZE];
|
||||
|
||||
setupIclassReader();
|
||||
|
||||
|
||||
while(!BUTTON_PRESS()) {
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
if(traceLen > TRACE_SIZE) {
|
||||
|
||||
if(traceLen > BigBuf_max_traceLen()) {
|
||||
DbpString("Trace full");
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -339,10 +339,10 @@ void SimulateIso14443Tag(void)
|
|||
uint8_t *resp;
|
||||
int respLen;
|
||||
|
||||
uint8_t *resp1 = (((uint8_t *)BigBuf) + 800);
|
||||
uint8_t *resp1 = BigBuf_get_addr() + 800;
|
||||
int resp1Len;
|
||||
|
||||
uint8_t *receivedCmd = (uint8_t *)BigBuf;
|
||||
uint8_t *receivedCmd = BigBuf_get_addr();
|
||||
int len;
|
||||
|
||||
int i;
|
||||
|
@ -629,31 +629,32 @@ static void GetSamplesFor14443Demod(int weTx, int n, int quiet)
|
|||
int gotFrame = FALSE;
|
||||
|
||||
//# define DMA_BUFFER_SIZE 8
|
||||
int8_t *dmaBuf;
|
||||
uint8_t *dmaBuf;
|
||||
|
||||
int lastRxCounter;
|
||||
int8_t *upTo;
|
||||
uint8_t *upTo;
|
||||
|
||||
int ci, cq;
|
||||
|
||||
int samples = 0;
|
||||
|
||||
// Clear out the state of the "UART" that receives from the tag.
|
||||
uint8_t *BigBuf = BigBuf_get_addr();
|
||||
memset(BigBuf, 0x00, 400);
|
||||
Demod.output = (uint8_t *)BigBuf;
|
||||
Demod.output = BigBuf;
|
||||
Demod.len = 0;
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
|
||||
// And the UART that receives from the reader
|
||||
Uart.output = (((uint8_t *)BigBuf) + 1024);
|
||||
Uart.output = BigBuf + 1024;
|
||||
Uart.byteCntMax = 100;
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
|
||||
// Setup for the DMA.
|
||||
dmaBuf = (int8_t *)(BigBuf + 32);
|
||||
dmaBuf = BigBuf + 32;
|
||||
upTo = dmaBuf;
|
||||
lastRxCounter = DEMOD_DMA_BUFFER_SIZE;
|
||||
FpgaSetupSscDma((uint8_t *)dmaBuf, DEMOD_DMA_BUFFER_SIZE);
|
||||
FpgaSetupSscDma(dmaBuf, DEMOD_DMA_BUFFER_SIZE);
|
||||
|
||||
// Signal field is ON with the appropriate LED:
|
||||
if (weTx) LED_D_ON(); else LED_D_OFF();
|
||||
|
@ -1012,20 +1013,21 @@ void RAMFUNC SnoopIso14443(void)
|
|||
int triggered = TRUE;
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
BigBuf_free();
|
||||
// The command (reader -> tag) that we're working on receiving.
|
||||
uint8_t *receivedCmd = (uint8_t *)(BigBuf) + DEMOD_TRACE_SIZE;
|
||||
uint8_t *receivedCmd = BigBuf_malloc(READER_TAG_BUFFER_SIZE);
|
||||
// The response (tag -> reader) that we're working on receiving.
|
||||
uint8_t *receivedResponse = (uint8_t *)(BigBuf) + DEMOD_TRACE_SIZE + READER_TAG_BUFFER_SIZE;
|
||||
uint8_t *receivedResponse = BigBuf_malloc(TAG_READER_BUFFER_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;
|
||||
int traceLen = 0;
|
||||
uint8_t *trace = BigBuf_get_addr();
|
||||
traceLen = 0;
|
||||
|
||||
// The DMA buffer, used to stream samples from the FPGA.
|
||||
int8_t *dmaBuf = (int8_t *)(BigBuf) + DEMOD_TRACE_SIZE + READER_TAG_BUFFER_SIZE + TAG_READER_BUFFER_SIZE;
|
||||
uint8_t *dmaBuf = BigBuf_malloc(DEMOD_DMA_BUFFER_SIZE);
|
||||
int lastRxCounter;
|
||||
int8_t *upTo;
|
||||
uint8_t *upTo;
|
||||
int ci, cq;
|
||||
int maxBehindBy = 0;
|
||||
|
||||
|
@ -1034,7 +1036,7 @@ void RAMFUNC SnoopIso14443(void)
|
|||
int samples = 0;
|
||||
|
||||
// Initialize the trace buffer
|
||||
memset(trace, 0x44, DEMOD_TRACE_SIZE);
|
||||
memset(trace, 0x44, BigBuf_max_traceLen());
|
||||
|
||||
// Set up the demodulator for tag -> reader responses.
|
||||
Demod.output = receivedResponse;
|
||||
|
@ -1049,7 +1051,7 @@ void RAMFUNC SnoopIso14443(void)
|
|||
|
||||
// Print some debug information about the buffer sizes
|
||||
Dbprintf("Snooping buffers initialized:");
|
||||
Dbprintf(" Trace: %i bytes", DEMOD_TRACE_SIZE);
|
||||
Dbprintf(" Trace: %i bytes", BigBuf_max_traceLen());
|
||||
Dbprintf(" Reader -> tag: %i bytes", READER_TAG_BUFFER_SIZE);
|
||||
Dbprintf(" tag -> Reader: %i bytes", TAG_READER_BUFFER_SIZE);
|
||||
Dbprintf(" DMA: %i bytes", DEMOD_DMA_BUFFER_SIZE);
|
||||
|
@ -1076,7 +1078,7 @@ void RAMFUNC SnoopIso14443(void)
|
|||
(DEMOD_DMA_BUFFER_SIZE-1);
|
||||
if(behindBy > maxBehindBy) {
|
||||
maxBehindBy = behindBy;
|
||||
if(behindBy > (DEMOD_DMA_BUFFER_SIZE-2)) { // TODO: understand whether we can increase/decrease as we want or not?
|
||||
if(behindBy > (9*DEMOD_DMA_BUFFER_SIZE/10)) { // TODO: understand whether we can increase/decrease as we want or not?
|
||||
Dbprintf("blew circular buffer! behindBy=0x%x", behindBy);
|
||||
goto done;
|
||||
}
|
||||
|
@ -1147,7 +1149,7 @@ void RAMFUNC SnoopIso14443(void)
|
|||
trace[traceLen++] = Demod.len;
|
||||
memcpy(trace+traceLen, receivedResponse, Demod.len);
|
||||
traceLen += Demod.len;
|
||||
if(traceLen > DEMOD_TRACE_SIZE) {
|
||||
if(traceLen > BigBuf_max_traceLen()) {
|
||||
DbpString("Reached trace limit");
|
||||
goto done;
|
||||
}
|
||||
|
@ -1173,9 +1175,9 @@ done:
|
|||
LED_A_OFF();
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
|
||||
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
|
||||
DbpString("Snoop statistics:");
|
||||
Dbprintf(" Max behind by: %i", maxBehindBy);
|
||||
Dbprintf(" Max behind by: %i", maxBehindBy);
|
||||
Dbprintf(" Uart State: %x", Uart.state);
|
||||
Dbprintf(" Uart ByteCnt: %i", Uart.byteCnt);
|
||||
Dbprintf(" Uart ByteCntMax: %i", Uart.byteCntMax);
|
||||
|
|
|
@ -10,20 +10,19 @@
|
|||
// Routines to support ISO 14443 type A.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "../include/proxmark3.h"
|
||||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "util.h"
|
||||
#include "string.h"
|
||||
#include "../common/cmd.h"
|
||||
#include "../common/iso14443crc.h"
|
||||
#include "cmd.h"
|
||||
|
||||
#include "iso14443crc.h"
|
||||
#include "iso14443a.h"
|
||||
#include "crapto1.h"
|
||||
#include "mifareutil.h"
|
||||
|
||||
static uint32_t iso14a_timeout;
|
||||
uint8_t *trace = (uint8_t *) BigBuf+TRACE_OFFSET;
|
||||
int rsamples = 0;
|
||||
int traceLen = 0;
|
||||
int tracing = TRUE;
|
||||
uint8_t trigger = 0;
|
||||
// the block number for the ISO14443-4 PCB
|
||||
|
@ -148,7 +147,9 @@ void iso14a_set_trigger(bool enable) {
|
|||
}
|
||||
|
||||
void iso14a_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;
|
||||
}
|
||||
|
||||
|
@ -169,7 +170,7 @@ byte_t oddparity (const byte_t bt)
|
|||
return OddByteParity[bt];
|
||||
}
|
||||
|
||||
void GetParity(const uint8_t * pbtCmd, uint16_t iLen, uint8_t *par)
|
||||
void GetParity(const uint8_t *pbtCmd, uint16_t iLen, uint8_t *par)
|
||||
{
|
||||
uint16_t paritybit_cnt = 0;
|
||||
uint16_t paritybyte_cnt = 0;
|
||||
|
@ -179,15 +180,15 @@ void GetParity(const uint8_t * pbtCmd, uint16_t iLen, uint8_t *par)
|
|||
// Generate the parity bits
|
||||
parityBits |= ((OddByteParity[pbtCmd[i]]) << (7-paritybit_cnt));
|
||||
if (paritybit_cnt == 7) {
|
||||
par[paritybyte_cnt] = parityBits; // save 8 Bits parity
|
||||
parityBits = 0; // and advance to next Parity Byte
|
||||
par[paritybyte_cnt] = parityBits; // save 8 Bits parity
|
||||
parityBits = 0; // and advance to next Parity Byte
|
||||
paritybyte_cnt++;
|
||||
paritybit_cnt = 0;
|
||||
} else {
|
||||
paritybit_cnt++;
|
||||
paritybit_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// save remaining parity bits
|
||||
par[paritybyte_cnt] = parityBits;
|
||||
|
||||
|
@ -203,11 +204,13 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_
|
|||
{
|
||||
if (!tracing) return FALSE;
|
||||
|
||||
uint16_t num_paritybytes = (iLen-1)/8 + 1; // number of valid paritybytes in *parity
|
||||
uint8_t *trace = BigBuf_get_addr();
|
||||
uint16_t num_paritybytes = (iLen-1)/8 + 1; // number of valid paritybytes in *parity
|
||||
uint16_t duration = timestamp_end - timestamp_start;
|
||||
|
||||
// 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
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -218,7 +221,7 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_
|
|||
// 16 bits data length (little endian, Highest Bit used as readerToTag flag)
|
||||
// y Bytes data
|
||||
// x Bytes parity (one byte per 8 bytes data)
|
||||
|
||||
|
||||
// timestamp (start)
|
||||
trace[traceLen++] = ((timestamp_start >> 0) & 0xff);
|
||||
trace[traceLen++] = ((timestamp_start >> 8) & 0xff);
|
||||
|
@ -228,28 +231,28 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_
|
|||
// duration
|
||||
trace[traceLen++] = ((duration >> 0) & 0xff);
|
||||
trace[traceLen++] = ((duration >> 8) & 0xff);
|
||||
|
||||
|
||||
// data length
|
||||
trace[traceLen++] = ((iLen >> 0) & 0xff);
|
||||
trace[traceLen++] = ((iLen >> 8) & 0xff);
|
||||
|
||||
|
||||
// readerToTag flag
|
||||
if (!readerToTag) {
|
||||
trace[traceLen - 1] |= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
// data bytes
|
||||
if (btBytes != NULL && iLen != 0) {
|
||||
memcpy(trace + traceLen, btBytes, iLen);
|
||||
}
|
||||
traceLen += iLen;
|
||||
|
||||
traceLen += iLen;
|
||||
|
||||
// parity bytes
|
||||
if (parity != NULL && iLen != 0) {
|
||||
memcpy(trace + traceLen, parity, num_paritybytes);
|
||||
}
|
||||
traceLen += num_paritybytes;
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -307,7 +310,7 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
|
|||
|
||||
Uart.twoBits = (Uart.twoBits << 8) | bit;
|
||||
|
||||
if (Uart.state == STATE_UNSYNCD) { // not yet synced
|
||||
if (Uart.state == STATE_UNSYNCD) { // not yet synced
|
||||
|
||||
if (Uart.highCnt < 7) { // wait for a stable unmodulated signal
|
||||
if (Uart.twoBits == 0xffff) {
|
||||
|
@ -315,7 +318,7 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
|
|||
} else {
|
||||
Uart.highCnt = 0;
|
||||
}
|
||||
} else {
|
||||
} else {
|
||||
Uart.syncBit = 0xFFFF; // not set
|
||||
// look for 00xx1111 (the start bit)
|
||||
if ((Uart.twoBits & 0x6780) == 0x0780) Uart.syncBit = 7;
|
||||
|
@ -355,9 +358,9 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
|
|||
Uart.parityBits |= ((Uart.shiftReg >> 8) & 0x01); // store parity bit
|
||||
Uart.bitCount = 0;
|
||||
Uart.shiftReg = 0;
|
||||
if((Uart.len & 0x0007) == 0) { // every 8 data bytes
|
||||
Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits
|
||||
Uart.parityBits = 0;
|
||||
if((Uart.len&0x0007) == 0) { // every 8 data bytes
|
||||
Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits
|
||||
Uart.parityBits = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -374,32 +377,32 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
|
|||
Uart.parityBits |= ((Uart.shiftReg >> 8) & 0x01); // store parity bit
|
||||
Uart.bitCount = 0;
|
||||
Uart.shiftReg = 0;
|
||||
if ((Uart.len & 0x0007) == 0) { // every 8 data bytes
|
||||
Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits
|
||||
if ((Uart.len&0x0007) == 0) { // every 8 data bytes
|
||||
Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits
|
||||
Uart.parityBits = 0;
|
||||
}
|
||||
}
|
||||
} else { // no modulation in both halves - Sequence Y
|
||||
if (Uart.state == STATE_MILLER_Z || Uart.state == STATE_MILLER_Y) { // Y after logic "0" - End of Communication
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
Uart.bitCount--; // last "0" was part of EOC sequence
|
||||
Uart.shiftReg <<= 1; // drop it
|
||||
if(Uart.bitCount > 0) { // if we decoded some bits
|
||||
Uart.shiftReg >>= (9 - Uart.bitCount); // right align them
|
||||
Uart.output[Uart.len++] = (Uart.shiftReg & 0xff); // add last byte to the output
|
||||
Uart.parityBits <<= 1; // add a (void) parity bit
|
||||
Uart.parityBits <<= (8 - (Uart.len & 0x0007)); // left align parity bits
|
||||
Uart.parity[Uart.parityLen++] = Uart.parityBits; // and store it
|
||||
return TRUE;
|
||||
} else if (Uart.len & 0x0007) { // there are some parity bits to store
|
||||
Uart.parityBits <<= (8 - (Uart.len & 0x0007)); // left align remaining parity bits
|
||||
Uart.parity[Uart.parityLen++] = Uart.parityBits; // and store them
|
||||
Uart.bitCount--; // last "0" was part of EOC sequence
|
||||
Uart.shiftReg <<= 1; // drop it
|
||||
if(Uart.bitCount > 0) { // if we decoded some bits
|
||||
Uart.shiftReg >>= (9 - Uart.bitCount); // right align them
|
||||
Uart.output[Uart.len++] = (Uart.shiftReg & 0xff); // add last byte to the output
|
||||
Uart.parityBits <<= 1; // add a (void) parity bit
|
||||
Uart.parityBits <<= (8 - (Uart.len&0x0007)); // left align parity bits
|
||||
Uart.parity[Uart.parityLen++] = Uart.parityBits; // and store it
|
||||
return TRUE;
|
||||
} else if (Uart.len & 0x0007) { // there are some parity bits to store
|
||||
Uart.parityBits <<= (8 - (Uart.len&0x0007)); // left align remaining parity bits
|
||||
Uart.parity[Uart.parityLen++] = Uart.parityBits; // and store them
|
||||
}
|
||||
if ( Uart.len) {
|
||||
return TRUE; // we are finished with decoding the raw data sequence
|
||||
if (Uart.len) {
|
||||
return TRUE; // we are finished with decoding the raw data sequence
|
||||
} else {
|
||||
UartReset(); // Nothing receiver - start over
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Uart.state == STATE_START_OF_COMMUNICATION) { // error - must not follow directly after SOC
|
||||
UartReset();
|
||||
|
@ -414,8 +417,8 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
|
|||
Uart.parityBits |= ((Uart.shiftReg >> 8) & 0x01); // store parity bit
|
||||
Uart.bitCount = 0;
|
||||
Uart.shiftReg = 0;
|
||||
if ((Uart.len & 0x0007) == 0) { // every 8 data bytes
|
||||
Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits
|
||||
if ((Uart.len&0x0007) == 0) { // every 8 data bytes
|
||||
Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits
|
||||
Uart.parityBits = 0;
|
||||
}
|
||||
}
|
||||
|
@ -423,7 +426,7 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE; // not finished yet, need more data
|
||||
}
|
||||
|
@ -527,8 +530,8 @@ static RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non
|
|||
Demod.parityBits |= ((Demod.shiftReg >> 8) & 0x01); // store parity bit
|
||||
Demod.bitCount = 0;
|
||||
Demod.shiftReg = 0;
|
||||
if((Demod.len & 0x0007) == 0) { // every 8 data bytes
|
||||
Demod.parity[Demod.parityLen++] = Demod.parityBits; // store 8 parity bits
|
||||
if((Demod.len&0x0007) == 0) { // every 8 data bytes
|
||||
Demod.parity[Demod.parityLen++] = Demod.parityBits; // store 8 parity bits
|
||||
Demod.parityBits = 0;
|
||||
}
|
||||
}
|
||||
|
@ -543,26 +546,26 @@ static RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non
|
|||
Demod.parityBits |= ((Demod.shiftReg >> 8) & 0x01); // store parity bit
|
||||
Demod.bitCount = 0;
|
||||
Demod.shiftReg = 0;
|
||||
if ((Demod.len & 0x0007) == 0) { // every 8 data bytes
|
||||
Demod.parity[Demod.parityLen++] = Demod.parityBits; // store 8 parity bits1
|
||||
if ((Demod.len&0x0007) == 0) { // every 8 data bytes
|
||||
Demod.parity[Demod.parityLen++] = Demod.parityBits; // store 8 parity bits1
|
||||
Demod.parityBits = 0;
|
||||
}
|
||||
}
|
||||
Demod.endTime = Demod.startTime + 8*(9*Demod.len + Demod.bitCount + 1);
|
||||
} else { // no modulation in both halves - End of communication
|
||||
if(Demod.bitCount > 0) { // there are some remaining data bits
|
||||
Demod.shiftReg >>= (9 - Demod.bitCount); // right align the decoded bits
|
||||
Demod.output[Demod.len++] = Demod.shiftReg & 0xff; // and add them to the output
|
||||
Demod.parityBits <<= 1; // add a (void) parity bit
|
||||
Demod.parityBits <<= (8 - (Demod.len & 0x0007)); // left align remaining parity bits
|
||||
Demod.parity[Demod.parityLen++] = Demod.parityBits; // and store them
|
||||
return TRUE;
|
||||
} else if (Demod.len & 0x0007) { // there are some parity bits to store
|
||||
Demod.parityBits <<= (8 - (Demod.len & 0x0007)); // left align remaining parity bits
|
||||
Demod.parity[Demod.parityLen++] = Demod.parityBits; // and store them
|
||||
}
|
||||
if (Demod.len) {
|
||||
return TRUE; // we are finished with decoding the raw data sequence
|
||||
if(Demod.bitCount > 0) { // there are some remaining data bits
|
||||
Demod.shiftReg >>= (9 - Demod.bitCount); // right align the decoded bits
|
||||
Demod.output[Demod.len++] = Demod.shiftReg & 0xff; // and add them to the output
|
||||
Demod.parityBits <<= 1; // add a (void) parity bit
|
||||
Demod.parityBits <<= (8 - (Demod.len&0x0007)); // left align remaining parity bits
|
||||
Demod.parity[Demod.parityLen++] = Demod.parityBits; // and store them
|
||||
return TRUE;
|
||||
} else if (Demod.len & 0x0007) { // there are some parity bits to store
|
||||
Demod.parityBits <<= (8 - (Demod.len&0x0007)); // left align remaining parity bits
|
||||
Demod.parity[Demod.parityLen++] = Demod.parityBits; // and store them
|
||||
}
|
||||
if (Demod.len) {
|
||||
return TRUE; // we are finished with decoding the raw data sequence
|
||||
} else { // nothing received. Start over
|
||||
DemodReset();
|
||||
}
|
||||
|
@ -590,9 +593,6 @@ void RAMFUNC SnoopIso14443a(uint8_t param) {
|
|||
// bit 1 - trigger from first reader 7-bit request
|
||||
|
||||
LEDsoff();
|
||||
// init trace buffer
|
||||
iso14a_clear_trace();
|
||||
iso14a_set_tracing(TRUE);
|
||||
|
||||
// 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
|
||||
|
@ -600,22 +600,25 @@ void RAMFUNC SnoopIso14443a(uint8_t param) {
|
|||
// triggered == FALSE -- to wait first for card
|
||||
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 length of a received command will in most cases be no more than 18 bytes.
|
||||
// So 32 should be enough!
|
||||
uint8_t *receivedCmd = ((uint8_t *)BigBuf) + RECV_CMD_OFFSET;
|
||||
uint8_t *receivedCmdPar = ((uint8_t *)BigBuf) + RECV_CMD_PAR_OFFSET;
|
||||
uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
|
||||
uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||
|
||||
// The response (tag -> reader) that we're receiving.
|
||||
uint8_t *receivedResponse = ((uint8_t *)BigBuf) + RECV_RESP_OFFSET;
|
||||
uint8_t *receivedResponsePar = ((uint8_t *)BigBuf) + RECV_RESP_PAR_OFFSET;
|
||||
|
||||
// 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;
|
||||
uint8_t *receivedResponse = BigBuf_malloc(MAX_FRAME_SIZE);
|
||||
uint8_t *receivedResponsePar = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||
|
||||
// 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 previous_data = 0;
|
||||
int maxDataLen = 0;
|
||||
|
@ -627,10 +630,10 @@ void RAMFUNC SnoopIso14443a(uint8_t param) {
|
|||
|
||||
// Set up the demodulator for tag -> reader responses.
|
||||
DemodInit(receivedResponse, receivedResponsePar);
|
||||
|
||||
|
||||
// Set up the demodulator for the reader -> tag commands
|
||||
UartInit(receivedCmd, receivedCmdPar);
|
||||
|
||||
|
||||
// Setup and start DMA.
|
||||
FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE);
|
||||
|
||||
|
@ -655,7 +658,7 @@ void RAMFUNC SnoopIso14443a(uint8_t param) {
|
|||
// test for length of buffer
|
||||
if(dataLen > maxDataLen) {
|
||||
maxDataLen = dataLen;
|
||||
if(dataLen > 400) {
|
||||
if(dataLen > (9 * DMA_BUFFER_SIZE / 10)) {
|
||||
Dbprintf("blew circular buffer! dataLen=%d", dataLen);
|
||||
break;
|
||||
}
|
||||
|
@ -687,12 +690,12 @@ void RAMFUNC SnoopIso14443a(uint8_t param) {
|
|||
if ((!triggered) && (param & 0x02) && (Uart.len == 1) && (Uart.bitCount == 7)) triggered = TRUE;
|
||||
|
||||
if(triggered) {
|
||||
if (!LogTrace(receivedCmd,
|
||||
Uart.len,
|
||||
Uart.startTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
|
||||
Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
|
||||
Uart.parity,
|
||||
TRUE)) break;
|
||||
if (!LogTrace(receivedCmd,
|
||||
Uart.len,
|
||||
Uart.startTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
|
||||
Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
|
||||
Uart.parity,
|
||||
TRUE)) break;
|
||||
}
|
||||
/* And ready to receive another command. */
|
||||
UartReset();
|
||||
|
@ -709,12 +712,12 @@ void RAMFUNC SnoopIso14443a(uint8_t param) {
|
|||
if(ManchesterDecoding(tagdata, 0, (rsamples-1)*4)) {
|
||||
LED_B_ON();
|
||||
|
||||
if (!LogTrace(receivedResponse,
|
||||
Demod.len,
|
||||
Demod.startTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
|
||||
Demod.endTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
|
||||
Demod.parity,
|
||||
FALSE)) break;
|
||||
if (!LogTrace(receivedResponse,
|
||||
Demod.len,
|
||||
Demod.startTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
|
||||
Demod.endTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
|
||||
Demod.parity,
|
||||
FALSE)) break;
|
||||
|
||||
if ((!triggered) && (param & 0x01)) triggered = TRUE;
|
||||
|
||||
|
@ -745,7 +748,7 @@ void RAMFUNC SnoopIso14443a(uint8_t param) {
|
|||
//-----------------------------------------------------------------------------
|
||||
// Prepare tag messages
|
||||
//-----------------------------------------------------------------------------
|
||||
static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *parity)
|
||||
static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *parity)
|
||||
{
|
||||
ToSendReset();
|
||||
|
||||
|
@ -763,7 +766,7 @@ static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *pa
|
|||
ToSend[++ToSendMax] = SEC_D;
|
||||
LastProxToAirDuration = 8 * ToSendMax - 4;
|
||||
|
||||
for( uint16_t i = 0; i < len; i++) {
|
||||
for(uint16_t i = 0; i < len; i++) {
|
||||
uint8_t b = cmd[i];
|
||||
|
||||
// Data bits
|
||||
|
@ -884,7 +887,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,
|
||||
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 {
|
||||
uint8_t* response;
|
||||
|
@ -894,10 +897,6 @@ typedef struct {
|
|||
uint32_t ProxToAirDuration;
|
||||
} 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) {
|
||||
// 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
|
||||
|
@ -909,7 +908,8 @@ 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
|
||||
//
|
||||
|
||||
|
||||
|
||||
// Prepare the tag modulation bits from the message
|
||||
CodeIso14443aAsTag(response_info->response,response_info->response_n);
|
||||
|
||||
|
@ -930,15 +930,22 @@ bool prepare_tag_modulation(tag_response_info_t* response_info, size_t max_buffe
|
|||
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) {
|
||||
// Retrieve and store the current buffer index
|
||||
response_info->modulation = free_buffer_pointer;
|
||||
|
||||
// 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
|
||||
if (prepare_tag_modulation(response_info,max_buffer_size)) {
|
||||
if (prepare_tag_modulation(response_info, max_buffer_size)) {
|
||||
// Update the free buffer offset
|
||||
free_buffer_pointer += ToSendMax;
|
||||
return true;
|
||||
|
@ -953,10 +960,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)
|
||||
{
|
||||
// Enable and clear the trace
|
||||
iso14a_clear_trace();
|
||||
iso14a_set_tracing(TRUE);
|
||||
|
||||
uint8_t sak;
|
||||
|
||||
// The first response contains the ATQA (note: bytes are transmitted in reverse order).
|
||||
|
@ -1000,10 +1003,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
|
||||
uint8_t response2[5];
|
||||
uint8_t response2[5] = {0x00};
|
||||
|
||||
// Check if the uid uses the (optional) part
|
||||
uint8_t response2a[5];
|
||||
uint8_t response2a[5] = {0x00};
|
||||
|
||||
if (uid_2nd) {
|
||||
response2[0] = 0x88;
|
||||
num_to_bytes(uid_1st,3,response2+1);
|
||||
|
@ -1024,18 +1028,18 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
|
|||
response2[4] = response2[0] ^ response2[1] ^ response2[2] ^ response2[3];
|
||||
|
||||
// Prepare the mandatory SAK (for 4 and 7 byte UID)
|
||||
uint8_t response3[3];
|
||||
uint8_t response3[3] = {0x00};
|
||||
response3[0] = sak;
|
||||
ComputeCrc14443(CRC_14443_A, response3, 1, &response3[1], &response3[2]);
|
||||
|
||||
// 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;
|
||||
ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]);
|
||||
|
||||
uint8_t response5[] = { 0x00, 0x00, 0x00, 0x00 }; // Very random tag nonce
|
||||
uint8_t response6[] = { 0x04, 0x58, 0x80, 0x02, 0x00, 0x00 }; // dummy ATS (pseudo-ATR), answer to RATS:
|
||||
// Format byte = 0x58: FSCI=0x08 (FSC=256), TA(1) and TC(1) present,
|
||||
uint8_t response6[] = { 0x04, 0x58, 0x80, 0x02, 0x00, 0x00 }; // dummy ATS (pseudo-ATR), answer to RATS:
|
||||
// Format byte = 0x58: FSCI=0x08 (FSC=256), TA(1) and TC(1) present,
|
||||
// TA(1) = 0x80: different divisors not supported, DR = 1, DS = 1
|
||||
// TB(1) = not present. Defaults: FWI = 4 (FWT = 256 * 16 * 2^4 * 1/fc = 4833us), SFGI = 0 (SFG = 256 * 16 * 2^0 * 1/fc = 302us)
|
||||
// TC(1) = 0x02: CID supported, NAD not supported
|
||||
|
@ -1065,9 +1069,17 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
|
|||
.modulation_n = 0
|
||||
};
|
||||
|
||||
// Reset the offset pointer of the free buffer
|
||||
reset_free_buffer();
|
||||
|
||||
BigBuf_free_keep_EM();
|
||||
|
||||
// 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
|
||||
// there will be not enough time to do this at the moment the reader sends it REQA
|
||||
for (size_t i=0; i<TAG_RESPONSE_COUNT; i++) {
|
||||
|
@ -1088,10 +1100,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.
|
||||
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;
|
||||
tag_response_info_t* p_response;
|
||||
|
||||
|
@ -1101,7 +1109,7 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
|
|||
|
||||
if(!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) {
|
||||
DbpString("Button press");
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
p_response = NULL;
|
||||
|
@ -1252,6 +1260,7 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
|
|||
|
||||
Dbprintf("%x %x %x", happened, happened2, cmdsRecvd);
|
||||
LED_A_OFF();
|
||||
BigBuf_free_keep_EM();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1323,14 +1332,14 @@ static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing
|
|||
}
|
||||
}
|
||||
|
||||
NextTransferTime = MAX(NextTransferTime, LastTimeProxToAirStart + REQUEST_GUARD_TIME);
|
||||
NextTransferTime = MAX(NextTransferTime, LastTimeProxToAirStart + REQUEST_GUARD_TIME);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Prepare reader command (in bits, support short frames) to send to FPGA
|
||||
//-----------------------------------------------------------------------------
|
||||
void CodeIso14443aBitsAsReaderPar(const uint8_t * cmd, uint16_t bits, const uint8_t *parity)
|
||||
void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, const uint8_t *parity)
|
||||
{
|
||||
int i, j;
|
||||
int last;
|
||||
|
@ -1411,7 +1420,7 @@ void CodeIso14443aBitsAsReaderPar(const uint8_t * cmd, uint16_t bits, const uint
|
|||
//-----------------------------------------------------------------------------
|
||||
// Prepare reader command to send to FPGA
|
||||
//-----------------------------------------------------------------------------
|
||||
void CodeIso14443aAsReaderPar(const uint8_t * cmd, uint16_t len, const uint8_t *parity)
|
||||
void CodeIso14443aAsReaderPar(const uint8_t *cmd, uint16_t len, const uint8_t *parity)
|
||||
{
|
||||
CodeIso14443aBitsAsReaderPar(cmd, len*8, parity);
|
||||
}
|
||||
|
@ -1595,7 +1604,7 @@ int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool correctionNeeded){
|
|||
GetParity(resp, respLen, par);
|
||||
return EmSendCmdExPar(resp, respLen, correctionNeeded, par);
|
||||
}
|
||||
|
||||
|
||||
int EmSendCmd(uint8_t *resp, uint16_t respLen){
|
||||
uint8_t par[MAX_PARITY_SIZE];
|
||||
GetParity(resp, respLen, par);
|
||||
|
@ -1610,16 +1619,16 @@ bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_Start
|
|||
uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity)
|
||||
{
|
||||
if (tracing) {
|
||||
// we cannot exactly measure the end and start of a received command from reader. However we know that the delay from
|
||||
// end of the received command to start of the tag's (simulated by us) answer is n*128+20 or n*128+84 resp.
|
||||
// with n >= 9. The start of the tags answer can be measured and therefore the end of the received command be calculated:
|
||||
uint16_t reader_modlen = reader_EndTime - reader_StartTime;
|
||||
uint16_t approx_fdt = tag_StartTime - reader_EndTime;
|
||||
uint16_t exact_fdt = (approx_fdt - 20 + 32)/64 * 64 + 20;
|
||||
reader_EndTime = tag_StartTime - exact_fdt;
|
||||
reader_StartTime = reader_EndTime - reader_modlen;
|
||||
if (!LogTrace(reader_data, reader_len, reader_StartTime, reader_EndTime, reader_Parity, TRUE)) {
|
||||
return FALSE;
|
||||
// we cannot exactly measure the end and start of a received command from reader. However we know that the delay from
|
||||
// end of the received command to start of the tag's (simulated by us) answer is n*128+20 or n*128+84 resp.
|
||||
// with n >= 9. The start of the tags answer can be measured and therefore the end of the received command be calculated:
|
||||
uint16_t reader_modlen = reader_EndTime - reader_StartTime;
|
||||
uint16_t approx_fdt = tag_StartTime - reader_EndTime;
|
||||
uint16_t exact_fdt = (approx_fdt - 20 + 32)/64 * 64 + 20;
|
||||
reader_EndTime = tag_StartTime - exact_fdt;
|
||||
reader_StartTime = reader_EndTime - reader_modlen;
|
||||
if (!LogTrace(reader_data, reader_len, reader_StartTime, reader_EndTime, reader_Parity, TRUE)) {
|
||||
return FALSE;
|
||||
} else return(!LogTrace(tag_data, tag_len, tag_StartTime, tag_EndTime, tag_Parity, FALSE));
|
||||
} else {
|
||||
return TRUE;
|
||||
|
@ -1643,7 +1652,7 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receive
|
|||
|
||||
// Now get the answer from the card
|
||||
DemodInit(receivedResponse, receivedResponsePar);
|
||||
|
||||
|
||||
// clear RXRDY:
|
||||
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
|
||||
|
@ -1685,23 +1694,23 @@ void ReaderTransmitPar(uint8_t* frame, uint16_t len, uint8_t *par, uint32_t *tim
|
|||
|
||||
void ReaderTransmitBits(uint8_t* frame, uint16_t len, uint32_t *timing)
|
||||
{
|
||||
// Generate parity and redirect
|
||||
uint8_t par[MAX_PARITY_SIZE];
|
||||
GetParity(frame, len/8, par);
|
||||
ReaderTransmitBitsPar(frame, len, par, timing);
|
||||
// Generate parity and redirect
|
||||
uint8_t par[MAX_PARITY_SIZE];
|
||||
GetParity(frame, len/8, par);
|
||||
ReaderTransmitBitsPar(frame, len, par, timing);
|
||||
}
|
||||
|
||||
void ReaderTransmit(uint8_t* frame, uint16_t len, uint32_t *timing)
|
||||
{
|
||||
// Generate parity and redirect
|
||||
uint8_t par[MAX_PARITY_SIZE];
|
||||
GetParity(frame, len, par);
|
||||
ReaderTransmitBitsPar(frame, len*8, par, timing);
|
||||
// Generate parity and redirect
|
||||
uint8_t par[MAX_PARITY_SIZE];
|
||||
GetParity(frame, len, par);
|
||||
ReaderTransmitBitsPar(frame, len*8, par, timing);
|
||||
}
|
||||
|
||||
int ReaderReceiveOffset(uint8_t* receivedAnswer, uint16_t offset, uint8_t *parity)
|
||||
{
|
||||
if (!GetIso14443aAnswerFromTag(receivedAnswer,parity,offset)) return FALSE;
|
||||
if (!GetIso14443aAnswerFromTag(receivedAnswer, parity, offset)) return FALSE;
|
||||
if (tracing) {
|
||||
LogTrace(receivedAnswer, Demod.len, Demod.startTime*16 - DELAY_AIR2ARM_AS_READER, Demod.endTime*16 - DELAY_AIR2ARM_AS_READER, parity, FALSE);
|
||||
}
|
||||
|
@ -1720,34 +1729,26 @@ int ReaderReceive(uint8_t *receivedAnswer, uint8_t *parity)
|
|||
/* performs iso14443a anticollision procedure
|
||||
* fills the uid pointer unless NULL
|
||||
* fills resp_data unless NULL */
|
||||
int iso14443a_select_card(byte_t* uid_ptr, iso14a_card_select_t* p_hi14a_card, uint32_t* cuid_ptr) {
|
||||
|
||||
//uint8_t deselect[] = {0xc2}; //DESELECT
|
||||
//uint8_t halt[] = { 0x50, 0x00, 0x57, 0xCD }; // HALT
|
||||
uint8_t wupa[] = { 0x52 }; // WAKE-UP
|
||||
//uint8_t reqa[] = { 0x26 }; // REQUEST A
|
||||
int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, uint32_t *cuid_ptr) {
|
||||
uint8_t wupa[] = { 0x52 }; // 0x26 - REQA 0x52 - WAKE-UP
|
||||
uint8_t sel_all[] = { 0x93,0x20 };
|
||||
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 *resp = ((uint8_t *)BigBuf) + RECV_RESP_OFFSET;
|
||||
uint8_t *resp_par = ((uint8_t *)BigBuf) + RECV_RESP_PAR_OFFSET;
|
||||
|
||||
uint8_t resp[MAX_FRAME_SIZE]; // theoretically. A usual RATS will be much smaller
|
||||
uint8_t resp_par[MAX_PARITY_SIZE];
|
||||
byte_t uid_resp[4];
|
||||
size_t uid_resp_len;
|
||||
|
||||
uint8_t sak = 0x04; // cascade uid
|
||||
int cascade_level = 0;
|
||||
int len =0;
|
||||
|
||||
// test for the SKYLANDERS TOY.
|
||||
// ReaderTransmit(deselect,sizeof(deselect), NULL);
|
||||
// len = ReaderReceive(resp, resp_par);
|
||||
|
||||
int len;
|
||||
|
||||
// Broadcast for a card, WUPA (0x52) will force response from all cards in the field
|
||||
ReaderTransmitBitsPar(wupa,7,0, NULL);
|
||||
ReaderTransmitBitsPar(wupa,7,0, NULL);
|
||||
|
||||
// Receive the ATQA
|
||||
if(!ReaderReceive(resp, resp_par)) return 0;
|
||||
|
||||
|
||||
if(p_hi14a_card) {
|
||||
memcpy(p_hi14a_card->atqa, resp, 2);
|
||||
p_hi14a_card->uidlen = 0;
|
||||
|
@ -1759,99 +1760,99 @@ int iso14443a_select_card(byte_t* uid_ptr, iso14a_card_select_t* p_hi14a_card, u
|
|||
memset(uid_ptr,0,10);
|
||||
}
|
||||
|
||||
// OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in
|
||||
// which case we need to make a cascade 2 request and select - this is a long UID
|
||||
// While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
|
||||
for(; sak & 0x04; cascade_level++) {
|
||||
// SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97)
|
||||
sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2;
|
||||
// OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in
|
||||
// which case we need to make a cascade 2 request and select - this is a long UID
|
||||
// While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
|
||||
for(; sak & 0x04; cascade_level++) {
|
||||
// SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97)
|
||||
sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2;
|
||||
|
||||
// SELECT_ALL
|
||||
ReaderTransmit(sel_all,sizeof(sel_all), NULL);
|
||||
if (!ReaderReceive(resp, resp_par)) return 0;
|
||||
|
||||
if (Demod.collisionPos) { // we had a collision and need to construct the UID bit by bit
|
||||
memset(uid_resp, 0, 4);
|
||||
uint16_t uid_resp_bits = 0;
|
||||
uint16_t collision_answer_offset = 0;
|
||||
// anti-collision-loop:
|
||||
while (Demod.collisionPos) {
|
||||
Dbprintf("Multiple tags detected. Collision after Bit %d", Demod.collisionPos);
|
||||
for (uint16_t i = collision_answer_offset; i < Demod.collisionPos; i++, uid_resp_bits++) { // add valid UID bits before collision point
|
||||
uint16_t UIDbit = (resp[i/8] >> (i % 8)) & 0x01;
|
||||
uid_resp[uid_resp_bits & 0xf8] |= UIDbit << (uid_resp_bits % 8);
|
||||
}
|
||||
uid_resp[uid_resp_bits/8] |= 1 << (uid_resp_bits % 8); // next time select the card(s) with a 1 in the collision position
|
||||
uid_resp_bits++;
|
||||
// construct anticollosion command:
|
||||
sel_uid[1] = ((2 + uid_resp_bits/8) << 4) | (uid_resp_bits & 0x07); // length of data in bytes and bits
|
||||
for (uint16_t i = 0; i <= uid_resp_bits/8; i++) {
|
||||
sel_uid[2+i] = uid_resp[i];
|
||||
}
|
||||
collision_answer_offset = uid_resp_bits%8;
|
||||
ReaderTransmitBits(sel_uid, 16 + uid_resp_bits, NULL);
|
||||
if (!ReaderReceiveOffset(resp, collision_answer_offset,resp_par)) return 0;
|
||||
}
|
||||
// finally, add the last bits and BCC of the UID
|
||||
for (uint16_t i = collision_answer_offset; i < (Demod.len-1)*8; i++, uid_resp_bits++) {
|
||||
uint16_t UIDbit = (resp[i/8] >> (i%8)) & 0x01;
|
||||
uid_resp[uid_resp_bits/8] |= UIDbit << (uid_resp_bits % 8);
|
||||
}
|
||||
|
||||
} else { // no collision, use the response to SELECT_ALL as current uid
|
||||
memcpy(uid_resp,resp,4);
|
||||
}
|
||||
uid_resp_len = 4;
|
||||
|
||||
// calculate crypto UID. Always use last 4 Bytes.
|
||||
if(cuid_ptr) {
|
||||
*cuid_ptr = bytes_to_num(uid_resp, 4);
|
||||
}
|
||||
|
||||
// Construct SELECT UID command
|
||||
sel_uid[1] = 0x70; // transmitting a full UID (1 Byte cmd, 1 Byte NVB, 4 Byte UID, 1 Byte BCC, 2 Bytes CRC)
|
||||
memcpy(sel_uid+2,uid_resp,4); // the UID
|
||||
sel_uid[6] = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate and add BCC
|
||||
AppendCrc14443a(sel_uid,7); // calculate and add CRC
|
||||
ReaderTransmit(sel_uid,sizeof(sel_uid), NULL);
|
||||
|
||||
// Receive the SAK
|
||||
// SELECT_ALL
|
||||
ReaderTransmit(sel_all, sizeof(sel_all), NULL);
|
||||
if (!ReaderReceive(resp, resp_par)) return 0;
|
||||
sak = resp[0];
|
||||
|
||||
|
||||
if (Demod.collisionPos) { // we had a collision and need to construct the UID bit by bit
|
||||
memset(uid_resp, 0, 4);
|
||||
uint16_t uid_resp_bits = 0;
|
||||
uint16_t collision_answer_offset = 0;
|
||||
// anti-collision-loop:
|
||||
while (Demod.collisionPos) {
|
||||
Dbprintf("Multiple tags detected. Collision after Bit %d", Demod.collisionPos);
|
||||
for (uint16_t i = collision_answer_offset; i < Demod.collisionPos; i++, uid_resp_bits++) { // add valid UID bits before collision point
|
||||
uint16_t UIDbit = (resp[i/8] >> (i % 8)) & 0x01;
|
||||
uid_resp[uid_resp_bits / 8] |= UIDbit << (uid_resp_bits % 8);
|
||||
}
|
||||
uid_resp[uid_resp_bits/8] |= 1 << (uid_resp_bits % 8); // next time select the card(s) with a 1 in the collision position
|
||||
uid_resp_bits++;
|
||||
// construct anticollosion command:
|
||||
sel_uid[1] = ((2 + uid_resp_bits/8) << 4) | (uid_resp_bits & 0x07); // length of data in bytes and bits
|
||||
for (uint16_t i = 0; i <= uid_resp_bits/8; i++) {
|
||||
sel_uid[2+i] = uid_resp[i];
|
||||
}
|
||||
collision_answer_offset = uid_resp_bits%8;
|
||||
ReaderTransmitBits(sel_uid, 16 + uid_resp_bits, NULL);
|
||||
if (!ReaderReceiveOffset(resp, collision_answer_offset, resp_par)) return 0;
|
||||
}
|
||||
// finally, add the last bits and BCC of the UID
|
||||
for (uint16_t i = collision_answer_offset; i < (Demod.len-1)*8; i++, uid_resp_bits++) {
|
||||
uint16_t UIDbit = (resp[i/8] >> (i%8)) & 0x01;
|
||||
uid_resp[uid_resp_bits/8] |= UIDbit << (uid_resp_bits % 8);
|
||||
}
|
||||
|
||||
} else { // no collision, use the response to SELECT_ALL as current uid
|
||||
memcpy(uid_resp, resp, 4);
|
||||
}
|
||||
uid_resp_len = 4;
|
||||
|
||||
// calculate crypto UID. Always use last 4 Bytes.
|
||||
if(cuid_ptr) {
|
||||
*cuid_ptr = bytes_to_num(uid_resp, 4);
|
||||
}
|
||||
|
||||
// Construct SELECT UID command
|
||||
sel_uid[1] = 0x70; // transmitting a full UID (1 Byte cmd, 1 Byte NVB, 4 Byte UID, 1 Byte BCC, 2 Bytes CRC)
|
||||
memcpy(sel_uid+2, uid_resp, 4); // the UID
|
||||
sel_uid[6] = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate and add BCC
|
||||
AppendCrc14443a(sel_uid, 7); // calculate and add CRC
|
||||
ReaderTransmit(sel_uid, sizeof(sel_uid), NULL);
|
||||
|
||||
// Receive the SAK
|
||||
if (!ReaderReceive(resp, resp_par)) return 0;
|
||||
sak = resp[0];
|
||||
|
||||
// Test if more parts of the uid are coming
|
||||
if ((sak & 0x04) /* && uid_resp[0] == 0x88 */) {
|
||||
// Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of:
|
||||
// http://www.nxp.com/documents/application_note/AN10927.pdf
|
||||
uid_resp[0] = uid_resp[1];
|
||||
uid_resp[1] = uid_resp[2];
|
||||
uid_resp[2] = uid_resp[3];
|
||||
|
||||
uid_resp_len = 3;
|
||||
}
|
||||
if ((sak & 0x04) /* && uid_resp[0] == 0x88 */) {
|
||||
// Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of:
|
||||
// http://www.nxp.com/documents/application_note/AN10927.pdf
|
||||
uid_resp[0] = uid_resp[1];
|
||||
uid_resp[1] = uid_resp[2];
|
||||
uid_resp[2] = uid_resp[3];
|
||||
|
||||
if(uid_ptr) {
|
||||
memcpy(uid_ptr + (cascade_level*3), uid_resp, uid_resp_len);
|
||||
}
|
||||
uid_resp_len = 3;
|
||||
}
|
||||
|
||||
if(p_hi14a_card) {
|
||||
memcpy(p_hi14a_card->uid + (cascade_level*3), uid_resp, uid_resp_len);
|
||||
p_hi14a_card->uidlen += uid_resp_len;
|
||||
}
|
||||
}
|
||||
if(uid_ptr) {
|
||||
memcpy(uid_ptr + (cascade_level*3), uid_resp, uid_resp_len);
|
||||
}
|
||||
|
||||
if(p_hi14a_card) {
|
||||
p_hi14a_card->sak = sak;
|
||||
p_hi14a_card->ats_len = 0;
|
||||
}
|
||||
if(p_hi14a_card) {
|
||||
memcpy(p_hi14a_card->uid + (cascade_level*3), uid_resp, uid_resp_len);
|
||||
p_hi14a_card->uidlen += uid_resp_len;
|
||||
}
|
||||
}
|
||||
|
||||
if(p_hi14a_card) {
|
||||
p_hi14a_card->sak = sak;
|
||||
p_hi14a_card->ats_len = 0;
|
||||
}
|
||||
|
||||
// non iso14443a compliant tag
|
||||
if( (sak & 0x20) == 0) return 2;
|
||||
|
||||
|
||||
// Request for answer to select
|
||||
AppendCrc14443a(rats, 2);
|
||||
ReaderTransmit(rats, sizeof(rats), NULL);
|
||||
|
||||
|
||||
if (!(len = ReaderReceive(resp, resp_par))) return 0;
|
||||
|
||||
|
||||
|
@ -1862,7 +1863,7 @@ int iso14443a_select_card(byte_t* uid_ptr, iso14a_card_select_t* p_hi14a_card, u
|
|||
|
||||
// reset the PCB block number
|
||||
iso14_pcb_blocknum = 0;
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void iso14443a_setup(uint8_t fpga_minor_mode) {
|
||||
|
@ -1873,7 +1874,8 @@ void iso14443a_setup(uint8_t fpga_minor_mode) {
|
|||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
// Signal field is on with the appropriate LED
|
||||
if (fpga_minor_mode == FPGA_HF_ISO14443A_READER_MOD || fpga_minor_mode == FPGA_HF_ISO14443A_READER_LISTEN) {
|
||||
if (fpga_minor_mode == FPGA_HF_ISO14443A_READER_MOD
|
||||
|| fpga_minor_mode == FPGA_HF_ISO14443A_READER_LISTEN) {
|
||||
LED_D_ON();
|
||||
} else {
|
||||
LED_D_OFF();
|
||||
|
@ -1886,7 +1888,7 @@ void iso14443a_setup(uint8_t fpga_minor_mode) {
|
|||
DemodReset();
|
||||
UartReset();
|
||||
NextTransferTime = 2*DELAY_ARM2AIR_AS_READER;
|
||||
iso14a_set_timeout(1050); // 10ms default 10*105 =
|
||||
iso14a_set_timeout(1050); // 10ms default
|
||||
}
|
||||
|
||||
int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data) {
|
||||
|
@ -1901,7 +1903,7 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data) {
|
|||
|
||||
ReaderTransmit(real_cmd, cmd_len+4, NULL);
|
||||
size_t len = ReaderReceive(data, parity);
|
||||
uint8_t * data_bytes = (uint8_t *) data;
|
||||
uint8_t *data_bytes = (uint8_t *) data;
|
||||
if (!len)
|
||||
return 0; //DATA LINK ERROR
|
||||
// if we received an I- or R(ACK)-Block with a block number equal to the
|
||||
|
@ -1965,8 +1967,8 @@ void ReaderIso14443a(UsbCommand *c)
|
|||
len += 2;
|
||||
if (lenbits) lenbits += 16;
|
||||
}
|
||||
if(lenbits>0) {
|
||||
GetParity(cmd, lenbits/8, par);
|
||||
if(lenbits>0) {
|
||||
GetParity(cmd, lenbits/8, par);
|
||||
ReaderTransmitBitsPar(cmd, lenbits, par, NULL);
|
||||
} else {
|
||||
ReaderTransmit(cmd,len, NULL);
|
||||
|
@ -2025,9 +2027,12 @@ void ReaderMifare(bool first_try)
|
|||
uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
|
||||
static uint8_t mf_nr_ar3;
|
||||
|
||||
uint8_t* receivedAnswer = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET);
|
||||
uint8_t* receivedAnswerPar = (((uint8_t *)BigBuf) + RECV_RESP_PAR_OFFSET);
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||
|
||||
// free eventually allocated BigBuf memory. We want all for tracing.
|
||||
BigBuf_free();
|
||||
|
||||
iso14a_clear_trace();
|
||||
iso14a_set_tracing(TRUE);
|
||||
|
||||
|
@ -2164,7 +2169,7 @@ void ReaderMifare(bool first_try)
|
|||
led_on = !led_on;
|
||||
if(led_on) LED_B_ON(); else LED_B_OFF();
|
||||
|
||||
par_list[nt_diff] = SwapBits(par[0], 8);
|
||||
par_list[nt_diff] = SwapBits(par[0], 8);
|
||||
ks_list[nt_diff] = receivedAnswer[0] ^ 0x05;
|
||||
|
||||
// Test if the information is complete
|
||||
|
@ -2237,10 +2242,10 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
|
|||
struct Crypto1State *pcs;
|
||||
pcs = &mpcs;
|
||||
uint32_t numReads = 0;//Counts numer of times reader read a block
|
||||
uint8_t* receivedCmd = get_bigbufptr_recvcmdbuf();
|
||||
uint8_t* receivedCmd_par = receivedCmd + MAX_FRAME_SIZE;
|
||||
uint8_t* response = get_bigbufptr_recvrespbuf();
|
||||
uint8_t* response_par = response + MAX_FRAME_SIZE;
|
||||
uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedCmd_par[MAX_MIFARE_PARITY_SIZE];
|
||||
uint8_t response[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t response_par[MAX_MIFARE_PARITY_SIZE];
|
||||
|
||||
uint8_t rATQA[] = {0x04, 0x00}; // Mifare classic 1k 4BUID
|
||||
uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62};
|
||||
|
@ -2257,6 +2262,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};
|
||||
uint8_t ar_nr_collected = 0;
|
||||
|
||||
// free eventually allocated BigBuf memory but keep Emulator Memory
|
||||
BigBuf_free_keep_EM();
|
||||
// clear trace
|
||||
iso14a_clear_trace();
|
||||
iso14a_set_tracing(TRUE);
|
||||
|
@ -2727,18 +2734,20 @@ void RAMFUNC SniffMifare(uint8_t param) {
|
|||
// The command (reader -> tag) that we're receiving.
|
||||
// The length of a received command will in most cases be no more than 18 bytes.
|
||||
// So 32 should be enough!
|
||||
uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
|
||||
uint8_t *receivedCmdPar = ((uint8_t *)BigBuf) + RECV_CMD_PAR_OFFSET;
|
||||
uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedCmdPar[MAX_MIFARE_PARITY_SIZE];
|
||||
// The response (tag -> reader) that we're receiving.
|
||||
uint8_t *receivedResponse = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET);
|
||||
uint8_t *receivedResponsePar = ((uint8_t *)BigBuf) + RECV_RESP_PAR_OFFSET;
|
||||
|
||||
uint8_t receivedResponse[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedResponsePar[MAX_MIFARE_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
|
||||
uint8_t *dmaBuf = ((uint8_t *)BigBuf) + DMA_BUFFER_OFFSET;
|
||||
// free eventually allocated BigBuf memory
|
||||
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 previous_data = 0;
|
||||
int maxDataLen = 0;
|
||||
|
@ -2797,7 +2806,7 @@ void RAMFUNC SniffMifare(uint8_t param) {
|
|||
// test for length of buffer
|
||||
if(dataLen > maxDataLen) { // we are more behind than ever...
|
||||
maxDataLen = dataLen;
|
||||
if(dataLen > 400) {
|
||||
if(dataLen > (9 * DMA_BUFFER_SIZE / 10)) {
|
||||
Dbprintf("blew circular buffer! dataLen=0x%x", dataLen);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -28,8 +28,8 @@ typedef struct {
|
|||
uint16_t bitCount;
|
||||
uint16_t collisionPos;
|
||||
uint16_t syncBit;
|
||||
uint8_t parityBits;
|
||||
uint8_t parityLen;
|
||||
uint8_t parityBits;
|
||||
uint8_t parityLen;
|
||||
uint16_t shiftReg;
|
||||
uint16_t samples;
|
||||
uint16_t len;
|
||||
|
@ -61,8 +61,8 @@ typedef struct {
|
|||
uint16_t byteCntMax;
|
||||
uint16_t posCnt;
|
||||
uint16_t syncBit;
|
||||
uint8_t parityBits;
|
||||
uint8_t parityLen;
|
||||
uint8_t parityBits;
|
||||
uint8_t parityLen;
|
||||
uint16_t highCnt;
|
||||
uint16_t twoBits;
|
||||
uint32_t startTime, endTime;
|
||||
|
|
|
@ -58,13 +58,12 @@
|
|||
// *) document all the functions
|
||||
|
||||
|
||||
#include "../include/proxmark3.h"
|
||||
#include "proxmark3.h"
|
||||
#include "util.h"
|
||||
#include "apps.h"
|
||||
#include "string.h"
|
||||
#include "../common/iso15693tools.h"
|
||||
#include "../common/cmd.h"
|
||||
|
||||
#include "iso15693tools.h"
|
||||
#include "cmd.h"
|
||||
|
||||
#define arraylen(x) (sizeof(x)/sizeof((x)[0]))
|
||||
|
||||
|
@ -297,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)
|
||||
{
|
||||
int c = 0;
|
||||
uint8_t *dest = (uint8_t *)BigBuf;
|
||||
uint8_t *dest = BigBuf_get_addr();
|
||||
int getNext = 0;
|
||||
|
||||
int8_t prev = 0;
|
||||
|
@ -447,12 +446,12 @@ static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *
|
|||
static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed)
|
||||
{
|
||||
int c = 0;
|
||||
uint8_t *dest = (uint8_t *)BigBuf;
|
||||
uint8_t *dest = BigBuf_get_addr();
|
||||
int getNext = 0;
|
||||
|
||||
int8_t prev = 0;
|
||||
|
||||
// NOW READ RESPONSE
|
||||
// NOW READ RESPONSE
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||
//spindelay(60); // greg - experiment to get rid of some of the 0 byte/failed reads
|
||||
c = 0;
|
||||
|
@ -468,7 +467,7 @@ static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int
|
|||
// tone that the tag AM-modulates, so every other sample is I,
|
||||
// every other is Q. We just want power, so abs(I) + abs(Q) is
|
||||
// close to what we want.
|
||||
if (getNext) {
|
||||
if(getNext) {
|
||||
int8_t r;
|
||||
|
||||
if(b < 0) {
|
||||
|
@ -597,7 +596,7 @@ static void BuildIdentifyRequest(void);
|
|||
//-----------------------------------------------------------------------------
|
||||
void AcquireRawAdcSamplesIso15693(void)
|
||||
{
|
||||
uint8_t *dest = (uint8_t *)BigBuf;
|
||||
uint8_t *dest = BigBuf_get_addr();
|
||||
|
||||
int c = 0;
|
||||
int getNext = 0;
|
||||
|
@ -679,7 +678,7 @@ void AcquireRawAdcSamplesIso15693(void)
|
|||
|
||||
void RecordRawAdcSamplesIso15693(void)
|
||||
{
|
||||
uint8_t *dest = (uint8_t *)BigBuf;
|
||||
uint8_t *dest = BigBuf_get_addr();
|
||||
|
||||
int c = 0;
|
||||
int getNext = 0;
|
||||
|
@ -690,8 +689,8 @@ void RecordRawAdcSamplesIso15693(void)
|
|||
FpgaSetupSsc();
|
||||
|
||||
// Start from off (no field generated)
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
SpinDelay(200);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
SpinDelay(200);
|
||||
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
|
@ -879,8 +878,8 @@ int SendDataTag(uint8_t *send, int sendlen, int init, int speed, uint8_t **recv)
|
|||
LED_D_OFF();
|
||||
|
||||
int answerLen=0;
|
||||
uint8_t *answer = (((uint8_t *)BigBuf) + 3660);
|
||||
if (recv!=NULL) memset(BigBuf + 3660, 0, 100);
|
||||
uint8_t *answer = BigBuf_get_addr() + 3660;
|
||||
if (recv != NULL) memset(answer, 0, 100);
|
||||
|
||||
if (init) Iso15693InitReader();
|
||||
|
||||
|
@ -993,16 +992,16 @@ void SetDebugIso15693(uint32_t debug) {
|
|||
// Simulate an ISO15693 reader, perform anti-collision and then attempt to read a sector
|
||||
// all demodulation performed in arm rather than host. - greg
|
||||
//-----------------------------------------------------------------------------
|
||||
void ReaderIso15693(uint32_t parameter )
|
||||
void ReaderIso15693(uint32_t parameter)
|
||||
{
|
||||
LED_A_ON();
|
||||
LED_B_ON();
|
||||
LED_C_OFF();
|
||||
LED_D_OFF();
|
||||
|
||||
uint8_t *answer1 = (((uint8_t *)BigBuf) + 3660); //
|
||||
uint8_t *answer2 = (((uint8_t *)BigBuf) + 3760);
|
||||
uint8_t *answer3 = (((uint8_t *)BigBuf) + 3860);
|
||||
uint8_t *answer1 = BigBuf_get_addr() + 3660;
|
||||
uint8_t *answer2 = BigBuf_get_addr() + 3760;
|
||||
uint8_t *answer3 = BigBuf_get_addr() + 3860;
|
||||
|
||||
int answerLen1 = 0;
|
||||
int answerLen2 = 0;
|
||||
|
@ -1014,9 +1013,9 @@ void ReaderIso15693(uint32_t parameter )
|
|||
int elapsed = 0;
|
||||
uint8_t TagUID[8] = {0x00};
|
||||
|
||||
|
||||
|
||||
// Blank arrays
|
||||
memset(BigBuf + 3660, 0x00, 300);
|
||||
memset(answer1, 0x00, 300);
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
|
@ -1025,9 +1024,9 @@ void ReaderIso15693(uint32_t parameter )
|
|||
FpgaSetupSsc();
|
||||
|
||||
// Start from off (no field generated)
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
SpinDelay(200);
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
SpinDelay(200);
|
||||
|
||||
// Give the tags time to energize
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||
SpinDelay(200);
|
||||
|
@ -1066,7 +1065,7 @@ void ReaderIso15693(uint32_t parameter )
|
|||
Dbhexdump(answerLen1,answer1,true);
|
||||
|
||||
// UID is reverse
|
||||
if (answerLen1 >= 12)
|
||||
if (answerLen1>=12)
|
||||
Dbprintf("UID = %02hX%02hX%02hX%02hX%02hX%02hX%02hX%02hX",
|
||||
TagUID[7],TagUID[6],TagUID[5],TagUID[4],
|
||||
TagUID[3],TagUID[2],TagUID[1],TagUID[0]);
|
||||
|
@ -1080,14 +1079,14 @@ void ReaderIso15693(uint32_t parameter )
|
|||
DbdecodeIso15693Answer(answerLen3,answer3);
|
||||
Dbhexdump(answerLen3,answer3,true);
|
||||
|
||||
// read all pages
|
||||
if (answerLen1 >= 12 && DEBUG) {
|
||||
// read all pages
|
||||
if (answerLen1>=12 && DEBUG) {
|
||||
i=0;
|
||||
while (i < 32) { // sanity check, assume max 32 pages
|
||||
while (i<32) { // sanity check, assume max 32 pages
|
||||
BuildReadBlockRequest(TagUID,i);
|
||||
TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait);
|
||||
answerLen2 = GetIso15693AnswerFromTag(answer2, 100, &samples, &elapsed);
|
||||
if (answerLen2 > 0) {
|
||||
TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait);
|
||||
answerLen2 = GetIso15693AnswerFromTag(answer2, 100, &samples, &elapsed);
|
||||
if (answerLen2>0) {
|
||||
Dbprintf("READ SINGLE BLOCK %d returned %d octets:",i,answerLen2);
|
||||
DbdecodeIso15693Answer(answerLen2,answer2);
|
||||
Dbhexdump(answerLen2,answer2,true);
|
||||
|
@ -1112,16 +1111,16 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid)
|
|||
LED_C_OFF();
|
||||
LED_D_OFF();
|
||||
|
||||
uint8_t *buf = (((uint8_t *)BigBuf) + 3660); //
|
||||
uint8_t *buf = BigBuf_get_addr() + 3660;
|
||||
|
||||
int answerLen1 = 0;
|
||||
int samples = 0;
|
||||
int tsamples = 0;
|
||||
int wait = 0;
|
||||
int elapsed = 0;
|
||||
|
||||
|
||||
memset(buf, 0x00, 100);
|
||||
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
@ -1129,8 +1128,8 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid)
|
|||
FpgaSetupSsc();
|
||||
|
||||
// Start from off (no field generated)
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
SpinDelay(200);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
SpinDelay(200);
|
||||
|
||||
LED_A_OFF();
|
||||
LED_B_OFF();
|
||||
|
@ -1147,7 +1146,7 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid)
|
|||
|
||||
BuildInventoryResponse(uid);
|
||||
|
||||
TransmitTo15693Reader(ToSend, ToSendMax, &tsamples, &wait);
|
||||
TransmitTo15693Reader(ToSend,ToSendMax, &tsamples, &wait);
|
||||
}
|
||||
|
||||
Dbprintf("%d octets read from reader command: %x %x %x %x %x %x %x %x %x", answerLen1,
|
||||
|
@ -1214,7 +1213,7 @@ void BruteforceIso15693Afi(uint32_t speed)
|
|||
void DirectTag15693Command(uint32_t datalen,uint32_t speed, uint32_t recv, uint8_t data[]) {
|
||||
|
||||
int recvlen=0;
|
||||
uint8_t *recvbuf=(uint8_t *)BigBuf;
|
||||
uint8_t *recvbuf = BigBuf_get_addr();
|
||||
// UsbCommand n;
|
||||
|
||||
if (DEBUG) {
|
||||
|
|
|
@ -98,13 +98,14 @@ static uint32_t get_key_stream(int skip, int count)
|
|||
}
|
||||
|
||||
/* Write Time Data into LOG */
|
||||
uint8_t *BigBuf = BigBuf_get_addr();
|
||||
if(count == 6) { i = -1; } else { i = legic_read_count; }
|
||||
((uint8_t*)BigBuf)[OFFSET_LOG+128+i] = legic_prng_count();
|
||||
((uint8_t*)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;
|
||||
((uint8_t*)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;
|
||||
((uint8_t*)BigBuf)[OFFSET_LOG+384+i] = count;
|
||||
BigBuf[OFFSET_LOG+128+i] = legic_prng_count();
|
||||
BigBuf[OFFSET_LOG+256+i*4] = (legic_prng_bc >> 0) & 0xff;
|
||||
BigBuf[OFFSET_LOG+256+i*4+1] = (legic_prng_bc >> 8) & 0xff;
|
||||
BigBuf[OFFSET_LOG+256+i*4+2] = (legic_prng_bc >>16) & 0xff;
|
||||
BigBuf[OFFSET_LOG+256+i*4+3] = (legic_prng_bc >>24) & 0xff;
|
||||
BigBuf[OFFSET_LOG+384+i] = count;
|
||||
|
||||
/* Generate KeyStream */
|
||||
for(i=0; i<count; i++) {
|
||||
|
@ -426,6 +427,7 @@ int LegicRfReader(int offset, int bytes) {
|
|||
|
||||
LegicCommonInit();
|
||||
|
||||
uint8_t *BigBuf = BigBuf_get_addr();
|
||||
memset(BigBuf, 0, 1024);
|
||||
|
||||
DbpString("setting up legic card");
|
||||
|
@ -465,7 +467,7 @@ int LegicRfReader(int offset, int bytes) {
|
|||
LED_C_OFF();
|
||||
return -1;
|
||||
}
|
||||
((uint8_t*)BigBuf)[byte_index] = r;
|
||||
BigBuf[byte_index] = r;
|
||||
WDT_HIT();
|
||||
byte_index++;
|
||||
if(byte_index & 0x10) LED_C_ON(); else LED_C_OFF();
|
||||
|
@ -480,7 +482,8 @@ int LegicRfReader(int offset, int bytes) {
|
|||
|
||||
void LegicRfWriter(int bytes, int offset) {
|
||||
int byte_index=0, addr_sz=0;
|
||||
|
||||
uint8_t *BigBuf = BigBuf_get_addr();
|
||||
|
||||
LegicCommonInit();
|
||||
|
||||
DbpString("setting up legic card");
|
||||
|
@ -512,7 +515,7 @@ void LegicRfWriter(int bytes, int offset) {
|
|||
perform_setup_phase_rwd(SESSION_IV);
|
||||
legic_prng_forward(2);
|
||||
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()) {
|
||||
Dbprintf("operation aborted @ 0x%03.3x", byte_index);
|
||||
switch_off_tag_rwd();
|
||||
|
@ -534,6 +537,8 @@ int timestamp;
|
|||
/* Handle (whether to respond) a frame in tag mode */
|
||||
static void frame_handle_tag(struct legic_frame const * const f)
|
||||
{
|
||||
uint8_t *BigBuf = BigBuf_get_addr();
|
||||
|
||||
/* First Part of Handshake (IV) */
|
||||
if(f->bits == 7) {
|
||||
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) {
|
||||
int key = get_key_stream(-1, 11); //legic_phase_drift, 11);
|
||||
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;
|
||||
((uint8_t*)BigBuf)[OFFSET_LOG+legic_read_count] = (uint8_t)addr;
|
||||
BigBuf[OFFSET_LOG+legic_read_count] = (uint8_t)addr;
|
||||
legic_read_count++;
|
||||
|
||||
//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;
|
||||
Dbprintf("IV: %03.3x", legic_prng_iv);
|
||||
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++) {
|
||||
uint32_t t;
|
||||
t = ((uint8_t*)BigBuf)[OFFSET_LOG+256+i*4];
|
||||
t |= ((uint8_t*)BigBuf)[OFFSET_LOG+256+i*4+1] << 8;
|
||||
t |= ((uint8_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];
|
||||
t |= BigBuf[OFFSET_LOG+256+i*4+1] << 8;
|
||||
t |= BigBuf[OFFSET_LOG+256+i*4+2] <<16;
|
||||
t |= BigBuf[OFFSET_LOG+256+i*4+3] <<24;
|
||||
|
||||
Dbprintf("Cycles: %u, Frame Length: %u, Time: %u",
|
||||
((uint8_t*)BigBuf)[OFFSET_LOG+128+i],
|
||||
((uint8_t*)BigBuf)[OFFSET_LOG+384+i],
|
||||
BigBuf[OFFSET_LOG+128+i],
|
||||
BigBuf[OFFSET_LOG+384+i],
|
||||
t);
|
||||
}
|
||||
}
|
||||
|
|
3064
armsrc/lfops.c
3064
armsrc/lfops.c
File diff suppressed because it is too large
Load diff
|
@ -16,8 +16,8 @@
|
|||
#include "mifarecmd.h"
|
||||
#include "apps.h"
|
||||
#include "util.h"
|
||||
#include "desfire.h"
|
||||
#include "../common/crc.h"
|
||||
|
||||
#include "crc.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Select, Authenticate, Read a MIFARE tag.
|
||||
|
@ -76,7 +76,7 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
// ----------------------------- crypto1 destroy
|
||||
crypto1_destroy(pcs);
|
||||
|
||||
if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");
|
||||
if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");
|
||||
|
||||
LED_B_ON();
|
||||
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16);
|
||||
|
@ -104,14 +104,14 @@ void MifareUC_Auth1(uint8_t arg0, uint8_t *datain){
|
|||
if(!iso14443a_select_card(uid, NULL, &cuid)) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||
Dbprintf("Can't select card");
|
||||
OnError(0);
|
||||
//OnError(0);
|
||||
return;
|
||||
};
|
||||
|
||||
if(mifare_ultra_auth1(cuid, dataoutbuf)){
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||
Dbprintf("Authentication part1: Fail.");
|
||||
OnError(1);
|
||||
//OnError(1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,7 @@ void MifareUC_Auth2(uint32_t arg0, uint8_t *datain){
|
|||
if(mifare_ultra_auth2(cuid, key, dataoutbuf)){
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||
Dbprintf("Authentication part2: Fail...");
|
||||
OnError(1);
|
||||
//OnError(1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -161,30 +161,30 @@ void MifareUReadBlock(uint8_t arg0,uint8_t *datain)
|
|||
LED_A_ON();
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
|
||||
|
||||
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);
|
||||
//OnError(1);
|
||||
return;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
len = mifare_ultra_readblock(cuid, blockNo, dataout);
|
||||
if(len) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error");
|
||||
OnError(2);
|
||||
//OnError(2);
|
||||
return;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
len = mifare_ultra_halt(cuid);
|
||||
if(len) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error");
|
||||
OnError(3);
|
||||
//OnError(3);
|
||||
return;
|
||||
};
|
||||
};
|
||||
|
||||
cmd_send(CMD_ACK,1,0,0,dataout,16);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
@ -261,14 +261,14 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
|
||||
void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain)
|
||||
{
|
||||
// params
|
||||
uint8_t sectorNo = arg0;
|
||||
// params
|
||||
uint8_t sectorNo = arg0;
|
||||
int Pages = arg1;
|
||||
int count_Pages = 0;
|
||||
byte_t dataout[176] = {0x00};;
|
||||
uint8_t uid[10] = {0x00};
|
||||
uint32_t cuid;
|
||||
|
||||
|
||||
LED_A_ON();
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
|
@ -284,7 +284,7 @@ void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain)
|
|||
if (!len) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||
Dbprintf("Can't select card");
|
||||
OnError(1);
|
||||
//OnError(1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -295,7 +295,7 @@ void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain)
|
|||
if (len) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||
Dbprintf("Read block %d error",i);
|
||||
OnError(2);
|
||||
//OnError(2);
|
||||
return;
|
||||
} else {
|
||||
count_Pages++;
|
||||
|
@ -306,7 +306,7 @@ void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain)
|
|||
if (len) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||
Dbprintf("Halt error");
|
||||
OnError(3);
|
||||
//OnError(3);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -400,49 +400,49 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
|
||||
void MifareUWriteBlock(uint8_t arg0, uint8_t *datain)
|
||||
{
|
||||
// params
|
||||
uint8_t blockNo = arg0;
|
||||
// params
|
||||
uint8_t blockNo = arg0;
|
||||
byte_t blockdata[16] = {0x00};
|
||||
|
||||
memcpy(blockdata, datain, 16);
|
||||
|
||||
// variables
|
||||
byte_t isOK = 0;
|
||||
uint8_t uid[10] = {0x00};
|
||||
uint32_t cuid;
|
||||
|
||||
iso14a_clear_trace();
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
|
||||
LED_A_ON();
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
|
||||
while (true) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
break;
|
||||
};
|
||||
|
||||
if(mifare_ultra_writeblock(cuid, blockNo, blockdata)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
|
||||
break;
|
||||
};
|
||||
|
||||
if(mifare_ultra_halt(cuid)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
|
||||
break;
|
||||
};
|
||||
|
||||
isOK = 1;
|
||||
break;
|
||||
}
|
||||
memcpy(blockdata, datain,16);
|
||||
|
||||
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
||||
// variables
|
||||
byte_t isOK = 0;
|
||||
uint8_t uid[10] = {0x00};
|
||||
uint32_t cuid;
|
||||
|
||||
cmd_send(CMD_ACK,isOK,0,0,0,0);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
iso14a_clear_trace();
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
|
||||
LED_A_ON();
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
|
||||
while (true) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
break;
|
||||
};
|
||||
|
||||
if(mifare_ultra_writeblock(cuid, blockNo, blockdata)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
|
||||
break;
|
||||
};
|
||||
|
||||
if(mifare_ultra_halt(cuid)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
|
||||
break;
|
||||
};
|
||||
|
||||
isOK = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
||||
|
||||
cmd_send(CMD_ACK,isOK,0,0,0,0);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
}
|
||||
|
||||
void MifareUWriteBlock_Special(uint8_t arg0, uint8_t *datain)
|
||||
|
@ -493,7 +493,7 @@ void MifareUWriteBlock_Special(uint8_t arg0, uint8_t *datain)
|
|||
}
|
||||
|
||||
// Return 1 if the nonce is invalid else return 0
|
||||
int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t * parity) {
|
||||
int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) {
|
||||
return ((oddparity((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \
|
||||
(oddparity((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \
|
||||
(oddparity((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0;
|
||||
|
@ -529,11 +529,13 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
|||
struct Crypto1State mpcs = {0, 0};
|
||||
struct Crypto1State *pcs;
|
||||
pcs = &mpcs;
|
||||
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||
|
||||
uint32_t auth1_time, auth2_time;
|
||||
static uint16_t delta_time;
|
||||
|
||||
// free eventually allocated BigBuf memory
|
||||
BigBuf_free();
|
||||
// clear trace
|
||||
iso14a_clear_trace();
|
||||
iso14a_set_tracing(false);
|
||||
|
@ -550,7 +552,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
|||
WDT_HIT();
|
||||
|
||||
davg = dmax = 0;
|
||||
dmin = 2000;
|
||||
dmin = 2000;
|
||||
delta_time = 0;
|
||||
|
||||
for (rtr = 0; rtr < 17; rtr++) {
|
||||
|
@ -605,7 +607,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
|||
}
|
||||
}
|
||||
|
||||
if (rtr <= 1) return;
|
||||
if (rtr <= 1) return;
|
||||
|
||||
davg = (davg + (rtr - 1)/2) / (rtr - 1);
|
||||
|
||||
|
@ -624,18 +626,9 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
|||
// get crypted nonces for target sector
|
||||
for(i=0; i < 2; i++) { // look for exactly two different nonces
|
||||
|
||||
WDT_HIT();
|
||||
if(BUTTON_PRESS()) {
|
||||
DbpString("Nested: cancelled");
|
||||
crypto1_destroy(pcs);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
return;
|
||||
}
|
||||
|
||||
target_nt[i] = 0;
|
||||
while(target_nt[i] == 0) { // continue until we have an unambiguous nonce
|
||||
|
||||
|
||||
// prepare next select. No need to power down the card.
|
||||
if(mifare_classic_halt(pcs, cuid)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Halt error");
|
||||
|
@ -695,7 +688,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
|||
if (target_nt[i] == 0 && j == dmax+1 && MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: dismissed (all invalid)", i+1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LED_C_OFF();
|
||||
|
||||
// ----------------------------- crypto1 destroy
|
||||
|
@ -929,15 +922,15 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
|||
uint8_t d_block[18] = {0x00};
|
||||
uint32_t cuid;
|
||||
|
||||
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||
|
||||
// reset FPGA and LED
|
||||
if (workFlags & 0x08) {
|
||||
LED_A_ON();
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
|
||||
|
||||
iso14a_clear_trace();
|
||||
iso14a_set_tracing(TRUE);
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
|
@ -1048,14 +1041,14 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
|||
uint8_t data[18] = {0x00};
|
||||
uint32_t cuid = 0;
|
||||
|
||||
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||
|
||||
if (workFlags & 0x08) {
|
||||
LED_A_ON();
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
|
||||
|
||||
iso14a_clear_trace();
|
||||
iso14a_set_tracing(TRUE);
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
|
@ -1113,8 +1106,8 @@ void MifareCIdent(){
|
|||
// variables
|
||||
byte_t isOK = 1;
|
||||
|
||||
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||
|
||||
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
||||
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||
|
@ -1133,7 +1126,7 @@ void MifareCIdent(){
|
|||
cmd_send(CMD_ACK,isOK,0,0,0,0);
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// DESFIRE
|
||||
//
|
||||
|
||||
|
@ -1150,14 +1143,14 @@ void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){
|
|||
if(!len) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||
Dbprintf("Can't select card");
|
||||
OnError(1);
|
||||
//OnError(1);
|
||||
return;
|
||||
};
|
||||
|
||||
if(mifare_desfire_des_auth1(cuid, dataout)){
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||
Dbprintf("Authentication part1: Fail.");
|
||||
OnError(4);
|
||||
//OnError(4);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1180,7 +1173,7 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){
|
|||
if( isOK) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_EXTENDED)
|
||||
Dbprintf("Authentication part2: Failed");
|
||||
OnError(4);
|
||||
//OnError(4);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1190,4 +1183,4 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){
|
|||
cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout));
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,10 +13,10 @@
|
|||
|
||||
static int sniffState = SNF_INIT;
|
||||
static uint8_t sniffUIDType;
|
||||
static uint8_t sniffUID[8];
|
||||
static uint8_t sniffATQA[2];
|
||||
static uint8_t sniffUID[8] = {0x00};
|
||||
static uint8_t sniffATQA[2] = {0x00};
|
||||
static uint8_t sniffSAK;
|
||||
static uint8_t sniffBuf[16];
|
||||
static uint8_t sniffBuf[16] = {0x00};
|
||||
static uint32_t timerData = 0;
|
||||
|
||||
|
||||
|
@ -151,12 +151,13 @@ bool intMfSniffSend() {
|
|||
int pckSize = 0;
|
||||
int pckLen = traceLen;
|
||||
int pckNum = 0;
|
||||
|
||||
uint8_t *trace = BigBuf_get_addr();
|
||||
|
||||
FpgaDisableSscDma();
|
||||
while (pckLen > 0) {
|
||||
pckSize = MIN(USB_CMD_DATA_SIZE, pckLen);
|
||||
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();
|
||||
|
||||
pckLen -= pckSize;
|
||||
|
|
|
@ -9,29 +9,18 @@
|
|||
// Work with mifare cards.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "../include/proxmark3.h"
|
||||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "util.h"
|
||||
#include "string.h"
|
||||
|
||||
#include "../common/iso14443crc.h"
|
||||
#include "iso14443crc.h"
|
||||
#include "iso14443a.h"
|
||||
#include "crapto1.h"
|
||||
#include "mifareutil.h"
|
||||
|
||||
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
|
||||
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len){
|
||||
uint8_t bt = 0;
|
||||
|
@ -76,26 +65,26 @@ uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data) {
|
|||
}
|
||||
|
||||
// send commands
|
||||
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing)
|
||||
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing)
|
||||
{
|
||||
return mifare_sendcmd_shortex(pcs, crypted, cmd, data, answer, answer_parity, 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)
|
||||
{
|
||||
uint8_t dcmd[8];
|
||||
dcmd[0] = cmd;
|
||||
return mifare_sendcmd_shortex(pcs, crypted, cmd, data, answer, answer_parity, 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)
|
||||
{
|
||||
uint8_t dcmd[8];
|
||||
dcmd[0] = cmd;
|
||||
dcmd[1] = data[0];
|
||||
dcmd[2] = data[1];
|
||||
dcmd[2] = data[1];
|
||||
dcmd[3] = data[2];
|
||||
dcmd[4] = data[3];
|
||||
dcmd[5] = data[4];
|
||||
AppendCrc14443a(dcmd, 6);
|
||||
ReaderTransmit(dcmd, sizeof(dcmd), NULL);
|
||||
int len = ReaderReceive(answer, answer_parity);
|
||||
if(!len) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout.");
|
||||
return 2;
|
||||
AppendCrc14443a(dcmd, 6);
|
||||
ReaderTransmit(dcmd, sizeof(dcmd), NULL);
|
||||
int len = ReaderReceive(answer, answer_parity);
|
||||
if(!len) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout.");
|
||||
return 2;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
@ -117,13 +106,13 @@ int mifare_sendcmd_short_mfucauth(struct Crypto1State *pcs, uint8_t crypted, uin
|
|||
if(len==1) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("NAK - Authentication failed.");
|
||||
return 1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing)
|
||||
{
|
||||
uint8_t dcmd[4], ecmd[4];
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing)
|
||||
{
|
||||
uint8_t dcmd[4], ecmd[4];
|
||||
uint16_t pos, res;
|
||||
uint8_t par[1]; // 1 Byte parity is enough here
|
||||
dcmd[0] = cmd;
|
||||
|
@ -149,7 +138,7 @@ int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cm
|
|||
int len = ReaderReceive(answer, par);
|
||||
|
||||
if (answer_parity) *answer_parity = par[0];
|
||||
|
||||
|
||||
if (crypted == CRYPT_ALL) {
|
||||
if (len == 1) {
|
||||
res = 0;
|
||||
|
@ -175,7 +164,7 @@ int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo,
|
|||
return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// variables
|
||||
int len;
|
||||
|
@ -186,9 +175,9 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
|
|||
uint32_t nt, ntpp; // Supplied tag nonce
|
||||
|
||||
uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
|
||||
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||
|
||||
// Transmit MIFARE_CLASSIC_AUTH
|
||||
len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing);
|
||||
if (MF_DBGLEVEL >= 4) Dbprintf("rand tag nonce len: %x", len);
|
||||
|
@ -273,8 +262,8 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
|
|||
int len;
|
||||
uint8_t bt[2];
|
||||
|
||||
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||
uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||
|
||||
// command MIFARE_CLASSIC_READBLOCK
|
||||
len = mifare_sendcmd_short(pcs, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||
|
@ -295,15 +284,15 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
|
|||
}
|
||||
|
||||
memcpy(blockData, receivedAnswer, 16);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// mifare ultralight commands
|
||||
int mifare_ultra_auth1(uint32_t uid, uint8_t *blockData){
|
||||
|
||||
uint16_t len;
|
||||
uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||
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) {
|
||||
|
@ -327,8 +316,8 @@ int mifare_ultra_auth1(uint32_t uid, uint8_t *blockData){
|
|||
int mifare_ultra_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){
|
||||
|
||||
uint16_t len;
|
||||
uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||
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) {
|
||||
|
@ -347,53 +336,53 @@ int mifare_ultra_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){
|
|||
}
|
||||
memcpy(blockData, receivedAnswer, 11);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
||||
{
|
||||
uint16_t len;
|
||||
uint8_t bt[2];
|
||||
uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||
}
|
||||
|
||||
int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
||||
{
|
||||
uint16_t len;
|
||||
uint8_t bt[2];
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||
|
||||
|
||||
// command MIFARE_CLASSIC_READBLOCK
|
||||
len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||
if (len == 1) {
|
||||
|
||||
// command MIFARE_CLASSIC_READBLOCK
|
||||
len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||
if (len == 1) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||
Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
||||
return 1;
|
||||
}
|
||||
if (len != 18) {
|
||||
Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
||||
return 1;
|
||||
}
|
||||
if (len != 18) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||
Dbprintf("Cmd Error: card timeout. len: %x", len);
|
||||
return 2;
|
||||
}
|
||||
|
||||
memcpy(bt, receivedAnswer + 16, 2);
|
||||
AppendCrc14443a(receivedAnswer, 16);
|
||||
if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {
|
||||
Dbprintf("Cmd Error: card timeout. len: %x", len);
|
||||
return 2;
|
||||
}
|
||||
|
||||
memcpy(bt, receivedAnswer + 16, 2);
|
||||
AppendCrc14443a(receivedAnswer, 16);
|
||||
if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||
Dbprintf("Cmd CRC response error.");
|
||||
return 3;
|
||||
}
|
||||
|
||||
memcpy(blockData, receivedAnswer, 14);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
||||
{
|
||||
// variables
|
||||
Dbprintf("Cmd CRC response error.");
|
||||
return 3;
|
||||
}
|
||||
|
||||
memcpy(blockData, receivedAnswer, 14);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
||||
{
|
||||
// variables
|
||||
uint16_t len, i;
|
||||
uint32_t pos;
|
||||
uint8_t par[3] = {0}; // enough for 18 Bytes to send
|
||||
byte_t res;
|
||||
|
||||
uint8_t d_block[18], d_block_enc[18];
|
||||
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||
uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||
|
||||
// command MIFARE_CLASSIC_WRITEBLOCK
|
||||
len = mifare_sendcmd_short(pcs, 1, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||
|
@ -427,68 +416,68 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
|
|||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
||||
{
|
||||
uint16_t len;
|
||||
uint8_t par[3] = {0}; // enough for 18 parity bits
|
||||
uint8_t d_block[18] = {0x00};
|
||||
uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||
|
||||
// command MIFARE_CLASSIC_WRITEBLOCK
|
||||
len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||
|
||||
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||
Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
memcpy(d_block, blockData, 16);
|
||||
AppendCrc14443a(d_block, 16);
|
||||
|
||||
ReaderTransmitPar(d_block, sizeof(d_block), par, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = ReaderReceive(receivedAnswer, receivedAnswerPar);
|
||||
|
||||
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
||||
int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
||||
{
|
||||
uint16_t len;
|
||||
uint8_t par[3] = {0}; // enough for 18 parity bits
|
||||
uint8_t d_block[18] = {0x00};
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||
|
||||
// command MIFARE_CLASSIC_WRITEBLOCK
|
||||
len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||
|
||||
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||
Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len);
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
||||
{
|
||||
uint16_t len;
|
||||
uint8_t d_block[8] = {0x00};
|
||||
uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||
|
||||
// command MIFARE_CLASSIC_WRITEBLOCK
|
||||
d_block[0]= blockNo;
|
||||
memcpy(d_block+1,blockData,4);
|
||||
AppendCrc14443a(d_block, 6);
|
||||
|
||||
len = mifare_sendcmd_short_special(NULL, 1, 0xA2, d_block, receivedAnswer, receivedAnswerPar, NULL);
|
||||
|
||||
if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK
|
||||
Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
memcpy(d_block, blockData, 16);
|
||||
AppendCrc14443a(d_block, 16);
|
||||
|
||||
ReaderTransmitPar(d_block, sizeof(d_block), par, NULL);
|
||||
|
||||
len = ReaderReceive(receivedAnswer, receivedAnswerPar);
|
||||
|
||||
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||
Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
|
||||
{
|
||||
Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len);
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
||||
{
|
||||
uint16_t len;
|
||||
uint8_t d_block[8] = {0x00};
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||
|
||||
// command MIFARE_CLASSIC_WRITEBLOCK
|
||||
d_block[0]= blockNo;
|
||||
memcpy(d_block+1,blockData,4);
|
||||
AppendCrc14443a(d_block, 6);
|
||||
|
||||
len = mifare_sendcmd_short_special(NULL, 1, 0xA2, d_block, receivedAnswer, receivedAnswerPar, NULL);
|
||||
|
||||
if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||
Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
|
||||
{
|
||||
uint16_t len;
|
||||
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||
|
||||
len = mifare_sendcmd_short(pcs, pcs == NULL ? false:true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL);
|
||||
if (len != 0) {
|
||||
|
@ -497,24 +486,24 @@ int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
|
|||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mifare_ultra_halt(uint32_t uid)
|
||||
{
|
||||
uint16_t len;
|
||||
uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||
|
||||
len = mifare_sendcmd_short(NULL, true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL);
|
||||
if (len != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mifare_ultra_halt(uint32_t uid)
|
||||
{
|
||||
uint16_t len;
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
|
||||
|
||||
len = mifare_sendcmd_short(NULL, true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL);
|
||||
if (len != 0) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR)
|
||||
Dbprintf("halt error. response len: %x", len);
|
||||
return 1;
|
||||
Dbprintf("halt error. response len: %x", len);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Mifare Memory Structure: up to 32 Sectors with 4 blocks each (1k and 2k cards),
|
||||
// plus evtl. 8 sectors with 16 blocks each (4k cards)
|
||||
|
@ -536,24 +525,24 @@ uint8_t FirstBlockOfSector(uint8_t sectorNo)
|
|||
}
|
||||
|
||||
|
||||
// work with emulator memory
|
||||
void emlSetMem(uint8_t *data, int blockNum, int blocksCount) {
|
||||
uint8_t* emCARD = get_bigbufptr_emlcardmem();
|
||||
// work with emulator memory
|
||||
void emlSetMem(uint8_t *data, int blockNum, int blocksCount) {
|
||||
uint8_t* emCARD = BigBuf_get_EM_addr();
|
||||
memcpy(emCARD + blockNum * 16, data, blocksCount * 16);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int emlCheckValBl(int blockNum) {
|
||||
uint8_t* emCARD = get_bigbufptr_emlcardmem();
|
||||
uint8_t* emCARD = BigBuf_get_EM_addr();
|
||||
uint8_t* data = emCARD + blockNum * 16;
|
||||
|
||||
if ((data[0] != (data[4] ^ 0xff)) || (data[0] != data[8]) ||
|
||||
|
@ -568,7 +557,7 @@ int emlCheckValBl(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;
|
||||
|
||||
if (emlCheckValBl(blockNum)) {
|
||||
|
@ -576,12 +565,12 @@ int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) {
|
|||
}
|
||||
|
||||
memcpy(blReg, data, 4);
|
||||
*blBlock = data[12];
|
||||
*blBlock = data[12];
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
memcpy(data + 0, &blReg, 4);
|
||||
|
@ -599,7 +588,7 @@ int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) {
|
|||
|
||||
uint64_t emlGetKey(int sectorNum, int keyType) {
|
||||
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);
|
||||
return bytes_to_num(key, 6);
|
||||
|
@ -610,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 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);
|
||||
|
||||
|
@ -665,8 +654,8 @@ 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 = get_bigbufptr_recvrespbuf();
|
||||
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||
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) {
|
||||
|
@ -695,8 +684,8 @@ int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){
|
|||
data[0] = 0xAF;
|
||||
memcpy(data+1,key,16);
|
||||
|
||||
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||
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);
|
||||
|
||||
|
@ -717,4 +706,4 @@ int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){
|
|||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#define CRYPT_NONE 0
|
||||
#define CRYPT_ALL 1
|
||||
#define CRYPT_REQUEST 2
|
||||
#define AUTH_FIRST 0
|
||||
#define AUTH_FIRST 0
|
||||
#define AUTH_NESTED 2
|
||||
|
||||
// mifare 4bit card answers
|
||||
|
@ -53,9 +53,8 @@ extern int MF_DBGLEVEL;
|
|||
#define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF();
|
||||
|
||||
//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_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);
|
||||
|
@ -83,11 +82,6 @@ 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);
|
||||
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
|
||||
uint8_t NumBlocksPerSector(uint8_t sectorNo);
|
||||
uint8_t FirstBlockOfSector(uint8_t sectorNo);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
int strlen(const char *str);
|
||||
RAMFUNC void *memcpy(void *dest, const void *src, int len);
|
||||
void *memset(void *dest, int c, int len);
|
||||
RAMFUNC int memcmp(const void *av, const void *bv, int len);
|
||||
RAMFUNC int memcmp(const void *av, const void *bv, int len);
|
||||
void memxor(uint8_t * dest, uint8_t * src, size_t len);
|
||||
char *strncat(char *dest, const char *src, unsigned int n);
|
||||
char *strcat(char *dest, const char *src);
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "../include/common.h"
|
||||
#include "common.h"
|
||||
|
||||
#define BYTEx(x, n) (((x) >> (n * 8)) & 0xff )
|
||||
|
||||
|
|
|
@ -9,18 +9,16 @@ include ../common/Makefile.common
|
|||
CC=gcc
|
||||
CXX=g++
|
||||
#COMMON_FLAGS = -m32
|
||||
|
||||
VPATH = ../common
|
||||
OBJDIR = obj
|
||||
|
||||
LDLIBS = -L/mingw/lib -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lm -lreadline -lpthread -lcrypto -lgdi32
|
||||
LDLIBS = -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthread -lm
|
||||
LDFLAGS = $(COMMON_FLAGS)
|
||||
CFLAGS = -std=c99 -lcrypto -I. -I../include -I../common -I/mingw/include -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
|
||||
|
||||
ifneq (,$(findstring MINGW,$(platform)))
|
||||
CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui -I$(QTDIR)/include/QtWidgets -I/mingw/include
|
||||
QTLDLIBS = -L$(QTDIR)/lib -lQt5Core -lQt5Gui -lQt5Widgets
|
||||
CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui
|
||||
QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4
|
||||
MOC = $(QTDIR)/bin/moc
|
||||
LUAPLATFORM = mingw
|
||||
else ifeq ($(platform),Darwin)
|
||||
|
@ -54,16 +52,15 @@ CORESRCS = uart.c \
|
|||
|
||||
|
||||
CMDSRCS = nonce2key/crapto1.c\
|
||||
nonce2key/crypto1.c\
|
||||
nonce2key/nonce2key.c\
|
||||
loclass/cipher.c \
|
||||
loclass/cipherutils.c \
|
||||
loclass/des.c \
|
||||
loclass/ikeys.c \
|
||||
loclass/elite_crack.c \
|
||||
loclass/fileutils.c \
|
||||
loclass/hash1_brute.c \
|
||||
mifarehost.c \
|
||||
nonce2key/crypto1.c\
|
||||
nonce2key/nonce2key.c\
|
||||
loclass/cipher.c \
|
||||
loclass/cipherutils.c \
|
||||
loclass/des.c \
|
||||
loclass/ikeys.c \
|
||||
loclass/elite_crack.c\
|
||||
loclass/fileutils.c\
|
||||
mifarehost.c\
|
||||
crc16.c \
|
||||
iso14443crc.c \
|
||||
iso15693tools.c \
|
||||
|
@ -80,12 +77,9 @@ CMDSRCS = nonce2key/crapto1.c\
|
|||
cmdhflegic.c \
|
||||
cmdhficlass.c \
|
||||
cmdhfmf.c \
|
||||
cmdhfmfu.c \
|
||||
cmdhfmfdes.c \
|
||||
cmdhfdes.c \
|
||||
cmdhfmfu.c \
|
||||
cmdhw.c \
|
||||
cmdlf.c \
|
||||
cmdlfawid26.c \
|
||||
cmdlfio.c \
|
||||
cmdlfhid.c \
|
||||
cmdlfem4x.c \
|
||||
|
@ -99,6 +93,7 @@ CMDSRCS = nonce2key/crapto1.c\
|
|||
scripting.c\
|
||||
cmdscript.c\
|
||||
pm3_bitlib.c\
|
||||
aes.c\
|
||||
|
||||
|
||||
COREOBJS = $(CORESRCS:%.c=$(OBJDIR)/%.o)
|
||||
|
|
1454
client/aes.c
Normal file
1454
client/aes.c
Normal file
File diff suppressed because it is too large
Load diff
257
client/aes.h
Normal file
257
client/aes.h
Normal file
|
@ -0,0 +1,257 @@
|
|||
/**
|
||||
* \file aes.h
|
||||
*
|
||||
* \brief AES block cipher
|
||||
*
|
||||
* Copyright (C) 2006-2014, Brainspark B.V.
|
||||
*
|
||||
* This file is part of PolarSSL (http://www.polarssl.org)
|
||||
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef POLARSSL_AES_H
|
||||
#define POLARSSL_AES_H
|
||||
|
||||
#if !defined(POLARSSL_CONFIG_FILE)
|
||||
#include "polarssl_config.h"
|
||||
#else
|
||||
#include POLARSSL_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
|
||||
#include <basetsd.h>
|
||||
typedef UINT32 uint32_t;
|
||||
#else
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
/* padlock.c and aesni.c rely on these values! */
|
||||
#define AES_ENCRYPT 1
|
||||
#define AES_DECRYPT 0
|
||||
|
||||
#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
|
||||
#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
|
||||
|
||||
#if !defined(POLARSSL_AES_ALT)
|
||||
// Regular implementation
|
||||
//
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief AES context structure
|
||||
*
|
||||
* \note buf is able to hold 32 extra bytes, which can be used:
|
||||
* - for alignment purposes if VIA padlock is used, and/or
|
||||
* - to simplify key expansion in the 256-bit case by
|
||||
* generating an extra round key
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int nr; /*!< number of rounds */
|
||||
uint32_t *rk; /*!< AES round keys */
|
||||
uint32_t buf[68]; /*!< unaligned data */
|
||||
}
|
||||
aes_context;
|
||||
|
||||
/**
|
||||
* \brief Initialize AES context
|
||||
*
|
||||
* \param ctx AES context to be initialized
|
||||
*/
|
||||
void aes_init( aes_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief Clear AES context
|
||||
*
|
||||
* \param ctx AES context to be cleared
|
||||
*/
|
||||
void aes_free( aes_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief AES key schedule (encryption)
|
||||
*
|
||||
* \param ctx AES context to be initialized
|
||||
* \param key encryption key
|
||||
* \param keysize must be 128, 192 or 256
|
||||
*
|
||||
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
|
||||
*/
|
||||
int aes_setkey_enc( aes_context *ctx, const unsigned char *key,
|
||||
unsigned int keysize );
|
||||
|
||||
/**
|
||||
* \brief AES key schedule (decryption)
|
||||
*
|
||||
* \param ctx AES context to be initialized
|
||||
* \param key decryption key
|
||||
* \param keysize must be 128, 192 or 256
|
||||
*
|
||||
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
|
||||
*/
|
||||
int aes_setkey_dec( aes_context *ctx, const unsigned char *key,
|
||||
unsigned int keysize );
|
||||
|
||||
/**
|
||||
* \brief AES-ECB block encryption/decryption
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode AES_ENCRYPT or AES_DECRYPT
|
||||
* \param input 16-byte input block
|
||||
* \param output 16-byte output block
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
int aes_crypt_ecb( aes_context *ctx,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] );
|
||||
|
||||
#if defined(POLARSSL_CIPHER_MODE_CBC)
|
||||
/**
|
||||
* \brief AES-CBC buffer encryption/decryption
|
||||
* Length should be a multiple of the block
|
||||
* size (16 bytes)
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode AES_ENCRYPT or AES_DECRYPT
|
||||
* \param length length of the input data
|
||||
* \param iv initialization vector (updated after use)
|
||||
* \param input buffer holding the input data
|
||||
* \param output buffer holding the output data
|
||||
*
|
||||
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH
|
||||
*/
|
||||
int aes_crypt_cbc( aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output );
|
||||
#endif /* POLARSSL_CIPHER_MODE_CBC */
|
||||
|
||||
#if defined(POLARSSL_CIPHER_MODE_CFB)
|
||||
/**
|
||||
* \brief AES-CFB128 buffer encryption/decryption.
|
||||
*
|
||||
* Note: Due to the nature of CFB you should use the same key schedule for
|
||||
* both encryption and decryption. So a context initialized with
|
||||
* aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode AES_ENCRYPT or AES_DECRYPT
|
||||
* \param length length of the input data
|
||||
* \param iv_off offset in IV (updated after use)
|
||||
* \param iv initialization vector (updated after use)
|
||||
* \param input buffer holding the input data
|
||||
* \param output buffer holding the output data
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
int aes_crypt_cfb128( aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
size_t *iv_off,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output );
|
||||
|
||||
/**
|
||||
* \brief AES-CFB8 buffer encryption/decryption.
|
||||
*
|
||||
* Note: Due to the nature of CFB you should use the same key schedule for
|
||||
* both encryption and decryption. So a context initialized with
|
||||
* aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode AES_ENCRYPT or AES_DECRYPT
|
||||
* \param length length of the input data
|
||||
* \param iv initialization vector (updated after use)
|
||||
* \param input buffer holding the input data
|
||||
* \param output buffer holding the output data
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
int aes_crypt_cfb8( aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output );
|
||||
#endif /*POLARSSL_CIPHER_MODE_CFB */
|
||||
|
||||
#if defined(POLARSSL_CIPHER_MODE_CTR)
|
||||
/**
|
||||
* \brief AES-CTR buffer encryption/decryption
|
||||
*
|
||||
* Warning: You have to keep the maximum use of your counter in mind!
|
||||
*
|
||||
* Note: Due to the nature of CTR you should use the same key schedule for
|
||||
* both encryption and decryption. So a context initialized with
|
||||
* aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param length The length of the data
|
||||
* \param nc_off The offset in the current stream_block (for resuming
|
||||
* within current cipher stream). The offset pointer to
|
||||
* should be 0 at the start of a stream.
|
||||
* \param nonce_counter The 128-bit nonce and counter.
|
||||
* \param stream_block The saved stream-block for resuming. Is overwritten
|
||||
* by the function.
|
||||
* \param input The input data stream
|
||||
* \param output The output data stream
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
int aes_crypt_ctr( aes_context *ctx,
|
||||
size_t length,
|
||||
size_t *nc_off,
|
||||
unsigned char nonce_counter[16],
|
||||
unsigned char stream_block[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output );
|
||||
#endif /* POLARSSL_CIPHER_MODE_CTR */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#else /* POLARSSL_AES_ALT */
|
||||
#include "aes_alt.h"
|
||||
#endif /* POLARSSL_AES_ALT */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Checkup routine
|
||||
*
|
||||
* \return 0 if successful, or 1 if the test failed
|
||||
*/
|
||||
int aes_self_test( int verbose );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* aes.h */
|
1705
client/cmddata.c
1705
client/cmddata.c
File diff suppressed because it is too large
Load diff
|
@ -14,7 +14,7 @@
|
|||
command_t * CmdDataCommands();
|
||||
|
||||
int CmdData(const char *Cmd);
|
||||
|
||||
void printDemodBuff();
|
||||
int CmdAmp(const char *Cmd);
|
||||
int Cmdaskdemod(const char *Cmd);
|
||||
int Cmdaskrawdemod(const char *Cmd);
|
||||
|
@ -26,10 +26,15 @@ int CmdBitstream(const char *Cmd);
|
|||
int CmdBuffClear(const char *Cmd);
|
||||
int CmdDec(const char *Cmd);
|
||||
int CmdDetectClockRate(const char *Cmd);
|
||||
int CmdFSKdemodAWID(const char *Cmd);
|
||||
int CmdFSKdemod(const char *Cmd);
|
||||
int CmdFSKdemodHID(const char *Cmd);
|
||||
int CmdFSKdemodIO(const char *Cmd);
|
||||
int CmdFSKdemodParadox(const char *Cmd);
|
||||
int CmdFSKdemodPyramid(const char *Cmd);
|
||||
int CmdFSKrawdemod(const char *Cmd);
|
||||
int CmdDetectNRZpskClockRate(const char *Cmd);
|
||||
int CmdpskNRZrawDemod(const char *Cmd);
|
||||
int CmdGrid(const char *Cmd);
|
||||
int CmdHexsamples(const char *Cmd);
|
||||
int CmdHide(const char *Cmd);
|
||||
|
@ -43,10 +48,18 @@ int CmdManchesterMod(const char *Cmd);
|
|||
int CmdNorm(const char *Cmd);
|
||||
int CmdPlot(const char *Cmd);
|
||||
int CmdSamples(const char *Cmd);
|
||||
int CmdTuneSamples(const char *Cmd);
|
||||
int CmdSave(const char *Cmd);
|
||||
int CmdScale(const char *Cmd);
|
||||
int CmdThreshold(const char *Cmd);
|
||||
int CmdDirectionalThreshold(const char *Cmd);
|
||||
int CmdZerocrossings(const char *Cmd);
|
||||
int CmdTuneSamples(const char *Cmd);
|
||||
int CmdIndalaDecode(const char *Cmd);
|
||||
|
||||
#define MAX_DEMOD_BUF_LEN (1024*128)
|
||||
extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
|
||||
extern int DemodBufferLen;
|
||||
|
||||
#define BIGBUF_SIZE 40000
|
||||
|
||||
#endif
|
||||
|
|
299
client/cmdhf.c
299
client/cmdhf.c
|
@ -23,8 +23,6 @@
|
|||
#include "cmdhficlass.h"
|
||||
#include "cmdhfmf.h"
|
||||
#include "cmdhfmfu.h"
|
||||
#include "cmdhfmfdes.h"
|
||||
#include "cmdhfdes.h"
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
|
@ -34,8 +32,6 @@ int CmdHFTune(const char *Cmd)
|
|||
SendCommand(&c);
|
||||
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
|
||||
/*
|
||||
|
@ -126,23 +122,28 @@ NXP/Philips CUSTOM COMMANDS
|
|||
40 = Long Range CMD (Standard ISO/TR7003:1990)
|
||||
*/
|
||||
|
||||
#define ICLASS_CMD_ACTALL 0x0A
|
||||
#define ICLASS_CMD_ACTALL 0x0A
|
||||
#define ICLASS_CMD_READ_OR_IDENTIFY 0x0C
|
||||
#define ICLASS_CMD_SELECT 0x81
|
||||
#define ICLASS_CMD_PAGESEL 0x84
|
||||
#define ICLASS_CMD_READCHECK 0x88
|
||||
#define ICLASS_CMD_CHECK 0x05
|
||||
#define ICLASS_CMD_SOF 0x0F
|
||||
#define ICLASS_CMD_HALT 0x00
|
||||
#define ICLASS_CMD_SELECT 0x81
|
||||
#define ICLASS_CMD_PAGESEL 0x84
|
||||
#define ICLASS_CMD_READCHECK_KD 0x88
|
||||
#define ICLASS_CMD_READCHECK_KC 0x18
|
||||
#define ICLASS_CMD_CHECK 0x05
|
||||
#define ICLASS_CMD_DETECT 0x0F
|
||||
#define ICLASS_CMD_HALT 0x00
|
||||
#define ICLASS_CMD_UPDATE 0x87
|
||||
#define ICLASS_CMD_ACT 0x8E
|
||||
#define ICLASS_CMD_READ4 0x06
|
||||
|
||||
#define ISO14443_CMD_REQA 0x26
|
||||
#define ISO14443_CMD_READBLOCK 0x30
|
||||
#define ISO14443_CMD_WUPA 0x52
|
||||
#define ISO14443_CMD_ANTICOLL_OR_SELECT 0x93
|
||||
#define ISO14443_CMD_ANTICOLL_OR_SELECT_2 0x95
|
||||
#define ISO14443_CMD_WRITEBLOCK 0xA0 // or 0xA2 ?
|
||||
#define ISO14443_CMD_HALT 0x50
|
||||
#define ISO14443_CMD_RATS 0xE0
|
||||
|
||||
#define ISO14443A_CMD_REQA 0x26
|
||||
#define ISO14443A_CMD_READBLOCK 0x30
|
||||
#define ISO14443A_CMD_WUPA 0x52
|
||||
#define ISO14443A_CMD_ANTICOLL_OR_SELECT 0x93
|
||||
#define ISO14443A_CMD_ANTICOLL_OR_SELECT_2 0x95
|
||||
#define ISO14443A_CMD_WRITEBLOCK 0xA0 // or 0xA2 ?
|
||||
#define ISO14443A_CMD_HALT 0x50
|
||||
#define ISO14443A_CMD_RATS 0xE0
|
||||
|
||||
#define MIFARE_AUTH_KEYA 0x60
|
||||
#define MIFARE_AUTH_KEYB 0x61
|
||||
|
@ -178,17 +179,20 @@ NXP/Philips CUSTOM COMMANDS
|
|||
#define ISO15693_READ_MULTI_SECSTATUS 0x2C
|
||||
|
||||
|
||||
#define ISO_14443A 0
|
||||
#define ICLASS 1
|
||||
#define ISO_14443B 2
|
||||
|
||||
|
||||
void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
|
||||
{
|
||||
switch(cmd[0])
|
||||
{
|
||||
case ISO14443_CMD_WUPA: snprintf(exp,size,"WUPA"); break;
|
||||
case ISO14443_CMD_ANTICOLL_OR_SELECT:{
|
||||
case ISO14443A_CMD_WUPA: snprintf(exp,size,"WUPA"); break;
|
||||
case ISO14443A_CMD_ANTICOLL_OR_SELECT:{
|
||||
// 93 20 = Anticollision (usage: 9320 - answer: 4bytes UID+1byte UID-bytes-xor)
|
||||
// 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;
|
||||
}else
|
||||
|
@ -196,7 +200,7 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
|
|||
snprintf(exp,size,"ANTICOLL"); break;
|
||||
}
|
||||
}
|
||||
case ISO14443_CMD_ANTICOLL_OR_SELECT_2:{
|
||||
case ISO14443A_CMD_ANTICOLL_OR_SELECT_2:{
|
||||
//95 20 = Anticollision of cascade level2
|
||||
//95 70 = Select of cascade level2
|
||||
if(cmd[2] == 0x70)
|
||||
|
@ -207,19 +211,19 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
|
|||
snprintf(exp,size,"ANTICOLL-2"); break;
|
||||
}
|
||||
}
|
||||
case ISO14443_CMD_REQA: snprintf(exp,size,"REQA"); break;
|
||||
case ISO14443_CMD_READBLOCK: snprintf(exp,size,"READBLOCK(%d)",cmd[1]); break;
|
||||
case ISO14443_CMD_WRITEBLOCK: snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); break;
|
||||
case ISO14443_CMD_HALT: snprintf(exp,size,"HALT"); break;
|
||||
case ISO14443_CMD_RATS: snprintf(exp,size,"RATS"); break;
|
||||
case ISO14443A_CMD_REQA: snprintf(exp,size,"REQA"); break;
|
||||
case ISO14443A_CMD_READBLOCK: snprintf(exp,size,"READBLOCK(%d)",cmd[1]); break;
|
||||
case ISO14443A_CMD_WRITEBLOCK: snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); break;
|
||||
case ISO14443A_CMD_HALT: snprintf(exp,size,"HALT"); break;
|
||||
case ISO14443A_CMD_RATS: snprintf(exp,size,"RATS"); break;
|
||||
case MIFARE_CMD_INC: snprintf(exp,size,"INC(%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_TRANSFER: snprintf(exp,size,"TRANSFER(%d)",cmd[1]); break;
|
||||
case MIFARE_AUTH_KEYA: snprintf(exp,size,"AUTH-A"); break;
|
||||
case MIFARE_AUTH_KEYB: snprintf(exp,size,"AUTH-B"); break;
|
||||
case MIFARE_AUTH_KEYA: snprintf(exp,size,"AUTH-A(%d)",cmd[1]); break;
|
||||
case MIFARE_AUTH_KEYB: snprintf(exp,size,"AUTH-B(%d)",cmd[1]); break;
|
||||
case MIFARE_MAGICMODE: snprintf(exp,size,"MAGIC"); break;
|
||||
default: snprintf(exp,size,"?"); break;
|
||||
default: snprintf(exp,size,"?"); break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -238,11 +242,15 @@ void annotateIclass(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
|
|||
break;
|
||||
}
|
||||
case ICLASS_CMD_SELECT: snprintf(exp,size,"SELECT"); break;
|
||||
case ICLASS_CMD_PAGESEL: snprintf(exp,size,"PAGESEL"); break;
|
||||
case ICLASS_CMD_READCHECK: snprintf(exp,size,"READCHECK"); break;
|
||||
case ICLASS_CMD_PAGESEL: snprintf(exp,size,"PAGESEL(%d)", cmd[1]); break;
|
||||
case ICLASS_CMD_READCHECK_KC:snprintf(exp,size,"READCHECK[Kc](%d)", cmd[1]); break;
|
||||
case ICLASS_CMD_READCHECK_KD:snprintf(exp,size,"READCHECK[Kd](%d)", cmd[1]); break;
|
||||
case ICLASS_CMD_CHECK: snprintf(exp,size,"CHECK"); break;
|
||||
case ICLASS_CMD_SOF: snprintf(exp,size,"SOF"); break;
|
||||
case ICLASS_CMD_DETECT: snprintf(exp,size,"DETECT"); break;
|
||||
case ICLASS_CMD_HALT: snprintf(exp,size,"HALT"); break;
|
||||
case ICLASS_CMD_UPDATE: snprintf(exp,size,"UPDATE(%d)",cmd[1]); break;
|
||||
case ICLASS_CMD_ACT: snprintf(exp,size,"ACT"); break;
|
||||
case ICLASS_CMD_READ4: snprintf(exp,size,"READ4(%d)",cmd[1]); break;
|
||||
default: snprintf(exp,size,"?"); break;
|
||||
}
|
||||
return;
|
||||
|
@ -275,23 +283,117 @@ void annotateIso15693(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
|
|||
case ISO15693_LOCK_DSFID :snprintf(exp, size, "LOCK_DSFID");break;
|
||||
case ISO15693_GET_SYSTEM_INFO :snprintf(exp, size, "GET_SYSTEM_INFO");break;
|
||||
case ISO15693_READ_MULTI_SECSTATUS :snprintf(exp, size, "READ_MULTI_SECSTATUS");break;
|
||||
default: snprintf(exp,size,"?"); break;
|
||||
default: snprintf(exp,size,"?"); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
void annotateIso14443b(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
|
||||
{
|
||||
switch(cmd[0]){
|
||||
case ISO14443B_REQB : snprintf(exp,size,"REQB");break;
|
||||
case ISO14443B_ATTRIB : snprintf(exp,size,"ATTRIB");break;
|
||||
case ISO14443B_HALT : snprintf(exp,size,"HALT");break;
|
||||
default: snprintf(exp,size ,"?");break;
|
||||
}
|
||||
|
||||
uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, bool iclass, bool showWaitCycles)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief iso14443B_CRC_Ok Checks CRC in command or response
|
||||
* @param isResponse
|
||||
* @param data
|
||||
* @param len
|
||||
* @return 0 : CRC-command, CRC not ok
|
||||
* 1 : CRC-command, CRC ok
|
||||
* 2 : Not crc-command
|
||||
*/
|
||||
|
||||
uint8_t iso14443B_CRC_check(bool isResponse, uint8_t* data, uint8_t len)
|
||||
{
|
||||
uint8_t b1,b2;
|
||||
|
||||
if(len <= 2) return 2;
|
||||
|
||||
ComputeCrc14443(CRC_14443_B, data, len-2, &b1, &b2);
|
||||
if(b1 != data[len-2] || b2 != data[len-1]) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief iclass_CRC_Ok Checks CRC in command or response
|
||||
* @param isResponse
|
||||
* @param data
|
||||
* @param len
|
||||
* @return 0 : CRC-command, CRC not ok
|
||||
* 1 : CRC-command, CRC ok
|
||||
* 2 : Not crc-command
|
||||
*/
|
||||
uint8_t iclass_CRC_check(bool isResponse, uint8_t* data, uint8_t len)
|
||||
{
|
||||
if(len < 4) return 2;//CRC commands (and responses) are all at least 4 bytes
|
||||
|
||||
uint8_t b1, b2;
|
||||
|
||||
if(!isResponse)//Commands to tag
|
||||
{
|
||||
/**
|
||||
These commands should have CRC. Total length leftmost
|
||||
4 READ
|
||||
4 READ4
|
||||
12 UPDATE - unsecured, ends with CRC16
|
||||
14 UPDATE - secured, ends with signature instead
|
||||
4 PAGESEL
|
||||
**/
|
||||
if(len == 4 || len == 12)//Covers three of them
|
||||
{
|
||||
//Don't include the command byte
|
||||
ComputeCrc14443(CRC_ICLASS, (data+1), len-3, &b1, &b2);
|
||||
return b1 == data[len -2] && b2 == data[len-1];
|
||||
}
|
||||
return 2;
|
||||
}else{
|
||||
/**
|
||||
These tag responses should have CRC. Total length leftmost
|
||||
|
||||
10 READ data[8] crc[2]
|
||||
34 READ4 data[32]crc[2]
|
||||
10 UPDATE data[8] crc[2]
|
||||
10 SELECT csn[8] crc[2]
|
||||
10 IDENTIFY asnb[8] crc[2]
|
||||
10 PAGESEL block1[8] crc[2]
|
||||
10 DETECT csn[8] crc[2]
|
||||
|
||||
These should not
|
||||
|
||||
4 CHECK chip_response[4]
|
||||
8 READCHECK data[8]
|
||||
1 ACTALL sof[1]
|
||||
1 ACT sof[1]
|
||||
|
||||
In conclusion, without looking at the command; any response
|
||||
of length 10 or 34 should have CRC
|
||||
**/
|
||||
if(len != 10 && len != 34) return true;
|
||||
|
||||
ComputeCrc14443(CRC_ICLASS, data, len-2, &b1, &b2);
|
||||
return b1 == data[len -2] && b2 == data[len-1];
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles)
|
||||
{
|
||||
bool isResponse;
|
||||
uint16_t duration, data_len,parity_len;
|
||||
uint16_t duration, data_len, parity_len;
|
||||
|
||||
uint32_t timestamp, first_timestamp, EndOfTransmissionTimestamp;
|
||||
char explanation[30] = {0};
|
||||
|
||||
if (tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) > traceLen) return traceLen;
|
||||
|
||||
first_timestamp = *((uint32_t *)(trace));
|
||||
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;
|
||||
duration = *((uint16_t *)(trace + tracepos));
|
||||
|
@ -307,8 +409,8 @@ uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, bool iclass, bool sho
|
|||
}
|
||||
parity_len = (data_len-1)/8 + 1;
|
||||
|
||||
if (tracepos + data_len + parity_len >= TRACE_SIZE) {
|
||||
return TRACE_SIZE;
|
||||
if (tracepos + data_len + parity_len > traceLen) {
|
||||
return traceLen;
|
||||
}
|
||||
|
||||
uint8_t *frame = trace + tracepos;
|
||||
|
@ -335,47 +437,45 @@ uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, bool iclass, bool sho
|
|||
}
|
||||
}
|
||||
//--- Draw the CRC column
|
||||
bool crcError = false;
|
||||
uint8_t crcStatus = 2;
|
||||
|
||||
if (data_len > 2) {
|
||||
uint8_t b1, b2;
|
||||
if(iclass)
|
||||
if(protocol == ICLASS)
|
||||
{
|
||||
if(!isResponse && data_len == 4 ) {
|
||||
// Rough guess that this is a command from the reader
|
||||
// For iClass the command byte is not part of the CRC
|
||||
ComputeCrc14443(CRC_ICLASS, &frame[1], data_len-3, &b1, &b2);
|
||||
} else {
|
||||
// For other data.. CRC might not be applicable (UPDATE commands etc.)
|
||||
ComputeCrc14443(CRC_ICLASS, frame, data_len-2, &b1, &b2);
|
||||
}
|
||||
crcStatus = iclass_CRC_check(isResponse, frame, data_len);
|
||||
|
||||
if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) {
|
||||
crcError = true;
|
||||
}
|
||||
|
||||
} else {//Iso 14443a
|
||||
}else if (protocol == ISO_14443B)
|
||||
{
|
||||
crcStatus = iso14443B_CRC_check(isResponse, frame, data_len);
|
||||
}
|
||||
else if (protocol == ISO_14443A){//Iso 14443a
|
||||
|
||||
ComputeCrc14443(CRC_14443_A, frame, data_len-2, &b1, &b2);
|
||||
|
||||
if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) {
|
||||
if(!(isResponse & (data_len < 6)))
|
||||
{
|
||||
crcError = true;
|
||||
crcStatus = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
char *crc = crcError ? "!crc" :" ";
|
||||
//0 CRC-command, CRC not ok
|
||||
//1 CRC-command, CRC ok
|
||||
//2 Not crc-command
|
||||
char *crc = (crcStatus == 0 ? "!crc" : (crcStatus == 1 ? " ok " : " "));
|
||||
|
||||
EndOfTransmissionTimestamp = timestamp + duration;
|
||||
|
||||
if(!isResponse)
|
||||
{
|
||||
if(iclass)
|
||||
if(protocol == ICLASS)
|
||||
annotateIclass(explanation,sizeof(explanation),frame,data_len);
|
||||
else
|
||||
else if (protocol == ISO_14443A)
|
||||
annotateIso14443a(explanation,sizeof(explanation),frame,data_len);
|
||||
else if(protocol == ISO_14443B)
|
||||
annotateIso14443b(explanation,sizeof(explanation),frame,data_len);
|
||||
}
|
||||
|
||||
int num_lines = (data_len - 1)/16 + 1;
|
||||
|
@ -391,11 +491,13 @@ uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, bool iclass, bool sho
|
|||
} else {
|
||||
PrintAndLog(" | | | %-64s| %s| %s",
|
||||
line[j],
|
||||
(j == num_lines-1) ? crc : " ",
|
||||
(j == num_lines-1)?crc:" ",
|
||||
(j == num_lines-1) ? explanation : "");
|
||||
}
|
||||
}
|
||||
|
||||
if (tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) > traceLen) return traceLen;
|
||||
|
||||
bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000;
|
||||
|
||||
if (showWaitCycles && !isResponse && next_isResponse) {
|
||||
|
@ -408,9 +510,11 @@ uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, bool iclass, bool sho
|
|||
(next_timestamp - EndOfTransmissionTimestamp));
|
||||
}
|
||||
}
|
||||
|
||||
return tracepos;
|
||||
}
|
||||
|
||||
|
||||
int CmdHFList(const char *Cmd)
|
||||
{
|
||||
bool showWaitCycles = false;
|
||||
|
@ -418,9 +522,9 @@ int CmdHFList(const char *Cmd)
|
|||
int tlen = param_getstr(Cmd,0,type);
|
||||
char param = param_getchar(Cmd, 1);
|
||||
bool errors = false;
|
||||
bool iclass = false;
|
||||
uint8_t protocol = 0;
|
||||
//Validate params
|
||||
if(tlen == 0 || (strcmp(type, "iclass") != 0 && strcmp(type,"14a") != 0))
|
||||
if(tlen == 0)
|
||||
{
|
||||
errors = true;
|
||||
}
|
||||
|
@ -428,34 +532,69 @@ int CmdHFList(const char *Cmd)
|
|||
{
|
||||
errors = true;
|
||||
}
|
||||
if(!errors)
|
||||
{
|
||||
if(strcmp(type, "iclass") == 0)
|
||||
{
|
||||
protocol = ICLASS;
|
||||
}else if(strcmp(type, "14a") == 0)
|
||||
{
|
||||
protocol = ISO_14443A;
|
||||
}
|
||||
else if(strcmp(type, "14b") == 0)
|
||||
{
|
||||
protocol = ISO_14443B;
|
||||
}else if(strcmp(type,"raw")== 0)
|
||||
{
|
||||
protocol = -1;//No crc, no annotations
|
||||
}else{
|
||||
errors = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (errors) {
|
||||
PrintAndLog("List protocol data in trace buffer.");
|
||||
PrintAndLog("Usage: hf list [14a|iclass] [f]");
|
||||
PrintAndLog(" 14a - interpret data as iso14443a communications");
|
||||
PrintAndLog(" iclass - interpret data as iclass communications");
|
||||
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(" 14b - interpret data as iso14443b communications");
|
||||
PrintAndLog(" iclass - interpret data as iclass communications");
|
||||
PrintAndLog("");
|
||||
PrintAndLog("example: hf list 14a f");
|
||||
PrintAndLog("example: hf list iclass");
|
||||
return 0;
|
||||
}
|
||||
if(strcmp(type, "iclass") == 0)
|
||||
{
|
||||
iclass = true;
|
||||
}
|
||||
|
||||
|
||||
if (param == 'f') {
|
||||
showWaitCycles = true;
|
||||
}
|
||||
|
||||
|
||||
uint8_t trace[TRACE_SIZE];
|
||||
uint8_t *trace;
|
||||
uint16_t tracepos = 0;
|
||||
GetFromBigBuf(trace, TRACE_SIZE, 0);
|
||||
WaitForResponse(CMD_ACK, NULL);
|
||||
trace = malloc(USB_CMD_DATA_SIZE);
|
||||
|
||||
PrintAndLog("Recorded Activity");
|
||||
// Query for the size of the trace
|
||||
UsbCommand response;
|
||||
GetFromBigBuf(trace, USB_CMD_DATA_SIZE, 0);
|
||||
WaitForResponse(CMD_ACK, &response);
|
||||
uint16_t traceLen = response.arg[2];
|
||||
if (traceLen > USB_CMD_DATA_SIZE) {
|
||||
uint8_t *p = realloc(trace, traceLen);
|
||||
if (p == NULL) {
|
||||
PrintAndLog("Cannot allocate memory for trace");
|
||||
free(trace);
|
||||
return 2;
|
||||
}
|
||||
trace = p;
|
||||
GetFromBigBuf(trace, traceLen, 0);
|
||||
WaitForResponse(CMD_ACK, NULL);
|
||||
}
|
||||
|
||||
PrintAndLog("Recorded Activity (TraceLen = %d bytes)", traceLen);
|
||||
PrintAndLog("");
|
||||
PrintAndLog("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)");
|
||||
|
@ -464,10 +603,12 @@ int CmdHFList(const char *Cmd)
|
|||
PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Annotation |");
|
||||
PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------|-----|--------------------|");
|
||||
|
||||
while(tracepos < TRACE_SIZE)
|
||||
while(tracepos < traceLen)
|
||||
{
|
||||
tracepos = printTraceLine(tracepos, trace, iclass, showWaitCycles);
|
||||
tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles);
|
||||
}
|
||||
|
||||
free(trace);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -481,13 +622,11 @@ static command_t CommandTable[] =
|
|||
{"epa", CmdHFEPA, 1, "{ German Identification Card... }"},
|
||||
{"legic", CmdHFLegic, 0, "{ LEGIC RFIDs... }"},
|
||||
{"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"},
|
||||
{"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"},
|
||||
{"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"},
|
||||
{"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"},
|
||||
{"mfdes", CmdHFMFDes, 1, "{ MIFARE Desfire RFIDs... }"},
|
||||
{"des", CmdHFDES, 0, "{ MIFARE DESfire}"},
|
||||
{"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"},
|
||||
{"list", CmdHFList, 1, "List protocol data in trace buffer"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
int CmdHF(const char *Cmd)
|
||||
|
|
|
@ -14,15 +14,15 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "util.h"
|
||||
#include "../common/iso14443crc.h"
|
||||
#include "iso14443crc.h"
|
||||
#include "data.h"
|
||||
#include "proxmark3.h"
|
||||
#include "ui.h"
|
||||
#include "cmdparser.h"
|
||||
#include "cmdhf14a.h"
|
||||
#include "../include/common.h"
|
||||
#include "common.h"
|
||||
#include "cmdmain.h"
|
||||
#include "../include/mifare.h"
|
||||
#include "mifare.h"
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
static void waitCmd(uint8_t iLen);
|
||||
|
@ -112,20 +112,15 @@ const manufactureName manufactureMapping[] = {
|
|||
// returns description of the best match
|
||||
char* getTagInfo(uint8_t uid) {
|
||||
|
||||
int i, best = -1;
|
||||
int i;
|
||||
int len = sizeof(manufactureMapping) / sizeof(manufactureName);
|
||||
|
||||
for ( i = 0; i < len; ++i ) {
|
||||
if ( uid == manufactureMapping[i].uid) {
|
||||
if (best == -1) {
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
for ( i = 0; i < len; ++i )
|
||||
if ( uid == manufactureMapping[i].uid)
|
||||
return manufactureMapping[i].desc;
|
||||
|
||||
if (best>=0) return manufactureMapping[best].desc;
|
||||
|
||||
return manufactureMapping[i].desc;
|
||||
//No match, return default
|
||||
return manufactureMapping[len-1].desc;
|
||||
}
|
||||
|
||||
int CmdHF14AList(const char *Cmd)
|
||||
|
@ -165,7 +160,7 @@ int CmdHF14AReader(const char *Cmd)
|
|||
PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]);
|
||||
PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen));
|
||||
PrintAndLog(" SAK : %02x [%d]", card.sak, resp.arg[0]);
|
||||
|
||||
|
||||
// Double & triple sized UID, can be mapped to a manufacturer.
|
||||
// HACK: does this apply for Ultralight cards?
|
||||
if ( card.uidlen > 4 ) {
|
||||
|
@ -189,7 +184,7 @@ int CmdHF14AReader(const char *Cmd)
|
|||
case 0x98: PrintAndLog("TYPE : Gemplus MPCOS"); break;
|
||||
default: ;
|
||||
}
|
||||
|
||||
|
||||
// try to request ATS even if tag claims not to support it
|
||||
if (select_status == 2) {
|
||||
uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
|
||||
|
@ -203,7 +198,7 @@ int CmdHF14AReader(const char *Cmd)
|
|||
memcpy(&card.ats, resp.d.asBytes, resp.arg[0]);
|
||||
card.ats_len = resp.arg[0]; // note: ats_len includes CRC Bytes
|
||||
}
|
||||
|
||||
|
||||
if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
|
||||
bool ta1 = 0, tb1 = 0, tc1 = 0;
|
||||
int pos;
|
||||
|
@ -359,7 +354,7 @@ int CmdHF14AReader(const char *Cmd)
|
|||
c.arg[1] = 0;
|
||||
c.arg[2] = 0;
|
||||
SendCommand(&c);
|
||||
|
||||
|
||||
return select_status;
|
||||
}
|
||||
|
||||
|
@ -417,9 +412,9 @@ int CmdHF14ASim(const char *Cmd)
|
|||
PrintAndLog(" syntax: hf 14a sim <type> <uid>");
|
||||
PrintAndLog(" types: 1 = MIFARE Classic");
|
||||
PrintAndLog(" 2 = MIFARE Ultralight");
|
||||
PrintAndLog(" 3 = MIFARE DESFIRE");
|
||||
PrintAndLog(" 3 = MIFARE Desfire");
|
||||
PrintAndLog(" 4 = ISO/IEC 14443-4");
|
||||
PrintAndLog(" 5 = MIFARE TNP3XXX");
|
||||
PrintAndLog(" 5 = MIFARE Tnp3xxx");
|
||||
PrintAndLog("");
|
||||
return 1;
|
||||
}
|
||||
|
@ -485,7 +480,8 @@ int CmdHF14ASim(const char *Cmd)
|
|||
int CmdHF14ASnoop(const char *Cmd) {
|
||||
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("Buffer accessible from command hf list 14a.");
|
||||
PrintAndLog("Usage: hf 14a snoop [c][r]");
|
||||
|
@ -496,7 +492,7 @@ int CmdHF14ASnoop(const char *Cmd) {
|
|||
}
|
||||
|
||||
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 == 'r' || ctmp == 'R') param |= 0x02;
|
||||
}
|
||||
|
@ -675,7 +671,7 @@ static command_t CommandTable[] =
|
|||
{"list", CmdHF14AList, 0, "[Deprecated] List ISO 14443a history"},
|
||||
{"reader", CmdHF14AReader, 0, "Act like an ISO14443 Type A reader"},
|
||||
{"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"},
|
||||
{"raw", CmdHF14ACmdRaw, 0, "Send raw hex data to tag"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
|
|
|
@ -145,11 +145,25 @@ demodError:
|
|||
|
||||
int CmdHF14BList(const char *Cmd)
|
||||
{
|
||||
uint8_t got[TRACE_BUFFER_SIZE];
|
||||
GetFromBigBuf(got,sizeof(got),0);
|
||||
WaitForResponse(CMD_ACK,NULL);
|
||||
uint8_t *got = malloc(USB_CMD_DATA_SIZE);
|
||||
|
||||
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)", traceLen);
|
||||
PrintAndLog(" time :rssi: who bytes");
|
||||
PrintAndLog("---------+----+----+-----------");
|
||||
|
||||
|
@ -158,7 +172,7 @@ int CmdHF14BList(const char *Cmd)
|
|||
|
||||
for(;;) {
|
||||
|
||||
if(i >= TRACE_BUFFER_SIZE) { break; }
|
||||
if(i >= traceLen) { break; }
|
||||
|
||||
bool isResponse;
|
||||
int timestamp = *((uint32_t *)(got+i));
|
||||
|
@ -175,7 +189,7 @@ int CmdHF14BList(const char *Cmd)
|
|||
if(len > 100) {
|
||||
break;
|
||||
}
|
||||
if(i + len >= TRACE_BUFFER_SIZE) {
|
||||
if(i + len >= traceLen) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -218,6 +232,7 @@ int CmdHF14BList(const char *Cmd)
|
|||
prev = timestamp;
|
||||
i += (len + 9);
|
||||
}
|
||||
free(got);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -275,11 +290,11 @@ int CmdHF14BCmdRaw (const char *cmd) {
|
|||
UsbCommand resp;
|
||||
uint8_t *recv;
|
||||
UsbCommand c = {CMD_ISO_14443B_COMMAND, {0, 0, 0}}; // len,recv?
|
||||
uint8_t reply = 1;
|
||||
uint8_t crc = 0;
|
||||
uint8_t power = 0;
|
||||
char buf[5] = "";
|
||||
int i = 0;
|
||||
uint8_t reply=1;
|
||||
uint8_t crc=0;
|
||||
uint8_t power=0;
|
||||
char buf[5]="";
|
||||
int i=0;
|
||||
uint8_t data[100] = {0x00};
|
||||
unsigned int datalen=0, temp;
|
||||
char *hexout;
|
||||
|
@ -301,15 +316,15 @@ int CmdHF14BCmdRaw (const char *cmd) {
|
|||
switch (cmd[i+1]) {
|
||||
case 'r':
|
||||
case 'R':
|
||||
reply = 0;
|
||||
reply=0;
|
||||
break;
|
||||
case 'c':
|
||||
case 'C':
|
||||
crc = 1;
|
||||
crc=1;
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
power = 1;
|
||||
power=1;
|
||||
break;
|
||||
default:
|
||||
PrintAndLog("Invalid option");
|
||||
|
@ -336,13 +351,13 @@ int CmdHF14BCmdRaw (const char *cmd) {
|
|||
PrintAndLog("Invalid char on input");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (datalen == 0) {
|
||||
if (datalen == 0)
|
||||
{
|
||||
PrintAndLog("Missing data input");
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(crc) {
|
||||
if(crc)
|
||||
{
|
||||
uint8_t first, second;
|
||||
ComputeCrc14443(CRC_14443_B, data, datalen, &first, &second);
|
||||
data[datalen++] = first;
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include "util.h"
|
||||
#include "cmdparser.h"
|
||||
#include "cmdhf15.h"
|
||||
#include "../common/iso15693tools.h"
|
||||
#include "iso15693tools.h"
|
||||
#include "cmdmain.h"
|
||||
|
||||
#define FrameSOF Iso15693FrameSOF
|
||||
|
@ -45,7 +45,6 @@
|
|||
#define Crc(data,datalen) Iso15693Crc(data,datalen)
|
||||
#define AddCrc(data,datalen) Iso15693AddCrc(data,datalen)
|
||||
#define sprintUID(target,uid) Iso15693sprintUID(target,uid)
|
||||
#define TRACE_BUFF_SIZE 12000
|
||||
|
||||
// structure and database for uid -> tagtype lookups
|
||||
typedef struct {
|
||||
|
@ -237,7 +236,7 @@ static char* getTagInfo(uint8_t *uid) {
|
|||
if (best==-1) {
|
||||
best=i;
|
||||
} else {
|
||||
if (uidmapping[i].mask > uidmapping[best].mask) {
|
||||
if (uidmapping[i].mask>uidmapping[best].mask) {
|
||||
best=i;
|
||||
}
|
||||
}
|
||||
|
@ -658,9 +657,9 @@ int CmdHF15CmdRaw (const char *cmd) {
|
|||
*/
|
||||
int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd[], int iso15cmdlen) {
|
||||
int temp;
|
||||
uint8_t *req = c->d.asBytes;
|
||||
uint8_t *req=c->d.asBytes;
|
||||
uint8_t uid[8] = {0x00};
|
||||
uint32_t reqlen = 0;
|
||||
uint32_t reqlen=0;
|
||||
|
||||
// strip
|
||||
while (**cmd==' ' || **cmd=='\t') (*cmd)++;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "ui.h"
|
||||
#include "cmdparser.h"
|
||||
#include "cmdhficlass.h"
|
||||
#include "../include/common.h"
|
||||
#include "common.h"
|
||||
#include "util.h"
|
||||
#include "cmdmain.h"
|
||||
#include "loclass/des.h"
|
||||
|
@ -34,17 +34,17 @@ static int CmdHelp(const char *Cmd);
|
|||
|
||||
int xorbits_8(uint8_t val)
|
||||
{
|
||||
uint8_t res = val ^ (val >> 1); //1st pass
|
||||
res = res ^ (res >> 1); // 2nd pass
|
||||
res = res ^ (res >> 2); // 3rd pass
|
||||
res = res ^ (res >> 4); // 4th pass
|
||||
return res & 1;
|
||||
uint8_t res = val ^ (val >> 1); //1st pass
|
||||
res = res ^ (res >> 1); // 2nd pass
|
||||
res = res ^ (res >> 2); // 3rd pass
|
||||
res = res ^ (res >> 4); // 4th pass
|
||||
return res & 1;
|
||||
}
|
||||
|
||||
int CmdHFiClassList(const char *Cmd)
|
||||
{
|
||||
PrintAndLog("Deprecated command, use 'hf list iclass' instead");
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHFiClassSnoop(const char *Cmd)
|
||||
|
@ -104,24 +104,24 @@ int CmdHFiClassSim(const char *Cmd)
|
|||
0x0c,0x90,0x32,0xf3,0x5d,0xff,0x12,0xe0 };
|
||||
*/
|
||||
|
||||
uint8_t csns[8*NUM_CSNS] = {
|
||||
0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
|
||||
|
||||
memcpy(c.d.asBytes, csns, 8*NUM_CSNS);
|
||||
uint8_t csns[8*NUM_CSNS] = {
|
||||
0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
|
||||
0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
|
||||
|
||||
memcpy(c.d.asBytes, csns, 8*NUM_CSNS);
|
||||
|
||||
SendCommand(&c);
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, -1)) {
|
||||
|
@ -130,7 +130,7 @@ int CmdHFiClassSim(const char *Cmd)
|
|||
}
|
||||
|
||||
uint8_t num_mac_responses = resp.arg[1];
|
||||
PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses, NUM_CSNS);
|
||||
PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses,NUM_CSNS);
|
||||
|
||||
size_t datalen = NUM_CSNS*24;
|
||||
/*
|
||||
|
@ -209,7 +209,7 @@ int CmdHFiClassReader_Replay(const char *Cmd)
|
|||
if (strlen(Cmd)<1) {
|
||||
PrintAndLog("Usage: hf iclass replay <MAC>");
|
||||
PrintAndLog(" sample: hf iclass replay 00112233");
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (param_gethex(Cmd, 0, MAC, 8)) {
|
||||
|
@ -283,57 +283,57 @@ int CmdHFiClassReader_Dump(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint8_t isOK = resp.arg[0] & 0xff;
|
||||
uint8_t * data = resp.d.asBytes;
|
||||
uint8_t isOK = resp.arg[0] & 0xff;
|
||||
uint8_t * data = resp.d.asBytes;
|
||||
|
||||
memcpy(CSN,data,8);
|
||||
memcpy(CCNR,data+8,8);
|
||||
memcpy(CSN,data,8);
|
||||
memcpy(CCNR,data+8,8);
|
||||
|
||||
PrintAndLog("isOk:%02x", isOK);
|
||||
PrintAndLog("isOk:%02x", isOK);
|
||||
|
||||
if(isOK > 0)
|
||||
{
|
||||
PrintAndLog("CSN: %s",sprint_hex(CSN,8));
|
||||
}
|
||||
if(isOK > 0)
|
||||
{
|
||||
PrintAndLog("CSN: %s",sprint_hex(CSN,8));
|
||||
}
|
||||
if(isOK <= 1){
|
||||
PrintAndLog("Failed to obtain CC! Aborting");
|
||||
return 0;
|
||||
}
|
||||
//Status 2 or higher
|
||||
|
||||
if(elite)
|
||||
{
|
||||
//Get the key index (hash1)
|
||||
uint8_t key_index[8] = {0};
|
||||
if(elite)
|
||||
{
|
||||
//Get the key index (hash1)
|
||||
uint8_t key_index[8] = {0};
|
||||
|
||||
hash1(CSN, key_index);
|
||||
printvar("hash1", key_index,8);
|
||||
for(i = 0; i < 8 ; i++)
|
||||
key_sel[i] = keytable[key_index[i]] & 0xFF;
|
||||
PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:");
|
||||
printvar("k_sel", key_sel,8);
|
||||
//Permute from iclass format to standard format
|
||||
permutekey_rev(key_sel,key_sel_p);
|
||||
used_key = key_sel_p;
|
||||
}else{
|
||||
used_key = KEY;
|
||||
}
|
||||
hash1(CSN, key_index);
|
||||
printvar("hash1", key_index,8);
|
||||
for(i = 0; i < 8 ; i++)
|
||||
key_sel[i] = keytable[key_index[i]] & 0xFF;
|
||||
PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:");
|
||||
printvar("k_sel", key_sel,8);
|
||||
//Permute from iclass format to standard format
|
||||
permutekey_rev(key_sel,key_sel_p);
|
||||
used_key = key_sel_p;
|
||||
}else{
|
||||
used_key = KEY;
|
||||
}
|
||||
|
||||
PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
|
||||
printvar("Used key",used_key,8);
|
||||
diversifyKey(CSN,used_key, div_key);
|
||||
PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
|
||||
printvar("Div key", div_key, 8);
|
||||
printvar("CC_NR:",CCNR,12);
|
||||
doMAC(CCNR,12,div_key, MAC);
|
||||
printvar("MAC", MAC, 4);
|
||||
PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
|
||||
printvar("Used key",used_key,8);
|
||||
diversifyKey(CSN,used_key, div_key);
|
||||
PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
|
||||
printvar("Div key", div_key, 8);
|
||||
printvar("CC_NR:",CCNR,12);
|
||||
doMAC(CCNR,12,div_key, MAC);
|
||||
printvar("MAC", MAC, 4);
|
||||
|
||||
uint8_t iclass_data[32000] = {0};
|
||||
uint8_t iclass_datalen = 0;
|
||||
uint8_t iclass_blocksFailed = 0;//Set to 1 if dump was incomplete
|
||||
|
||||
UsbCommand d = {CMD_READER_ICLASS_REPLAY, {readerType}};
|
||||
memcpy(d.d.asBytes, MAC, 4);
|
||||
UsbCommand d = {CMD_READER_ICLASS_REPLAY, {readerType}};
|
||||
memcpy(d.d.asBytes, MAC, 4);
|
||||
clearCommandBuffer();
|
||||
SendCommand(&d);
|
||||
PrintAndLog("Waiting for device to dump data. Press button on device and key on keyboard to abort...");
|
||||
|
@ -505,16 +505,16 @@ int CmdHFiClass_loclass(const char *Cmd)
|
|||
|
||||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"list", CmdHFiClassList, 0, "[Deprecated] List iClass history"},
|
||||
{"snoop", CmdHFiClassSnoop, 0, "Eavesdrop iClass communication"},
|
||||
{"sim", CmdHFiClassSim, 0, "Simulate iClass tag"},
|
||||
{"reader",CmdHFiClassReader, 0, "Read an iClass tag"},
|
||||
{"replay", CmdHFiClassReader_Replay, 0, "Read an iClass tag via Reply Attack"},
|
||||
{"dump", CmdHFiClassReader_Dump, 0, "Authenticate and Dump iClass tag"},
|
||||
{"write", CmdHFiClass_iso14443A_write, 0, "Authenticate and Write iClass block"},
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"list", CmdHFiClassList, 0, "[Deprecated] List iClass history"},
|
||||
{"snoop", CmdHFiClassSnoop, 0, "Eavesdrop iClass communication"},
|
||||
{"sim", CmdHFiClassSim, 0, "Simulate iClass tag"},
|
||||
{"reader",CmdHFiClassReader, 0, "Read an iClass tag"},
|
||||
{"replay",CmdHFiClassReader_Replay, 0, "Read an iClass tag via Reply Attack"},
|
||||
{"dump", CmdHFiClassReader_Dump, 0, "Authenticate and Dump iClass tag"},
|
||||
{"write", CmdHFiClass_iso14443A_write, 0, "Authenticate and Write iClass block"},
|
||||
{"loclass", CmdHFiClass_loclass, 1, "Use loclass to perform bruteforce of reader attack dump"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
int CmdHFiClass(const char *Cmd)
|
||||
|
@ -526,5 +526,5 @@ int CmdHFiClass(const char *Cmd)
|
|||
int CmdHelp(const char *Cmd)
|
||||
{
|
||||
CmdsHelp(CommandTable);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "cmdparser.h"
|
||||
#include "cmdhflegic.h"
|
||||
#include "cmdmain.h"
|
||||
|
||||
#include "util.h"
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
static command_t CommandTable[] =
|
||||
|
|
273
client/cmdhfmf.c
273
client/cmdhfmf.c
|
@ -7,7 +7,7 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// High frequency MIFARE commands
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "../include/mifare.h"
|
||||
|
||||
#include "cmdhfmf.h"
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
@ -34,7 +34,7 @@ start:
|
|||
SendCommand(&c);
|
||||
|
||||
//flush queue
|
||||
while (ukbhit()) getchar();
|
||||
while (ukbhit()) getchar();
|
||||
|
||||
// wait cycle
|
||||
while (true) {
|
||||
|
@ -71,14 +71,14 @@ start:
|
|||
PrintAndLog("Key not found (lfsr_common_prefix list is null). Nt=%08x", nt);
|
||||
} else {
|
||||
printf("------------------------------------------------------------------\n");
|
||||
PrintAndLog("Key found :%012"llx" \n", r_key);
|
||||
PrintAndLog("Key found:%012"llx" \n", r_key);
|
||||
|
||||
num_to_bytes(r_key, 6, keyBlock);
|
||||
isOK = mfCheckKeys(0, 0, 1, keyBlock, &r_key);
|
||||
}
|
||||
|
||||
if (!isOK)
|
||||
PrintAndLog("Found valid key :%012"llx, r_key);
|
||||
PrintAndLog("Found valid key:%012"llx, r_key);
|
||||
else
|
||||
{
|
||||
if (isOK != 2) PrintAndLog("Found invalid key. ");
|
||||
|
@ -124,10 +124,10 @@ int CmdHF14AMfWrBl(const char *Cmd)
|
|||
PrintAndLog("--block no:%d, key type:%c, key:%s", blockNo, keyType?'B':'A', sprint_hex(key, 6));
|
||||
PrintAndLog("--data: %s", sprint_hex(bldata, 16));
|
||||
|
||||
UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};
|
||||
UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};
|
||||
memcpy(c.d.asBytes, key, 6);
|
||||
memcpy(c.d.asBytes + 10, bldata, 16);
|
||||
SendCommand(&c);
|
||||
SendCommand(&c);
|
||||
|
||||
UsbCommand resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
|
@ -168,9 +168,9 @@ int CmdHF14AMfRdBl(const char *Cmd)
|
|||
}
|
||||
PrintAndLog("--block no:%d, key type:%c, key:%s ", blockNo, keyType?'B':'A', sprint_hex(key, 6));
|
||||
|
||||
UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};
|
||||
UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};
|
||||
memcpy(c.d.asBytes, key, 6);
|
||||
SendCommand(&c);
|
||||
SendCommand(&c);
|
||||
|
||||
UsbCommand resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
|
@ -298,7 +298,7 @@ int CmdHF14AMfDump(const char *Cmd)
|
|||
}
|
||||
|
||||
if ((fin = fopen("dumpkeys.bin","rb")) == NULL) {
|
||||
PrintAndLog("Could not find file dumpkeys.bin");
|
||||
PrintAndLog("Could not find file dumpkeys.bin");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -321,7 +321,7 @@ int CmdHF14AMfDump(const char *Cmd)
|
|||
}
|
||||
|
||||
fclose(fin);
|
||||
|
||||
|
||||
PrintAndLog("|-----------------------------------------|");
|
||||
PrintAndLog("|------ Reading sector access bits...-----|");
|
||||
PrintAndLog("|-----------------------------------------|");
|
||||
|
@ -374,12 +374,12 @@ int CmdHF14AMfDump(const char *Cmd)
|
|||
received = WaitForResponseTimeout(CMD_ACK,&resp,1500);
|
||||
} else if (rights[sectorNo][data_area] == 0x07) { // no key would work
|
||||
isOK = false;
|
||||
PrintAndLog("Access rights do not allow reading of sector %2d block %3d", sectorNo, blockNo);
|
||||
PrintAndLog("Access rights do not allow reading of sector %2d block %3d", sectorNo, blockNo);
|
||||
} else { // key A would work
|
||||
UsbCommand c = {CMD_MIFARE_READBL, {FirstBlockOfSector(sectorNo) + blockNo, 0, 0}};
|
||||
memcpy(c.d.asBytes, keyA[sectorNo], 6);
|
||||
SendCommand(&c);
|
||||
received = WaitForResponseTimeout(CMD_ACK,&resp,1500);
|
||||
UsbCommand c = {CMD_MIFARE_READBL, {FirstBlockOfSector(sectorNo) + blockNo, 0, 0}};
|
||||
memcpy(c.d.asBytes, keyA[sectorNo], 6);
|
||||
SendCommand(&c);
|
||||
received = WaitForResponseTimeout(CMD_ACK,&resp,1500);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -426,7 +426,7 @@ int CmdHF14AMfDump(const char *Cmd)
|
|||
fclose(fout);
|
||||
PrintAndLog("Dumped %d blocks (%d bytes) to file dumpdata.bin", numblocks, 16*numblocks);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -461,7 +461,7 @@ int CmdHF14AMfRestore(const char *Cmd)
|
|||
PrintAndLog(" hf mf restore 4");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if ((fkeys = fopen("dumpkeys.bin","rb")) == NULL) {
|
||||
PrintAndLog("Could not find file dumpkeys.bin");
|
||||
return 1;
|
||||
|
@ -470,6 +470,8 @@ int CmdHF14AMfRestore(const char *Cmd)
|
|||
for (sectorNo = 0; sectorNo < numSectors; sectorNo++) {
|
||||
if (fread(keyA[sectorNo], 1, 6, fkeys) == 0) {
|
||||
PrintAndLog("File reading error (dumpkeys.bin).");
|
||||
|
||||
fclose(fkeys);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
@ -477,12 +479,13 @@ int CmdHF14AMfRestore(const char *Cmd)
|
|||
for (sectorNo = 0; sectorNo < numSectors; sectorNo++) {
|
||||
if (fread(keyB[sectorNo], 1, 6, fkeys) == 0) {
|
||||
PrintAndLog("File reading error (dumpkeys.bin).");
|
||||
fclose(fkeys);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fkeys);
|
||||
|
||||
|
||||
if ((fdump = fopen("dumpdata.bin","rb")) == NULL) {
|
||||
PrintAndLog("Could not find file dumpdata.bin");
|
||||
return 1;
|
||||
|
@ -690,13 +693,6 @@ int CmdHF14AMfNested(const char *Cmd)
|
|||
bool calibrate = true;
|
||||
for (i = 0; i < NESTED_SECTOR_RETRY; i++) {
|
||||
for (uint8_t sectorNo = 0; sectorNo < SectorsCnt; sectorNo++) {
|
||||
|
||||
if (ukbhit()) {
|
||||
printf("\naborted via keyboard!\n");
|
||||
free(e_sector);
|
||||
return 2;
|
||||
}
|
||||
|
||||
for (trgKeyType = 0; trgKeyType < 2; trgKeyType++) {
|
||||
if (e_sector[sectorNo].foundKey[trgKeyType]) continue;
|
||||
PrintAndLog("-----------------------------------------------");
|
||||
|
@ -773,7 +769,7 @@ int CmdHF14AMfNested(const char *Cmd)
|
|||
}
|
||||
fclose(fkeys);
|
||||
}
|
||||
|
||||
|
||||
free(e_sector);
|
||||
}
|
||||
return 0;
|
||||
|
@ -791,8 +787,8 @@ int CmdHF14AMfChk(const char *Cmd)
|
|||
PrintAndLog(" hf mf chk *1 ? t");
|
||||
PrintAndLog(" hf mf chk *1 ? d");
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FILE * f;
|
||||
char filename[FILE_PATH_SIZE]={0};
|
||||
char buf[13];
|
||||
|
@ -937,8 +933,8 @@ int CmdHF14AMfChk(const char *Cmd)
|
|||
PrintAndLog("No key specified, trying default keys");
|
||||
for (;keycnt < defaultKeysSize; keycnt++)
|
||||
PrintAndLog("chk default key[%2d] %02x%02x%02x%02x%02x%02x", keycnt,
|
||||
(keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2],
|
||||
(keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6);
|
||||
(keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2],
|
||||
(keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6);
|
||||
}
|
||||
|
||||
// initialize storage for found keys
|
||||
|
@ -983,13 +979,13 @@ int CmdHF14AMfChk(const char *Cmd)
|
|||
for (uint16_t t = 0; t < 2; t++) {
|
||||
if (validKey[t][sectorNo]) {
|
||||
memcpy(block + t*10, foundKey[t][sectorNo], 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mfEmlSetMem(block, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);
|
||||
}
|
||||
}
|
||||
PrintAndLog("Found keys have been transferred to the emulator memory");
|
||||
}
|
||||
}
|
||||
|
||||
if (createDumpFile) {
|
||||
FILE *fkeys = fopen("dumpkeys.bin","wb");
|
||||
|
@ -997,7 +993,7 @@ int CmdHF14AMfChk(const char *Cmd)
|
|||
PrintAndLog("Could not create file dumpkeys.bin");
|
||||
free(keyBlock);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
for (uint16_t t = 0; t < 2; t++) {
|
||||
fwrite(foundKey[t], 1, 6*SectorsCnt, fkeys);
|
||||
}
|
||||
|
@ -1007,7 +1003,7 @@ int CmdHF14AMfChk(const char *Cmd)
|
|||
|
||||
free(keyBlock);
|
||||
PrintAndLog("");
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHF14AMf1kSim(const char *Cmd)
|
||||
|
@ -1016,12 +1012,16 @@ int CmdHF14AMf1kSim(const char *Cmd)
|
|||
uint8_t exitAfterNReads = 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(" h this help");
|
||||
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(" 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("");
|
||||
PrintAndLog(" sample: hf mf sim u 0a0a0a0a ");
|
||||
return 0;
|
||||
}
|
||||
|
@ -1102,7 +1102,7 @@ int CmdHF14AMfDbg(const char *Cmd)
|
|||
int CmdHF14AMfEGet(const char *Cmd)
|
||||
{
|
||||
uint8_t blockNo = 0;
|
||||
uint8_t data[16];
|
||||
uint8_t data[16] = {0x00};
|
||||
|
||||
if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {
|
||||
PrintAndLog("Usage: hf mf eget <block number>");
|
||||
|
@ -1169,14 +1169,11 @@ int CmdHF14AMfELoad(const char *Cmd)
|
|||
FILE * f;
|
||||
char filename[FILE_PATH_SIZE];
|
||||
char *fnameptr = filename;
|
||||
char buf[64];
|
||||
uint8_t buf8[64];
|
||||
char buf[64] = {0x00};
|
||||
uint8_t buf8[64] = {0x00};
|
||||
int i, len, blockNum, numBlocks;
|
||||
int nameParamNo = 1;
|
||||
|
||||
memset(filename, 0, sizeof(filename));
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
char ctmp = param_getchar(Cmd, 0);
|
||||
|
||||
if ( ctmp == 'h' || ctmp == 0x00) {
|
||||
|
@ -1246,11 +1243,13 @@ int CmdHF14AMfELoad(const char *Cmd)
|
|||
fclose(f);
|
||||
return 3;
|
||||
}
|
||||
printf(".");
|
||||
blockNum++;
|
||||
|
||||
if (blockNum >= numBlocks) break;
|
||||
}
|
||||
fclose(f);
|
||||
printf("\n");
|
||||
|
||||
if ((blockNum != numBlocks)) {
|
||||
PrintAndLog("File content error. Got %d must be %d blocks.",blockNum, numBlocks);
|
||||
|
@ -1276,7 +1275,7 @@ int CmdHF14AMfESave(const char *Cmd)
|
|||
char ctmp = param_getchar(Cmd, 0);
|
||||
|
||||
if ( ctmp == 'h' || ctmp == 'H') {
|
||||
PrintAndLog("It saves emul dump into the file `filename.eml` or `cardID.eml`");
|
||||
PrintAndLog("It saves emul dump into the file `filename.eml` or `cardID.eml`");
|
||||
PrintAndLog(" Usage: hf mf esave [card memory] [file name w/o `.eml`]");
|
||||
PrintAndLog(" [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K");
|
||||
PrintAndLog("");
|
||||
|
@ -1285,7 +1284,7 @@ int CmdHF14AMfESave(const char *Cmd)
|
|||
PrintAndLog(" hf mf esave 4 filename");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
switch (ctmp) {
|
||||
case '0' : numBlocks = 5*4; break;
|
||||
case '1' :
|
||||
|
@ -1320,7 +1319,7 @@ int CmdHF14AMfESave(const char *Cmd)
|
|||
|
||||
// open file
|
||||
f = fopen(filename, "w+");
|
||||
|
||||
|
||||
if ( !f ) {
|
||||
PrintAndLog("Can't open file %s ", filename);
|
||||
return 1;
|
||||
|
@ -1452,13 +1451,13 @@ int CmdHF14AMfCSetUID(const char *Cmd)
|
|||
char ctmp = param_getchar(Cmd, 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);
|
||||
if (res) {
|
||||
PrintAndLog("Can't set UID. error=%d", res);
|
||||
return 1;
|
||||
}
|
||||
PrintAndLog("Can't set UID. error=%d", res);
|
||||
return 1;
|
||||
}
|
||||
|
||||
PrintAndLog("old UID:%s", sprint_hex(oldUid, 4));
|
||||
PrintAndLog("new UID:%s", sprint_hex(uid, 4));
|
||||
|
@ -1467,11 +1466,10 @@ int CmdHF14AMfCSetUID(const char *Cmd)
|
|||
|
||||
int CmdHF14AMfCSetBlk(const char *Cmd)
|
||||
{
|
||||
uint8_t uid[8];
|
||||
uint8_t memBlock[16];
|
||||
uint8_t uid[8] = {0x00};
|
||||
uint8_t memBlock[16] = {0x00};
|
||||
uint8_t blockNo = 0;
|
||||
int res;
|
||||
memset(memBlock, 0x00, sizeof(memBlock));
|
||||
|
||||
if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {
|
||||
PrintAndLog("Usage: hf mf csetblk <block number> <block data (32 hex symbols)>");
|
||||
|
@ -1496,7 +1494,6 @@ int CmdHF14AMfCSetBlk(const char *Cmd)
|
|||
return 1;
|
||||
}
|
||||
|
||||
PrintAndLog("UID:%s", sprint_hex(uid, 4));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1511,11 +1508,8 @@ int CmdHF14AMfCLoad(const char *Cmd)
|
|||
uint8_t fillFromEmulator = 0;
|
||||
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) {
|
||||
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("Usage: hf mf cload <file name w/o `.eml`>");
|
||||
PrintAndLog(" or: hf mf cload e ");
|
||||
|
@ -1562,7 +1556,9 @@ int CmdHF14AMfCLoad(const char *Cmd)
|
|||
blockNum = 0;
|
||||
flags = CSETBLOCK_INIT_FIELD + CSETBLOCK_WUPC;
|
||||
while(!feof(f)){
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (fgets(buf, sizeof(buf), f) == NULL) {
|
||||
PrintAndLog("File reading error.");
|
||||
return 2;
|
||||
|
@ -1597,6 +1593,7 @@ int CmdHF14AMfCLoad(const char *Cmd)
|
|||
PrintAndLog("Loaded from file: %s", filename);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHF14AMfCGetBlk(const char *Cmd) {
|
||||
|
@ -1628,10 +1625,9 @@ int CmdHF14AMfCGetBlk(const char *Cmd) {
|
|||
|
||||
|
||||
int CmdHF14AMfCGetSc(const char *Cmd) {
|
||||
uint8_t memBlock[16];
|
||||
uint8_t memBlock[16] = {0x00};
|
||||
uint8_t sectorNo = 0;
|
||||
int i, res, flags;
|
||||
memset(memBlock, 0x00, sizeof(memBlock));
|
||||
|
||||
if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {
|
||||
PrintAndLog("Usage: hf mf cgetsc <sector number>");
|
||||
|
@ -1729,7 +1725,7 @@ int CmdHF14AMfCSave(const char *Cmd) {
|
|||
|
||||
// open file
|
||||
f = fopen(filename, "w+");
|
||||
|
||||
|
||||
if (f == NULL) {
|
||||
PrintAndLog("File not found or locked.");
|
||||
return 1;
|
||||
|
@ -1769,18 +1765,19 @@ int CmdHF14AMfSniff(const char *Cmd){
|
|||
int res = 0;
|
||||
int len = 0;
|
||||
int blockLen = 0;
|
||||
int num = 0;
|
||||
int pckNum = 0;
|
||||
int num = 0;
|
||||
uint8_t uid[7];
|
||||
uint8_t uid_len;
|
||||
uint8_t atqa[2];
|
||||
uint8_t atqa[2] = {0x00};
|
||||
uint8_t sak;
|
||||
bool isTag;
|
||||
uint8_t buf[3000];
|
||||
uint8_t * bufPtr = buf;
|
||||
memset(buf, 0x00, 3000);
|
||||
uint8_t *buf = NULL;
|
||||
uint16_t bufsize = 0;
|
||||
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("You can specify:");
|
||||
PrintAndLog(" l - save encrypted sequence to logfile `uid.log`");
|
||||
|
@ -1793,7 +1790,7 @@ int CmdHF14AMfSniff(const char *Cmd){
|
|||
}
|
||||
|
||||
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 == 'd' || ctmp == 'D') wantDecrypt = true;
|
||||
//if (ctmp == 'e' || ctmp == 'E') wantSaveToEml = true; TODO
|
||||
|
@ -1820,32 +1817,47 @@ int CmdHF14AMfSniff(const char *Cmd){
|
|||
break;
|
||||
}
|
||||
|
||||
UsbCommand resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,2000)) {
|
||||
UsbCommand resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,2000)) {
|
||||
res = resp.arg[0] & 0xff;
|
||||
len = resp.arg[1];
|
||||
num = resp.arg[2];
|
||||
|
||||
if (res == 0) return 0;
|
||||
if (res == 1) {
|
||||
if (num ==0) {
|
||||
uint16_t traceLen = resp.arg[1];
|
||||
len = resp.arg[2];
|
||||
|
||||
if (res == 0) return 0; // we are done
|
||||
|
||||
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;
|
||||
memset(buf, 0x00, 3000);
|
||||
bufsize = traceLen;
|
||||
memset(buf, 0x00, traceLen);
|
||||
}
|
||||
memcpy(bufPtr, resp.d.asBytes, len);
|
||||
bufPtr += len;
|
||||
pckNum++;
|
||||
}
|
||||
if (res == 2) {
|
||||
|
||||
if (res == 2) { // received all data, start displaying
|
||||
blockLen = bufPtr - buf;
|
||||
bufPtr = buf;
|
||||
printf(">\n");
|
||||
PrintAndLog("received trace len: %d packages: %d", blockLen, pckNum);
|
||||
num = 0;
|
||||
while (bufPtr - buf < blockLen) {
|
||||
bufPtr += 6;
|
||||
bufPtr += 6; // skip (void) timing information
|
||||
len = *((uint16_t *)bufPtr);
|
||||
|
||||
if(len & 0x8000) {
|
||||
isTag = true;
|
||||
len &= 0x7fff;
|
||||
|
@ -1854,12 +1866,10 @@ int CmdHF14AMfSniff(const char *Cmd){
|
|||
}
|
||||
bufPtr += 2;
|
||||
if ((len == 14) && (bufPtr[0] == 0xff) && (bufPtr[1] == 0xff) && (bufPtr[12] == 0xff) && (bufPtr[13] == 0xff)) {
|
||||
|
||||
memcpy(uid, bufPtr + 2, 7);
|
||||
memcpy(atqa, bufPtr + 2 + 7, 2);
|
||||
uid_len = (atqa[0] & 0xC0) == 0x40 ? 7 : 4;
|
||||
sak = bufPtr[11];
|
||||
|
||||
PrintAndLog("tag select uid:%s atqa:0x%02x%02x sak:0x%02x",
|
||||
sprint_hex(uid + (7 - uid_len), uid_len),
|
||||
atqa[1],
|
||||
|
@ -1877,109 +1887,20 @@ int CmdHF14AMfSniff(const char *Cmd){
|
|||
AddLogHex(logHexFileName, isTag ? "TAG: ":"RDR: ", bufPtr, len);
|
||||
if (wantDecrypt)
|
||||
mfTraceDecode(bufPtr, len, wantSaveToEmlFile);
|
||||
num++;
|
||||
}
|
||||
bufPtr += len;
|
||||
bufPtr += ((len-1)/8+1); // ignore parity
|
||||
num++;
|
||||
bufPtr += ((len-1)/8+1); // ignore parity
|
||||
}
|
||||
pckNum = 0;
|
||||
}
|
||||
} // resp not NULL
|
||||
} // while (true)
|
||||
|
||||
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Tries to identify cardsize.
|
||||
// Returns <num> where num is:
|
||||
// -1 unidentified
|
||||
// 0 - MINI (320bytes)
|
||||
// 1 - 1K
|
||||
// 2 - 2K
|
||||
// 4 - 4K
|
||||
int GetCardSize()
|
||||
{
|
||||
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}};
|
||||
SendCommand(&c);
|
||||
|
||||
UsbCommand resp;
|
||||
WaitForResponse(CMD_ACK,&resp);
|
||||
|
||||
if(resp.arg[0] == 0) {
|
||||
PrintAndLog("iso14443a card select failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
iso14a_card_select_t *card = (iso14a_card_select_t *)resp.d.asBytes;
|
||||
|
||||
PrintAndLog("Trying to detect card size.");
|
||||
|
||||
uint16_t atqa = 0;
|
||||
uint8_t sak = 0;
|
||||
atqa = (card->atqa[1] & 0xff) << 8;
|
||||
atqa += card->atqa[0] & 0xff;
|
||||
sak = card->sak;
|
||||
|
||||
// https://code.google.com/p/libnfc/source/browse/libnfc/target-subr.c
|
||||
|
||||
PrintAndLog("found ATAQ: %04X SAK: %02X", atqa, sak);
|
||||
|
||||
|
||||
// NXP MIFARE Mini 0.3k
|
||||
if ( ( (atqa & 0xff0f) == 0x0004) && (sak == 0x09) ) return 0;
|
||||
|
||||
// MIFARE Classic 1K
|
||||
if ( ((atqa & 0xff0f) == 0x0004) && (sak == 0x08) ) return 1;
|
||||
|
||||
// MIFARE Classik 4K
|
||||
if ( ((atqa & 0xff0f) == 0x0002) && (sak == 0x18) ) return 4;
|
||||
|
||||
// SmartMX with MIFARE 1K emulation
|
||||
if ( ((atqa & 0xf0ff) == 0x0004) ) return 1;
|
||||
|
||||
// SmartMX with MIFARE 4K emulation
|
||||
if ( ((atqa & 0xf0ff) == 0x0002) ) return 4;
|
||||
|
||||
// Infineon MIFARE CLASSIC 1K
|
||||
if ( ((atqa & 0xffff) == 0x0004) && (sak == 0x88) ) return 1;
|
||||
|
||||
// MFC 4K emulated by Nokia 6212 Classic
|
||||
if ( ((atqa & 0xffff) == 0x0002) && (sak == 0x38) ) return 4;
|
||||
|
||||
// MFC 4K emulated by Nokia 6131 NFC
|
||||
if ( ((atqa & 0xffff) == 0x0008) && (sak == 0x38) ) return 4;
|
||||
|
||||
|
||||
//PrintAndLog("BEFOOO 1K %02X", (atqa & 0xff0f));
|
||||
|
||||
// MIFARE Plus (4 Byte UID or 4 Byte RID)
|
||||
// MIFARE Plus (7 Byte UID)
|
||||
if (
|
||||
((atqa & 0xffff) == 0x0002) |
|
||||
((atqa & 0xffff) == 0x0004) |
|
||||
((atqa & 0xffff) == 0x0042) |
|
||||
((atqa & 0xffff) == 0x0044)
|
||||
)
|
||||
{
|
||||
switch(sak){
|
||||
case 0x08:
|
||||
case 0x10: {
|
||||
//case 0x20:
|
||||
PrintAndLog("2");
|
||||
return 2;
|
||||
break;
|
||||
}
|
||||
case 0x11:
|
||||
case 0x18:{
|
||||
//case 0x20:
|
||||
PrintAndLog("4");
|
||||
return 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] =
|
||||
{
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// High frequency MIFARE ULTRALIGHT (C) commands
|
||||
//-----------------------------------------------------------------------------
|
||||
#include <openssl/des.h>
|
||||
//#include <openssl/des.h>
|
||||
#include "loclass/des.h"
|
||||
#include "cmdhfmfu.h"
|
||||
#include "cmdhfmf.h"
|
||||
#include "cmdhf14a.h"
|
||||
|
@ -16,29 +17,25 @@
|
|||
#define MAX_ULTRA_BLOCKS 0x0f
|
||||
#define MAX_ULTRAC_BLOCKS 0x2f
|
||||
//#define MAX_ULTRAC_BLOCKS 0x2c
|
||||
uint8_t key1_blnk_data[16] = { 0x00 };
|
||||
uint8_t key2_defa_data[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
|
||||
uint8_t key3_3des_data[16] = { 0x49,0x45,0x4D,0x4B,0x41,0x45,0x52,0x42,0x21,0x4E,0x41,0x43,0x55,0x4F,0x59,0x46 };
|
||||
uint8_t key4_nfc_data[16] = { 0x42,0x52,0x45,0x41,0x4b,0x4d,0x45,0x49,0x46,0x59,0x4f,0x55,0x43,0x41,0x4e,0x21 };
|
||||
uint8_t key5_ones_data[16] = { 0x01 };
|
||||
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
int CmdHF14AMfUInfo(const char *Cmd){
|
||||
|
||||
uint8_t datatemp[7] = {0x00};
|
||||
uint8_t isOK = 0;
|
||||
uint8_t *data = NULL;
|
||||
uint8_t datatemp[7] = {0x00};
|
||||
uint8_t isOK = 0;
|
||||
uint8_t *data = NULL;
|
||||
|
||||
UsbCommand c = {CMD_MIFAREU_READCARD, {0, 4}};
|
||||
SendCommand(&c);
|
||||
UsbCommand resp;
|
||||
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 (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||
isOK = resp.arg[0] & 0xff;
|
||||
data = resp.d.asBytes;
|
||||
|
||||
if (!isOK) {
|
||||
if (!isOK) {
|
||||
PrintAndLog("Error reading from tag");
|
||||
return -1;
|
||||
}
|
||||
|
@ -89,40 +86,40 @@ int CmdHF14AMfUInfo(const char *Cmd){
|
|||
// 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;
|
||||
uint8_t blockNo = -1;
|
||||
bool chinese_card = FALSE;
|
||||
uint8_t bldata[16] = {0x00};
|
||||
UsbCommand resp;
|
||||
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
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("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(" sample: hf mfu wrbl 0 01020304");
|
||||
PrintAndLog("");
|
||||
return 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;
|
||||
}
|
||||
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 (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 (strchr(Cmd,'w') != 0 || strchr(Cmd,'W') != 0 ) {
|
||||
chinese_card = TRUE;
|
||||
}
|
||||
|
||||
if ( blockNo <= 3) {
|
||||
if ( blockNo <= 3) {
|
||||
if (!chinese_card){
|
||||
PrintAndLog("Access Denied");
|
||||
} else {
|
||||
|
@ -139,19 +136,19 @@ int CmdHF14AMfUWrBl(const char *Cmd){
|
|||
}
|
||||
}
|
||||
} else {
|
||||
PrintAndLog("--block no:%02x", blockNo);
|
||||
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
|
||||
UsbCommand e = {CMD_MIFAREU_WRITEBL, {blockNo}};
|
||||
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;
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
uint8_t isOK = resp.arg[0] & 0xff;
|
||||
PrintAndLog("isOk:%02x", isOK);
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -159,40 +156,40 @@ int CmdHF14AMfUWrBl(const char *Cmd){
|
|||
//
|
||||
int CmdHF14AMfURdBl(const char *Cmd){
|
||||
|
||||
uint8_t blockNo = -1;
|
||||
uint8_t blockNo = -1;
|
||||
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
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);
|
||||
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;
|
||||
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));
|
||||
if (isOK)
|
||||
PrintAndLog("Data: %s", sprint_hex(data, 4));
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
return 0;
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -200,28 +197,28 @@ int CmdHF14AMfURdBl(const char *Cmd){
|
|||
//
|
||||
int CmdHF14AMfUDump(const char *Cmd){
|
||||
|
||||
FILE *fout;
|
||||
FILE *fout;
|
||||
char filename[FILE_PATH_SIZE] = {0x00};
|
||||
char * fnameptr = filename;
|
||||
|
||||
uint8_t *lockbytes_t = NULL;
|
||||
uint8_t lockbytes[2] = {0x00};
|
||||
uint8_t *lockbytes_t = NULL;
|
||||
uint8_t lockbytes[2] = {0x00};
|
||||
|
||||
uint8_t *lockbytes_t2 = NULL;
|
||||
uint8_t lockbytes2[2] = {0x00};
|
||||
uint8_t *lockbytes_t2 = NULL;
|
||||
uint8_t lockbytes2[2] = {0x00};
|
||||
|
||||
bool bit[16] = {0x00};
|
||||
bool bit[16] = {0x00};
|
||||
bool bit2[16] = {0x00};
|
||||
|
||||
int i;
|
||||
uint8_t BlockNo = 0;
|
||||
int Pages = 16;
|
||||
int i;
|
||||
uint8_t BlockNo = 0;
|
||||
int Pages = 16;
|
||||
|
||||
bool tmplockbit = false;
|
||||
uint8_t isOK = 0;
|
||||
uint8_t *data = NULL;
|
||||
uint8_t isOK = 0;
|
||||
uint8_t *data = NULL;
|
||||
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
|
||||
if (cmdp == 'h' || cmdp == 'H') {
|
||||
PrintAndLog("Reads all pages from Mifare Ultralight or Ultralight-C tag.");
|
||||
|
@ -238,14 +235,14 @@ int CmdHF14AMfUDump(const char *Cmd){
|
|||
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;
|
||||
|
||||
UsbCommand c = {CMD_MIFAREU_READCARD, {BlockNo,Pages}};
|
||||
SendCommand(&c);
|
||||
UsbCommand resp;
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
isOK = resp.arg[0] & 0xff;
|
||||
if (!isOK) {
|
||||
if (!isOK) {
|
||||
PrintAndLog("Command error");
|
||||
return 0;
|
||||
}
|
||||
|
@ -282,7 +279,7 @@ int CmdHF14AMfUDump(const char *Cmd){
|
|||
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;
|
||||
|
@ -336,33 +333,19 @@ int CmdHF14AMfUDump(const char *Cmd){
|
|||
else
|
||||
len = param_getstr(Cmd,1,filename);
|
||||
|
||||
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
|
||||
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", data[0]);
|
||||
fnameptr += 2;
|
||||
sprintf(fnameptr, "%02X", data[1]);
|
||||
fnameptr += 2;
|
||||
sprintf(fnameptr, "%02X", data[2]);
|
||||
fnameptr += 2;
|
||||
sprintf(fnameptr, "%02X", data[4]);
|
||||
fnameptr += 2;
|
||||
sprintf(fnameptr, "%02X", data[5]);
|
||||
fnameptr += 2;
|
||||
sprintf(fnameptr, "%02X", data[6]);
|
||||
fnameptr += 2;
|
||||
sprintf(fnameptr, "%02X", data[7]);
|
||||
fnameptr += 2;
|
||||
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 {
|
||||
fnameptr += len;
|
||||
sprintf(fnameptr + len," .bin");
|
||||
}
|
||||
|
||||
// add file extension
|
||||
sprintf(fnameptr, ".bin");
|
||||
|
||||
if ((fout = fopen(filename,"wb")) == NULL) {
|
||||
PrintAndLog("Could not create file name %s", filename);
|
||||
|
@ -372,16 +355,16 @@ int CmdHF14AMfUDump(const char *Cmd){
|
|||
fclose(fout);
|
||||
|
||||
PrintAndLog("Dumped %d pages, wrote %d bytes to %s", Pages, Pages*4, filename);
|
||||
return 0;
|
||||
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;
|
||||
uint8_t first = data[0];
|
||||
for (size_t i = 0; i < len-1; i++) {
|
||||
data[i] = data[i+1];
|
||||
}
|
||||
data[len-1] = first;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
|
@ -392,64 +375,51 @@ void rol (uint8_t *data, const size_t len){
|
|||
// Ultralight C Authentication Demo {currently uses hard-coded key}
|
||||
//
|
||||
int CmdHF14AMfucAuth(const char *Cmd){
|
||||
|
||||
uint8_t blockNo = 0, keyNo = 0;
|
||||
uint8_t e_RndB[8] = {0x00};
|
||||
uint32_t cuid = 0;
|
||||
unsigned char RndARndB[16] = {0x00};
|
||||
uint8_t key[16] = {0x00};
|
||||
DES_cblock RndA, RndB;
|
||||
DES_cblock iv;
|
||||
DES_key_schedule ks1,ks2;
|
||||
DES_cblock key1,key2;
|
||||
|
||||
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);
|
||||
//
|
||||
memset(iv, 0, 8);
|
||||
|
||||
if (cmdp == 'h' || cmdp == 'H') {
|
||||
PrintAndLog("Usage: hf mfu cauth k <key number>");
|
||||
PrintAndLog(" 1 = all zeros key");
|
||||
PrintAndLog(" 2 = 0x00-0x0F key");
|
||||
PrintAndLog(" 3 = nfc key");
|
||||
PrintAndLog(" 4 = all ones key");
|
||||
PrintAndLog(" defaults to 3DES standard key");
|
||||
PrintAndLog(" sample : hf mfu cauth k");
|
||||
PrintAndLog(" : hf mfu cauth k 3");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Change key to user defined one
|
||||
if (cmdp == 'k' || cmdp == 'K'){
|
||||
|
||||
uint8_t keyNo = 0;
|
||||
bool errors = false;
|
||||
//Change key to user defined one
|
||||
if (cmdp == 'k' || cmdp == 'K'){
|
||||
keyNo = param_get8(Cmd, 1);
|
||||
|
||||
switch(keyNo){
|
||||
case 0:
|
||||
memcpy(key,key1_blnk_data,16);
|
||||
break;
|
||||
case 1:
|
||||
memcpy(key,key2_defa_data,16);
|
||||
break;
|
||||
case 2:
|
||||
memcpy(key,key4_nfc_data,16);
|
||||
break;
|
||||
case 3:
|
||||
memcpy(key,key5_ones_data,16);
|
||||
break;
|
||||
default:
|
||||
memcpy(key,key3_3des_data,16);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
|
||||
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);
|
||||
|
@ -461,31 +431,57 @@ int CmdHF14AMfucAuth(const char *Cmd){
|
|||
|
||||
if (isOK){
|
||||
PrintAndLog("enc(RndB):%s", sprint_hex(data+1, 8));
|
||||
memcpy(e_RndB,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;
|
||||
}
|
||||
|
||||
//Do crypto magic
|
||||
DES_random_key(&RndA);
|
||||
DES_ede2_cbc_encrypt(e_RndB,RndB,sizeof(e_RndB),&ks1,&ks2,&iv,0);
|
||||
PrintAndLog(" RndB:%s",sprint_hex(RndB, 8));
|
||||
PrintAndLog(" RndA:%s",sprint_hex(RndA, 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));
|
||||
|
||||
//Auth2
|
||||
UsbCommand d = {CMD_MIFAREUC_AUTH2, {cuid}};
|
||||
memcpy(d.d.asBytes,RndARndB, 16);
|
||||
SendCommand(&d);
|
||||
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)) {
|
||||
|
@ -502,91 +498,186 @@ int CmdHF14AMfucAuth(const char *Cmd){
|
|||
PrintAndLog("Command execute timeout");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
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);
|
||||
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;
|
||||
//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));
|
||||
if (isOK)
|
||||
PrintAndLog("Data: %s", sprint_hex(data, 4));
|
||||
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
return 0;
|
||||
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;
|
||||
|
||||
uint8_t blockNo = -1;
|
||||
bool chinese_card = FALSE;
|
||||
uint8_t bldata[16] = {0x00};
|
||||
UsbCommand resp;
|
||||
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
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("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(" sample: hf mfu cwrbl 0 01020304");
|
||||
PrintAndLog("");
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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 (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 (strchr(Cmd,'w') != 0 || strchr(Cmd,'W') != 0 ) {
|
||||
chinese_card = TRUE;
|
||||
}
|
||||
|
||||
if ( blockNo <= 3 ) {
|
||||
if (!chinese_card){
|
||||
|
@ -605,17 +696,17 @@ int CmdHF14AMfUCWrBl(const char *Cmd){
|
|||
}
|
||||
}
|
||||
} 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");
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -625,25 +716,26 @@ int CmdHF14AMfUCWrBl(const char *Cmd){
|
|||
//------------------------------------
|
||||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1,"This help"},
|
||||
{"dbg", CmdHF14AMfDbg, 0,"Set default debug mode"},
|
||||
{"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"},
|
||||
{"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"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
//{"testdes", CmdTestDES , 1, "Test DES"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
int CmdHFMFUltra(const char *Cmd){
|
||||
WaitForResponseTimeout(CMD_ACK,NULL,100);
|
||||
CmdsParse(CommandTable, Cmd);
|
||||
return 0;
|
||||
WaitForResponseTimeout(CMD_ACK,NULL,100);
|
||||
CmdsParse(CommandTable, Cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHelp(const char *Cmd){
|
||||
CmdsHelp(CommandTable);
|
||||
return 0;
|
||||
CmdsHelp(CommandTable);
|
||||
return 0;
|
||||
}
|
717
client/cmdlf.c
717
client/cmdlf.c
|
@ -19,8 +19,8 @@
|
|||
#include "cmdparser.h"
|
||||
#include "cmdmain.h"
|
||||
#include "cmddata.h"
|
||||
#include "util.h"
|
||||
#include "cmdlf.h"
|
||||
#include "cmdlfawid26.h"
|
||||
#include "cmdlfhid.h"
|
||||
#include "cmdlfti.h"
|
||||
#include "cmdlfem4x.h"
|
||||
|
@ -48,377 +48,374 @@ int CmdLFCommandRead(const char *Cmd)
|
|||
|
||||
int CmdFlexdemod(const char *Cmd)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < GraphTraceLen; ++i) {
|
||||
if (GraphBuffer[i] < 0) {
|
||||
GraphBuffer[i] = -1;
|
||||
} else {
|
||||
GraphBuffer[i] = 1;
|
||||
}
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < GraphTraceLen; ++i) {
|
||||
if (GraphBuffer[i] < 0) {
|
||||
GraphBuffer[i] = -1;
|
||||
} else {
|
||||
GraphBuffer[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
#define LONG_WAIT 100
|
||||
int start;
|
||||
for (start = 0; start < GraphTraceLen - LONG_WAIT; start++) {
|
||||
int first = GraphBuffer[start];
|
||||
for (i = start; i < start + LONG_WAIT; i++) {
|
||||
if (GraphBuffer[i] != first) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == (start + LONG_WAIT)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (start == GraphTraceLen - LONG_WAIT) {
|
||||
//PrintAndLog("nothing to wait for");
|
||||
return 0;
|
||||
}
|
||||
#define LONG_WAIT 100
|
||||
int start;
|
||||
for (start = 0; start < GraphTraceLen - LONG_WAIT; start++) {
|
||||
int first = GraphBuffer[start];
|
||||
for (i = start; i < start + LONG_WAIT; i++) {
|
||||
if (GraphBuffer[i] != first) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == (start + LONG_WAIT)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (start == GraphTraceLen - LONG_WAIT) {
|
||||
PrintAndLog("nothing to wait for");
|
||||
return 0;
|
||||
}
|
||||
|
||||
GraphBuffer[start] = 2;
|
||||
GraphBuffer[start+1] = -2;
|
||||
GraphBuffer[start] = 2;
|
||||
GraphBuffer[start+1] = -2;
|
||||
uint8_t bits[64] = {0x00};
|
||||
|
||||
int bit, sum;
|
||||
i = start;
|
||||
for (bit = 0; bit < 64; bit++) {
|
||||
i = start;
|
||||
for (bit = 0; bit < 64; bit++) {
|
||||
sum = 0;
|
||||
for (int j = 0; j < 16; j++) {
|
||||
sum += GraphBuffer[i++];
|
||||
}
|
||||
sum += GraphBuffer[i++];
|
||||
}
|
||||
|
||||
bits[bit] = (sum > 0) ? 1 : 0;
|
||||
|
||||
PrintAndLog("bit %d sum %d", bit, sum);
|
||||
}
|
||||
PrintAndLog("bit %d sum %d", bit, sum);
|
||||
}
|
||||
|
||||
for (bit = 0; bit < 64; bit++) {
|
||||
int j;
|
||||
int sum = 0;
|
||||
for (j = 0; j < 16; j++) {
|
||||
sum += GraphBuffer[i++];
|
||||
}
|
||||
if (sum > 0 && bits[bit] != 1) {
|
||||
PrintAndLog("oops1 at %d", bit);
|
||||
}
|
||||
if (sum < 0 && bits[bit] != 0) {
|
||||
PrintAndLog("oops2 at %d", bit);
|
||||
}
|
||||
}
|
||||
for (bit = 0; bit < 64; bit++) {
|
||||
int j;
|
||||
int sum = 0;
|
||||
for (j = 0; j < 16; j++) {
|
||||
sum += GraphBuffer[i++];
|
||||
}
|
||||
if (sum > 0 && bits[bit] != 1) {
|
||||
PrintAndLog("oops1 at %d", bit);
|
||||
}
|
||||
if (sum < 0 && bits[bit] != 0) {
|
||||
PrintAndLog("oops2 at %d", bit);
|
||||
}
|
||||
}
|
||||
|
||||
// HACK writing back to graphbuffer.
|
||||
GraphTraceLen = 32*64;
|
||||
i = 0;
|
||||
int phase = 0;
|
||||
for (bit = 0; bit < 64; bit++) {
|
||||
GraphTraceLen = 32*64;
|
||||
i = 0;
|
||||
int phase = 0;
|
||||
for (bit = 0; bit < 64; bit++) {
|
||||
|
||||
phase = (bits[bit] == 0) ? 0 : 1;
|
||||
|
||||
int j;
|
||||
for (j = 0; j < 32; j++) {
|
||||
GraphBuffer[i++] = phase;
|
||||
phase = !phase;
|
||||
}
|
||||
}
|
||||
int j;
|
||||
for (j = 0; j < 32; j++) {
|
||||
GraphBuffer[i++] = phase;
|
||||
phase = !phase;
|
||||
}
|
||||
}
|
||||
|
||||
RepaintGraphWindow();
|
||||
return 0;
|
||||
RepaintGraphWindow();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdIndalaDemod(const char *Cmd)
|
||||
{
|
||||
// Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
|
||||
// Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
|
||||
|
||||
int state = -1;
|
||||
int count = 0;
|
||||
int i, j;
|
||||
int state = -1;
|
||||
int count = 0;
|
||||
int i, j;
|
||||
|
||||
// worst case with GraphTraceLen=64000 is < 4096
|
||||
// under normal conditions it's < 2048
|
||||
// worst case with GraphTraceLen=64000 is < 4096
|
||||
// under normal conditions it's < 2048
|
||||
|
||||
uint8_t rawbits[4096];
|
||||
int rawbit = 0;
|
||||
int worst = 0, worstPos = 0;
|
||||
uint8_t rawbits[4096];
|
||||
int rawbit = 0;
|
||||
int worst = 0, worstPos = 0;
|
||||
// PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32);
|
||||
for (i = 0; i < GraphTraceLen-1; i += 2) {
|
||||
count += 1;
|
||||
if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) {
|
||||
if (state == 0) {
|
||||
for (j = 0; j < count - 8; j += 16) {
|
||||
rawbits[rawbit++] = 0;
|
||||
}
|
||||
if ((abs(count - j)) > worst) {
|
||||
worst = abs(count - j);
|
||||
worstPos = i;
|
||||
}
|
||||
}
|
||||
state = 1;
|
||||
count = 0;
|
||||
} else if ((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) {
|
||||
if (state == 1) {
|
||||
for (j = 0; j < count - 8; j += 16) {
|
||||
rawbits[rawbit++] = 1;
|
||||
}
|
||||
if ((abs(count - j)) > worst) {
|
||||
worst = abs(count - j);
|
||||
worstPos = i;
|
||||
}
|
||||
}
|
||||
state = 0;
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < GraphTraceLen-1; i += 2) {
|
||||
count += 1;
|
||||
if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) {
|
||||
if (state == 0) {
|
||||
for (j = 0; j < count - 8; j += 16) {
|
||||
rawbits[rawbit++] = 0;
|
||||
}
|
||||
if ((abs(count - j)) > worst) {
|
||||
worst = abs(count - j);
|
||||
worstPos = i;
|
||||
}
|
||||
}
|
||||
state = 1;
|
||||
count = 0;
|
||||
} else if ((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) {
|
||||
if (state == 1) {
|
||||
for (j = 0; j < count - 8; j += 16) {
|
||||
rawbits[rawbit++] = 1;
|
||||
}
|
||||
if ((abs(count - j)) > worst) {
|
||||
worst = abs(count - j);
|
||||
worstPos = i;
|
||||
}
|
||||
}
|
||||
state = 0;
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (rawbit>0){
|
||||
PrintAndLog("Recovered %d raw bits, expected: %d", rawbit, GraphTraceLen/32);
|
||||
PrintAndLog("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos);
|
||||
if (rawbit>0){
|
||||
PrintAndLog("Recovered %d raw bits, expected: %d", rawbit, GraphTraceLen/32);
|
||||
PrintAndLog("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Finding the start of a UID
|
||||
int uidlen, long_wait;
|
||||
if (strcmp(Cmd, "224") == 0) {
|
||||
uidlen = 224;
|
||||
long_wait = 30;
|
||||
} else {
|
||||
uidlen = 64;
|
||||
long_wait = 29;
|
||||
}
|
||||
// Finding the start of a UID
|
||||
int uidlen, long_wait;
|
||||
if (strcmp(Cmd, "224") == 0) {
|
||||
uidlen = 224;
|
||||
long_wait = 30;
|
||||
} else {
|
||||
uidlen = 64;
|
||||
long_wait = 29;
|
||||
}
|
||||
|
||||
int start;
|
||||
int first = 0;
|
||||
for (start = 0; start <= rawbit - uidlen; start++) {
|
||||
first = rawbits[start];
|
||||
for (i = start; i < start + long_wait; i++) {
|
||||
if (rawbits[i] != first) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == (start + long_wait)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
int start;
|
||||
int first = 0;
|
||||
for (start = 0; start <= rawbit - uidlen; start++) {
|
||||
first = rawbits[start];
|
||||
for (i = start; i < start + long_wait; i++) {
|
||||
if (rawbits[i] != first) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == (start + long_wait)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (start == rawbit - uidlen + 1) {
|
||||
//PrintAndLog("nothing to wait for");
|
||||
return 0;
|
||||
}
|
||||
if (start == rawbit - uidlen + 1) {
|
||||
PrintAndLog("nothing to wait for");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Inverting signal if needed
|
||||
if (first == 1) {
|
||||
for (i = start; i < rawbit; i++) {
|
||||
rawbits[i] = !rawbits[i];
|
||||
}
|
||||
}
|
||||
// Inverting signal if needed
|
||||
if (first == 1) {
|
||||
for (i = start; i < rawbit; i++) {
|
||||
rawbits[i] = !rawbits[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Dumping UID
|
||||
// Dumping UID
|
||||
uint8_t bits[224] = {0x00};
|
||||
char showbits[225] = {0x00};
|
||||
int bit;
|
||||
i = start;
|
||||
int times = 0;
|
||||
int bit;
|
||||
i = start;
|
||||
int times = 0;
|
||||
|
||||
if (uidlen > rawbit) {
|
||||
PrintAndLog("Warning: not enough raw bits to get a full UID");
|
||||
for (bit = 0; bit < rawbit; bit++) {
|
||||
bits[bit] = rawbits[i++];
|
||||
// As we cannot know the parity, let's use "." and "/"
|
||||
showbits[bit] = '.' + bits[bit];
|
||||
}
|
||||
showbits[bit+1]='\0';
|
||||
PrintAndLog("Partial UID=%s", showbits);
|
||||
return 0;
|
||||
} else {
|
||||
for (bit = 0; bit < uidlen; bit++) {
|
||||
bits[bit] = rawbits[i++];
|
||||
showbits[bit] = '0' + bits[bit];
|
||||
}
|
||||
times = 1;
|
||||
}
|
||||
if (uidlen > rawbit) {
|
||||
PrintAndLog("Warning: not enough raw bits to get a full UID");
|
||||
for (bit = 0; bit < rawbit; bit++) {
|
||||
bits[bit] = rawbits[i++];
|
||||
// As we cannot know the parity, let's use "." and "/"
|
||||
showbits[bit] = '.' + bits[bit];
|
||||
}
|
||||
showbits[bit+1]='\0';
|
||||
PrintAndLog("Partial UID=%s", showbits);
|
||||
return 0;
|
||||
} else {
|
||||
for (bit = 0; bit < uidlen; bit++) {
|
||||
bits[bit] = rawbits[i++];
|
||||
showbits[bit] = '0' + bits[bit];
|
||||
}
|
||||
times = 1;
|
||||
}
|
||||
|
||||
//convert UID to HEX
|
||||
uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7;
|
||||
int idx;
|
||||
//convert UID to HEX
|
||||
uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7;
|
||||
int idx;
|
||||
uid1 = uid2 = 0;
|
||||
|
||||
if (uidlen == 64){
|
||||
for( idx=0; idx<64; idx++) {
|
||||
if (showbits[idx] == '0') {
|
||||
uid1 = (uid1<<1) | (uid2>>31);
|
||||
uid2 = (uid2<<1) | 0;
|
||||
} else {
|
||||
uid1 = (uid1<<1) | (uid2>>31);
|
||||
uid2 = (uid2<<1) | 1;
|
||||
}
|
||||
}
|
||||
PrintAndLog("UID=%s (%x%08x)", showbits, uid1, uid2);
|
||||
}
|
||||
else {
|
||||
if (uidlen==64){
|
||||
for( idx=0; idx<64; idx++) {
|
||||
if (showbits[idx] == '0') {
|
||||
uid1=(uid1<<1)|(uid2>>31);
|
||||
uid2=(uid2<<1)|0;
|
||||
} else {
|
||||
uid1=(uid1<<1)|(uid2>>31);
|
||||
uid2=(uid2<<1)|1;
|
||||
}
|
||||
}
|
||||
PrintAndLog("UID=%s (%x%08x)", showbits, uid1, uid2);
|
||||
}
|
||||
else {
|
||||
uid3 = uid4 = uid5 = uid6 = uid7 = 0;
|
||||
|
||||
for( idx=0; idx<224; idx++) {
|
||||
uid1 = (uid1<<1) | (uid2>>31);
|
||||
uid2 = (uid2<<1) | (uid3>>31);
|
||||
uid3 = (uid3<<1) | (uid4>>31);
|
||||
uid4 = (uid4<<1) | (uid5>>31);
|
||||
uid5 = (uid5<<1) | (uid6>>31);
|
||||
uid6 = (uid6<<1) | (uid7>>31);
|
||||
for( idx=0; idx<224; idx++) {
|
||||
uid1=(uid1<<1)|(uid2>>31);
|
||||
uid2=(uid2<<1)|(uid3>>31);
|
||||
uid3=(uid3<<1)|(uid4>>31);
|
||||
uid4=(uid4<<1)|(uid5>>31);
|
||||
uid5=(uid5<<1)|(uid6>>31);
|
||||
uid6=(uid6<<1)|(uid7>>31);
|
||||
|
||||
if (showbits[idx] == '0')
|
||||
uid7 = (uid7<<1) | 0;
|
||||
else
|
||||
uid7 = (uid7<<1) | 1;
|
||||
}
|
||||
PrintAndLog("UID=%s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7);
|
||||
}
|
||||
}
|
||||
PrintAndLog("UID=%s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7);
|
||||
}
|
||||
|
||||
// Checking UID against next occurrences
|
||||
int failed = 0;
|
||||
// Checking UID against next occurrences
|
||||
int failed = 0;
|
||||
for (; i + uidlen <= rawbit;) {
|
||||
failed = 0;
|
||||
for (bit = 0; bit < uidlen; bit++) {
|
||||
if (bits[bit] != rawbits[i++]) {
|
||||
failed = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (failed == 1) {
|
||||
break;
|
||||
}
|
||||
times += 1;
|
||||
}
|
||||
for (bit = 0; bit < uidlen; bit++) {
|
||||
if (bits[bit] != rawbits[i++]) {
|
||||
failed = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (failed == 1) {
|
||||
break;
|
||||
}
|
||||
times += 1;
|
||||
}
|
||||
|
||||
PrintAndLog("Occurrences: %d (expected %d)", times, (rawbit - start) / uidlen);
|
||||
PrintAndLog("Occurrences: %d (expected %d)", times, (rawbit - start) / uidlen);
|
||||
|
||||
// Remodulating for tag cloning
|
||||
// Remodulating for tag cloning
|
||||
// HACK: 2015-01-04 this will have an impact on our new way of seening lf commands (demod)
|
||||
// since this changes graphbuffer data.
|
||||
GraphTraceLen = 32 * uidlen;
|
||||
i = 0;
|
||||
int phase = 0;
|
||||
for (bit = 0; bit < uidlen; bit++) {
|
||||
if (bits[bit] == 0) {
|
||||
phase = 0;
|
||||
} else {
|
||||
phase = 1;
|
||||
}
|
||||
int j;
|
||||
for (j = 0; j < 32; j++) {
|
||||
GraphBuffer[i++] = phase;
|
||||
phase = !phase;
|
||||
}
|
||||
}
|
||||
GraphTraceLen = 32*uidlen;
|
||||
i = 0;
|
||||
int phase = 0;
|
||||
for (bit = 0; bit < uidlen; bit++) {
|
||||
if (bits[bit] == 0) {
|
||||
phase = 0;
|
||||
} else {
|
||||
phase = 1;
|
||||
}
|
||||
int j;
|
||||
for (j = 0; j < 32; j++) {
|
||||
GraphBuffer[i++] = phase;
|
||||
phase = !phase;
|
||||
}
|
||||
}
|
||||
|
||||
RepaintGraphWindow();
|
||||
return 1;
|
||||
RepaintGraphWindow();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CmdIndalaClone(const char *Cmd)
|
||||
{
|
||||
UsbCommand c;
|
||||
UsbCommand c;
|
||||
unsigned int uid1, uid2, uid3, uid4, uid5, uid6, uid7;
|
||||
|
||||
uid1 = uid2 = uid3 = uid4 = uid5 = uid6 = uid7 = 0;
|
||||
int n = 0, i = 0;
|
||||
int n = 0, i = 0;
|
||||
|
||||
if (strchr(Cmd,'l') != 0) {
|
||||
while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
|
||||
uid1 = (uid1 << 4) | (uid2 >> 28);
|
||||
uid2 = (uid2 << 4) | (uid3 >> 28);
|
||||
uid3 = (uid3 << 4) | (uid4 >> 28);
|
||||
uid4 = (uid4 << 4) | (uid5 >> 28);
|
||||
uid5 = (uid5 << 4) | (uid6 >> 28);
|
||||
uid6 = (uid6 << 4) | (uid7 >> 28);
|
||||
uid7 = (uid7 << 4) | (n & 0xf);
|
||||
}
|
||||
PrintAndLog("Cloning 224bit tag with UID %x%08x%08x%08x%08x%08x%08x", uid1, uid2, uid3, uid4, uid5, uid6, uid7);
|
||||
c.cmd = CMD_INDALA_CLONE_TAG_L;
|
||||
c.d.asDwords[0] = uid1;
|
||||
c.d.asDwords[1] = uid2;
|
||||
c.d.asDwords[2] = uid3;
|
||||
c.d.asDwords[3] = uid4;
|
||||
c.d.asDwords[4] = uid5;
|
||||
c.d.asDwords[5] = uid6;
|
||||
c.d.asDwords[6] = uid7;
|
||||
if (strchr(Cmd,'l') != 0) {
|
||||
while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
|
||||
uid1 = (uid1 << 4) | (uid2 >> 28);
|
||||
uid2 = (uid2 << 4) | (uid3 >> 28);
|
||||
uid3 = (uid3 << 4) | (uid4 >> 28);
|
||||
uid4 = (uid4 << 4) | (uid5 >> 28);
|
||||
uid5 = (uid5 << 4) | (uid6 >> 28);
|
||||
uid6 = (uid6 << 4) | (uid7 >> 28);
|
||||
uid7 = (uid7 << 4) | (n & 0xf);
|
||||
}
|
||||
PrintAndLog("Cloning 224bit tag with UID %x%08x%08x%08x%08x%08x%08x", uid1, uid2, uid3, uid4, uid5, uid6, uid7);
|
||||
c.cmd = CMD_INDALA_CLONE_TAG_L;
|
||||
c.d.asDwords[0] = uid1;
|
||||
c.d.asDwords[1] = uid2;
|
||||
c.d.asDwords[2] = uid3;
|
||||
c.d.asDwords[3] = uid4;
|
||||
c.d.asDwords[4] = uid5;
|
||||
c.d.asDwords[5] = uid6;
|
||||
c.d.asDwords[6] = uid7;
|
||||
} else {
|
||||
while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
|
||||
uid1 = (uid1 << 4) | (uid2 >> 28);
|
||||
uid2 = (uid2 << 4) | (n & 0xf);
|
||||
}
|
||||
PrintAndLog("Cloning 64bit tag with UID %x%08x", uid1, uid2);
|
||||
c.cmd = CMD_INDALA_CLONE_TAG;
|
||||
c.arg[0] = uid1;
|
||||
c.arg[1] = uid2;
|
||||
}
|
||||
while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
|
||||
uid1 = (uid1 << 4) | (uid2 >> 28);
|
||||
uid2 = (uid2 << 4) | (n & 0xf);
|
||||
}
|
||||
PrintAndLog("Cloning 64bit tag with UID %x%08x", uid1, uid2);
|
||||
c.cmd = CMD_INDALA_CLONE_TAG;
|
||||
c.arg[0] = uid1;
|
||||
c.arg[1] = uid2;
|
||||
}
|
||||
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdLFRead(const char *Cmd)
|
||||
{
|
||||
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K};
|
||||
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K};
|
||||
|
||||
// 'h' means higher-low-frequency, 134 kHz
|
||||
if(*Cmd == 'h') {
|
||||
c.arg[0] = 1;
|
||||
} else if (*Cmd == '\0') {
|
||||
c.arg[0] = 0;
|
||||
} else if (sscanf(Cmd, "%"lli, &c.arg[0]) != 1) {
|
||||
// 'h' means higher-low-frequency, 134 kHz
|
||||
if(*Cmd == 'h') {
|
||||
c.arg[0] = 1;
|
||||
} 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;
|
||||
}
|
||||
SendCommand(&c);
|
||||
WaitForResponse(CMD_ACK,NULL);
|
||||
|
||||
CmdSamples("");
|
||||
ShowGraphWindow();
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
SendCommand(&c);
|
||||
WaitForResponse(CMD_ACK,NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ChkBitstream(const char *str)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
/* convert to bitstream if necessary */
|
||||
/* convert to bitstream if necessary */
|
||||
for (i = 0; i < (int)(GraphTraceLen / 2); i++){
|
||||
if (GraphBuffer[i] > 1 || GraphBuffer[i] < 0) {
|
||||
CmdBitstream(str);
|
||||
break;
|
||||
}
|
||||
}
|
||||
CmdBitstream(str);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//appears to attempt to simulate manchester
|
||||
int CmdLFSim(const char *Cmd)
|
||||
{
|
||||
int i,j;
|
||||
static int gap;
|
||||
static int gap;
|
||||
|
||||
sscanf(Cmd, "%i", &gap);
|
||||
sscanf(Cmd, "%i", &gap);
|
||||
|
||||
/* convert to bitstream if necessary */
|
||||
ChkBitstream(Cmd);
|
||||
/* convert to bitstream if necessary */
|
||||
ChkBitstream(Cmd);
|
||||
|
||||
printf("Sending [%d bytes]", GraphTraceLen);
|
||||
for (i = 0; i < GraphTraceLen; i += USB_CMD_DATA_SIZE) {
|
||||
UsbCommand c={CMD_DOWNLOADED_SIM_SAMPLES_125K, {i, 0, 0}};
|
||||
UsbCommand c={CMD_DOWNLOADED_SIM_SAMPLES_125K, {i, 0, 0}};
|
||||
|
||||
for (j = 0; j < USB_CMD_DATA_SIZE; j++) {
|
||||
c.d.asBytes[j] = GraphBuffer[i+j];
|
||||
}
|
||||
SendCommand(&c);
|
||||
WaitForResponse(CMD_ACK,NULL);
|
||||
c.d.asBytes[j] = GraphBuffer[i+j];
|
||||
}
|
||||
SendCommand(&c);
|
||||
WaitForResponse(CMD_ACK,NULL);
|
||||
printf(".");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
PrintAndLog("Starting to simulate");
|
||||
UsbCommand c = {CMD_SIMULATE_TAG_125K, {GraphTraceLen, gap, 0}};
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
UsbCommand c = {CMD_SIMULATE_TAG_125K, {GraphTraceLen, gap, 0}};
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdLFSimBidir(const char *Cmd)
|
||||
|
@ -434,57 +431,51 @@ int CmdLFSimBidir(const char *Cmd)
|
|||
/* simulate an LF Manchester encoded tag with specified bitstream, clock rate and inter-id gap */
|
||||
int CmdLFSimManchester(const char *Cmd)
|
||||
{
|
||||
static int clock, gap;
|
||||
static char data[1024], gapstring[8];
|
||||
static int clock, gap;
|
||||
static char data[1024], gapstring[8];
|
||||
|
||||
sscanf(Cmd, "%i %s %i", &clock, &data[0], &gap);
|
||||
sscanf(Cmd, "%i %s %i", &clock, &data[0], &gap);
|
||||
|
||||
ClearGraph(0);
|
||||
ClearGraph(0);
|
||||
|
||||
for (int i = 0; i < strlen(data) ; ++i)
|
||||
AppendGraph(0, clock, data[i]- '0');
|
||||
for (int i = 0; i < strlen(data) ; ++i)
|
||||
AppendGraph(0, clock, data[i]- '0');
|
||||
|
||||
CmdManchesterMod("");
|
||||
CmdManchesterMod("");
|
||||
|
||||
RepaintGraphWindow();
|
||||
RepaintGraphWindow();
|
||||
|
||||
sprintf(&gapstring[0], "%i", gap);
|
||||
CmdLFSim(gapstring);
|
||||
return 0;
|
||||
sprintf(&gapstring[0], "%i", gap);
|
||||
CmdLFSim(gapstring);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdLFSnoop(const char *Cmd)
|
||||
{
|
||||
UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES};
|
||||
UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES};
|
||||
|
||||
// 'h' means higher-low-frequency, 134 kHz
|
||||
c.arg[0] = 0;
|
||||
c.arg[1] = -1;
|
||||
// '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) {
|
||||
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(" 2: snoop <l|h> [trigger threshold]");
|
||||
PrintAndLog(" 3: snoop <divisor> [trigger threshold]");
|
||||
return 0;
|
||||
}
|
||||
PrintAndLog("");
|
||||
PrintAndLog("Sample: lf snoop l 200");
|
||||
PrintAndLog(" : lf snoop 95 200");
|
||||
return 0;
|
||||
}
|
||||
|
||||
SendCommand(&c);
|
||||
WaitForResponse(CMD_ACK,NULL);
|
||||
|
||||
#define BUFF_SIZE 8000
|
||||
uint8_t data[BUFF_SIZE] = {0x00};
|
||||
|
||||
GetFromBigBuf(data,BUFF_SIZE,0);
|
||||
WaitForResponseTimeout(CMD_ACK,NULL, 1500);
|
||||
|
||||
SetGraphBuf(data, BUFF_SIZE);
|
||||
|
||||
return 0;
|
||||
SendCommand(&c);
|
||||
WaitForResponse(CMD_ACK,NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdVchDemod(const char *Cmd)
|
||||
|
@ -566,7 +557,7 @@ int CmdVchDemod(const char *Cmd)
|
|||
//by marshmellow
|
||||
int CmdLFfind(const char *Cmd)
|
||||
{
|
||||
int ans = 0;
|
||||
int ans=0;
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
|
||||
if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') {
|
||||
|
@ -578,69 +569,77 @@ int CmdLFfind(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!offline || (cmdp != '1') ){
|
||||
ans = CmdLFRead("");
|
||||
if (!offline && (cmdp != '1')){
|
||||
ans=CmdLFRead("");
|
||||
ans=CmdSamples("20000");
|
||||
} else if (GraphTraceLen < 1000) {
|
||||
PrintAndLog("Data in Graphbuffer was too small.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLog("Checking for known tags:");
|
||||
|
||||
ans = Cmdaskmandemod("");
|
||||
PrintAndLog("ASK_MAN: %s", (ans) ? "YES":"NO" );
|
||||
|
||||
ans = CmdFSKdemodHID("");
|
||||
PrintAndLog("HID: %s", (ans) ? "YES":"NO" );
|
||||
|
||||
ans = CmdFSKdemodIO("");
|
||||
PrintAndLog("IO prox: %s", (ans) ? "YES":"NO" );
|
||||
|
||||
ans = CmdIndalaDemod("");
|
||||
PrintAndLog("Indala (64): %s", (ans) ? "YES":"NO" );
|
||||
|
||||
ans = CmdIndalaDemod("224");
|
||||
PrintAndLog("Indala (224): %s", (ans) ? "YES":"NO" );
|
||||
|
||||
// ans = CmdVchDemod("");
|
||||
// PrintAndLog("VeriChip: %s", (ans) ? "YES":"NO" );
|
||||
|
||||
// ans = CmdFlexdemod("");
|
||||
// PrintAndLog("FlexPass: %s", (ans) ? "YES":"NO" );
|
||||
|
||||
if (!ans)
|
||||
PrintAndLog("No Known Tags Found!\n");
|
||||
|
||||
return 0;
|
||||
PrintAndLog("NOTE: some demods output possible binary\n if it finds something that looks like a tag");
|
||||
PrintAndLog("\nChecking for known tags:\n");
|
||||
ans=CmdFSKdemodIO("");
|
||||
if (ans>0) {
|
||||
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;
|
||||
}
|
||||
ans=CmdFSKdemodHID("");
|
||||
if (ans>0) {
|
||||
PrintAndLog("\nValid HID Prox ID Found!");
|
||||
return 1;
|
||||
}
|
||||
//add psk and indala
|
||||
ans=CmdIndalaDecode("");
|
||||
if (ans>0) {
|
||||
PrintAndLog("\nValid Indala ID Found!");
|
||||
return 1;
|
||||
}
|
||||
ans=Cmdaskmandemod("");
|
||||
if (ans>0) {
|
||||
PrintAndLog("\nValid EM410x ID Found!");
|
||||
return 1;
|
||||
}
|
||||
PrintAndLog("No Known Tags Found!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] =
|
||||
{
|
||||
{"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)"},
|
||||
|
||||
{"em4x", CmdLFEM4X, 1, "{ EM4X RFIDs... }"},
|
||||
{"flexdemod", CmdFlexdemod, 1, "Demodulate samples for FlexPass"},
|
||||
{"hid", CmdLFHID, 1, "{ HID RFIDs... }"},
|
||||
{"io", CmdLFIO, 1, "{ ioProx tags... }"},
|
||||
{"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 (UID in HEX)(option 'l' for 224 UID"},
|
||||
{"vchdemod", CmdVchDemod, 1, "['clone'] -- Demodulate samples for VeriChip"},
|
||||
|
||||
|
||||
{"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))"},
|
||||
{"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)"},
|
||||
{"simbidir", CmdLFSimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
|
||||
{"simman", CmdLFSimManchester, 0, "<Clock> <Bitstream> [GAP] Simulate arbitrary Manchester LF tag"},
|
||||
{"snoop", CmdLFSnoop, 0, "['l'|'h'|<divisor>] [trigger threshold]-- Snoop LF (l:125khz, h:134khz)"},
|
||||
|
||||
{"awid26", CmdLFAWID26, 1, "{ AWID26 tags }"},
|
||||
{"em4x", CmdLFEM4X, 1, "{ EM4X tags }"},
|
||||
{"hid", CmdLFHID, 1, "{ HID tags }"},
|
||||
{"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders }"},
|
||||
{"io", CmdLFIO, 1, "{ ioProx tags }"},
|
||||
{"pcf7931", CmdLFPCF7931, 1, "{ PCF7931 tags }"},
|
||||
{"ti", CmdLFTI, 1, "{ TI tags }"},
|
||||
{"t55xx", CmdLFT55XX, 1, "{ T55xx tags }"},
|
||||
|
||||
{"ti", CmdLFTI, 1, "{ TI RFIDs... }"},
|
||||
{"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"},
|
||||
{"vchdemod", CmdVchDemod, 1, "['clone'] -- Demodulate samples for VeriChip"},
|
||||
{"t55xx", CmdLFT55XX, 1, "{ T55xx RFIDs... }"},
|
||||
{"pcf7931", CmdLFPCF7931, 1, "{PCF7931 RFIDs...}"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
|
@ -13,17 +13,12 @@
|
|||
#include <inttypes.h>
|
||||
#include "proxmark3.h"
|
||||
#include "ui.h"
|
||||
#include "util.h"
|
||||
#include "graph.h"
|
||||
#include "cmdmain.h"
|
||||
#include "cmdparser.h"
|
||||
#include "cmddata.h"
|
||||
#include "cmdlf.h"
|
||||
#include "cmdlfem4x.h"
|
||||
#include "util.h"
|
||||
#include "data.h"
|
||||
#define LF_TRACE_BUFF_SIZE 12000
|
||||
#define LF_BITSSTREAM_LEN 1000
|
||||
|
||||
char *global_em410xId;
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
@ -32,10 +27,10 @@ int CmdEMdemodASK(const char *Cmd)
|
|||
{
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
int findone = (cmdp == '1') ? 1 : 0;
|
||||
UsbCommand c = { CMD_EM410X_DEMOD };
|
||||
c.arg[0] = findone;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
UsbCommand c={CMD_EM410X_DEMOD};
|
||||
c.arg[0]=findone;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the ID of an EM410x tag.
|
||||
|
@ -56,15 +51,19 @@ int CmdEM410xRead(const char *Cmd)
|
|||
uint8_t BitStream[MAX_GRAPH_TRACE_LEN];
|
||||
high = low = 0;
|
||||
|
||||
// get clock
|
||||
clock = GetClock(Cmd, 0);
|
||||
|
||||
// Detect high and lows and clock
|
||||
DetectHighLowInGraph( &high, &low, TRUE);
|
||||
/* Detect high and lows and clock */
|
||||
for (i = 0; i < GraphTraceLen; i++)
|
||||
{
|
||||
if (GraphBuffer[i] > high)
|
||||
high = GraphBuffer[i];
|
||||
else if (GraphBuffer[i] < low)
|
||||
low = GraphBuffer[i];
|
||||
}
|
||||
|
||||
PrintAndLog("NUMNUM");
|
||||
|
||||
// parity for our 4 columns
|
||||
/* get clock */
|
||||
clock = GetClock(Cmd, high, 0);
|
||||
|
||||
/* parity for our 4 columns */
|
||||
parity[0] = parity[1] = parity[2] = parity[3] = 0;
|
||||
header = rows = 0;
|
||||
|
||||
|
@ -101,10 +100,10 @@ int CmdEM410xRead(const char *Cmd)
|
|||
|
||||
BitStream[bit2idx++] = bit;
|
||||
}
|
||||
|
||||
|
||||
retest:
|
||||
/* We go till 5 before the graph ends because we'll get that far below */
|
||||
for (i = 0; i < bit2idx - 5; i++)
|
||||
for (i = 1; i < bit2idx - 5; i++)
|
||||
{
|
||||
/* Step 2: We have our header but need our tag ID */
|
||||
if (header == 9 && rows < 10)
|
||||
|
@ -133,7 +132,7 @@ retest:
|
|||
PrintAndLog("Thought we had a valid tag but failed at word %d (i=%d)", rows + 1, i);
|
||||
|
||||
/* Start back rows * 5 + 9 header bits, -1 to not start at same place */
|
||||
i -= 9 + (5 * rows) -5;
|
||||
i -= 9 + (5 * rows) - 5;
|
||||
|
||||
rows = header = 0;
|
||||
}
|
||||
|
@ -183,12 +182,12 @@ retest:
|
|||
/* if we've already retested after flipping bits, return */
|
||||
if (retested++){
|
||||
PrintAndLog("Failed to decode");
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if this didn't work, try flipping bits */
|
||||
for (i = 0; i < bit2idx; i++)
|
||||
BitStream[i] ^= 1;
|
||||
for (i = 0; i < bit2idx; i++)
|
||||
BitStream[i] ^= 1;
|
||||
|
||||
goto retest;
|
||||
}
|
||||
|
@ -202,7 +201,7 @@ retest:
|
|||
* 0 <-- stop bit, end of tag
|
||||
*/
|
||||
int CmdEM410xSim(const char *Cmd)
|
||||
{
|
||||
{
|
||||
int i, n, j, binary[4], parity[4];
|
||||
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
|
@ -222,13 +221,13 @@ int CmdEM410xSim(const char *Cmd)
|
|||
|
||||
PrintAndLog("Starting simulating UID %02X%02X%02X%02X%02X", uid[0],uid[1],uid[2],uid[3],uid[4]);
|
||||
PrintAndLog("Press pm3-button to about simulation");
|
||||
|
||||
|
||||
/* clock is 64 in EM410x tags */
|
||||
int clock = 64;
|
||||
|
||||
/* clear our graph */
|
||||
ClearGraph(0);
|
||||
|
||||
|
||||
/* write 9 start bits */
|
||||
for (i = 0; i < 9; i++)
|
||||
AppendGraph(0, clock, 1);
|
||||
|
@ -264,7 +263,7 @@ int CmdEM410xSim(const char *Cmd)
|
|||
AppendGraph(0, clock, parity[2]);
|
||||
AppendGraph(0, clock, parity[3]);
|
||||
|
||||
/* stop bit */
|
||||
/* stop bit */
|
||||
AppendGraph(1, clock, 0);
|
||||
|
||||
CmdLFSim("240"); //240 start_gap.
|
||||
|
@ -292,7 +291,7 @@ int CmdEM410xWatch(const char *Cmd)
|
|||
}
|
||||
|
||||
CmdLFRead(read_h ? "h" : "");
|
||||
CmdSamples("6000");
|
||||
CmdSamples("6000");
|
||||
} while (
|
||||
!CmdEM410xRead("")
|
||||
);
|
||||
|
@ -522,79 +521,47 @@ int CmdEM410xWrite(const char *Cmd)
|
|||
int CmdReadWord(const char *Cmd)
|
||||
{
|
||||
int Word = -1; //default to invalid word
|
||||
UsbCommand c;
|
||||
UsbCommand c;
|
||||
|
||||
sscanf(Cmd, "%d", &Word);
|
||||
sscanf(Cmd, "%d", &Word);
|
||||
|
||||
if ( (Word > 15) | (Word < 0) ) {
|
||||
PrintAndLog("Word must be between 0 and 15");
|
||||
return 1;
|
||||
}
|
||||
PrintAndLog("Word must be between 0 and 15");
|
||||
return 1;
|
||||
}
|
||||
|
||||
PrintAndLog("Reading word %d", Word);
|
||||
PrintAndLog("Reading word %d", Word);
|
||||
|
||||
c.cmd = CMD_EM4X_READ_WORD;
|
||||
c.d.asBytes[0] = 0x0; //Normal mode
|
||||
c.arg[0] = 0;
|
||||
c.arg[1] = Word;
|
||||
c.arg[2] = 0;
|
||||
SendCommand(&c);
|
||||
WaitForResponse(CMD_ACK, NULL);
|
||||
|
||||
uint8_t data[LF_TRACE_BUFF_SIZE] = {0x00};
|
||||
|
||||
GetFromBigBuf(data,LF_TRACE_BUFF_SIZE,0); //3560 -- should be offset..
|
||||
WaitForResponseTimeout(CMD_ACK,NULL, 1500);
|
||||
|
||||
for (int j = 0; j < LF_TRACE_BUFF_SIZE; j++) {
|
||||
GraphBuffer[j] = ((int)data[j]);
|
||||
}
|
||||
GraphTraceLen = LF_TRACE_BUFF_SIZE;
|
||||
|
||||
uint8_t bits[LF_BITSSTREAM_LEN] = {0x00};
|
||||
uint8_t * bitstream = bits;
|
||||
manchester_decode(GraphBuffer, LF_TRACE_BUFF_SIZE, bitstream,LF_BITSSTREAM_LEN);
|
||||
RepaintGraphWindow();
|
||||
c.cmd = CMD_EM4X_READ_WORD;
|
||||
c.d.asBytes[0] = 0x0; //Normal mode
|
||||
c.arg[0] = 0;
|
||||
c.arg[1] = Word;
|
||||
c.arg[2] = 0;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdReadWordPWD(const char *Cmd)
|
||||
{
|
||||
int Word = -1; //default to invalid word
|
||||
int Password = 0xFFFFFFFF; //default to blank password
|
||||
UsbCommand c;
|
||||
|
||||
sscanf(Cmd, "%d %x", &Word, &Password);
|
||||
|
||||
if ( (Word > 15) | (Word < 0) ) {
|
||||
PrintAndLog("Word must be between 0 and 15");
|
||||
return 1;
|
||||
}
|
||||
int Password = 0xFFFFFFFF; //default to blank password
|
||||
UsbCommand c;
|
||||
|
||||
PrintAndLog("Reading word %d with password %08X", Word, Password);
|
||||
|
||||
c.cmd = CMD_EM4X_READ_WORD;
|
||||
c.d.asBytes[0] = 0x1; //Password mode
|
||||
c.arg[0] = 0;
|
||||
c.arg[1] = Word;
|
||||
c.arg[2] = Password;
|
||||
SendCommand(&c);
|
||||
WaitForResponse(CMD_ACK, NULL);
|
||||
|
||||
uint8_t data[LF_TRACE_BUFF_SIZE] = {0x00};
|
||||
|
||||
GetFromBigBuf(data,LF_TRACE_BUFF_SIZE,0); //3560 -- should be offset..
|
||||
WaitForResponseTimeout(CMD_ACK,NULL, 1500);
|
||||
|
||||
for (int j = 0; j < LF_TRACE_BUFF_SIZE; j++) {
|
||||
GraphBuffer[j] = ((int)data[j]);
|
||||
}
|
||||
GraphTraceLen = LF_TRACE_BUFF_SIZE;
|
||||
|
||||
uint8_t bits[LF_BITSSTREAM_LEN] = {0x00};
|
||||
uint8_t * bitstream = bits;
|
||||
manchester_decode(GraphBuffer, LF_TRACE_BUFF_SIZE, bitstream, LF_BITSSTREAM_LEN);
|
||||
RepaintGraphWindow();
|
||||
sscanf(Cmd, "%d %x", &Word, &Password);
|
||||
|
||||
if ( (Word > 15) | (Word < 0) ) {
|
||||
PrintAndLog("Word must be between 0 and 15");
|
||||
return 1;
|
||||
}
|
||||
|
||||
PrintAndLog("Reading word %d with password %08X", Word, Password);
|
||||
|
||||
c.cmd = CMD_EM4X_READ_WORD;
|
||||
c.d.asBytes[0] = 0x1; //Password mode
|
||||
c.arg[0] = 0;
|
||||
c.arg[1] = Word;
|
||||
c.arg[2] = Password;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -650,280 +617,20 @@ int CmdWriteWordPWD(const char *Cmd)
|
|||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"410xdemod", CmdEMdemodASK, 0, "[clock rate] -- Extract ID from EM410x tag"},
|
||||
{"410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag"},
|
||||
{"410xsim", CmdEM410xSim, 0, "<UID> -- Simulate EM410x tag"},
|
||||
{"replay", MWRem4xReplay, 0, "Watches for tag and simulates manchester encoded em4x tag"},
|
||||
{"410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
|
||||
{"410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" },
|
||||
{"410xwrite", CmdEM410xWrite, 1, "<UID> <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"},
|
||||
{"4x50read", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"},
|
||||
{"rd", CmdReadWord, 1, "<Word 1-15> -- Read EM4xxx word data"},
|
||||
{"rdpwd", CmdReadWordPWD, 1, "<Word 1-15> <Password> -- Read EM4xxx word data in password mode "},
|
||||
{"wr", CmdWriteWord, 1, "<Data> <Word 1-15> -- Write EM4xxx word data"},
|
||||
{"wrpwd", CmdWriteWordPWD, 1, "<Data> <Word 1-15> <Password> -- Write EM4xxx word data in password mode"},
|
||||
{"em410xdemod", CmdEMdemodASK, 0, "[findone] -- Extract ID from EM410x tag (option 0 for continuous loop, 1 for only 1 tag)"},
|
||||
{"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag"},
|
||||
{"em410xsim", CmdEM410xSim, 0, "<UID> -- Simulate EM410x tag"},
|
||||
{"em410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
|
||||
{"em410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" },
|
||||
{"em410xwrite", CmdEM410xWrite, 1, "<UID> <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"},
|
||||
{"em4x50read", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"},
|
||||
{"readword", CmdReadWord, 1, "<Word> -- Read EM4xxx word data"},
|
||||
{"readwordPWD", CmdReadWordPWD, 1, "<Word> <Password> -- Read EM4xxx word data in password mode"},
|
||||
{"writeword", CmdWriteWord, 1, "<Data> <Word> -- Write EM4xxx word data"},
|
||||
{"writewordPWD", CmdWriteWordPWD, 1, "<Data> <Word> <Password> -- Write EM4xxx word data in password mode"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
||||
//Confirms the parity of a bitstream as well as obtaining the data (TagID) from within the appropriate memory space.
|
||||
//Arguments:
|
||||
// Pointer to a string containing the desired bitsream
|
||||
// Pointer to a string that will receive the decoded tag ID
|
||||
// Length of the bitsream pointed at in the first argument, char* _strBitStream
|
||||
//Retuns:
|
||||
//1 Parity confirmed
|
||||
//0 Parity not confirmed
|
||||
int ConfirmEm410xTagParity( char* _strBitStream, char* pID, int LengthOfBitstream )
|
||||
{
|
||||
int i = 0;
|
||||
int rows = 0;
|
||||
int Parity[4] = {0x00};
|
||||
char ID[11] = {0x00};
|
||||
int k = 0;
|
||||
int BitStream[70] = {0x00};
|
||||
int counter = 0;
|
||||
//prepare variables
|
||||
for ( i = 0; i <= LengthOfBitstream; i++)
|
||||
{
|
||||
if (_strBitStream[i] == '1')
|
||||
{
|
||||
k =1;
|
||||
memcpy(&BitStream[i], &k,4);
|
||||
}
|
||||
else if (_strBitStream[i] == '0')
|
||||
{
|
||||
k = 0;
|
||||
memcpy(&BitStream[i], &k,4);
|
||||
}
|
||||
}
|
||||
while ( counter < 2 )
|
||||
{
|
||||
//set/reset variables and counters
|
||||
memset(ID,0x00,sizeof(ID));
|
||||
memset(Parity,0x00,sizeof(Parity));
|
||||
rows = 0;
|
||||
for ( i = 9; i <= LengthOfBitstream; i++)
|
||||
{
|
||||
if ( rows < 10 )
|
||||
{
|
||||
if ((BitStream[i] ^ BitStream[i+1] ^ BitStream[i+2] ^ BitStream[i+3]) == BitStream[i+4])
|
||||
{
|
||||
sprintf(ID+rows, "%x", (8 * BitStream[i]) + (4 * BitStream[i+1]) + (2 * BitStream[i+2]) + (1 * BitStream[i+3]));
|
||||
rows++;
|
||||
/* Keep parity info and move four bits ahead*/
|
||||
Parity[0] ^= BitStream[i];
|
||||
Parity[1] ^= BitStream[i+1];
|
||||
Parity[2] ^= BitStream[i+2];
|
||||
Parity[3] ^= BitStream[i+3];
|
||||
i += 4;
|
||||
}
|
||||
}
|
||||
if ( rows == 10 )
|
||||
{
|
||||
if ( BitStream[i] == Parity[0] && BitStream[i+1] == Parity[1] &&
|
||||
BitStream[i+2] == Parity[2] && BitStream[i+3] == Parity[3] &&
|
||||
BitStream[i+4] == 0)
|
||||
{
|
||||
memcpy(pID,ID,strlen(ID));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("[PARITY ->]Failed. Flipping Bits, and rechecking parity for bitstream:\n[PARITY ->]");
|
||||
for (k = 0; k < LengthOfBitstream; k++)
|
||||
{
|
||||
BitStream[k] ^= 1;
|
||||
printf("%i", BitStream[k]);
|
||||
}
|
||||
puts(" ");
|
||||
counter++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//Reads and demodulates an em410x RFID tag. It further allows slight modification to the decoded bitstream
|
||||
//Once a suitable bitstream has been identified, and if needed, modified, it is replayed. Allowing emulation of the
|
||||
//"stolen" rfid tag.
|
||||
//No meaningful returns or arguments.
|
||||
int MWRem4xReplay(const char* Cmd)
|
||||
{
|
||||
// //header traces
|
||||
// static char ArrayTraceZero[] = { '0','0','0','0','0','0','0','0','0' };
|
||||
// static char ArrayTraceOne[] = { '1','1','1','1','1','1','1','1','1' };
|
||||
// //local string variables
|
||||
// char strClockRate[10] = {0x00};
|
||||
// char strAnswer[4] = {0x00};
|
||||
// char strTempBufferMini[2] = {0x00};
|
||||
// //our outbound bit-stream
|
||||
// char strSimulateBitStream[65] = {0x00};
|
||||
// //integers
|
||||
// int iClockRate = 0;
|
||||
// int needle = 0;
|
||||
// int j = 0;
|
||||
// int iFirstHeaderOffset = 0x00000000;
|
||||
// int numManchesterDemodBits=0;
|
||||
// //boolean values
|
||||
// bool bInverted = false;
|
||||
// //pointers to strings. memory will be allocated.
|
||||
// char* pstrInvertBitStream = 0x00000000;
|
||||
// char* pTempBuffer = 0x00000000;
|
||||
// char* pID = 0x00000000;
|
||||
// char* strBitStreamBuffer = 0x00000000;
|
||||
|
||||
|
||||
// puts("###################################");
|
||||
// puts("#### Em4x Replay ##");
|
||||
// puts("#### R.A.M. June 2013 ##");
|
||||
// puts("###################################");
|
||||
// //initialize
|
||||
// CmdLFRead("");
|
||||
// //Collect ourselves 10,000 samples
|
||||
// CmdSamples("10000");
|
||||
// puts("[->]preforming ASK demodulation\n");
|
||||
// //demodulate ask
|
||||
// Cmdaskdemod("0");
|
||||
// iClockRate = DetectClock(0);
|
||||
// sprintf(strClockRate, "%i\n",iClockRate);
|
||||
// printf("[->]Detected ClockRate: %s\n", strClockRate);
|
||||
|
||||
// //If detected clock rate is something completely unreasonable, dont go ahead
|
||||
// if ( iClockRate < 0xFFFE )
|
||||
// {
|
||||
// pTempBuffer = (char*)malloc(MAX_GRAPH_TRACE_LEN);
|
||||
// if (pTempBuffer == 0x00000000)
|
||||
// return 0;
|
||||
// memset(pTempBuffer,0x00,MAX_GRAPH_TRACE_LEN);
|
||||
// //Preform manchester de-modulation and display in a single line.
|
||||
// numManchesterDemodBits = CmdManchesterDemod( strClockRate );
|
||||
// //note: numManchesterDemodBits is set above in CmdManchesterDemod()
|
||||
// if ( numManchesterDemodBits == 0 )
|
||||
// return 0;
|
||||
// strBitStreamBuffer = malloc(numManchesterDemodBits+1);
|
||||
// if ( strBitStreamBuffer == 0x00000000 )
|
||||
// return 0;
|
||||
// memset(strBitStreamBuffer, 0x00, (numManchesterDemodBits+1));
|
||||
// //fill strBitStreamBuffer with demodulated, string formatted bits.
|
||||
// for ( j = 0; j <= numManchesterDemodBits; j++ )
|
||||
// {
|
||||
// sprintf(strTempBufferMini, "%i",BitStream[j]);
|
||||
// strcat(strBitStreamBuffer,strTempBufferMini);
|
||||
// }
|
||||
// printf("[->]Demodulated Bitstream: \n%s\n", strBitStreamBuffer);
|
||||
// //Reset counter and select most probable bit stream
|
||||
// j = 0;
|
||||
// while ( j < numManchesterDemodBits )
|
||||
// {
|
||||
// memset(strSimulateBitStream,0x00,64);
|
||||
// //search for header of nine (9) 0's : 000000000 or nine (9) 1's : 1111 1111 1
|
||||
// if ( ( strncmp(strBitStreamBuffer+j, ArrayTraceZero, sizeof(ArrayTraceZero)) == 0 ) ||
|
||||
// ( strncmp(strBitStreamBuffer+j, ArrayTraceOne, sizeof(ArrayTraceOne)) == 0 ) )
|
||||
// {
|
||||
// iFirstHeaderOffset = j;
|
||||
// memcpy(strSimulateBitStream, strBitStreamBuffer+j,64);
|
||||
// printf("[->]Offset of Header");
|
||||
// if ( strncmp(strBitStreamBuffer+iFirstHeaderOffset, "0", 1) == 0 )
|
||||
// printf("'%s'", ArrayTraceZero );
|
||||
// else
|
||||
// printf("'%s'", ArrayTraceOne );
|
||||
// printf(": %i\nHighlighted string : %s\n",iFirstHeaderOffset,strSimulateBitStream);
|
||||
// //allow us to escape loop or choose another frame
|
||||
// puts("[<-]Are we happy with this sample? [Y]es/[N]o");
|
||||
// gets(strAnswer);
|
||||
// if ( ( strncmp(strAnswer,"y",1) == 0 ) || ( strncmp(strAnswer,"Y",1) == 0 ) )
|
||||
// {
|
||||
// j = numManchesterDemodBits+1;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// j++;
|
||||
// }
|
||||
// }
|
||||
// else return 0;
|
||||
|
||||
// //Do we want the buffer inverted?
|
||||
// memset(strAnswer, 0x00, sizeof(strAnswer));
|
||||
// printf("[<-]Do you wish to invert the highlighted bitstream? [Y]es/[N]o\n");
|
||||
// gets(strAnswer);
|
||||
// if ( ( strncmp("y", strAnswer,1) == 0 ) || ( strncmp("Y", strAnswer, 1 ) == 0 ) )
|
||||
// {
|
||||
// //allocate heap memory
|
||||
// pstrInvertBitStream = (char*)malloc(numManchesterDemodBits);
|
||||
// if ( pstrInvertBitStream != 0x00000000 )
|
||||
// {
|
||||
// memset(pstrInvertBitStream,0x00,numManchesterDemodBits);
|
||||
// bInverted = true;
|
||||
// //Invert Bitstream
|
||||
// for ( needle = 0; needle <= numManchesterDemodBits; needle++ )
|
||||
// {
|
||||
// if (strSimulateBitStream[needle] == '0')
|
||||
// strcat(pstrInvertBitStream,"1");
|
||||
// else if (strSimulateBitStream[needle] == '1')
|
||||
// strcat(pstrInvertBitStream,"0");
|
||||
// }
|
||||
// printf("[->]Inverted bitstream: %s\n", pstrInvertBitStream);
|
||||
// }
|
||||
// }
|
||||
// //Confirm parity of selected string
|
||||
// pID = (char*)malloc(11);
|
||||
// if (pID != 0x00000000)
|
||||
// {
|
||||
// memset(pID, 0x00, 11);
|
||||
// if (ConfirmEm410xTagParity(strSimulateBitStream,pID, 64) == 1)
|
||||
// {
|
||||
// printf("[->]Parity confirmed for selected bitstream!\n");
|
||||
// printf("[->]Tag ID was detected as: [hex]:%s\n",pID );
|
||||
// }
|
||||
// else
|
||||
// printf("[->]Parity check failed for the selected bitstream!\n");
|
||||
// }
|
||||
|
||||
// //Spoof
|
||||
// memset(strAnswer, 0x00, sizeof(strAnswer));
|
||||
// printf("[<-]Do you wish to continue with the EM4x simulation? [Y]es/[N]o\n");
|
||||
// gets(strAnswer);
|
||||
// if ( ( strncmp(strAnswer,"y",1) == 0 ) || ( strncmp(strAnswer,"Y",1) == 0 ) )
|
||||
// {
|
||||
// strcat(pTempBuffer, strClockRate);
|
||||
// strcat(pTempBuffer, " ");
|
||||
// if (bInverted == true)
|
||||
// strcat(pTempBuffer,pstrInvertBitStream);
|
||||
// if (bInverted == false)
|
||||
// strcat(pTempBuffer,strSimulateBitStream);
|
||||
// //inform the user
|
||||
// puts("[->]Starting simulation now: \n");
|
||||
// //Simulate tag with prepared buffer.
|
||||
// CmdLFSimManchester(pTempBuffer);
|
||||
// }
|
||||
// else if ( ( strcmp("n", strAnswer) == 0 ) || ( strcmp("N", strAnswer ) == 0 ) )
|
||||
// printf("[->]Exiting procedure now...\n");
|
||||
// else
|
||||
// printf("[->]Erroneous selection\nExiting procedure now....\n");
|
||||
|
||||
// //Clean up -- Exit function
|
||||
// //clear memory, then release pointer.
|
||||
// if ( pstrInvertBitStream != 0x00000000 )
|
||||
// {
|
||||
// memset(pstrInvertBitStream,0x00,numManchesterDemodBits);
|
||||
// free(pstrInvertBitStream);
|
||||
// }
|
||||
// if ( pTempBuffer != 0x00000000 )
|
||||
// {
|
||||
// memset(pTempBuffer,0x00,MAX_GRAPH_TRACE_LEN);
|
||||
// free(pTempBuffer);
|
||||
// }
|
||||
// if ( pID != 0x00000000 )
|
||||
// {
|
||||
// memset(pID,0x00,11);
|
||||
// free(pID);
|
||||
// }
|
||||
// if ( strBitStreamBuffer != 0x00000000 )
|
||||
// {
|
||||
// memset(strBitStreamBuffer,0x00,numManchesterDemodBits);
|
||||
// free(strBitStreamBuffer);
|
||||
// }
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdLFEM4X(const char *Cmd)
|
||||
{
|
||||
CmdsParse(CommandTable, Cmd);
|
||||
|
|
|
@ -39,12 +39,12 @@ int CmdHIDDemod(const char *Cmd)
|
|||
|
||||
int CmdHIDDemodFSK(const char *Cmd)
|
||||
{
|
||||
int findone = 0;
|
||||
int findone=0;
|
||||
if(Cmd[0]=='1') findone=1;
|
||||
UsbCommand c = {CMD_HID_DEMOD_FSK};
|
||||
c.arg[0]=findone;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
UsbCommand c={CMD_HID_DEMOD_FSK};
|
||||
c.arg[0]=findone;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHIDSim(const char *Cmd)
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
#include "proxmark3.h"
|
||||
#include "ui.h"
|
||||
#include "cmdparser.h"
|
||||
#include "../include/common.h"
|
||||
#include "common.h"
|
||||
#include "util.h"
|
||||
#include "../include/hitag2.h"
|
||||
#include "hitag2.h"
|
||||
#include "sleep.h"
|
||||
#include "cmdmain.h"
|
||||
|
||||
|
@ -29,110 +29,125 @@ size_t nbytes(size_t nbits) {
|
|||
|
||||
int CmdLFHitagList(const char *Cmd)
|
||||
{
|
||||
uint8_t got[TRACE_BUFFER_SIZE];
|
||||
GetFromBigBuf(got,sizeof(got),0);
|
||||
WaitForResponse(CMD_ACK,NULL);
|
||||
uint8_t *got = malloc(USB_CMD_DATA_SIZE);
|
||||
|
||||
PrintAndLog("recorded activity:");
|
||||
PrintAndLog(" ETU :nbits: who bytes");
|
||||
PrintAndLog("---------+-----+----+-----------");
|
||||
|
||||
int i = 0;
|
||||
int prev = -1;
|
||||
int len = strlen(Cmd);
|
||||
|
||||
char filename[FILE_PATH_SIZE] = { 0x00 };
|
||||
FILE* pf = NULL;
|
||||
|
||||
if (len > FILE_PATH_SIZE)
|
||||
len = FILE_PATH_SIZE;
|
||||
memcpy(filename, Cmd, len);
|
||||
|
||||
if (strlen(filename) > 0) {
|
||||
if ((pf = fopen(filename,"wb")) == NULL) {
|
||||
PrintAndLog("Error: Could not open file [%s]",filename);
|
||||
return 1;
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
|
||||
if(i >= TRACE_BUFFER_SIZE) { break; }
|
||||
|
||||
bool isResponse;
|
||||
int timestamp = *((uint32_t *)(got+i));
|
||||
if (timestamp & 0x80000000) {
|
||||
timestamp &= 0x7fffffff;
|
||||
isResponse = 1;
|
||||
} else {
|
||||
isResponse = 0;
|
||||
}
|
||||
|
||||
int parityBits = *((uint32_t *)(got+i+4));
|
||||
// 4 bytes of additional information...
|
||||
// maximum of 32 additional parity bit information
|
||||
//
|
||||
// TODO:
|
||||
// at each quarter bit period we can send power level (16 levels)
|
||||
// or each half bit period in 256 levels.
|
||||
|
||||
int bits = got[i+8];
|
||||
int len = nbytes(got[i+8]);
|
||||
|
||||
if (len > 100) {
|
||||
break;
|
||||
}
|
||||
if (i + len >= TRACE_BUFFER_SIZE) { break;}
|
||||
|
||||
uint8_t *frame = (got+i+9);
|
||||
|
||||
// Break and stick with current result if buffer was not completely full
|
||||
if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }
|
||||
|
||||
char line[1000] = "";
|
||||
int j;
|
||||
for (j = 0; j < len; j++) {
|
||||
int oddparity = 0x01;
|
||||
int k;
|
||||
|
||||
for (k=0;k<8;k++) {
|
||||
oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
|
||||
}
|
||||
|
||||
//if((parityBits >> (len - j - 1)) & 0x01) {
|
||||
if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
|
||||
sprintf(line+(j*4), "%02x! ", frame[j]);
|
||||
}
|
||||
else {
|
||||
sprintf(line+(j*4), "%02x ", frame[j]);
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLog(" +%7d: %3d: %s %s",
|
||||
(prev < 0 ? 0 : (timestamp - prev)),
|
||||
bits,
|
||||
(isResponse ? "TAG" : " "),
|
||||
line);
|
||||
|
||||
|
||||
if (pf) {
|
||||
fprintf(pf," +%7d: %3d: %s %s\n",
|
||||
(prev < 0 ? 0 : (timestamp - prev)),
|
||||
bits,
|
||||
(isResponse ? "TAG" : " "),
|
||||
line);
|
||||
}
|
||||
|
||||
prev = timestamp;
|
||||
i += (len + 9);
|
||||
}
|
||||
PrintAndLog("recorded activity (TraceLen = %d bytes):");
|
||||
PrintAndLog(" ETU :nbits: who bytes");
|
||||
PrintAndLog("---------+-----+----+-----------");
|
||||
|
||||
int i = 0;
|
||||
int prev = -1;
|
||||
int len = strlen(Cmd);
|
||||
|
||||
char filename[FILE_PATH_SIZE] = { 0x00 };
|
||||
FILE* pf = NULL;
|
||||
|
||||
if (len > FILE_PATH_SIZE)
|
||||
len = FILE_PATH_SIZE;
|
||||
memcpy(filename, Cmd, len);
|
||||
|
||||
if (strlen(filename) > 0) {
|
||||
if ((pf = fopen(filename,"wb")) == NULL) {
|
||||
PrintAndLog("Error: Could not open file [%s]",filename);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
|
||||
if (pf) {
|
||||
fclose(pf);
|
||||
PrintAndLog("Recorded activity succesfully written to file: %s", filename);
|
||||
}
|
||||
|
||||
return 0;
|
||||
if(i > traceLen) { break; }
|
||||
|
||||
bool isResponse;
|
||||
int timestamp = *((uint32_t *)(got+i));
|
||||
if (timestamp & 0x80000000) {
|
||||
timestamp &= 0x7fffffff;
|
||||
isResponse = 1;
|
||||
} else {
|
||||
isResponse = 0;
|
||||
}
|
||||
|
||||
int parityBits = *((uint32_t *)(got+i+4));
|
||||
// 4 bytes of additional information...
|
||||
// maximum of 32 additional parity bit information
|
||||
//
|
||||
// TODO:
|
||||
// at each quarter bit period we can send power level (16 levels)
|
||||
// or each half bit period in 256 levels.
|
||||
|
||||
int bits = got[i+8];
|
||||
int len = nbytes(got[i+8]);
|
||||
|
||||
if (len > 100) {
|
||||
break;
|
||||
}
|
||||
if (i + len > traceLen) { break;}
|
||||
|
||||
uint8_t *frame = (got+i+9);
|
||||
|
||||
// Break and stick with current result if buffer was not completely full
|
||||
if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }
|
||||
|
||||
char line[1000] = "";
|
||||
int j;
|
||||
for (j = 0; j < len; j++) {
|
||||
int oddparity = 0x01;
|
||||
int k;
|
||||
|
||||
for (k=0;k<8;k++) {
|
||||
oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
|
||||
}
|
||||
|
||||
//if((parityBits >> (len - j - 1)) & 0x01) {
|
||||
if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
|
||||
sprintf(line+(j*4), "%02x! ", frame[j]);
|
||||
}
|
||||
else {
|
||||
sprintf(line+(j*4), "%02x ", frame[j]);
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLog(" +%7d: %3d: %s %s",
|
||||
(prev < 0 ? 0 : (timestamp - prev)),
|
||||
bits,
|
||||
(isResponse ? "TAG" : " "),
|
||||
line);
|
||||
|
||||
if (pf) {
|
||||
fprintf(pf," +%7d: %3d: %s %s\n",
|
||||
(prev < 0 ? 0 : (timestamp - prev)),
|
||||
bits,
|
||||
(isResponse ? "TAG" : " "),
|
||||
line);
|
||||
}
|
||||
|
||||
prev = timestamp;
|
||||
i += (len + 9);
|
||||
}
|
||||
|
||||
if (pf) {
|
||||
fclose(pf);
|
||||
PrintAndLog("Recorded activity succesfully written to file: %s", filename);
|
||||
}
|
||||
|
||||
free(got);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdLFHitagSnoop(const char *Cmd) {
|
||||
|
@ -143,14 +158,14 @@ int CmdLFHitagSnoop(const char *Cmd) {
|
|||
|
||||
int CmdLFHitagSim(const char *Cmd) {
|
||||
|
||||
UsbCommand c = {CMD_SIMULATE_HITAG};
|
||||
UsbCommand c = {CMD_SIMULATE_HITAG};
|
||||
char filename[FILE_PATH_SIZE] = { 0x00 };
|
||||
FILE* pf;
|
||||
bool tag_mem_supplied;
|
||||
int len = strlen(Cmd);
|
||||
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
|
||||
memcpy(filename, Cmd, len);
|
||||
|
||||
|
||||
if (strlen(filename) > 0) {
|
||||
if ((pf = fopen(filename,"rb+")) == NULL) {
|
||||
PrintAndLog("Error: Could not open file [%s]",filename);
|
||||
|
@ -158,10 +173,10 @@ int CmdLFHitagSim(const char *Cmd) {
|
|||
}
|
||||
tag_mem_supplied = true;
|
||||
if (fread(c.d.asBytes,48,1,pf) == 0) {
|
||||
PrintAndLog("Error: File reading error");
|
||||
PrintAndLog("Error: File reading error");
|
||||
fclose(pf);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
fclose(pf);
|
||||
} else {
|
||||
tag_mem_supplied = false;
|
||||
|
@ -249,7 +264,7 @@ static command_t CommandTable[] =
|
|||
{"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader"},
|
||||
{"sim", CmdLFHitagSim, 1, "<infile> Simulate Hitag transponder"},
|
||||
{"snoop", CmdLFHitagSnoop, 1, "Eavesdrop Hitag communication"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
int CmdLFHitag(const char *Cmd)
|
||||
|
|
|
@ -16,13 +16,13 @@ static int CmdHelp(const char *Cmd);
|
|||
|
||||
int CmdIODemodFSK(const char *Cmd)
|
||||
{
|
||||
int findone = 0;
|
||||
if (Cmd[0] =='1') findone = 1;
|
||||
int findone=0;
|
||||
if(Cmd[0]=='1') findone=1;
|
||||
|
||||
UsbCommand c={CMD_IO_DEMOD_FSK};
|
||||
c.arg[0] = findone;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
UsbCommand c={CMD_IO_DEMOD_FSK};
|
||||
c.arg[0]=findone;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdIOProxDemod(const char *Cmd){
|
||||
|
@ -66,10 +66,10 @@ int CmdIOClone(const char *Cmd)
|
|||
|
||||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"demod", CmdIOProxDemod, 1, "Demodulate Stream"},
|
||||
{"fskdemod", CmdIODemodFSK, 0, "['1'] Realtime IO FSK demodulator (option '1' for one tag only)"},
|
||||
{"clone", CmdIOClone, 0, "Clone ioProx Tag"},
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"demod", CmdIOProxDemod, 1, "Demodulate Stream"},
|
||||
{"fskdemod", CmdIODemodFSK, 0, "['1'] Realtime IO FSK demodulator (option '1' for one tag only)"},
|
||||
{"clone", CmdIOClone, 0, "Clone ioProx Tag"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "cmdparser.h"
|
||||
#include "proxmark3.h"
|
||||
#include "data.h"
|
||||
#include "../include/usb_cmd.h"
|
||||
#include "usb_cmd.h"
|
||||
#include "ui.h"
|
||||
#include "cmdhf.h"
|
||||
#include "cmddata.h"
|
||||
|
@ -42,14 +42,14 @@ static int cmd_tail;//Starts as 0
|
|||
|
||||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help. Use '<command> help' for details of a particular command."},
|
||||
{"data", CmdData, 1, "{ Plot window / data buffer manipulation... }"},
|
||||
{"help", CmdHelp, 1, "This help. Use '<command> help' for details of a particular command."},
|
||||
{"data", CmdData, 1, "{ Plot window / data buffer manipulation... }"},
|
||||
{"hf", CmdHF, 1, "{ High Frequency commands... }"},
|
||||
{"hw", CmdHW, 1, "{ Hardware commands... }"},
|
||||
{"hw", CmdHW, 1, "{ Hardware commands... }"},
|
||||
{"lf", CmdLF, 1, "{ Low Frequency commands... }"},
|
||||
{"script", CmdScript, 1, "{ Scripting commands }"},
|
||||
{"quit", CmdQuit, 1, "Exit program"},
|
||||
{"exit", CmdQuit, 1, "Exit program"},
|
||||
{"script", CmdScript, 1,"{ Scripting commands }"},
|
||||
{"quit", CmdQuit, 1, "Exit program"},
|
||||
{"exit", CmdQuit, 1, "Exit program"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
@ -130,26 +130,26 @@ int getCommand(UsbCommand* response)
|
|||
* @return true if command was returned, otherwise false
|
||||
*/
|
||||
bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout) {
|
||||
|
||||
UsbCommand resp;
|
||||
|
||||
UsbCommand resp;
|
||||
|
||||
if (response == NULL)
|
||||
response = &resp;
|
||||
response = &resp;
|
||||
|
||||
|
||||
// Wait until the command is received
|
||||
for(size_t dm_seconds=0; dm_seconds < ms_timeout/10; dm_seconds++) {
|
||||
// Wait until the command is received
|
||||
for(size_t dm_seconds=0; dm_seconds < ms_timeout/10; dm_seconds++) {
|
||||
|
||||
while (getCommand(response)) {
|
||||
if(response->cmd == cmd){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
msleep(10); // XXX ugh
|
||||
if (dm_seconds == 200) { // Two seconds elapsed
|
||||
PrintAndLog("Waiting for a response from the proxmark...");
|
||||
PrintAndLog("Don't forget to cancel its operation first by pressing on the button");
|
||||
}
|
||||
while(getCommand(response)) {
|
||||
if(response->cmd == cmd){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
msleep(10); // XXX ugh
|
||||
if (dm_seconds == 200) { // Two seconds elapsed
|
||||
PrintAndLog("Waiting for a response from the proxmark...");
|
||||
PrintAndLog("Don't forget to cancel its operation first by pressing on the button");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -175,27 +175,26 @@ void UsbCommandReceived(UsbCommand *UC)
|
|||
switch(UC->cmd) {
|
||||
// First check if we are handling a debug message
|
||||
case CMD_DEBUG_PRINT_STRING: {
|
||||
char s[USB_CMD_DATA_SIZE+1] = {0x00};
|
||||
size_t len = MIN(UC->arg[0],USB_CMD_DATA_SIZE);
|
||||
memcpy(s,UC->d.asBytes,len);
|
||||
PrintAndLog("#db# %s ", s);
|
||||
return;
|
||||
char s[USB_CMD_DATA_SIZE+1] = {0x00};
|
||||
size_t len = MIN(UC->arg[0],USB_CMD_DATA_SIZE);
|
||||
memcpy(s,UC->d.asBytes,len);
|
||||
PrintAndLog("#db# %s ", s);
|
||||
return;
|
||||
} break;
|
||||
|
||||
case CMD_DEBUG_PRINT_INTEGERS: {
|
||||
PrintAndLog("#db# %08x, %08x, %08x \r\n", UC->arg[0], UC->arg[1], UC->arg[2]);
|
||||
return;
|
||||
PrintAndLog("#db# %08x, %08x, %08x \r\n", UC->arg[0], UC->arg[1], UC->arg[2]);
|
||||
return;
|
||||
} break;
|
||||
|
||||
|
||||
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;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
storeCommand(UC);
|
||||
storeCommand(UC);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,11 +16,9 @@
|
|||
#include "cmdmain.h"
|
||||
|
||||
uint8_t* sample_buf;
|
||||
size_t sample_buf_len;
|
||||
|
||||
void GetFromBigBuf(uint8_t *dest, int bytes, int start_index)
|
||||
{
|
||||
sample_buf_len = 0;
|
||||
sample_buf = dest;
|
||||
UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {start_index, bytes, 0}};
|
||||
SendCommand(&c);
|
||||
|
|
|
@ -13,13 +13,9 @@
|
|||
|
||||
#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 SAMPLE_BUFFER_SIZE 64
|
||||
|
||||
extern uint8_t* sample_buf;
|
||||
extern size_t sample_buf_len;
|
||||
#define arraylen(x) (sizeof(x)/sizeof((x)[0]))
|
||||
|
||||
void GetFromBigBuf(uint8_t *dest, int bytes, int start_index);
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "flash.h"
|
||||
#include "elf.h"
|
||||
#include "proxendian.h"
|
||||
#include "../include/usb_cmd.h"
|
||||
#include "usb_cmd.h"
|
||||
|
||||
void SendCommand(UsbCommand* txcmd);
|
||||
void ReceiveCommand(UsbCommand* rxcmd);
|
||||
|
@ -275,7 +275,7 @@ static int get_proxmark_state(uint32_t *state)
|
|||
{
|
||||
UsbCommand c;
|
||||
c.cmd = CMD_DEVICE_INFO;
|
||||
SendCommand(&c);
|
||||
SendCommand(&c);
|
||||
UsbCommand resp;
|
||||
ReceiveCommand(&resp);
|
||||
|
||||
|
@ -404,11 +404,11 @@ static int write_block(uint32_t address, uint8_t *data, uint32_t length)
|
|||
|
||||
memset(block_buf, 0xFF, BLOCK_SIZE);
|
||||
memcpy(block_buf, data, length);
|
||||
UsbCommand c;
|
||||
UsbCommand c;
|
||||
c.cmd = CMD_FINISH_WRITE;
|
||||
c.arg[0] = address;
|
||||
memcpy(c.d.asBytes, block_buf, length);
|
||||
SendCommand(&c);
|
||||
SendCommand(&c);
|
||||
return wait_for_ack();
|
||||
}
|
||||
|
||||
|
@ -469,7 +469,7 @@ void flash_free(flash_file_t *ctx)
|
|||
// just reset the unit
|
||||
int flash_stop_flashing(void) {
|
||||
UsbCommand c = {CMD_HARDWARE_RESET};
|
||||
SendCommand(&c);
|
||||
msleep(100);
|
||||
return 0;
|
||||
SendCommand(&c);
|
||||
msleep(100);
|
||||
return 0;
|
||||
}
|
||||
|
|
118
client/graph.c
118
client/graph.c
|
@ -22,92 +22,85 @@ int GraphTraceLen;
|
|||
void AppendGraph(int redraw, int clock, int bit)
|
||||
{
|
||||
int i;
|
||||
int half = (int)(clock/2);
|
||||
int firstbit = bit ^ 1;
|
||||
|
||||
for (i = 0; i < half; ++i)
|
||||
GraphBuffer[GraphTraceLen++] = firstbit;
|
||||
|
||||
for (i = 0; i <= half; ++i)
|
||||
|
||||
for (i = 0; i < (int)(clock / 2); ++i)
|
||||
GraphBuffer[GraphTraceLen++] = bit ^ 1;
|
||||
|
||||
for (i = (int)(clock / 2); i < clock; ++i)
|
||||
GraphBuffer[GraphTraceLen++] = bit;
|
||||
|
||||
if (redraw)
|
||||
RepaintGraphWindow();
|
||||
}
|
||||
|
||||
/* clear out our graph window */
|
||||
// clear out our graph window
|
||||
int ClearGraph(int redraw)
|
||||
{
|
||||
int gtl = GraphTraceLen;
|
||||
memset(GraphBuffer, 0x00, GraphTraceLen);
|
||||
|
||||
GraphTraceLen = 0;
|
||||
|
||||
|
||||
if (redraw)
|
||||
RepaintGraphWindow();
|
||||
|
||||
return gtl;
|
||||
}
|
||||
|
||||
void SetGraphBuf(uint8_t *buff, int size)
|
||||
// DETECT CLOCK NOW IN LFDEMOD.C
|
||||
|
||||
void setGraphBuf(uint8_t *buff, size_t size)
|
||||
{
|
||||
if ( buff == NULL ) return;
|
||||
|
||||
uint16_t i = 0;
|
||||
if ( size > MAX_GRAPH_TRACE_LEN )
|
||||
size = MAX_GRAPH_TRACE_LEN;
|
||||
ClearGraph(0);
|
||||
for (; i < size; ++i){
|
||||
GraphBuffer[i] = buff[i];
|
||||
}
|
||||
GraphTraceLen = size;
|
||||
RepaintGraphWindow();
|
||||
return;
|
||||
ClearGraph(0);
|
||||
for (; i < size; ++i){
|
||||
GraphBuffer[i]=buff[i]-128;
|
||||
}
|
||||
GraphTraceLen=size;
|
||||
RepaintGraphWindow();
|
||||
return;
|
||||
}
|
||||
size_t getFromGraphBuf(uint8_t *buff)
|
||||
{
|
||||
if ( buff == NULL ) return 0;
|
||||
|
||||
uint32_t i;
|
||||
for (i=0;i<GraphTraceLen;++i){
|
||||
if (GraphBuffer[i]>127) GraphBuffer[i]=127; //trim
|
||||
if (GraphBuffer[i]<-127) GraphBuffer[i]=-127; //trim
|
||||
buff[i]=(uint8_t)(GraphBuffer[i]+128);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
// Copies grahpbuff to buff.
|
||||
// while triming values to the range -127 -- 127.
|
||||
int GetFromGraphBuf(uint8_t *buff)
|
||||
{
|
||||
if ( buff == NULL ) return -1;
|
||||
uint32_t i = 0;
|
||||
|
||||
for (; i < GraphTraceLen; ++i){
|
||||
|
||||
// trim upper and lower values.
|
||||
if (GraphBuffer[i] > 127)
|
||||
GraphBuffer[i] = 127;
|
||||
else if (GraphBuffer[i] < -127)
|
||||
GraphBuffer[i] = -127;
|
||||
|
||||
buff[i] = (uint8_t)(GraphBuffer[i] + 128);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
/* Get or auto-detect clock rate */
|
||||
int GetClock(const char *str, int verbose)
|
||||
|
||||
// Get or auto-detect clock rate
|
||||
int GetClock(const char *str, int peak, int verbose)
|
||||
{
|
||||
int clock;
|
||||
|
||||
sscanf(str, "%i", &clock);
|
||||
if (!strcmp(str, ""))
|
||||
clock = 0;
|
||||
|
||||
/* Auto-detect clock */
|
||||
if (!clock) {
|
||||
|
||||
uint8_t grph[MAX_GRAPH_TRACE_LEN] = {0x00};
|
||||
int size = GetFromGraphBuf(grph);
|
||||
if ( size < 0 ) {
|
||||
// Auto-detect clock
|
||||
if (!clock)
|
||||
{
|
||||
uint8_t grph[MAX_GRAPH_TRACE_LEN]={0};
|
||||
size_t size = getFromGraphBuf(grph);
|
||||
if ( size == 0 ) {
|
||||
PrintAndLog("Failed to copy from graphbuffer");
|
||||
return -1;
|
||||
}
|
||||
clock = DetectASKClock(grph, size, 0);
|
||||
|
||||
/* Only print this message if we're not looping something */
|
||||
if (verbose)
|
||||
clock = DetectASKClock(grph,size,0);
|
||||
// Only print this message if we're not looping something
|
||||
if (!verbose){
|
||||
PrintAndLog("Auto-detected clock rate: %d", clock);
|
||||
}
|
||||
}
|
||||
return clock;
|
||||
}
|
||||
|
||||
|
@ -141,4 +134,29 @@ void DetectHighLowInGraph(int *high, int *low, bool addFuzz) {
|
|||
*high = (int)(*high * .88);
|
||||
*low = (int)(*low * .88);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int GetNRZpskClock(const char *str, int peak, int verbose)
|
||||
{
|
||||
int clock;
|
||||
sscanf(str, "%i", &clock);
|
||||
if (!strcmp(str, ""))
|
||||
clock = 0;
|
||||
|
||||
// Auto-detect clock
|
||||
if (!clock)
|
||||
{
|
||||
uint8_t grph[MAX_GRAPH_TRACE_LEN]={0};
|
||||
size_t size = getFromGraphBuf(grph);
|
||||
if ( size == 0 ) {
|
||||
PrintAndLog("Failed to copy from graphbuffer");
|
||||
return -1;
|
||||
}
|
||||
clock = DetectpskNRZClock(grph,size,0);
|
||||
// Only print this message if we're not looping something
|
||||
if (!verbose){
|
||||
PrintAndLog("Auto-detected clock rate: %d", clock);
|
||||
}
|
||||
}
|
||||
return clock;
|
||||
}
|
||||
|
|
|
@ -10,12 +10,16 @@
|
|||
|
||||
#ifndef GRAPH_H__
|
||||
#define GRAPH_H__
|
||||
#include <stdint.h>
|
||||
|
||||
void AppendGraph(int redraw, int clock, int bit);
|
||||
int ClearGraph(int redraw);
|
||||
int GetFromGraphBuf(uint8_t *buff);
|
||||
int GetClock(const char *str, int verbose);
|
||||
void SetGraphBuf(uint8_t *buff,int size);
|
||||
//int DetectClock(int peak);
|
||||
size_t getFromGraphBuf(uint8_t *buff);
|
||||
int GetClock(const char *str, int peak, int verbose);
|
||||
int GetNRZpskClock(const char *str, int peak, int verbose);
|
||||
void setGraphBuf(uint8_t *buff, size_t size);
|
||||
|
||||
bool HasGraphData();
|
||||
void DetectHighLowInGraph(int *high, int *low, bool addFuzz);
|
||||
|
||||
|
|
|
@ -30,9 +30,13 @@
|
|||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with IClassCipher. If not, see <http://www.gnu.org/licenses/>.
|
||||
* along with loclass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "cipher.h"
|
||||
#include "cipherutils.h"
|
||||
#include <stdio.h>
|
||||
|
|
|
@ -30,9 +30,13 @@
|
|||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with IClassCipher. If not, see <http://www.gnu.org/licenses/>.
|
||||
* along with loclass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef CIPHER_H
|
||||
#define CIPHER_H
|
||||
#include <stdint.h>
|
||||
|
|
|
@ -30,7 +30,10 @@
|
|||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with IClassCipher. If not, see <http://www.gnu.org/licenses/>.
|
||||
* along with loclass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
|
|
@ -30,9 +30,13 @@
|
|||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with IClassCipher. If not, see <http://www.gnu.org/licenses/>.
|
||||
* along with loclass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef CIPHERUTILS_H
|
||||
#define CIPHERUTILS_H
|
||||
#include <stdint.h>
|
||||
|
|
|
@ -28,7 +28,13 @@
|
|||
#define POLARSSL_DES_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>
|
||||
|
||||
#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
|
||||
|
|
|
@ -552,6 +552,7 @@ int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[])
|
|||
*/
|
||||
int bruteforceFile(const char *filename, uint16_t keytable[])
|
||||
{
|
||||
|
||||
FILE *f = fopen(filename, "rb");
|
||||
if(!f) {
|
||||
prnlog("Failed to read from file '%s'", filename);
|
||||
|
@ -618,7 +619,7 @@ int _testBruteforce()
|
|||
//Test a few variants
|
||||
if(fileExists("iclass_dump.bin"))
|
||||
{
|
||||
errors |= bruteforceFile("iclass_dump.bin",keytable);
|
||||
errors |= bruteforceFile("iclass_dump.bin",keytable);
|
||||
}else if(fileExists("loclass/iclass_dump.bin")){
|
||||
errors |= bruteforceFile("loclass/iclass_dump.bin",keytable);
|
||||
}else if(fileExists("client/loclass/iclass_dump.bin")){
|
||||
|
@ -659,6 +660,21 @@ int _test_iclass_key_permutation()
|
|||
prnlog("[+] Iclass key permutation OK!");
|
||||
return 0;
|
||||
}
|
||||
int _testHash1()
|
||||
{
|
||||
uint8_t csn[8]= {0x01,0x02,0x03,0x04,0xF7,0xFF,0x12,0xE0};
|
||||
uint8_t k[8] = {0};
|
||||
hash1(csn, k);
|
||||
uint8_t expected[8] = {0x7E,0x72,0x2F,0x40,0x2D,0x02,0x51,0x42};
|
||||
if(memcmp(k,expected,8) != 0)
|
||||
{
|
||||
prnlog("Error with hash1!");
|
||||
printarr("calculated", k, 8);
|
||||
printarr("expected", expected, 8);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int testElite()
|
||||
{
|
||||
|
@ -691,11 +707,13 @@ int testElite()
|
|||
prnlog("[+] Hash2 looks fine...");
|
||||
}
|
||||
|
||||
prnlog("[+] Testing key diversification ...");
|
||||
|
||||
int errors = 0 ;
|
||||
errors +=_test_iclass_key_permutation();
|
||||
prnlog("[+] Testing hash1...");
|
||||
errors += _testHash1();
|
||||
prnlog("[+] Testing key diversification ...");
|
||||
errors +=_test_iclass_key_permutation();
|
||||
errors += _testBruteforce();
|
||||
|
||||
return errors;
|
||||
|
||||
}
|
||||
|
|
|
@ -78,31 +78,18 @@ int saveFile(const char *preferredName, const char *suffix, const void* data, si
|
|||
/*Opening file for writing in binary mode*/
|
||||
FILE *fileHandle=fopen(fileName,"wb");
|
||||
if(!fileHandle) {
|
||||
PrintAndLog("Failed to write to file '%s'", fileName);
|
||||
prnlog("Failed to write to file '%s'", fileName);
|
||||
free(fileName);
|
||||
return 1;
|
||||
}
|
||||
fwrite(data, 1, datalen, fileHandle);
|
||||
fclose(fileHandle);
|
||||
PrintAndLog("Saved data to '%s'", fileName);
|
||||
prnlog("Saved data to '%s'", fileName);
|
||||
free(fileName);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int loadFile(const char *fileName, void* data, size_t datalen)
|
||||
{
|
||||
FILE *filehandle = fopen(fileName, "rb");
|
||||
if(!filehandle) {
|
||||
PrintAndLog("Failed to read from file '%s'", fileName);
|
||||
free(filehandle);
|
||||
return 1;
|
||||
}
|
||||
fread(data,datalen,1,filehandle);
|
||||
fclose(filehandle);
|
||||
free(filehandle);
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* Utility function to print to console. This is used consistently within the library instead
|
||||
* of printf, but it actually only calls printf (and adds a linebreak).
|
||||
|
|
BIN
client/loclass/iclass_dump.bin
Normal file
BIN
client/loclass/iclass_dump.bin
Normal file
Binary file not shown.
|
@ -18,10 +18,6 @@
|
|||
* Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
|
||||
* Milosch Meriac in the paper "Dismantling IClass".
|
||||
*
|
||||
* This is a reference implementation of iclass key diversification. I'm sure it can be
|
||||
* optimized heavily. It is written for ease of understanding and correctness, please take it
|
||||
* and tweak it and make a super fast version instead, using this for testing and verification.
|
||||
|
||||
* Copyright (C) 2014 Martin Holst Swende
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
|
@ -34,8 +30,12 @@
|
|||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with IClassCipher. If not, see <http://www.gnu.org/licenses/>.
|
||||
* along with loclass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
|
||||
|
||||
|
|
4
client/loclass/loclass_main.h
Normal file
4
client/loclass/loclass_main.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
#ifndef LOCLASS_MAIN_H
|
||||
#define LOCLASS_MAIN_H
|
||||
|
||||
#endif // LOCLASS_MAIN_H
|
|
@ -38,7 +38,6 @@
|
|||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cipherutils.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
@ -56,11 +55,15 @@ int unitTests()
|
|||
errors += testMAC();
|
||||
errors += doKeyTests(0);
|
||||
errors += testElite();
|
||||
if(errors)
|
||||
{
|
||||
prnlog("OBS! There were errors!!!");
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
int showHelp()
|
||||
{
|
||||
prnlog("Usage: iclazz [options]");
|
||||
prnlog("Usage: loclass [options]");
|
||||
prnlog("Options:");
|
||||
prnlog("-t Perform self-test");
|
||||
prnlog("-h Show this help");
|
||||
|
|
|
@ -48,7 +48,7 @@ local _commands = {
|
|||
CMD_EM4X_READ_WORD = 0x0218,
|
||||
CMD_EM4X_WRITE_WORD = 0x0219,
|
||||
CMD_IO_DEMOD_FSK = 0x021A,
|
||||
CMD_IO_CLONE_TAG = 0x021B,
|
||||
CMD_IO_CLONE_TAG = 0x021B,
|
||||
CMD_EM410X_DEMOD = 0x021c,
|
||||
--/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
|
||||
|
||||
|
@ -109,7 +109,7 @@ local _commands = {
|
|||
CMD_MIFARE_CSETBLOCK = 0x0605,
|
||||
CMD_MIFARE_CGETBLOCK = 0x0606,
|
||||
CMD_MIFARE_CIDENT = 0x0607,
|
||||
|
||||
|
||||
CMD_SIMULATE_MIFARE_CARD = 0x0610,
|
||||
|
||||
CMD_READER_MIFARE = 0x0611,
|
||||
|
@ -212,7 +212,6 @@ function Command:getBytes()
|
|||
local data = self.data
|
||||
local cmd = self.cmd
|
||||
local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3
|
||||
|
||||
return bin.pack("LLLLH",cmd, arg1, arg2, arg3,data);
|
||||
end
|
||||
return _commands
|
|
@ -49,7 +49,7 @@ end
|
|||
|
||||
local function save_TEXT(data,filename)
|
||||
-- Open the output file
|
||||
local outfile = io.open(filename, "wb")
|
||||
local outfile = io.open(filename, "w")
|
||||
if outfile == nil then
|
||||
return oops(string.format("Could not write to file %s",tostring(filename)))
|
||||
end
|
||||
|
@ -195,4 +195,6 @@ return {
|
|||
convert_eml_to_bin = convert_eml_to_bin,
|
||||
SaveAsBinary = save_BIN,
|
||||
SaveAsText = save_TEXT,
|
||||
SaveAsBinary = save_BIN,
|
||||
SaveAsText = save_TEXT,
|
||||
}
|
||||
|
|
|
@ -158,6 +158,20 @@ local _keys = {
|
|||
'eff603e1efe9',
|
||||
'644672bd4afe',
|
||||
|
||||
'b5ff67cba951',
|
||||
}
|
||||
|
||||
--[[
|
||||
Kiev metro cards
|
||||
--]]
|
||||
'8fe644038790',
|
||||
'f14ee7cae863',
|
||||
'632193be1c3c',
|
||||
'569369c5a0e5',
|
||||
'9de89e070277',
|
||||
'eff603e1efe9',
|
||||
'644672bd4afe',
|
||||
|
||||
'b5ff67cba951',
|
||||
}
|
||||
|
||||
|
|
|
@ -108,6 +108,24 @@ local Utils =
|
|||
return retval
|
||||
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
|
||||
|
||||
--
|
||||
|
@ -116,7 +134,7 @@ local Utils =
|
|||
local B,K,OUT,I,D=16,"0123456789ABCDEF","",0
|
||||
while IN>0 do
|
||||
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
|
||||
end
|
||||
return OUT
|
||||
|
|
|
@ -72,7 +72,6 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo
|
|||
uint16_t i, len;
|
||||
uint32_t uid;
|
||||
UsbCommand resp;
|
||||
|
||||
StateList_t statelists[2];
|
||||
struct Crypto1State *p1, *p2, *p3, *p4;
|
||||
|
||||
|
@ -232,14 +231,27 @@ int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount) {
|
|||
// "MAGIC" CARD
|
||||
|
||||
int mfCSetUID(uint8_t *uid, uint8_t *oldUID, bool wantWipe) {
|
||||
|
||||
uint8_t oldblock0[16] = {0x00};
|
||||
uint8_t block0[16] = {0x00};
|
||||
memcpy(block0, uid, 4);
|
||||
block0[4] = block0[0]^block0[1]^block0[2]^block0[3]; // Mifare UID BCC
|
||||
// mifare classic SAK(byte 5) and ATQA(byte 6 and 7)
|
||||
block0[5] = 0x08;
|
||||
block0[6] = 0x04;
|
||||
block0[7] = 0x00;
|
||||
//block0[5] = 0x08;
|
||||
//block0[6] = 0x04;
|
||||
//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);
|
||||
}
|
||||
|
||||
|
@ -253,8 +265,10 @@ int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWipe, uin
|
|||
UsbCommand resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
isOK = resp.arg[0] & 0xff;
|
||||
if (uid != NULL) memcpy(uid, resp.d.asBytes, 4);
|
||||
if (!isOK) return 2;
|
||||
if (uid != NULL)
|
||||
memcpy(uid, resp.d.asBytes, 4);
|
||||
if (!isOK)
|
||||
return 2;
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
return 1;
|
||||
|
@ -286,9 +300,9 @@ int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params) {
|
|||
static uint8_t trailerAccessBytes[4] = {0x08, 0x77, 0x8F, 0x00};
|
||||
|
||||
// variables
|
||||
char logHexFileName[200] = {0x00};
|
||||
char logHexFileName[FILE_PATH_SIZE] = {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 uint8_t traceCurBlock = 0;
|
||||
static uint8_t traceCurKey = 0;
|
||||
|
@ -323,20 +337,28 @@ int isBlockTrailer(int blockN) {
|
|||
|
||||
int loadTraceCard(uint8_t *tuid) {
|
||||
FILE * f;
|
||||
char buf[64];
|
||||
uint8_t buf8[64];
|
||||
char buf[64] = {0x00};
|
||||
uint8_t buf8[64] = {0x00};
|
||||
int i, blockNum;
|
||||
|
||||
if (!isTraceCardEmpty()) saveTraceCard();
|
||||
if (!isTraceCardEmpty())
|
||||
saveTraceCard();
|
||||
|
||||
memset(traceCard, 0x00, 4096);
|
||||
memcpy(traceCard, tuid + 3, 4);
|
||||
|
||||
FillFileNameByUID(traceFileName, tuid, ".eml", 7);
|
||||
|
||||
f = fopen(traceFileName, "r");
|
||||
if (!f) return 1;
|
||||
if (!f) {
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
blockNum = 0;
|
||||
|
||||
while(!feof(f)){
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
if (fgets(buf, sizeof(buf), f) == NULL) {
|
||||
PrintAndLog("File reading error.");
|
||||
|
@ -368,22 +390,30 @@ int saveTraceCard(void) {
|
|||
if ((!strlen(traceFileName)) || (isTraceCardEmpty())) return 0;
|
||||
|
||||
f = fopen(traceFileName, "w+");
|
||||
if ( !f ) {
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 64; i++) { // blocks
|
||||
for (int j = 0; j < 16; j++) // bytes
|
||||
fprintf(f, "%02x", *(traceCard + i * 16 + j));
|
||||
fprintf(f,"\n");
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (wantSaveToEmlFile) loadTraceCard(tuid);
|
||||
if (wantSaveToEmlFile)
|
||||
loadTraceCard(tuid);
|
||||
|
||||
traceCard[4] = traceCard[0] ^ traceCard[1] ^ traceCard[2] ^ traceCard[3];
|
||||
traceCard[5] = sak;
|
||||
memcpy(&traceCard[6], atqa, 2);
|
||||
|
|
|
@ -47,7 +47,7 @@ typedef struct {
|
|||
int foundKey[2];
|
||||
} 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 mfCheckKeys (uint8_t blockNo, uint8_t keyType, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key);
|
||||
|
|
|
@ -545,9 +545,9 @@ lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8],
|
|||
statelist = malloc((sizeof *statelist) << 21); //how large should be?
|
||||
if(!statelist || !odd || !even)
|
||||
{
|
||||
free(statelist);
|
||||
free(odd);
|
||||
free(even);
|
||||
free(statelist);
|
||||
free(odd);
|
||||
free(even);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
2179
client/polarssl_config.h
Normal file
2179
client/polarssl_config.h
Normal file
File diff suppressed because it is too large
Load diff
|
@ -34,15 +34,15 @@ static UsbCommand txcmd;
|
|||
volatile static bool txcmd_pending = false;
|
||||
|
||||
void SendCommand(UsbCommand *c) {
|
||||
#if 0
|
||||
#if 0
|
||||
printf("Sending %d bytes\n", sizeof(UsbCommand));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (offline) {
|
||||
PrintAndLog("Sending bytes to proxmark failed - offline");
|
||||
return;
|
||||
}
|
||||
/**
|
||||
/**
|
||||
The while-loop below causes hangups at times, when the pm3 unit is unresponsive
|
||||
or disconnected. The main console thread is alive, but comm thread just spins here.
|
||||
Not good.../holiman
|
||||
|
@ -68,30 +68,30 @@ static void *uart_receiver(void *targ) {
|
|||
struct receiver_arg *arg = (struct receiver_arg*)targ;
|
||||
size_t rxlen;
|
||||
size_t cmd_count;
|
||||
|
||||
|
||||
while (arg->run) {
|
||||
rxlen = sizeof(UsbCommand);
|
||||
if (uart_receive(sp,prx,&rxlen)) {
|
||||
if (uart_receive(sp, prx, &rxlen)) {
|
||||
prx += rxlen;
|
||||
if (((prx-rx) % sizeof(UsbCommand)) != 0) {
|
||||
continue;
|
||||
}
|
||||
cmd_count = (prx-rx) / sizeof(UsbCommand);
|
||||
|
||||
for (size_t i=0; i<cmd_count; i++) {
|
||||
for (size_t i = 0; i < cmd_count; i++) {
|
||||
UsbCommandReceived((UsbCommand*)(rx+(i*sizeof(UsbCommand))));
|
||||
}
|
||||
}
|
||||
prx = rx;
|
||||
|
||||
|
||||
if(txcmd_pending) {
|
||||
if (!uart_send(sp,(byte_t*)&txcmd,sizeof(UsbCommand))) {
|
||||
if (!uart_send(sp, (byte_t*) &txcmd, sizeof(UsbCommand))) {
|
||||
PrintAndLog("Sending bytes to proxmark failed");
|
||||
}
|
||||
txcmd_pending = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pthread_exit(NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -103,13 +103,13 @@ static void *main_loop(void *targ) {
|
|||
pthread_t reader_thread;
|
||||
|
||||
if (arg->usb_present == 1) {
|
||||
rarg.run=1;
|
||||
rarg.run = 1;
|
||||
pthread_create(&reader_thread, NULL, &uart_receiver, &rarg);
|
||||
}
|
||||
|
||||
|
||||
FILE *script_file = NULL;
|
||||
char script_cmd_buf[256]; // iceman, needs lua script the same file_path_buffer as the rest
|
||||
|
||||
char script_cmd_buf[256]; // iceman, needs lua script the same file_path_buffer as the rest
|
||||
|
||||
if (arg->script_cmds_file) {
|
||||
script_file = fopen(arg->script_cmds_file, "r");
|
||||
if (script_file) {
|
||||
|
@ -134,7 +134,7 @@ static void *main_loop(void *targ) {
|
|||
|
||||
nl = strrchr(script_cmd_buf, '\n');
|
||||
if (nl) *nl = '\0';
|
||||
|
||||
|
||||
if ((cmd = (char*) malloc(strlen(script_cmd_buf) + 1)) != NULL) {
|
||||
memset(cmd, 0, strlen(script_cmd_buf));
|
||||
strcpy(cmd, script_cmd_buf);
|
||||
|
@ -173,12 +173,12 @@ static void *main_loop(void *targ) {
|
|||
rarg.run = 0;
|
||||
pthread_join(reader_thread, NULL);
|
||||
}
|
||||
|
||||
|
||||
if (script_file) {
|
||||
fclose(script_file);
|
||||
script_file = NULL;
|
||||
}
|
||||
|
||||
|
||||
ExitGraphics();
|
||||
pthread_exit(NULL);
|
||||
return NULL;
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
#include "util.h"
|
||||
#include "nonce2key/nonce2key.h"
|
||||
#include "../common/iso15693tools.h"
|
||||
#include <openssl/aes.h>
|
||||
#include "../common/crc16.h"
|
||||
#include "aes.h"
|
||||
/**
|
||||
* The following params expected:
|
||||
* UsbCommand c
|
||||
|
@ -240,10 +240,10 @@ static int l_aes(lua_State *L)
|
|||
|
||||
const char *p_encTxt = luaL_checklstring(L, 2, &size);
|
||||
|
||||
unsigned char indata[AES_BLOCK_SIZE] = {0x00};
|
||||
unsigned char outdata[AES_BLOCK_SIZE] = {0x00};
|
||||
unsigned char aes_key[AES_BLOCK_SIZE] = {0x00};
|
||||
unsigned char iv[AES_BLOCK_SIZE] = {0x00};
|
||||
unsigned char indata[16] = {0x00};
|
||||
unsigned char outdata[16] = {0x00};
|
||||
unsigned char aes_key[16] = {0x00};
|
||||
unsigned char iv[16] = {0x00};
|
||||
|
||||
// convert key to bytearray
|
||||
for (i = 0; i < 32; i += 2) {
|
||||
|
@ -255,10 +255,14 @@ static int l_aes(lua_State *L)
|
|||
sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]);
|
||||
}
|
||||
|
||||
AES_KEY key;
|
||||
AES_set_decrypt_key(aes_key, 128, &key);
|
||||
AES_cbc_encrypt(indata, outdata, sizeof(indata), &key, iv, AES_DECRYPT);
|
||||
//AES_KEY key;
|
||||
//AES_set_decrypt_key(aes_key, 128, &key);
|
||||
//AES_cbc_encrypt(indata, outdata, sizeof(indata), &key, iv, AES_DECRYPT);
|
||||
|
||||
aes_context ctx;
|
||||
aes_init(&ctx);
|
||||
aes_setkey_enc(&ctx,(const unsigned char *)p_key,128);
|
||||
aes_crypt_cbc(&ctx,AES_DECRYPT,sizeof(indata), iv, indata,outdata );
|
||||
//Push decrypted array as a string
|
||||
lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
|
||||
return 1;// return 1 to signal one return value
|
||||
|
|
63
client/scripts/remagic.lua
Normal file
63
client/scripts/remagic.lua
Normal file
|
@ -0,0 +1,63 @@
|
|||
local getopt = require('getopt')
|
||||
|
||||
example = "script run remagic"
|
||||
author = "Iceman"
|
||||
|
||||
desc =
|
||||
[[
|
||||
This is a script that tries to bring back a chinese magic card (1k generation1)
|
||||
from the dead when it's block 0 has been written with bad values.
|
||||
|
||||
Arguments:
|
||||
-h this help
|
||||
]]
|
||||
---
|
||||
-- A debug printout-function
|
||||
function dbg(args)
|
||||
if DEBUG then
|
||||
print("###", args)
|
||||
end
|
||||
end
|
||||
---
|
||||
-- This is only meant to be used when errors occur
|
||||
function oops(err)
|
||||
print("ERROR: ",err)
|
||||
end
|
||||
|
||||
---
|
||||
-- Usage help
|
||||
function help()
|
||||
print(desc)
|
||||
print("Example usage")
|
||||
print(example)
|
||||
end
|
||||
|
||||
---
|
||||
-- The main entry point
|
||||
function main(args)
|
||||
|
||||
|
||||
-- Read the parameters
|
||||
for o, a in getopt.getopt(args, 'h') do
|
||||
if o == "h" then help() return end
|
||||
end
|
||||
|
||||
local _cmds = {
|
||||
--[[
|
||||
--]]
|
||||
[0] = "hf 14a raw -p -a -b 7 40",
|
||||
[1] = "hf 14a raw -p -a 43",
|
||||
[2] = "hf 14a raw -c -p -a A000",
|
||||
[3] = "hf 14a raw -c -p -a 01 02 03 04 04 98 02 00 00 00 00 00 00 00 10 01",
|
||||
}
|
||||
core.clearCommandBuffer()
|
||||
|
||||
local i
|
||||
--for _,c in pairs(_cmds) do
|
||||
for i = 0, 3 do
|
||||
print ( _cmds[i] )
|
||||
core.console( _cmds[i] )
|
||||
end
|
||||
end
|
||||
|
||||
main(args)
|
|
@ -249,17 +249,18 @@ local function main(args)
|
|||
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 itemtype = block1:sub(1,4)
|
||||
local cardid = block1:sub(9,24)
|
||||
|
||||
-- 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
|
||||
print( string.rep('--',20) )
|
||||
|
|
|
@ -241,18 +241,20 @@ local function main(args)
|
|||
local cmdSetDbgOff = "hf mf dbg 0"
|
||||
core.console( cmdSetDbgOff)
|
||||
|
||||
-- Look for tag present on reader,
|
||||
result, err = lib14a.read1443a(false)
|
||||
if not result then return oops(err) end
|
||||
-- if not loadFromDump then
|
||||
-- -- Look for tag present on reader,
|
||||
-- result, err = lib14a.read1443a(false)
|
||||
-- if not result then return oops(err) end
|
||||
|
||||
core.clearCommandBuffer()
|
||||
-- core.clearCommandBuffer()
|
||||
|
||||
if 0x01 ~= result.sak then -- NXP MIFARE TNP3xxx
|
||||
return oops('This is not a TNP3xxx tag. aborting.')
|
||||
end
|
||||
-- if 0x01 ~= result.sak then -- NXP MIFARE TNP3xxx
|
||||
-- return oops('This is not a TNP3xxx tag. aborting.')
|
||||
-- end
|
||||
|
||||
-- Show tag info
|
||||
print((' Found tag : %s'):format(result.name))
|
||||
-- -- Show tag info
|
||||
-- print((' Found tag : %s'):format(result.name))
|
||||
-- end
|
||||
|
||||
-- Load dump.bin file
|
||||
print( (' Load data from %s'):format(inputTemplate))
|
||||
|
@ -349,7 +351,7 @@ local function main(args)
|
|||
err = LoadEmulator(blocks)
|
||||
if err then return oops(err) end
|
||||
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
|
||||
main(args)
|
|
@ -84,17 +84,19 @@ local function main(args)
|
|||
local files = {}
|
||||
|
||||
-- Find a set of traces staring with EM
|
||||
local p = io.popen(tracesEM)
|
||||
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 = io.popen(tracesMOD)
|
||||
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
|
||||
|
|
|
@ -69,6 +69,8 @@ INCLUDES = ../include/proxmark3.h ../include/at91sam7s512.h ../include/config_gp
|
|||
CFLAGS = -c $(INCLUDE) -Wall -Werror -pedantic -std=c99 $(APP_CFLAGS) -Os
|
||||
LDFLAGS = -nostartfiles -nodefaultlibs -Wl,-gc-sections -n
|
||||
|
||||
LIBS = -lgcc
|
||||
|
||||
LIBS = -lgcc
|
||||
|
||||
THUMBOBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(THUMBSRC))
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
#include "cmd.h"
|
||||
#include "string.h"
|
||||
#include "../include/proxmark3.h"
|
||||
#include "proxmark3.h"
|
||||
|
||||
bool cmd_receive(UsbCommand* cmd) {
|
||||
|
||||
|
|
|
@ -33,8 +33,8 @@
|
|||
#ifndef _PROXMARK_CMD_H_
|
||||
#define _PROXMARK_CMD_H_
|
||||
|
||||
#include "../include/common.h"
|
||||
#include "../include/usb_cmd.h"
|
||||
#include "common.h"
|
||||
#include "usb_cmd.h"
|
||||
#include "usb_cdc.h"
|
||||
|
||||
bool cmd_receive(UsbCommand* cmd);
|
||||
|
|
1746
common/lfdemod.c
1746
common/lfdemod.c
File diff suppressed because it is too large
Load diff
|
@ -1,10 +1,14 @@
|
|||
// Copyright (C) 2014
|
||||
// Copyright (C) 2014
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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__
|
||||
|
@ -12,14 +16,30 @@
|
|||
#include <stdint.h>
|
||||
|
||||
int DetectASKClock(uint8_t dest[], size_t size, int clock);
|
||||
int askmandemod(uint8_t *BinStream,uint32_t *BitLen,int *clk, int *invert);
|
||||
uint64_t Em410xDecode(uint8_t *BitStream,uint32_t BitLen);
|
||||
int manrawdecode(uint8_t *BitStream, int *bitLen);
|
||||
int BiphaseRawDecode(uint8_t * BitStream, int *bitLen, int offset);
|
||||
int askrawdemod(uint8_t *BinStream, int *bitLen,int *clk, int *invert);
|
||||
int HIDdemodFSK(uint8_t *dest, size_t size, uint32_t *hi2, uint32_t *hi, uint32_t *lo);
|
||||
int askmandemod(uint8_t *BinStream, size_t *size, int *clk, int *invert);
|
||||
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 BiphaseRawDecode(uint8_t * BitStream, size_t *size, int offset, 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 IOdemodFSK(uint8_t *dest, size_t size);
|
||||
int fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow);
|
||||
uint32_t bytebits_to_byte(uint8_t* src, int numbits);
|
||||
uint32_t bytebits_to_byte(uint8_t* src, size_t numbits);
|
||||
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 indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert);
|
||||
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
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
*/
|
||||
|
||||
#include "usb_cdc.h"
|
||||
#include "../include/config_gpio.h"
|
||||
#include "config_gpio.h"
|
||||
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
@ -235,31 +235,31 @@ void usb_disable() {
|
|||
//* \brief This function Activates the USB device
|
||||
//*----------------------------------------------------------------------------
|
||||
void usb_enable() {
|
||||
// Set the PLL USB Divider
|
||||
AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ;
|
||||
|
||||
// Specific Chip USB Initialisation
|
||||
// Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock
|
||||
AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;
|
||||
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP);
|
||||
|
||||
// Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO
|
||||
// Set in PIO mode and Configure in Output
|
||||
AT91C_BASE_PIOA->PIO_PER = GPIO_USB_PU; // Set in PIO mode
|
||||
// Set the PLL USB Divider
|
||||
AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ;
|
||||
|
||||
// Specific Chip USB Initialisation
|
||||
// Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock
|
||||
AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;
|
||||
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP);
|
||||
|
||||
// Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO
|
||||
// Set in PIO mode and Configure in Output
|
||||
AT91C_BASE_PIOA->PIO_PER = GPIO_USB_PU; // Set in PIO mode
|
||||
AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; // Configure as Output
|
||||
|
||||
// Clear for set the Pullup resistor
|
||||
|
||||
// Clear for set the Pullup resistor
|
||||
AT91C_BASE_PIOA->PIO_CODR = GPIO_USB_PU;
|
||||
|
||||
// Disconnect and reconnect USB controller for 100ms
|
||||
usb_disable();
|
||||
|
||||
// Wait for a short while
|
||||
for (volatile size_t i=0; i<0x100000; i++);
|
||||
|
||||
// Disconnect and reconnect USB controller for 100ms
|
||||
usb_disable();
|
||||
|
||||
// Wait for a short while
|
||||
for (volatile size_t i=0; i<0x100000; i++);
|
||||
|
||||
// Reconnect USB reconnect
|
||||
AT91C_BASE_PIOA->PIO_SODR = GPIO_USB_PU;
|
||||
AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU;
|
||||
// Reconnect USB reconnect
|
||||
AT91C_BASE_PIOA->PIO_SODR = GPIO_USB_PU;
|
||||
AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
|
@ -298,26 +298,26 @@ bool usb_poll()
|
|||
//* \brief Read available data from Endpoint OUT
|
||||
//*----------------------------------------------------------------------------
|
||||
uint32_t usb_read(byte_t* data, size_t len) {
|
||||
byte_t bank = btReceiveBank;
|
||||
byte_t bank = btReceiveBank;
|
||||
uint32_t packetSize, nbBytesRcv = 0;
|
||||
uint32_t time_out = 0;
|
||||
uint32_t time_out = 0;
|
||||
|
||||
while (len) {
|
||||
if (!usb_check()) break;
|
||||
|
||||
if ( pUdp->UDP_CSR[AT91C_EP_OUT] & bank ) {
|
||||
packetSize = MIN(pUdp->UDP_CSR[AT91C_EP_OUT] >> 16, len);
|
||||
len -= packetSize;
|
||||
len -= packetSize;
|
||||
while(packetSize--)
|
||||
data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT];
|
||||
pUdp->UDP_CSR[AT91C_EP_OUT] &= ~(bank);
|
||||
if (bank == AT91C_UDP_RX_DATA_BK0) {
|
||||
bank = AT91C_UDP_RX_DATA_BK1;
|
||||
} else {
|
||||
} else {
|
||||
bank = AT91C_UDP_RX_DATA_BK0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (time_out++ == 0x1fff) break;
|
||||
if (time_out++ == 0x1fff) break;
|
||||
}
|
||||
|
||||
btReceiveBank = bank;
|
||||
|
@ -349,7 +349,7 @@ uint32_t usb_write(const byte_t* data, const size_t len) {
|
|||
// Wait for the the first bank to be sent
|
||||
while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
|
||||
if (!usb_check()) return length;
|
||||
}
|
||||
}
|
||||
pUdp->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP);
|
||||
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);
|
||||
pUdp->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY;
|
||||
|
@ -370,7 +370,7 @@ uint32_t usb_write(const byte_t* data, const size_t len) {
|
|||
//* \fn AT91F_USB_SendData
|
||||
//* \brief Send Data through the control endpoint
|
||||
//*----------------------------------------------------------------------------
|
||||
unsigned int csrTab[100];
|
||||
unsigned int csrTab[100] = {0x00};
|
||||
unsigned char csrIdx = 0;
|
||||
|
||||
static void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) {
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#ifndef _USB_CDC_H_
|
||||
#define _USB_CDC_H_
|
||||
|
||||
#include "../include/common.h"
|
||||
#include "common.h"
|
||||
|
||||
void usb_disable();
|
||||
void usb_enable();
|
||||
|
|
BIN
fpga/fpga_hf.bit
BIN
fpga/fpga_hf.bit
Binary file not shown.
BIN
fpga/fpga_lf.bit
BIN
fpga/fpga_lf.bit
Binary file not shown.
|
@ -50,12 +50,38 @@ begin
|
|||
else if(~(| adc_d[7:5])) after_hysteresis = 1'b0;
|
||||
end
|
||||
|
||||
|
||||
// Divide 13.56 MHz by 32 to produce the SSP_CLK
|
||||
// The register is bigger to allow higher division factors of up to /128
|
||||
reg [6:0] ssp_clk_divider;
|
||||
reg [10:0] ssp_clk_divider;
|
||||
|
||||
always @(posedge adc_clk)
|
||||
ssp_clk_divider <= (ssp_clk_divider + 1);
|
||||
assign ssp_clk = ssp_clk_divider[4];
|
||||
|
||||
reg ssp_clk;
|
||||
reg ssp_frame;
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
//If we're in 101, we only need a new bit every 8th carrier bit (53Hz). Otherwise, get next bit at 424Khz
|
||||
if(mod_type == 3'b101)
|
||||
begin
|
||||
if(ssp_clk_divider[7:0] == 8'b00000000)
|
||||
ssp_clk <= 1'b0;
|
||||
if(ssp_clk_divider[7:0] == 8'b10000000)
|
||||
ssp_clk <= 1'b1;
|
||||
|
||||
end
|
||||
else
|
||||
begin
|
||||
if(ssp_clk_divider[4:0] == 5'd0)//[4:0] == 5'b00000)
|
||||
ssp_clk <= 1'b1;
|
||||
if(ssp_clk_divider[4:0] == 5'd16) //[4:0] == 5'b10000)
|
||||
ssp_clk <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
//assign ssp_clk = ssp_clk_divider[4];
|
||||
|
||||
// Divide SSP_CLK by 8 to produce the byte framing signal; the phase of
|
||||
// this is arbitrary, because it's just a bitstream.
|
||||
|
@ -69,12 +95,13 @@ reg [2:0] ssp_frame_divider_from_arm;
|
|||
always @(negedge ssp_clk)
|
||||
ssp_frame_divider_from_arm <= (ssp_frame_divider_from_arm + 1);
|
||||
|
||||
reg ssp_frame;
|
||||
|
||||
|
||||
always @(ssp_frame_divider_to_arm or ssp_frame_divider_from_arm or mod_type)
|
||||
if(mod_type == 3'b000) // not modulating, so listening, to ARM
|
||||
ssp_frame = (ssp_frame_divider_to_arm == 3'b000);
|
||||
else
|
||||
ssp_frame = (ssp_frame_divider_from_arm == 3'b000);
|
||||
ssp_frame = (ssp_frame_divider_from_arm == 3'b000);
|
||||
|
||||
// Synchronize up the after-hysteresis signal, to produce DIN.
|
||||
reg ssp_din;
|
||||
|
@ -90,7 +117,7 @@ always @(mod_type or ssp_clk or ssp_dout)
|
|||
modulating_carrier <= ssp_dout ^ ssp_clk_divider[3]; // XOR means BPSK
|
||||
else if(mod_type == 3'b010)
|
||||
modulating_carrier <= ssp_dout & ssp_clk_divider[5]; // switch 212kHz subcarrier on/off
|
||||
else if(mod_type == 3'b100)
|
||||
else if(mod_type == 3'b100 || mod_type == 3'b101)
|
||||
modulating_carrier <= ssp_dout & ssp_clk_divider[4]; // switch 424kHz modulation on/off
|
||||
else
|
||||
modulating_carrier <= 1'b0; // yet unused
|
||||
|
@ -106,7 +133,7 @@ assign pwr_oe4 = modulating_carrier;
|
|||
// This one is always on, so that we can watch the carrier.
|
||||
assign pwr_oe3 = 1'b0;
|
||||
|
||||
assign dbg = after_hysteresis;
|
||||
assign dbg = modulating_carrier;
|
||||
//reg dbg;
|
||||
//always @(ssp_dout)
|
||||
// dbg <= ssp_dout;
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
typedef enum {
|
||||
RHT2F_PASSWORD = 21,
|
||||
RHT2F_AUTHENTICATE = 22,
|
||||
RHT2F_CRYPTO = 23,
|
||||
RHT2F_TEST_AUTH_ATTEMPTS = 25,
|
||||
RHT2F_CRYPTO = 23,
|
||||
RHT2F_TEST_AUTH_ATTEMPTS = 25,
|
||||
} hitag_function;
|
||||
|
||||
typedef struct {
|
||||
|
@ -33,7 +33,7 @@ typedef struct {
|
|||
typedef union {
|
||||
rht2d_password pwd;
|
||||
rht2d_authenticate auth;
|
||||
rht2d_crypto crypto;
|
||||
rht2d_crypto crypto;
|
||||
} hitag_data;
|
||||
|
||||
#endif
|
||||
|
|
16000
traces/ATA5577-HIDemu-FC1-C9.pm3
Normal file
16000
traces/ATA5577-HIDemu-FC1-C9.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/AWID-15-259.pm3
Normal file
20000
traces/AWID-15-259.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/HID-weak-fob-11647.pm3
Normal file
20000
traces/HID-weak-fob-11647.pm3
Normal file
File diff suppressed because it is too large
Load diff
16000
traces/Paradox-96_40426-APJN08.pm3
Normal file
16000
traces/Paradox-96_40426-APJN08.pm3
Normal file
File diff suppressed because it is too large
Load diff
|
@ -15,3 +15,12 @@ Transit999-best.pm3: Transit 999 format (UID 99531670)
|
|||
The files 'modulation-'... are all encoded with identical data (hex 00 01 02 03 04 05 06 07 08 09 0A 0B)
|
||||
for the purpose of recognition and testing of demodulation schemes. They were created by writing Q5 tags
|
||||
appropriately configured. The raw data is in 'modulation-data.dat'.
|
||||
|
||||
ata5577-HIDemu-FC1-C9.pm3: ata5577 in hid prox 26 bit emulation facility code:1 card#:9
|
||||
casi-12ed825c29.pm3: casi rusco 40 bit (EM410x ID: 12ed825c29)
|
||||
EM4102-Fob.pm3: (ID: 0400193cbe)
|
||||
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
|
||||
indala-504278295.pm3: PSK 26 bit indala
|
||||
AWID-15-259.pm3: AWID FSK RF/50 FC: 15 Card: 259
|
||||
HID-weak-fob-11647.pm3: HID 32bit Prox Card#: 11647. very weak tag/read but just readable.
|
20000
traces/modulation-ask-biph-50.pm3
Normal file
20000
traces/modulation-ask-biph-50.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-ask-man-100.pm3
Normal file
20000
traces/modulation-ask-man-100.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-ask-man-128.pm3
Normal file
20000
traces/modulation-ask-man-128.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-ask-man-16.pm3
Normal file
20000
traces/modulation-ask-man-16.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-ask-man-32.pm3
Normal file
20000
traces/modulation-ask-man-32.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-ask-man-40.pm3
Normal file
20000
traces/modulation-ask-man-40.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-ask-man-8.pm3
Normal file
20000
traces/modulation-ask-man-8.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-direct-32.pm3
Normal file
20000
traces/modulation-direct-32.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-direct-40.pm3
Normal file
20000
traces/modulation-direct-40.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-direct-50.pm3
Normal file
20000
traces/modulation-direct-50.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-fsk1-50.pm3
Normal file
20000
traces/modulation-fsk1-50.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-fsk1a-50.pm3
Normal file
20000
traces/modulation-fsk1a-50.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-fsk2-50.pm3
Normal file
20000
traces/modulation-fsk2-50.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-fsk2a-40.pm3
Normal file
20000
traces/modulation-fsk2a-40.pm3
Normal file
File diff suppressed because it is too large
Load diff
20000
traces/modulation-fsk2a-50.pm3
Normal file
20000
traces/modulation-fsk2a-50.pm3
Normal file
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue