make style

This commit is contained in:
Philippe Teuwen 2019-03-10 00:00:59 +01:00
parent 0d9223a547
commit 0373696662
483 changed files with 56514 additions and 52451 deletions

View file

@ -90,6 +90,11 @@ print-%: ; @echo $* = $($*)
style:
find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" \) -exec perl -pi -e 's/[ \t\r]+$$//' {} \;
find . \( -name "*.[ch]" -or -name "*.cpp" \) -exec astyle --formatted --mode=c --suffix=none \
--indent=spaces=4 --indent-switches --indent-preprocessor \
--keep-one-line-blocks --max-instatement-indent=60 \
--style=linux --pad-oper --unpad-paren --pad-header \
--align-pointer=name {} \;
# Dummy target to test for GNU make availability
_test:

View file

@ -13,7 +13,7 @@
// 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)];
static uint32_t BigBuf[BIGBUF_SIZE / sizeof(uint32_t)];
/* BigBuf memory layout:
Pointer to highest available memory: BigBuf_hi
@ -34,12 +34,14 @@ static uint32_t traceLen = 0;
static bool tracing = true; //todo static?
// get the address of BigBuf
uint8_t *BigBuf_get_addr(void) {
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) {
uint8_t *BigBuf_get_EM_addr(void)
{
// not yet allocated
if (emulator_memory == NULL)
emulator_memory = BigBuf_malloc(CARD_MEMORY_SIZE);
@ -48,28 +50,33 @@ uint8_t *BigBuf_get_EM_addr(void) {
}
// clear ALL of BigBuf
void BigBuf_Clear(void) {
void BigBuf_Clear(void)
{
BigBuf_Clear_ext(true);
}
// clear ALL of BigBuf
void BigBuf_Clear_ext(bool verbose) {
void BigBuf_Clear_ext(bool verbose)
{
memset(BigBuf, 0, BIGBUF_SIZE);
if (verbose)
Dbprintf("Buffer cleared (%i bytes)", BIGBUF_SIZE);
}
void BigBuf_Clear_EM(void) {
void BigBuf_Clear_EM(void)
{
memset(BigBuf_get_EM_addr(), 0, CARD_MEMORY_SIZE);
}
void BigBuf_Clear_keep_EM(void) {
void BigBuf_Clear_keep_EM(void)
{
memset(BigBuf, 0, BigBuf_hi);
}
// 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) {
uint8_t *BigBuf_malloc(uint16_t chunksize)
{
if (BigBuf_hi - chunksize < 0)
return NULL; // no memory left
@ -79,14 +86,16 @@ uint8_t *BigBuf_malloc(uint16_t chunksize) {
}
// free ALL allocated chunks. The whole BigBuf is available for traces or samples again.
void BigBuf_free(void){
void BigBuf_free(void)
{
BigBuf_hi = BIGBUF_SIZE;
emulator_memory = NULL;
// shouldn't this empty BigBuf also?
}
// free allocated chunks EXCEPT the emulator memory
void BigBuf_free_keep_EM(void) {
void BigBuf_free_keep_EM(void)
{
if (emulator_memory != NULL)
BigBuf_hi = emulator_memory - (uint8_t *)BigBuf;
else
@ -95,7 +104,8 @@ void BigBuf_free_keep_EM(void) {
// shouldn't this empty BigBuf also?
}
void BigBuf_print_status(void) {
void BigBuf_print_status(void)
{
Dbprintf("Memory");
Dbprintf(" BIGBUF_SIZE.............%d", BIGBUF_SIZE);
Dbprintf(" Available memory........%d", BigBuf_hi);
@ -105,21 +115,26 @@ void BigBuf_print_status(void) {
}
// return the maximum trace length (i.e. the unallocated size of BigBuf)
uint16_t BigBuf_max_traceLen(void) {
uint16_t BigBuf_max_traceLen(void)
{
return BigBuf_hi;
}
void clear_trace(void) {
void clear_trace(void)
{
traceLen = 0;
}
void set_tracelen(uint32_t value) {
void set_tracelen(uint32_t value)
{
traceLen = value;
}
void set_tracing(bool enable) {
void set_tracing(bool enable)
{
tracing = enable;
}
bool get_tracing(void) {
bool get_tracing(void)
{
return tracing;
}
@ -127,7 +142,8 @@ bool get_tracing(void) {
* Get the number of bytes traced
* @return
*/
uint32_t BigBuf_get_traceLen(void) {
uint32_t BigBuf_get_traceLen(void)
{
return traceLen;
}
@ -137,12 +153,13 @@ uint32_t BigBuf_get_traceLen(void) {
by 'hf list raw', alternatively 'hf list <proto>' for protocol-specific
annotation of commands/responses.
**/
bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag) {
bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag)
{
if (!tracing) return false;
uint8_t *trace = BigBuf_get_addr();
uint32_t num_paritybytes = (iLen-1)/8 + 1; // number of valid paritybytes in *parity
uint32_t num_paritybytes = (iLen - 1) / 8 + 1; // number of valid paritybytes in *parity
uint32_t duration = timestamp_end - timestamp_start;
// Return when trace is full
@ -195,7 +212,8 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_
return true;
}
int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int readerToTag) {
int LogTraceHitag(const uint8_t *btBytes, int iBits, int iSamples, uint32_t dwParity, int readerToTag)
{
/**
Todo, rewrite the logger to use the generic functionality instead. It should be noted, however,
that this logger takes number of bits as argument, not number of bytes.
@ -237,10 +255,11 @@ int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwP
}
// Emulator memory
uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length){
uint8_t* mem = BigBuf_get_EM_addr();
uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length)
{
uint8_t *mem = BigBuf_get_EM_addr();
if (offset + length < CARD_MEMORY_SIZE) {
memcpy(mem+offset, data, length);
memcpy(mem + offset, data, length);
return 0;
}
Dbprintf("Error, trying to set memory outside of bounds! %d > %d", (offset + length), CARD_MEMORY_SIZE);

View file

@ -42,6 +42,6 @@ extern void set_tracing(bool enable);
extern void set_tracelen(uint32_t value);
extern bool get_tracing(void);
extern bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag);
extern int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int bReader);
extern int LogTraceHitag(const uint8_t *btBytes, int iBits, int iSamples, uint32_t dwParity, int bReader);
extern uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length);
#endif /* __BIGBUF_H */

View file

@ -13,7 +13,7 @@ void LCDSend(unsigned int data)
while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); // wait for the transfer to complete
// For clarity's sake we pass data with 9th bit clear and commands with 9th
// bit set since they're implemented as defines, se we need to invert bit
AT91C_BASE_SPI->SPI_TDR = data^0x100; // Send the data/command
AT91C_BASE_SPI->SPI_TDR = data ^ 0x100; // Send the data/command
}
void LCDSetXY(unsigned char x, unsigned char y)
@ -29,29 +29,28 @@ void LCDSetXY(unsigned char x, unsigned char y)
void LCDSetPixel(unsigned char x, unsigned char y, unsigned char color)
{
LCDSetXY(x,y); // Set position
LCDSetXY(x, y); // Set position
LCDSend(PRAMWR); // Now write the pixel to the display
LCDSend(color); // Write the data in the specified Color
}
void LCDFill (unsigned char xs,unsigned char ys,unsigned char width,unsigned char height, unsigned char color)
void LCDFill(unsigned char xs, unsigned char ys, unsigned char width, unsigned char height, unsigned char color)
{
unsigned char i,j;
unsigned char i, j;
for (i=0;i < height;i++) // Number of horizontal lines
{
LCDSetXY(xs,ys+i); // Goto start of fill area (Top Left)
for (i = 0; i < height; i++) { // Number of horizontal lines
LCDSetXY(xs, ys + i); // Goto start of fill area (Top Left)
LCDSend(PRAMWR); // Write to display
for (j=0;j < width;j++) // pixels per line
for (j = 0; j < width; j++) // pixels per line
LCDSend(color);
}
}
void LCDString (char *lcd_string, const char *font_style,unsigned char x, unsigned char y, unsigned char fcolor, unsigned char bcolor)
void LCDString(char *lcd_string, const char *font_style, unsigned char x, unsigned char y, unsigned char fcolor, unsigned char bcolor)
{
unsigned int i;
unsigned char mask=0, px, py, xme, yme, offset;
unsigned char mask = 0, px, py, xme, yme, offset;
const char *data;
data = font_style; // point to the start of the font table
@ -62,29 +61,28 @@ void LCDString (char *lcd_string, const char *font_style,unsigned char x, unsign
data++;
offset = *data; // get data bytes per font
do
{
do {
// point to data in table to be loaded
data = (font_style + offset) + (offset * (int)(*lcd_string - 32));
for (i=0;i < yme;i++) {
mask |=0x80;
for (i = 0; i < yme; i++) {
mask |= 0x80;
for (px=x; px < (x + xme); px++) {
py= y + i;
for (px = x; px < (x + xme); px++) {
py = y + i;
if (*data & mask) LCDSetPixel (px,py,fcolor);
else LCDSetPixel (px,py,bcolor);
if (*data & mask) LCDSetPixel(px, py, fcolor);
else LCDSetPixel(px, py, bcolor);
mask>>=1;
mask >>= 1;
}
data++;
}
x+=xme;
x += xme;
lcd_string++; // next character in string
} while(*lcd_string !='\0'); // keep spitting chars out until end of string
} while (*lcd_string != '\0'); // keep spitting chars out until end of string
}
void LCDReset(void)
@ -121,29 +119,29 @@ void LCDInit(void)
LCDSend(0xDC);
// clear display
LCDSetXY(0,0);
LCDSetXY(0, 0);
LCDSend(PRAMWR); // Write to display
i=LCD_XRES*LCD_YRES;
while(i--) LCDSend(WHITE);
i = LCD_XRES * LCD_YRES;
while (i--) LCDSend(WHITE);
// test text on different colored backgrounds
LCDString(" The quick brown fox ", (char *)&FONT6x8,1,1+8*0,WHITE ,BLACK );
LCDString(" jumped over the ", (char *)&FONT6x8,1,1+8*1,BLACK ,WHITE );
LCDString(" lazy dog. ", (char *)&FONT6x8,1,1+8*2,YELLOW ,RED );
LCDString(" AaBbCcDdEeFfGgHhIiJj ", (char *)&FONT6x8,1,1+8*3,RED ,GREEN );
LCDString(" KkLlMmNnOoPpQqRrSsTt ", (char *)&FONT6x8,1,1+8*4,MAGENTA,BLUE );
LCDString("UuVvWwXxYyZz0123456789", (char *)&FONT6x8,1,1+8*5,BLUE ,YELLOW);
LCDString("`-=[]_;',./~!@#$%^&*()", (char *)&FONT6x8,1,1+8*6,BLACK ,CYAN );
LCDString(" _+{}|:\\\"<>? ", (char *)&FONT6x8,1,1+8*7,BLUE ,MAGENTA);
LCDString(" The quick brown fox ", (char *)&FONT6x8, 1, 1 + 8 * 0, WHITE, BLACK);
LCDString(" jumped over the ", (char *)&FONT6x8, 1, 1 + 8 * 1, BLACK, WHITE);
LCDString(" lazy dog. ", (char *)&FONT6x8, 1, 1 + 8 * 2, YELLOW, RED);
LCDString(" AaBbCcDdEeFfGgHhIiJj ", (char *)&FONT6x8, 1, 1 + 8 * 3, RED, GREEN);
LCDString(" KkLlMmNnOoPpQqRrSsTt ", (char *)&FONT6x8, 1, 1 + 8 * 4, MAGENTA, BLUE);
LCDString("UuVvWwXxYyZz0123456789", (char *)&FONT6x8, 1, 1 + 8 * 5, BLUE, YELLOW);
LCDString("`-=[]_;',./~!@#$%^&*()", (char *)&FONT6x8, 1, 1 + 8 * 6, BLACK, CYAN);
LCDString(" _+{}|:\\\"<>? ", (char *)&FONT6x8, 1, 1 + 8 * 7, BLUE, MAGENTA);
// color bands
LCDFill(0, 1+8* 8, 132, 8, BLACK);
LCDFill(0, 1+8* 9, 132, 8, WHITE);
LCDFill(0, 1+8*10, 132, 8, RED);
LCDFill(0, 1+8*11, 132, 8, GREEN);
LCDFill(0, 1+8*12, 132, 8, BLUE);
LCDFill(0, 1+8*13, 132, 8, YELLOW);
LCDFill(0, 1+8*14, 132, 8, CYAN);
LCDFill(0, 1+8*15, 132, 8, MAGENTA);
LCDFill(0, 1 + 8 * 8, 132, 8, BLACK);
LCDFill(0, 1 + 8 * 9, 132, 8, WHITE);
LCDFill(0, 1 + 8 * 10, 132, 8, RED);
LCDFill(0, 1 + 8 * 11, 132, 8, GREEN);
LCDFill(0, 1 + 8 * 12, 132, 8, BLUE);
LCDFill(0, 1 + 8 * 13, 132, 8, YELLOW);
LCDFill(0, 1 + 8 * 14, 132, 8, CYAN);
LCDFill(0, 1 + 8 * 15, 132, 8, MAGENTA);
}

View file

@ -124,7 +124,7 @@ void LCDInit(void);
void LCDReset(void);
void LCDSetXY(unsigned char x, unsigned char y);
void LCDSetPixel(unsigned char x, unsigned char y, unsigned char color);
void LCDString (char *lcd_string, const char *font_style,unsigned char x, unsigned char y, unsigned char fcolor, unsigned char bcolor);
void LCDFill (unsigned char xs,unsigned char ys,unsigned char width,unsigned char height, unsigned char color);
void LCDString(char *lcd_string, const char *font_style, unsigned char x, unsigned char y, unsigned char fcolor, unsigned char bcolor);
void LCDFill(unsigned char xs, unsigned char ys, unsigned char width, unsigned char height, unsigned char color);
#endif

View file

@ -27,13 +27,13 @@ from the client to view the stored quadlets.
// Maximum number of auth attempts per standalone session
#define MAX_PWDS_PER_SESSION 64
uint8_t FindOffsetInFlash() {
uint8_t FindOffsetInFlash()
{
uint8_t mem[4] = { 0x00, 0x00, 0x00, 0x00 };
uint8_t eom[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
uint8_t memcnt = 0;
while (memcnt < 0xFF)
{
while (memcnt < 0xFF) {
Flash_ReadData(memcnt, mem, 4);
if (memcmp(mem, eom, 4) == 0) {
return memcnt;
@ -44,14 +44,15 @@ uint8_t FindOffsetInFlash() {
return 0; // wrap-around
}
void EraseMemory() {
if (!FlashInit()){
void EraseMemory()
{
if (!FlashInit()) {
return;
}
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase4k(0,0);
Flash_Erase4k(0, 0);
if (MF_DBGLEVEL > 1) Dbprintf("[!] Erased flash!");
FlashStop();
@ -59,13 +60,15 @@ void EraseMemory() {
}
// This is actually copied from SniffIso14443a
void RAMFUNC SniffAndStore(uint8_t param) {
void RAMFUNC SniffAndStore(uint8_t param)
{
iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER);
// Allocate memory from BigBuf for some buffers
// free all previous allocations first
BigBuf_free(); BigBuf_Clear_ext(false);
BigBuf_free();
BigBuf_Clear_ext(false);
clear_trace();
set_tracing(true);
@ -96,13 +99,13 @@ void RAMFUNC SniffAndStore(uint8_t param) {
UartInit(receivedCmd, receivedCmdPar);
// Setup and start DMA.
if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, DMA_BUFFER_SIZE) ){
if (!FpgaSetupSscDma((uint8_t *) dmaBuf, DMA_BUFFER_SIZE)) {
if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting");
return;
}
tUart* uart = GetUart();
tDemod* demod = GetDemod();
tUart *uart = GetUart();
tDemod *demod = GetDemod();
// 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
@ -155,7 +158,7 @@ void RAMFUNC SniffAndStore(uint8_t param) {
if (!TagIsActive) { // no need to try decoding reader data if the tag is sending
uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4);
if (MillerDecoding(readerdata, (rsamples-1)*4)) {
if (MillerDecoding(readerdata, (rsamples - 1) * 4)) {
LED_C_ON();
// check - if there is a short 7bit request from reader
@ -166,14 +169,14 @@ void RAMFUNC SniffAndStore(uint8_t param) {
if (MF_DBGLEVEL > 1) Dbprintf("PWD-AUTH KEY: 0x%02x%02x%02x%02x", receivedCmd[1], receivedCmd[2], receivedCmd[3], receivedCmd[4]);
// temporarily save the captured pwd in our array
memcpy(&capturedPwds[4 * auth_attempts], receivedCmd+1, 4);
memcpy(&capturedPwds[4 * auth_attempts], receivedCmd + 1, 4);
auth_attempts++;
}
if (!LogTrace(receivedCmd,
uart->len,
uart->startTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
uart->endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
uart->startTime * 16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
uart->endTime * 16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
uart->parity,
true)) break;
}
@ -190,13 +193,13 @@ void RAMFUNC SniffAndStore(uint8_t param) {
// no need to try decoding tag data if the reader is sending - and we cannot afford the time
if (!ReaderIsActive) {
uint8_t tagdata = (previous_data << 4) | (*data & 0x0F);
if (ManchesterDecoding(tagdata, 0, (rsamples-1)*4)) {
if (ManchesterDecoding(tagdata, 0, (rsamples - 1) * 4)) {
LED_B_ON();
if (!LogTrace(receivedResp,
demod->len,
demod->startTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
demod->endTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
demod->startTime * 16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
demod->endTime * 16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
demod->parity,
false)) break;
@ -239,8 +242,7 @@ void RAMFUNC SniffAndStore(uint8_t param) {
uint8_t memoffset = FindOffsetInFlash();
if (MF_DBGLEVEL > 1) Dbprintf("[!] Memory offset = %u", memoffset);
if ((memoffset + 4 * auth_attempts) > 0xFF)
{
if ((memoffset + 4 * auth_attempts) > 0xFF) {
// We opt to keep the new data only
memoffset = 0;
if (MF_DBGLEVEL > 1) Dbprintf("[!] Size of total data > 256 bytes. Discarding the old data.");
@ -248,8 +250,7 @@ void RAMFUNC SniffAndStore(uint8_t param) {
// Get previous data from flash mem
uint8_t *previousdata = BigBuf_malloc(memoffset);
if (memoffset > 0)
{
if (memoffset > 0) {
uint16_t readlen = Flash_ReadData(0, previousdata, memoffset);
if (MF_DBGLEVEL > 1) Dbprintf("[!] Read %u bytes from flash mem", readlen);
}
@ -283,7 +284,8 @@ void RAMFUNC SniffAndStore(uint8_t param) {
}
}
void RunMod() {
void RunMod()
{
StandAloneMode();

View file

@ -112,16 +112,12 @@ void ReadLastTagFromFlash()
uint32_t end_time;
uint32_t start_time = end_time = GetTickCount();
for (size_t i = 0; i < len; i += size)
{
for (size_t i = 0; i < len; i += size) {
len = MIN((len - i), size);
isok = Flash_ReadDataCont(startidx + i, mem, len);
if (isok == len)
{
if (isok == len) {
emlSetMem(mem, 0, 64);
}
else
{
} else {
DbprintfEx(FLAG_NOLOG, "FlashMem reading failed | %d | %d", len, isok);
cjSetCursLeft();
FlashStop();
@ -153,24 +149,23 @@ void WriteTagToFlash(uint8_t index, size_t size)
uint32_t bytes_sent = 0;
uint32_t bytes_remaining = len;
uint8_t data[(size * (16 * 64))/1024];
uint8_t data[(size * (16 * 64)) / 1024];
uint8_t buff[PAGESIZE];
emlGetMem(data, 0, (size * 64)/1024);
emlGetMem(data, 0, (size * 64) / 1024);
if (!FlashInit()){
if (!FlashInit()) {
return;
}
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase4k(0,0);
Flash_Erase4k(0, 0);
uint32_t end_time;
uint32_t start_time = end_time = GetTickCount();
while (bytes_remaining > 0)
{
while (bytes_remaining > 0) {
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
@ -184,8 +179,7 @@ void WriteTagToFlash(uint8_t index, size_t size)
isok = (res == bytes_in_packet) ? 1 : 0;
if (!isok)
{
if (!isok) {
DbprintfEx(FLAG_NOLOG, "FlashMem write FAILEd [offset %u]", bytes_sent);
cjSetCursLeft();
SpinOff(100);
@ -223,40 +217,40 @@ void RunMod()
uint8_t *keyBlock = NULL; // Where the keys will be held in memory.
/* VIGIK EXPIRED DUMP FOR STUDY
Sector 0
121C7F730208040001FA33F5CB2D021D
44001049164916491649000000000000
00000000000000000000000000000000
A0A1A2A3A4A579678800010203040506
Sector 1
0F000000000000000000000000000000
AA0700002102080000740C110600AF13
000000000000000001740C1108220000
314B4947495679678800010203040506
Sector 2
24E572B923A3D243B402D60CAB576956
216D6501FC8618B6C426762511AC2DEE
25BF4CEC3618D0BAB3A6E9210D887746
314B4947495679678800010203040506
Sector 3
0FBC41A5D95398E76A1B2029E8EA9735
088BA2CE732653D0C1147596AFCF94D7
77B4D91F0442182273A29DEAF7A2D095
314B4947495679678800010203040506
Sector 4
4CEE715866E508CDBC95C640EC9D1E58
E800457CF8B079414E1B45DD3E6C9317
77B4D91F0442182273A29DEAF7A2D095
314B4947495679678800010203040506
010203040506 0
Sector 5-0F
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
FFFFFFFFFFFFFF078069FFFFFFFFFFFF
KEY A : 1KGIV ;
ACCBITS : 796788[00]+VALUE
*/
Sector 0
121C7F730208040001FA33F5CB2D021D
44001049164916491649000000000000
00000000000000000000000000000000
A0A1A2A3A4A579678800010203040506
Sector 1
0F000000000000000000000000000000
AA0700002102080000740C110600AF13
000000000000000001740C1108220000
314B4947495679678800010203040506
Sector 2
24E572B923A3D243B402D60CAB576956
216D6501FC8618B6C426762511AC2DEE
25BF4CEC3618D0BAB3A6E9210D887746
314B4947495679678800010203040506
Sector 3
0FBC41A5D95398E76A1B2029E8EA9735
088BA2CE732653D0C1147596AFCF94D7
77B4D91F0442182273A29DEAF7A2D095
314B4947495679678800010203040506
Sector 4
4CEE715866E508CDBC95C640EC9D1E58
E800457CF8B079414E1B45DD3E6C9317
77B4D91F0442182273A29DEAF7A2D095
314B4947495679678800010203040506
010203040506 0
Sector 5-0F
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
FFFFFFFFFFFFFF078069FFFFFFFFFFFF
KEY A : 1KGIV ;
ACCBITS : 796788[00]+VALUE
*/
//----------------------------
// Set of keys to be used.
@ -310,8 +304,7 @@ ACCBITS : 796788[00]+VALUE
keyBlock = BigBuf_malloc(STKEYS * 6);
int mfKeysCnt = sizeof(mfKeys) / sizeof(uint64_t);
for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++)
{
for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) {
num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t *)(keyBlock + mfKeyCounter * 6));
}
@ -319,10 +312,8 @@ ACCBITS : 796788[00]+VALUE
// and why not a simple memset abuse to 0xffize the whole space in one go ?
// uint8_t foundKey[2][40][6]; //= [ {0xff} ]; /* C99 abusal 6.7.8.21
uint8_t foundKey[2][40][6];
for (uint16_t t = 0; t < 2; t++)
{
for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++)
{
for (uint16_t t = 0; t < 2; t++) {
for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) {
foundKey[t][sectorNo][0] = 0xFF;
foundKey[t][sectorNo][1] = 0xFF;
foundKey[t][sectorNo][2] = 0xFF;
@ -363,18 +354,15 @@ failtag:
LED_A_ON();
uint8_t ticker = 0;
//while (!BUTTON_PRESS() && !iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true))
while (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true))
{
while (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) {
WDT_HIT();
ticker++;
if (ticker % 64 == 0)
{
if (ticker % 64 == 0) {
LED_A_INV();
}
if (BUTTON_HELD(10) > 0)
{
if (BUTTON_HELD(10) > 0) {
WDT_HIT();
DbprintfEx(FLAG_NOLOG, "\t\t\t[ READING FLASH ]");
ReadLastTagFromFlash();
@ -393,8 +381,7 @@ failtag:
DbprintfEx(FLAG_NOLOG, "\t%sGOT TAG :%s %08x%s", _RED_, _CYAN_, cjcuid, _WHITE_);
if (cjcuid == 0)
{
if (cjcuid == 0) {
cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, "%s>>%s BUG: 0000_CJCUID! Retrying...", _RED_, _WHITE_);
SpinErr(0, 100, 8);
@ -441,29 +428,22 @@ failtag:
// also we could avoid first UID check for every block
// then lets expose this “optimal case” of “well known vigik schemes” :
for (uint8_t type = 0; type < 2 && !err && !trapped; type++)
{
for (int sec = 0; sec < sectorsCnt && !err && !trapped; ++sec)
{
for (uint8_t type = 0; type < 2 && !err && !trapped; type++) {
for (int sec = 0; sec < sectorsCnt && !err && !trapped; ++sec) {
key = cjat91_saMifareChkKeys(sec * 4, type, NULL, size, &keyBlock[0], &key64);
if (key == -1)
{
if (key == -1) {
err = 1;
allKeysFound = false;
// used in “portable” imlementation on microcontroller: it reports back the fail and open the standalone lock
// cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0);
break;
}
else if (key == -2)
{
} else if (key == -2) {
err = 1; // Can't select card.
allKeysFound = false;
// cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0);
break;
}
else
{
} else {
/* BRACE YOURSELF : AS LONG AS WE TRAP A KNOWN KEY, WE STOP CHECKING AND ENFORCE KNOWN SCHEMES */
// uint8_t tosendkey[13];
char tosendkey[13];
@ -471,8 +451,7 @@ failtag:
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %012" PRIx64 " ; TYP: %i", sec, key64, type);
/*cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sec, type, tosendkey, 12);*/
switch (key64)
{
switch (key64) {
/////////////////////////////////////////////////////////
// COMMON SCHEME 1 : INFINITRON/HEXACT
case 0x484558414354:
@ -493,8 +472,7 @@ failtag:
;
// Type 0 / A first
uint16_t t = 0;
for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++)
{
for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) {
num_to_bytes(0x484558414354, 6, foundKey[t][sectorNo]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
@ -640,10 +618,8 @@ failtag:
// emlClearMem();
// A very weak one...
for (uint16_t t = 0; t < 2; t++)
{
for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++)
{
for (uint16_t t = 0; t < 2; t++) {
for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) {
num_to_bytes(key64, 6, foundKey[t][sectorNo]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
@ -677,8 +653,7 @@ failtag:
DbprintfEx(FLAG_NOLOG, "%s>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%s", _GREEN_, _WHITE_);
;
t = 0;
for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++)
{
for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) {
num_to_bytes(0x414c41524f4e, 6, foundKey[t][sectorNo]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
@ -688,8 +663,7 @@ failtag:
;
}
t = 1;
for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++)
{
for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) {
num_to_bytes(0x424c41524f4e, 6, foundKey[t][sectorNo]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
@ -706,8 +680,7 @@ failtag:
}
}
if (!allKeysFound)
{
if (!allKeysFound) {
cjSetCursLeft();
cjTabulize();
DbprintfEx(FLAG_NOLOG, "%s[ FAIL ]%s\r\n->did not found all the keys :'(", _RED_, _WHITE_);
@ -720,11 +693,9 @@ failtag:
/* Settings keys to emulator */
emlClearMem();
uint8_t mblock[16];
for (uint8_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++)
{
for (uint8_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) {
emlGetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);
for (uint8_t t = 0; t < 2; t++)
{
for (uint8_t t = 0; t < 2; t++) {
memcpy(mblock + t * 10, foundKey[t][sectorNo], 6);
}
emlSetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);
@ -739,16 +710,14 @@ failtag:
DbprintfEx(FLAG_NOLOG, "%s>>%s Filling Emulator <- from A keys...", _YELLOW_, _WHITE_);
e_MifareECardLoad(sectorsCnt, 0, 0, &filled);
if (filled != 1)
{
if (filled != 1) {
cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, "%s>>%s W_FAILURE ! %sTrying fallback B keys....", _RED_, _ORANGE_, _WHITE_);
/* no trace, no dbg */
e_MifareECardLoad(sectorsCnt, 1, 0, &filled);
if (filled != 1)
{
if (filled != 1) {
cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, "FATAL:EML_FALLBACKFILL_B");
@ -856,30 +825,23 @@ void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *dat
bool isOK = true;
if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true))
{
if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) {
isOK = false;
if (MF_DBGLEVEL >= 1)
DbprintfEx(FLAG_RAWPRINT, "Can't select card");
}
for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++)
{
for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) {
ui64Key = emlGetKey(sectorNo, keyType);
if (sectorNo == 0)
{
if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST))
{
if (sectorNo == 0) {
if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) {
isOK = false;
if (MF_DBGLEVEL >= 1)
DbprintfEx(FLAG_NOLOG, "Sector[%2d]. Auth error", sectorNo);
break;
}
}
else
{
if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED))
{
} else {
if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) {
isOK = false;
if (MF_DBGLEVEL >= 1)
DbprintfEx(FLAG_NOLOG, "Sector[%2d]. Auth nested error", sectorNo);
@ -887,38 +849,30 @@ void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *dat
}
}
for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++)
{
if (isOK && mifare_classic_readblock(pcs, cjcuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf))
{
for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
if (isOK && mifare_classic_readblock(pcs, cjcuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) {
isOK = false;
if (MF_DBGLEVEL >= 1)
DbprintfEx(FLAG_NOLOG, "Error reading sector %2d block %2d", sectorNo, blockNo);
break;
};
if (isOK)
{
if (isOK) {
*datain = 1;
if (blockNo < NumBlocksPerSector(sectorNo) - 1)
{
if (blockNo < NumBlocksPerSector(sectorNo) - 1) {
emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1);
}
else
{ // sector trailer, keep the keys, set only the AC
} else {
// sector trailer, keep the keys, set only the AC
emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1);
memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4);
emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1);
}
}
else
{
} else {
*datain = 0;
}
}
}
if (mifare_classic_halt(pcs, cjcuid))
{
if (mifare_classic_halt(pcs, cjcuid)) {
if (MF_DBGLEVEL >= 1)
DbprintfEx(FLAG_NOLOG, "Halt error");
};
@ -944,21 +898,18 @@ int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, ui
struct Crypto1State *pcs;
pcs = &mpcs;
for (int i = 0; i < keyCount; ++i)
{
for (int i = 0; i < keyCount; ++i) {
/* no need for anticollision. just verify tag is still here */
// if (!iso14443a_fast_select_card(cjuid, 0)) {
if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true))
{
if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) {
cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, "%sFATAL%s : E_MF_LOSTTAG", _RED_, _WHITE_);
return -1;
}
uint64_t ui64Key = bytes_to_num(datain + i * 6, 6);
if (mifare_classic_auth(pcs, cjcuid, blockNo, keyType, ui64Key, AUTH_FIRST))
{
if (mifare_classic_auth(pcs, cjcuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
uint8_t dummy_answer = 0;
ReaderTransmit(&dummy_answer, 1, NULL);
// wait for the card to become ready again
@ -990,8 +941,7 @@ void saMifareMakeTag(void)
DbprintfEx(FLAG_NOLOG, ">> Write to Special:");
int flags = 0;
for (int blockNum = 0; blockNum < 16 * 4; blockNum++)
{
for (int blockNum = 0; blockNum < 16 * 4; blockNum++) {
uint8_t mblock[16];
// cnt = 0;
emlGetMem(mblock, blockNum, 1);
@ -1007,12 +957,11 @@ void saMifareMakeTag(void)
if (blockNum == 16 * 4 - 1)
flags = 0x04 + 0x10;
if (saMifareCSetBlock(0, flags & 0xFE, blockNum, mblock))
{ //&& cnt <= retry) {
if (saMifareCSetBlock(0, flags & 0xFE, blockNum, mblock)) {
//&& cnt <= retry) {
// cnt++;
cjSetCursFRight();
if (currfline > 53)
{
if (currfline > 53) {
currfline = 54;
}
DbprintfEx(FLAG_NOLOG, "Block :%02x %sOK%s", blockNum, _GREEN_, _WHITE_);
@ -1020,9 +969,7 @@ void saMifareMakeTag(void)
// cfail=1;
// return;
continue;
}
else
{
} else {
cjSetCursLeft();
cjSetCursLeft();
@ -1041,8 +988,7 @@ void saMifareMakeTag(void)
break;
} */
}
if (cfail == 0)
{
if (cfail == 0) {
SpinUp(50);
SpinUp(50);
SpinUp(50);
@ -1078,52 +1024,43 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
// reset FPGA and LED
if (workFlags & 0x08)
{
if (workFlags & 0x08) {
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
// clear_trace();
set_tracing(FALSE);
}
while (true)
{
while (true) {
cjSetCursLeft();
// get UID from chip
if (workFlags & 0x01)
{
if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true))
{
if (workFlags & 0x01) {
if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) {
DbprintfEx(FLAG_NOLOG, "Can't select card");
break;
};
if (mifare_classic_halt(NULL, cjcuid))
{
if (mifare_classic_halt(NULL, cjcuid)) {
DbprintfEx(FLAG_NOLOG, "Halt error");
break;
};
};
// reset chip
if (needWipe)
{
if (needWipe) {
ReaderTransmitBitsPar(wupC1, 7, 0, NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a))
{
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
DbprintfEx(FLAG_NOLOG, "wupC1 error");
break;
};
ReaderTransmit(wipeC, sizeof(wipeC), NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a))
{
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
DbprintfEx(FLAG_NOLOG, "wipeC error");
break;
};
if (mifare_classic_halt(NULL, cjcuid))
{
if (mifare_classic_halt(NULL, cjcuid)) {
DbprintfEx(FLAG_NOLOG, "Halt error");
break;
};
@ -1131,25 +1068,21 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
// chaud
// write block
if (workFlags & 0x02)
{
if (workFlags & 0x02) {
ReaderTransmitBitsPar(wupC1, 7, 0, NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a))
{
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
DbprintfEx(FLAG_NOLOG, "wupC1 error");
break;
};
ReaderTransmit(wupC2, sizeof(wupC2), NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a))
{
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
DbprintfEx(FLAG_NOLOG, "wupC2 errorv");
break;
};
}
if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a))
{
if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {
DbprintfEx(FLAG_NOLOG, "write block send command error");
break;
};
@ -1157,16 +1090,13 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
memcpy(d_block, datain, 16);
AddCrc14A(d_block, 16);
ReaderTransmit(d_block, sizeof(d_block), NULL);
if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a))
{
if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) {
DbprintfEx(FLAG_NOLOG, "write block send data error");
break;
};
if (workFlags & 0x04)
{
if (mifare_classic_halt(NULL, cjcuid))
{
if (workFlags & 0x04) {
if (mifare_classic_halt(NULL, cjcuid)) {
cjSetCursFRight();
DbprintfEx(FLAG_NOLOG, "Halt error");
@ -1178,8 +1108,7 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
break;
}
if ((workFlags & 0x10) || (!isOK))
{
if ((workFlags & 0x10) || (!isOK)) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
}

View file

@ -67,49 +67,40 @@ static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
// reset FPGA and LED
if (workFlags & 0x08)
{
if (workFlags & 0x08) {
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
set_tracing(false);
}
while (true)
{
while (true) {
// get UID from chip
if (workFlags & 0x01)
{
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true))
{
if (workFlags & 0x01) {
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
DbprintfEx(FLAG_NOLOG, "Can't select card");
break;
};
if (mifare_classic_halt(NULL, cuid))
{
if (mifare_classic_halt(NULL, cuid)) {
DbprintfEx(FLAG_NOLOG, "Halt error");
break;
};
};
// reset chip
if (needWipe)
{
if (needWipe) {
ReaderTransmitBitsPar(wupC1, 7, 0, NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a))
{
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
DbprintfEx(FLAG_NOLOG, "wupC1 error");
break;
};
ReaderTransmit(wipeC, sizeof(wipeC), NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a))
{
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
DbprintfEx(FLAG_NOLOG, "wipeC error");
break;
};
if (mifare_classic_halt(NULL, cuid))
{
if (mifare_classic_halt(NULL, cuid)) {
DbprintfEx(FLAG_NOLOG, "Halt error");
break;
};
@ -117,25 +108,21 @@ static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_
// chaud
// write block
if (workFlags & 0x02)
{
if (workFlags & 0x02) {
ReaderTransmitBitsPar(wupC1, 7, 0, NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a))
{
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
DbprintfEx(FLAG_NOLOG, "wupC1 error");
break;
};
ReaderTransmit(wupC2, sizeof(wupC2), NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a))
{
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
DbprintfEx(FLAG_NOLOG, "wupC2 errorv");
break;
};
}
if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a))
{
if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {
DbprintfEx(FLAG_NOLOG, "write block send command error");
break;
};
@ -143,16 +130,13 @@ static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_
memcpy(d_block, datain, 16);
AddCrc14A(d_block, 16);
ReaderTransmit(d_block, sizeof(d_block), NULL);
if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a))
{
if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) {
DbprintfEx(FLAG_NOLOG, "write block send data error");
break;
};
if (workFlags & 0x04)
{
if (mifare_classic_halt(NULL, cuid))
{
if (workFlags & 0x04) {
if (mifare_classic_halt(NULL, cuid)) {
DbprintfEx(FLAG_NOLOG, "Halt error");
break;
};
@ -162,8 +146,7 @@ static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_
break;
}
if ((workFlags & 0x10) || (!isOK))
{
if ((workFlags & 0x10) || (!isOK)) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
}
@ -182,20 +165,17 @@ static int saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, ui
struct Crypto1State *pcs;
pcs = &mpcs;
for (int i = 0; i < keyCount; ++i)
{
for (int i = 0; i < keyCount; ++i) {
/* no need for anticollision. just verify tag is still here */
// if (!iso14443a_fast_select_card(cjuid, 0)) {
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true))
{
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
DbprintfEx(FLAG_NOLOG, "FATAL : E_MF_LOSTTAG");
return -1;
}
uint64_t ui64Key = bytes_to_num(datain + i * 6, 6);
if (mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST))
{
if (mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
uint8_t dummy_answer = 0;
ReaderTransmit(&dummy_answer, 1, NULL);
// wait for the card to become ready again
@ -214,7 +194,8 @@ static int saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, ui
}
void RunMod() {
void RunMod()
{
StandAloneMode();
Dbprintf(">> Matty mifare chk/dump/sim a.k.a MattyRun Started <<");
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
@ -249,7 +230,7 @@ void RunMod() {
uint16_t mifare_size = 1024; // Mifare 1k (only 1k supported for now)
uint8_t sectorSize = 64; // 1k's sector size is 64 bytes.
uint8_t blockNo = 3; // Security block is number 3 for each sector.
uint8_t sectorsCnt = (mifare_size/sectorSize);
uint8_t sectorsCnt = (mifare_size / sectorSize);
uint8_t keyType = 2; // Keytype buffer
uint64_t key64; // Defines current key
uint8_t *keyBlock = NULL; // Where the keys will be held in memory.
@ -284,7 +265,7 @@ void RunMod() {
int mfKeysCnt = sizeof(mfKeys) / sizeof(uint64_t);
for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) {
num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t*)(keyBlock + mfKeyCounter * 6));
num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t *)(keyBlock + mfKeyCounter * 6));
}
/*
@ -294,8 +275,8 @@ void RunMod() {
Dbprintf("[+] Printing mf keys");
for (uint8_t keycnt = 0; keycnt < mfKeysCnt; keycnt++)
Dbprintf("[-] chk mf 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);
DbpString("--------------------------------------------------------");
}
@ -327,7 +308,7 @@ void RunMod() {
for (int type = !keyType; type < 2 && !err; keyType == 2 ? (type++) : (type = 2)) {
block = blockNo;
for (int sec = 0; sec < sectorsCnt && !err; ++sec) {
Dbprintf("\tCurrent sector:%3d, block:%3d, key type: %c, key count: %i ", sec, block, type ? 'B':'A', mfKeysCnt);
Dbprintf("\tCurrent sector:%3d, block:%3d, key type: %c, key count: %i ", sec, block, type ? 'B' : 'A', mfKeysCnt);
key = saMifareChkKeys(block, type, true, size, &keyBlock[0], &key64);
if (key == -1) {
LED(LED_RED, 50); //red
@ -342,8 +323,8 @@ void RunMod() {
validKey[type][sec] = true;
keyFound = true;
Dbprintf("\t✓ Found valid key: [%02x%02x%02x%02x%02x%02x]\n",
(keyBlock + 6*key)[0], (keyBlock + 6*key)[1], (keyBlock + 6*key)[2],
(keyBlock + 6*key)[3], (keyBlock + 6*key)[4], (keyBlock + 6*key)[5]
(keyBlock + 6 * key)[0], (keyBlock + 6 * key)[1], (keyBlock + 6 * key)[2],
(keyBlock + 6 * key)[3], (keyBlock + 6 * key)[4], (keyBlock + 6 * key)[5]
);
}
@ -380,7 +361,7 @@ void RunMod() {
emlGetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); // data, block num, blocks count (max 4)
for (uint16_t t = 0; t < 2; t++) {
if (validKey[t][sectorNo]) {
memcpy(mblock + t*10, foundKey[t][sectorNo], 6);
memcpy(mblock + t * 10, foundKey[t][sectorNo], 6);
}
}
emlSetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);
@ -409,7 +390,7 @@ void RunMod() {
LED_B_ON(); // green
// assuming arg0==0, use hardcoded uid 0xdeadbeaf
Mifare1ksim( FLAG_4B_UID_IN_DATA | FLAG_UID_IN_EMUL, 0, 0, uid);
Mifare1ksim(FLAG_4B_UID_IN_DATA | FLAG_UID_IN_EMUL, 0, 0, uid);
LED_B_OFF();
/*

View file

@ -18,7 +18,8 @@ typedef struct {
} __attribute__((__packed__)) card_clone_t;
void RunMod() {
void RunMod()
{
StandAloneMode();
Dbprintf(">> Craig Young Mifare sniff UID/clone uid 2 magic/sim a.k.a YoungRun Started <<");
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
@ -59,9 +60,9 @@ void RunMod() {
if (cardRead[selected]) {
Dbprintf("Button press detected -- replaying card in bank[%d]", selected);
break;
} else if (cardRead[(selected+1) % OPTS]) {
Dbprintf("Button press detected but no card in bank[%d] so playing from bank[%d]", selected, (selected+1)%OPTS);
selected = (selected+1) % OPTS;
} else if (cardRead[(selected + 1) % OPTS]) {
Dbprintf("Button press detected but no card in bank[%d] so playing from bank[%d]", selected, (selected + 1) % OPTS);
selected = (selected + 1) % OPTS;
break; // playing = 1;
} else {
Dbprintf("Button press detected but no stored tag to play. (Ignoring button)");
@ -75,12 +76,12 @@ void RunMod() {
Dbprintf("Read UID:");
Dbhexdump(card[selected].uidlen, card[selected].uid, 0);
if (memcmp(uids[(selected+1)%OPTS].uid, card[selected].uid, card[selected].uidlen ) == 0 ) {
if (memcmp(uids[(selected + 1) % OPTS].uid, card[selected].uid, card[selected].uidlen) == 0) {
Dbprintf("Card selected has same UID as what is stored in the other bank. Skipping.");
} else {
uids[selected].sak = card[selected].sak;
uids[selected].uidlen = card[selected].uidlen;
memcpy(uids[selected].uid , card[selected].uid, uids[selected].uidlen);
memcpy(uids[selected].uid, card[selected].uid, uids[selected].uidlen);
memcpy(uids[selected].atqa, card[selected].atqa, 2);
if (uids[selected].uidlen > 4)
@ -110,8 +111,8 @@ void RunMod() {
}
/* MF Classic UID clone */
else if (iGotoClone==1) {
iGotoClone=0;
else if (iGotoClone == 1) {
iGotoClone = 0;
LEDsoff();
LED(selected + 1, 0);
LED(LED_ORANGE, 250);
@ -176,7 +177,7 @@ void RunMod() {
MifareCSetBlock(params, 0, newBlock0);
MifareCGetBlock(params, 0, testBlock0);
if (memcmp(testBlock0, newBlock0, 16)==0) {
if (memcmp(testBlock0, newBlock0, 16) == 0) {
DbpString("Cloned successfull!");
cardRead[selected] = 0; // Only if the card was cloned successfully should we clear it
playing = 0;
@ -193,19 +194,19 @@ void RunMod() {
// Change where to record (or begin playing)
// button_pressed == BUTTON_SINGLE_CLICK && cardRead[selected])
else if (playing==1) {
else if (playing == 1) {
LEDsoff();
LED(selected + 1, 0);
// Begin transmitting
LED(LED_GREEN, 0);
DbpString("Playing");
for ( ; ; ) {
for (; ;) {
// exit from Standalone Mode, send a usbcommand.
if (usb_poll_validate_length()) return;
int button_action = BUTTON_HELD(1000);
if ( button_action == 0) { // No button action, proceed with sim
if (button_action == 0) { // No button action, proceed with sim
uint8_t flags = FLAG_4B_UID_IN_DATA;
uint8_t data[USB_CMD_DATA_SIZE] = {0}; // in case there is a read command received we shouldn't break
@ -214,7 +215,7 @@ void RunMod() {
uint64_t tmpuid = bytes_to_num(uids[selected].uid, uids[selected].uidlen);
if ( uids[selected].uidlen == 7 ) {
if (uids[selected].uidlen == 7) {
flags = FLAG_7B_UID_IN_DATA;
Dbprintf("Simulating ISO14443a tag with uid: %014" PRIx64 " [Bank: %d]", tmpuid, selected);
} else {

View file

@ -27,7 +27,8 @@
#include "lf_hidbrute.h"
// samy's sniff and repeat routine for LF
void RunMod() {
void RunMod()
{
StandAloneMode();
Dbprintf(">> LF HID corporate bruteforce a.k.a CorporateBrute Started <<");
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
@ -60,7 +61,7 @@ void RunMod() {
DbpString("[=] starting recording");
// wait for button to be released
while(BUTTON_PRESS())
while (BUTTON_PRESS())
WDT_HIT();
/* need this delay to prevent catching some weird data */
@ -76,8 +77,7 @@ void RunMod() {
// so next button push begins playing what we recorded
playing = 0;
cardRead = 1;
}
else if (button_pressed > 0 && cardRead == 1) {
} else if (button_pressed > 0 && cardRead == 1) {
LEDsoff();
LED(selected + 1, 0);
LED(LED_ORANGE, 0);
@ -86,7 +86,7 @@ void RunMod() {
Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]);
// wait for button to be released
while(BUTTON_PRESS())
while (BUTTON_PRESS())
WDT_HIT();
/* need this delay to prevent catching some weird data */
@ -141,15 +141,13 @@ void RunMod() {
playing = !playing;
LEDsoff();
LED(selected + 1, 0);
}
else if (playing && selected == 2)
{
} else if (playing && selected == 2) {
// Now it work only with HID Corporate 1000 (35bit), but is easily extensible to others RFID.
// It is necessary only to calculate the correct parity.
// Brute force code
// Check if the badge is an HID Corporate 1000
if( (high[selected] & 0xFFFFFFF8) != 0x28 ) {
if ((high[selected] & 0xFFFFFFF8) != 0x28) {
DbpString("[-] Card is not a HID Corporate 1000. Skipping bruteforce.");
continue;
}
@ -162,7 +160,7 @@ void RunMod() {
// Calculate Facility Code and Card Number from high and low
uint32_t cardnum = (low[selected] >> 1) & 0xFFFFF;
uint32_t fc = ((high[selected] & 1 ) << 11 ) | (low[selected] >> 21);
uint32_t fc = ((high[selected] & 1) << 11) | (low[selected] >> 21);
uint32_t original_cardnum = cardnum;
Dbprintf("[=] Proxbrute - starting decrementing card number");
@ -235,7 +233,7 @@ void RunMod() {
LED(selected + 1, 0);
} else {
while(BUTTON_PRESS())
while (BUTTON_PRESS())
WDT_HIT();
}
}
@ -247,7 +245,8 @@ out:
}
// Function that calculate next value for the brutforce of HID corporate 1000
void hid_corporate_1000_calculate_checksum_and_set( uint32_t *high, uint32_t *low, uint32_t cardnum, uint32_t fc) {
void hid_corporate_1000_calculate_checksum_and_set(uint32_t *high, uint32_t *low, uint32_t cardnum, uint32_t fc)
{
uint32_t new_high = 0;
uint32_t new_low = 0;
@ -264,8 +263,8 @@ void hid_corporate_1000_calculate_checksum_and_set( uint32_t *high, uint32_t *lo
uint32_t parity_bit_34_low = new_low & 0xB6DB6DB6;
n_ones = 0;
// Calculate number of ones in low number
for ( i = 1; i != 0; i <<= 1) {
if( parity_bit_34_low & i )
for (i = 1; i != 0; i <<= 1) {
if (parity_bit_34_low & i)
n_ones++;
}
// Calculate number of ones in high number
@ -282,15 +281,15 @@ void hid_corporate_1000_calculate_checksum_and_set( uint32_t *high, uint32_t *lo
n_ones = 0;
// Calculate number of ones in low number
for ( i=1; i != 0; i <<= 1) {
if( parity_bit_1_low & i )
for (i = 1; i != 0; i <<= 1) {
if (parity_bit_1_low & i)
n_ones++;
}
// Calculate number of ones in high number
if ( new_high & 0x1)
if (new_high & 0x1)
n_ones++;
if ( new_high & 0x2)
if (new_high & 0x2)
n_ones++;
// Set parity bit (Odd parity)
@ -301,14 +300,14 @@ void hid_corporate_1000_calculate_checksum_and_set( uint32_t *high, uint32_t *lo
n_ones = 0;
// Calculate number of ones in low number (all bit of low, bitmask unnecessary)
for (i = 1; i != 0; i <<= 1) {
if ( new_low & i )
if (new_low & i)
n_ones++;
}
// Calculate number of ones in high number
if ( new_high & 0x1)
if (new_high & 0x1)
n_ones++;
if ( new_high & 0x2)
if (new_high & 0x2)
n_ones++;
// Set parity bit (Odd parity)

View file

@ -19,6 +19,6 @@
#define OPTS 3
void hid_corporate_1000_calculate_checksum_and_set( uint32_t *high, uint32_t *low, uint32_t cardnum, uint32_t fc);
void hid_corporate_1000_calculate_checksum_and_set(uint32_t *high, uint32_t *low, uint32_t cardnum, uint32_t fc);
#endif /* __LF_HIDBRUTE_H */

View file

@ -12,7 +12,8 @@
#include "lf_proxbrute.h"
// samy's sniff and repeat routine for LF
void RunMod() {
void RunMod()
{
StandAloneMode();
Dbprintf(">> LF HID proxII bruteforce a.k.a ProxBrute Started (Brad Antoniewicz) <<");
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
@ -61,8 +62,7 @@ void RunMod() {
// so next button push begins playing what we recorded
playing = 0;
cardRead = 1;
}
else if (button_pressed > 0 && cardRead == 1) {
} else if (button_pressed > 0 && cardRead == 1) {
LEDsoff();
LED(selected + 1, 0);
LED(LED_ORANGE, 0);
@ -119,12 +119,12 @@ void RunMod() {
worked or not, so its a crap shoot. One option is to time how long
it takes to get a valid ID then start from scratch every time.
*/
if ( selected == 1 ) {
if (selected == 1) {
DbpString("[=] entering ProxBrute Mode");
Dbprintf("[=] current Tag: Selected = %x Facility = %08x ID = %08x", selected, high[selected], low[selected]);
LED(LED_ORANGE, 0);
LED(LED_RED, 0);
for (uint16_t i = low[selected]-1; i > 0; i--) {
for (uint16_t i = low[selected] - 1; i > 0; i--) {
if (BUTTON_PRESS()) {
DbpString("[-] told to stop");
break;
@ -156,8 +156,7 @@ void RunMod() {
playing = !playing;
LEDsoff();
LED(selected + 1, 0);
}
else {
} else {
while (BUTTON_PRESS())
WDT_HIT();
}

View file

@ -11,7 +11,8 @@
#include "lf_samyrun.h"
// samy's sniff and repeat routine for LF
void RunMod() {
void RunMod()
{
StandAloneMode();
Dbprintf(">> LF HID Read/Clone/Sim a.k.a SamyRun Started <<");
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
@ -64,8 +65,7 @@ void RunMod() {
cardRead = 1;
gotCard = true;
}
else if (button_pressed > 0 && cardRead == 1) {
} else if (button_pressed > 0 && cardRead == 1) {
LEDsoff();
LED(selected + 1, 0);
LED(LED_ORANGE, 0);
@ -129,8 +129,7 @@ void RunMod() {
playing = !playing;
LEDsoff();
LED(selected + 1, 0);
}
else {
} else {
while (BUTTON_PRESS())
WDT_HIT();
}

View file

@ -685,7 +685,7 @@ int aes_setkey_enc(unsigned int rk[], const unsigned char cipherKey[], int keyBy
int i = 0;
unsigned int temp;
rk[0] = GETU32(cipherKey );
rk[0] = GETU32(cipherKey);
rk[1] = GETU32(cipherKey + 4);
rk[2] = GETU32(cipherKey + 8);
rk[3] = GETU32(cipherKey + 12);
@ -695,7 +695,7 @@ int aes_setkey_enc(unsigned int rk[], const unsigned char cipherKey[], int keyBy
rk[4] = rk[0] ^
(Te4[(temp >> 16) & 0xff] & 0xff000000) ^
(Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
(Te4[(temp ) & 0xff] & 0x0000ff00) ^
(Te4[(temp) & 0xff] & 0x0000ff00) ^
(Te4[(temp >> 24) ] & 0x000000ff) ^
rcon[i];
rk[5] = rk[1] ^ rk[4];
@ -715,7 +715,7 @@ int aes_setkey_enc(unsigned int rk[], const unsigned char cipherKey[], int keyBy
rk[ 6] = rk[ 0] ^
(Te4[(temp >> 16) & 0xff] & 0xff000000) ^
(Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
(Te4[(temp ) & 0xff] & 0x0000ff00) ^
(Te4[(temp) & 0xff] & 0x0000ff00) ^
(Te4[(temp >> 24) ] & 0x000000ff) ^
rcon[i];
rk[ 7] = rk[ 1] ^ rk[ 6];
@ -737,7 +737,7 @@ int aes_setkey_enc(unsigned int rk[], const unsigned char cipherKey[], int keyBy
rk[ 8] = rk[ 0] ^
(Te4[(temp >> 16) & 0xff] & 0xff000000) ^
(Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
(Te4[(temp ) & 0xff] & 0x0000ff00) ^
(Te4[(temp) & 0xff] & 0x0000ff00) ^
(Te4[(temp >> 24) ] & 0x000000ff) ^
rcon[i];
rk[ 9] = rk[ 1] ^ rk[ 8];
@ -751,7 +751,7 @@ int aes_setkey_enc(unsigned int rk[], const unsigned char cipherKey[], int keyBy
(Te4[(temp >> 24) ] & 0xff000000) ^
(Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^
(Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^
(Te4[(temp ) & 0xff] & 0x000000ff);
(Te4[(temp) & 0xff] & 0x000000ff);
rk[13] = rk[ 5] ^ rk[12];
rk[14] = rk[ 6] ^ rk[13];
rk[15] = rk[ 7] ^ rk[14];
@ -790,22 +790,22 @@ int AesGenKeySched(unsigned int rk[], unsigned int rrk[], const unsigned char ci
Td0[Te4[(rk[0] >> 24) ] & 0xff] ^
Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^
Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^
Td3[Te4[(rk[0] ) & 0xff] & 0xff];
Td3[Te4[(rk[0]) & 0xff] & 0xff];
rrk[1] =
Td0[Te4[(rk[1] >> 24) ] & 0xff] ^
Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^
Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^
Td3[Te4[(rk[1] ) & 0xff] & 0xff];
Td3[Te4[(rk[1]) & 0xff] & 0xff];
rrk[2] =
Td0[Te4[(rk[2] >> 24) ] & 0xff] ^
Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^
Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^
Td3[Te4[(rk[2] ) & 0xff] & 0xff];
Td3[Te4[(rk[2]) & 0xff] & 0xff];
rrk[3] =
Td0[Te4[(rk[3] >> 24) ] & 0xff] ^
Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^
Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^
Td3[Te4[(rk[3] ) & 0xff] & 0xff];
Td3[Te4[(rk[3]) & 0xff] & 0xff];
}
// invert the order of the last round keys
rrk -= 4;
@ -833,7 +833,7 @@ void AesEncBlk(AesCtx *pCtx, const unsigned char pt[], unsigned char ct[])
* map byte array block to cipher state
* and add initial round key:
*/
s0 = GETU32(pt ) ^ rk[0];
s0 = GETU32(pt) ^ rk[0];
s1 = GETU32(pt + 4) ^ rk[1];
s2 = GETU32(pt + 8) ^ rk[2];
s3 = GETU32(pt + 12) ^ rk[3];
@ -852,25 +852,25 @@ void AesEncBlk(AesCtx *pCtx, const unsigned char pt[], unsigned char ct[])
Te0[(s0 >> 24) ] ^
Te1[(s1 >> 16) & 0xff] ^
Te2[(s2 >> 8) & 0xff] ^
Te3[(s3 ) & 0xff] ^
Te3[(s3) & 0xff] ^
rk[4];
t1 =
Te0[(s1 >> 24) ] ^
Te1[(s2 >> 16) & 0xff] ^
Te2[(s3 >> 8) & 0xff] ^
Te3[(s0 ) & 0xff] ^
Te3[(s0) & 0xff] ^
rk[5];
t2 =
Te0[(s2 >> 24) ] ^
Te1[(s3 >> 16) & 0xff] ^
Te2[(s0 >> 8) & 0xff] ^
Te3[(s1 ) & 0xff] ^
Te3[(s1) & 0xff] ^
rk[6];
t3 =
Te0[(s3 >> 24) ] ^
Te1[(s0 >> 16) & 0xff] ^
Te2[(s1 >> 8) & 0xff] ^
Te3[(s2 ) & 0xff] ^
Te3[(s2) & 0xff] ^
rk[7];
rk += 8;
@ -882,25 +882,25 @@ void AesEncBlk(AesCtx *pCtx, const unsigned char pt[], unsigned char ct[])
Te0[(t0 >> 24) ] ^
Te1[(t1 >> 16) & 0xff] ^
Te2[(t2 >> 8) & 0xff] ^
Te3[(t3 ) & 0xff] ^
Te3[(t3) & 0xff] ^
rk[0];
s1 =
Te0[(t1 >> 24) ] ^
Te1[(t2 >> 16) & 0xff] ^
Te2[(t3 >> 8) & 0xff] ^
Te3[(t0 ) & 0xff] ^
Te3[(t0) & 0xff] ^
rk[1];
s2 =
Te0[(t2 >> 24) ] ^
Te1[(t3 >> 16) & 0xff] ^
Te2[(t0 >> 8) & 0xff] ^
Te3[(t1 ) & 0xff] ^
Te3[(t1) & 0xff] ^
rk[2];
s3 =
Te0[(t3 >> 24) ] ^
Te1[(t0 >> 16) & 0xff] ^
Te2[(t1 >> 8) & 0xff] ^
Te3[(t2 ) & 0xff] ^
Te3[(t2) & 0xff] ^
rk[3];
}
/*
@ -911,28 +911,28 @@ void AesEncBlk(AesCtx *pCtx, const unsigned char pt[], unsigned char ct[])
(Te4[(t0 >> 24) ] & 0xff000000) ^
(Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
(Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^
(Te4[(t3 ) & 0xff] & 0x000000ff) ^
(Te4[(t3) & 0xff] & 0x000000ff) ^
rk[0];
PUTU32(ct , s0);
PUTU32(ct, s0);
s1 =
(Te4[(t1 >> 24) ] & 0xff000000) ^
(Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
(Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^
(Te4[(t0 ) & 0xff] & 0x000000ff) ^
(Te4[(t0) & 0xff] & 0x000000ff) ^
rk[1];
PUTU32(ct + 4, s1);
s2 =
(Te4[(t2 >> 24) ] & 0xff000000) ^
(Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
(Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^
(Te4[(t1 ) & 0xff] & 0x000000ff) ^
(Te4[(t1) & 0xff] & 0x000000ff) ^
rk[2];
PUTU32(ct + 8, s2);
s3 =
(Te4[(t3 >> 24) ] & 0xff000000) ^
(Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
(Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^
(Te4[(t2 ) & 0xff] & 0x000000ff) ^
(Te4[(t2) & 0xff] & 0x000000ff) ^
rk[3];
PUTU32(ct + 12, s3);
@ -959,10 +959,14 @@ void AesDecBlk(AesCtx *pCtx, const unsigned char ct[], unsigned char pt[])
* map byte array block to cipher state
* and add initial round key:
*/
v0 = GETU32(ct ); s0 = v0 ^ rk[0];
v1 = GETU32(ct + 4); s1 = v1 ^ rk[1];
v2 = GETU32(ct + 8); s2 = v2 ^ rk[2];
v3 = GETU32(ct + 12); s3 = v3 ^ rk[3];
v0 = GETU32(ct);
s0 = v0 ^ rk[0];
v1 = GETU32(ct + 4);
s1 = v1 ^ rk[1];
v2 = GETU32(ct + 8);
s2 = v2 ^ rk[2];
v3 = GETU32(ct + 12);
s3 = v3 ^ rk[3];
/*
* Nr - 1 full rounds:
*/
@ -972,25 +976,25 @@ void AesDecBlk(AesCtx *pCtx, const unsigned char ct[], unsigned char pt[])
Td0[(s0 >> 24) ] ^
Td1[(s3 >> 16) & 0xff] ^
Td2[(s2 >> 8) & 0xff] ^
Td3[(s1 ) & 0xff] ^
Td3[(s1) & 0xff] ^
rk[4];
t1 =
Td0[(s1 >> 24) ] ^
Td1[(s0 >> 16) & 0xff] ^
Td2[(s3 >> 8) & 0xff] ^
Td3[(s2 ) & 0xff] ^
Td3[(s2) & 0xff] ^
rk[5];
t2 =
Td0[(s2 >> 24) ] ^
Td1[(s1 >> 16) & 0xff] ^
Td2[(s0 >> 8) & 0xff] ^
Td3[(s3 ) & 0xff] ^
Td3[(s3) & 0xff] ^
rk[6];
t3 =
Td0[(s3 >> 24) ] ^
Td1[(s2 >> 16) & 0xff] ^
Td2[(s1 >> 8) & 0xff] ^
Td3[(s0 ) & 0xff] ^
Td3[(s0) & 0xff] ^
rk[7];
rk += 8;
@ -1002,25 +1006,25 @@ void AesDecBlk(AesCtx *pCtx, const unsigned char ct[], unsigned char pt[])
Td0[(t0 >> 24) ] ^
Td1[(t3 >> 16) & 0xff] ^
Td2[(t2 >> 8) & 0xff] ^
Td3[(t1 ) & 0xff] ^
Td3[(t1) & 0xff] ^
rk[0];
s1 =
Td0[(t1 >> 24) ] ^
Td1[(t0 >> 16) & 0xff] ^
Td2[(t3 >> 8) & 0xff] ^
Td3[(t2 ) & 0xff] ^
Td3[(t2) & 0xff] ^
rk[1];
s2 =
Td0[(t2 >> 24) ] ^
Td1[(t1 >> 16) & 0xff] ^
Td2[(t0 >> 8) & 0xff] ^
Td3[(t3 ) & 0xff] ^
Td3[(t3) & 0xff] ^
rk[2];
s3 =
Td0[(t3 >> 24) ] ^
Td1[(t2 >> 16) & 0xff] ^
Td2[(t1 >> 8) & 0xff] ^
Td3[(t0 ) & 0xff] ^
Td3[(t0) & 0xff] ^
rk[3];
}
/*
@ -1031,35 +1035,39 @@ void AesDecBlk(AesCtx *pCtx, const unsigned char ct[], unsigned char pt[])
(Td4[(t0 >> 24) ] & 0xff000000) ^
(Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
(Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^
(Td4[(t1 ) & 0xff] & 0x000000ff) ^
(Td4[(t1) & 0xff] & 0x000000ff) ^
rk[0];
s1 =
(Td4[(t1 >> 24) ] & 0xff000000) ^
(Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
(Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^
(Td4[(t2 ) & 0xff] & 0x000000ff) ^
(Td4[(t2) & 0xff] & 0x000000ff) ^
rk[1];
s2 =
(Td4[(t2 >> 24) ] & 0xff000000) ^
(Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
(Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^
(Td4[(t3 ) & 0xff] & 0x000000ff) ^
(Td4[(t3) & 0xff] & 0x000000ff) ^
rk[2];
s3 =
(Td4[(t3 >> 24) ] & 0xff000000) ^
(Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
(Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^
(Td4[(t0 ) & 0xff] & 0x000000ff) ^
(Td4[(t0) & 0xff] & 0x000000ff) ^
rk[3];
if (pCtx->Mode) {
s0 = s0 ^ iv[0]; iv[0] = v0;
s1 = s1 ^ iv[1]; iv[1] = v1;
s2 = s2 ^ iv[2]; iv[2] = v2;
s3 = s3 ^ iv[3]; iv[3] = v3;
s0 = s0 ^ iv[0];
iv[0] = v0;
s1 = s1 ^ iv[1];
iv[1] = v1;
s2 = s2 ^ iv[2];
iv[2] = v2;
s3 = s3 ^ iv[3];
iv[3] = v3;
}
PUTU32(pt , s0);
PUTU32(pt, s0);
PUTU32(pt + 4, s1);
PUTU32(pt + 8, s2);
PUTU32(pt + 12, s3);
@ -1082,9 +1090,9 @@ int AesCtxIni(AesCtx *pCtx, unsigned char *pIV, unsigned char *pKey, unsigned in
// initialize IV
if (pIV != 0) {
pCtx->Iv[0] = GETU32(pIV );
pCtx->Iv[1] = GETU32(pIV + 4 );
pCtx->Iv[2] = GETU32(pIV + 8 );
pCtx->Iv[0] = GETU32(pIV);
pCtx->Iv[1] = GETU32(pIV + 4);
pCtx->Iv[2] = GETU32(pIV + 8);
pCtx->Iv[3] = GETU32(pIV + 12);
}
@ -1149,18 +1157,18 @@ int main()
// initialize context and encrypt data at one end
if( AesCtxIni(&ctx, iv, key, KEY128, CBC) < 0)
if (AesCtxIni(&ctx, iv, key, KEY128, CBC) < 0)
printf("init error\n");
if (AesEncrypt(&ctx, databuf, databuf, sizeof(databuf) ) < 0)
if (AesEncrypt(&ctx, databuf, databuf, sizeof(databuf)) < 0)
printf("error in encryption\n");
// initialize context and decrypt cipher at other end
if( AesCtxIni(&ctx, iv, key, KEY128, CBC) < 0)
if (AesCtxIni(&ctx, iv, key, KEY128, CBC) < 0)
printf("init error\n");
if (AesDecrypt(&ctx, databuf, databuf, sizeof(databuf) ) < 0)
if (AesDecrypt(&ctx, databuf, databuf, sizeof(databuf)) < 0)
printf("error in decryption\n");
printf("%s\n", databuf);

View file

@ -27,7 +27,7 @@
#define DEBUG 1
#ifdef WITH_LCD
#include "LCD.h"
#include "LCD.h"
#endif
#ifdef WITH_SMARTCARD
@ -54,55 +54,59 @@ int ToSendMax = -1;
static int ToSendBit;
struct common_area common_area __attribute__((section(".commonarea")));
void ToSendReset(void) {
void ToSendReset(void)
{
ToSendMax = -1;
ToSendBit = 8;
}
void ToSendStuffBit(int b) {
if(ToSendBit >= 8) {
void ToSendStuffBit(int b)
{
if (ToSendBit >= 8) {
ToSendMax++;
ToSend[ToSendMax] = 0;
ToSendBit = 0;
}
if(b)
if (b)
ToSend[ToSendMax] |= (1 << (7 - ToSendBit));
ToSendBit++;
if(ToSendMax >= sizeof(ToSend)) {
if (ToSendMax >= sizeof(ToSend)) {
ToSendBit = 0;
DbpString("ToSendStuffBit overflowed!");
}
}
void PrintToSendBuffer(void) {
void PrintToSendBuffer(void)
{
DbpString("Printing ToSendBuffer:");
Dbhexdump(ToSendMax, ToSend, 0);
}
void print_result(char *name, uint8_t *buf, size_t len) {
void print_result(char *name, uint8_t *buf, size_t len)
{
uint8_t *p = buf;
uint16_t tmp = len & 0xFFF0;
for(; p-buf < tmp; p += 16) {
for (; p - buf < tmp; p += 16) {
Dbprintf("[%s: %02d/%02d] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
name,
p-buf,
p - buf,
len,
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]
);
}
if (len % 16 != 0) {
char s[46] = {0};
char *sp = s;
for (; p-buf < len; p++ ) {
sprintf(sp, "%02x ", p[0] );
for (; p - buf < len; p++) {
sprintf(sp, "%02x ", p[0]);
sp += 3;
}
Dbprintf("[%s: %02d/%02d] %s", name, p-buf, len, s);
Dbprintf("[%s: %02d/%02d] %s", name, p - buf, len, s);
}
}
@ -110,25 +114,29 @@ void print_result(char *name, uint8_t *buf, size_t len) {
// Debug print functions, to go out over USB, to the usual PC-side client.
//=============================================================================
void DbpStringEx(char *str, uint32_t cmd) {
void DbpStringEx(char *str, uint32_t cmd)
{
#if DEBUG
uint8_t len = strlen(str);
cmd_send(CMD_DEBUG_PRINT_STRING, len, cmd, 0, (uint8_t*)str, len);
cmd_send(CMD_DEBUG_PRINT_STRING, len, cmd, 0, (uint8_t *)str, len);
#endif
}
void DbpString(char *str) {
void DbpString(char *str)
{
#if DEBUG
DbpStringEx(str, 0);
#endif
}
#if 0
void DbpIntegers(int x1, int x2, int x3) {
cmd_send(CMD_DEBUG_PRINT_INTEGERS,x1,x2,x3,0,0);
void DbpIntegers(int x1, int x2, int x3)
{
cmd_send(CMD_DEBUG_PRINT_INTEGERS, x1, x2, x3, 0, 0);
}
#endif
void DbprintfEx(uint32_t cmd, const char *fmt, ...) {
void DbprintfEx(uint32_t cmd, const char *fmt, ...)
{
#if DEBUG
// should probably limit size here; oh well, let's just use a big buffer
char output_string[128] = {0x00};
@ -141,7 +149,8 @@ void DbprintfEx(uint32_t cmd, const char *fmt, ...) {
#endif
}
void Dbprintf(const char *fmt, ...) {
void Dbprintf(const char *fmt, ...)
{
#if DEBUG
// should probably limit size here; oh well, let's just use a big buffer
char output_string[128] = {0x00};
@ -156,9 +165,10 @@ void Dbprintf(const char *fmt, ...) {
}
// prints HEX & ASCII
void Dbhexdump(int len, uint8_t *d, bool bAsci) {
void Dbhexdump(int len, uint8_t *d, bool bAsci)
{
#if DEBUG
int l=0, i;
int l = 0, i;
char ascii[9];
while (len > 0) {
@ -169,7 +179,7 @@ void Dbhexdump(int len, uint8_t *d, bool bAsci) {
ascii[l] = 0;
// filter safe ascii
for (i=0; i<l; i++) {
for (i = 0; i < l; i++) {
if (ascii[i] < 32 || ascii[i] > 126) {
ascii[i] = '.';
}
@ -191,7 +201,8 @@ void Dbhexdump(int len, uint8_t *d, bool bAsci) {
// in ADC units (0 to 1023). Also a routine to average 32 samples and
// return that.
//-----------------------------------------------------------------------------
static uint16_t ReadAdc(int ch) {
static uint16_t ReadAdc(int ch)
{
// Note: ADC_MODE_PRESCALE and ADC_MODE_SAMPLE_HOLD_TIME are set to the maximum allowed value.
// AMPL_HI is are high impedance (10MOhm || 1MOhm) output, the input capacitance of the ADC is 12pF (typical). This results in a time constant
@ -217,16 +228,18 @@ static uint16_t ReadAdc(int ch) {
}
// was static - merlok
uint16_t AvgAdc(int ch) {
uint16_t AvgAdc(int ch)
{
uint16_t a = 0;
for(uint8_t i = 0; i < 32; i++)
for (uint8_t i = 0; i < 32; i++)
a += ReadAdc(ch);
//division by 32
return (a + 15) >> 5;
}
void MeasureAntennaTuning(void) {
void MeasureAntennaTuning(void)
{
uint8_t LF_Results[256];
uint32_t i, adcval = 0, peak = 0, peakv = 0, peakf = 0;
@ -235,7 +248,7 @@ void MeasureAntennaTuning(void) {
memset(LF_Results, 0, sizeof(LF_Results));
LED_B_ON();
/*
/*
* Sweeps the useful LF range of the proxmark from
* 46.8kHz (divisor=255) to 600kHz (divisor=19) and
* read the voltage in the antenna, the result left
@ -259,7 +272,7 @@ void MeasureAntennaTuning(void) {
v_lf134 = adcval; // voltage at 134Khz
LF_Results[i] = adcval >> 9; // scale int to fit in byte for graphing purposes
if(LF_Results[i] > peak) {
if (LF_Results[i] > peak) {
peakv = adcval;
peakf = i;
peak = LF_Results[i];
@ -274,7 +287,7 @@ void MeasureAntennaTuning(void) {
v_hf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
// RDV40 will hit the roof, try other ADC channel used in that hardware revision.
if ( v_hf > MAX_ADC_HF_VOLTAGE-300 ) {
if (v_hf > MAX_ADC_HF_VOLTAGE - 300) {
v_hf = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10;
}
@ -291,29 +304,31 @@ void MeasureAntennaTuning(void) {
LEDsoff();
}
void MeasureAntennaTuningHf(void) {
void MeasureAntennaTuningHf(void)
{
uint16_t volt = 0; // in mV
// Let the FPGA drive the high-frequency antenna around 13.56 MHz.
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
SpinDelay(50);
volt = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
bool use_high = ( volt > MAX_ADC_HF_VOLTAGE-300 );
bool use_high = (volt > MAX_ADC_HF_VOLTAGE - 300);
while( !BUTTON_PRESS() ){
while (!BUTTON_PRESS()) {
SpinDelay(20);
if ( !use_high ) {
if (!use_high) {
volt = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
} else {
volt = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10;
}
DbprintfEx(FLAG_NONEWLINE, "%u mV / %5u V", volt, (uint16_t)(volt/1000));
DbprintfEx(FLAG_NONEWLINE, "%u mV / %5u V", volt, (uint16_t)(volt / 1000));
}
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
DbprintfEx(FLAG_NOOPT, "\n[+] cancelled", 1);
}
void ReadMem(int addr) {
void ReadMem(int addr)
{
const uint8_t *data = ((uint8_t *)addr);
Dbprintf("%x: %02x %02x %02x %02x %02x %02x %02x %02x", addr, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
@ -323,7 +338,8 @@ void ReadMem(int addr) {
extern struct version_information version_information;
/* bootrom version information is pointed to from _bootphase1_version_pointer */
extern char *_bootphase1_version_pointer, _flash_start, _flash_end, _bootrom_start, _bootrom_end, __data_src_start__;
void SendVersion(void) {
void SendVersion(void)
{
char temp[USB_CMD_DATA_SIZE]; /* Limited data payload in USB packets */
char VersionString[USB_CMD_DATA_SIZE] = { '\0' };
@ -331,11 +347,11 @@ void SendVersion(void) {
* symbol _bootphase1_version_pointer, perform slight sanity checks on the
* pointer, then use it.
*/
char *bootrom_version = *(char**)&_bootphase1_version_pointer;
char *bootrom_version = *(char **)&_bootphase1_version_pointer;
strncat(VersionString, " [ ARM ]\n", sizeof(VersionString) - strlen(VersionString) - 1);
if( bootrom_version < &_flash_start || bootrom_version >= &_flash_end ) {
if (bootrom_version < &_flash_start || bootrom_version >= &_flash_end) {
strcat(VersionString, "bootrom version information appears invalid\n");
} else {
FormatVersionInformation(temp, sizeof(temp), " bootrom: ", bootrom_version);
@ -361,11 +377,12 @@ void SendVersion(void) {
// measure the USB Speed by sending SpeedTestBufferSize bytes to client and measuring the elapsed time.
// Note: this mimics GetFromBigbuf(), i.e. we have the overhead of the UsbCommand structure included.
void printUSBSpeed(void) {
void printUSBSpeed(void)
{
Dbprintf("USB Speed");
Dbprintf(" Sending USB packets to client...");
#define USB_SPEED_TEST_MIN_TIME 1500 // in milliseconds
#define USB_SPEED_TEST_MIN_TIME 1500 // in milliseconds
uint8_t *test_data = BigBuf_get_addr();
uint32_t end_time;
@ -388,7 +405,8 @@ void printUSBSpeed(void) {
/**
* Prints runtime information about the PM3.
**/
void SendStatus(void) {
void SendStatus(void)
{
BigBuf_print_status();
Fpga_print_status();
#ifdef WITH_FLASH
@ -412,7 +430,8 @@ void SendStatus(void) {
}
// Show some leds in a pattern to identify StandAlone mod is running
void StandAloneMode(void) {
void StandAloneMode(void)
{
DbpString("Stand-alone mode! No PC necessary.");
@ -425,7 +444,8 @@ void StandAloneMode(void) {
}
// detection of which Standalone Modes is installed
// (iceman)
void printStandAloneModes(void) {
void printStandAloneModes(void)
{
DbpString("Installed StandAlone Mode");
@ -501,9 +521,10 @@ static const char LIGHT_SCHEME[] = {
0xE, /* -XXX | 86% of maximum current detected */
0xF, /* XXXX | 100% of maximum current detected */
};
static const int LIGHT_LEN = sizeof(LIGHT_SCHEME)/sizeof(LIGHT_SCHEME[0]);
static const int LIGHT_LEN = sizeof(LIGHT_SCHEME) / sizeof(LIGHT_SCHEME[0]);
void ListenReaderField(int limit) {
void ListenReaderField(int limit)
{
#define LF_ONLY 1
#define HF_ONLY 2
#define REPORT_CHANGE 10 // report new values only if they have changed at least by REPORT_CHANGE
@ -530,8 +551,8 @@ void ListenReaderField(int limit) {
// iceman, useless, since we are measuring readerfield, not our field. My tests shows a max of 20v from a reader.
// RDV40 will hit the roof, try other ADC channel used in that hardware revision.
bool use_high = ( ((MAX_ADC_HF_VOLTAGE * hf_max) >> 10) > MAX_ADC_HF_VOLTAGE-300 );
if ( use_high ) {
bool use_high = (((MAX_ADC_HF_VOLTAGE * hf_max) >> 10) > MAX_ADC_HF_VOLTAGE - 300);
if (use_high) {
hf_av = hf_max = AvgAdc(ADC_CHAN_HF_RDV40);
}
@ -540,7 +561,7 @@ void ListenReaderField(int limit) {
hf_baseline = hf_av;
}
for(;;) {
for (;;) {
// Switch modes with button
if (BUTTON_PRESS()) {
SpinDelay(500);
@ -560,7 +581,7 @@ void ListenReaderField(int limit) {
WDT_HIT();
if (limit != HF_ONLY) {
if(mode == 1) {
if (mode == 1) {
if (ABS(lf_av - lf_baseline) > REPORT_CHANGE)
LED_D_ON();
else
@ -578,7 +599,7 @@ void ListenReaderField(int limit) {
}
if (limit != LF_ONLY) {
if (mode == 1){
if (mode == 1) {
if (ABS(hf_av - hf_baseline) > REPORT_CHANGE)
LED_B_ON();
else
@ -588,7 +609,7 @@ void ListenReaderField(int limit) {
hf_av_new = (use_high) ? AvgAdc(ADC_CHAN_HF_RDV40) : AvgAdc(ADC_CHAN_HF);
// see if there's a significant change
if(ABS(hf_av - hf_av_new) > REPORT_CHANGE) {
if (ABS(hf_av - hf_av_new) > REPORT_CHANGE) {
Dbprintf("HF 13.56MHz Field Change: %5dmV", (MAX_ADC_HF_VOLTAGE * hf_av_new) >> 10);
hf_av = hf_av_new;
if (hf_av > hf_max)
@ -604,7 +625,7 @@ void ListenReaderField(int limit) {
display_val = hf_av;
display_max = hf_max;
} else { /* Pick one at random */
if( (hf_max - hf_baseline) > (lf_max - lf_baseline) ) {
if ((hf_max - hf_baseline) > (lf_max - lf_baseline)) {
display_val = hf_av;
display_max = hf_max;
} else {
@ -612,12 +633,16 @@ void ListenReaderField(int limit) {
display_max = lf_max;
}
}
for (i=0; i<LIGHT_LEN; i++) {
if (display_val >= ((display_max/LIGHT_LEN)*i) && display_val <= ((display_max/LIGHT_LEN)*(i+1))) {
if (LIGHT_SCHEME[i] & 0x1) LED_C_ON(); else LED_C_OFF();
if (LIGHT_SCHEME[i] & 0x2) LED_A_ON(); else LED_A_OFF();
if (LIGHT_SCHEME[i] & 0x4) LED_B_ON(); else LED_B_OFF();
if (LIGHT_SCHEME[i] & 0x8) LED_D_ON(); else LED_D_OFF();
for (i = 0; i < LIGHT_LEN; i++) {
if (display_val >= ((display_max / LIGHT_LEN)*i) && display_val <= ((display_max / LIGHT_LEN) * (i + 1))) {
if (LIGHT_SCHEME[i] & 0x1) LED_C_ON();
else LED_C_OFF();
if (LIGHT_SCHEME[i] & 0x2) LED_A_ON();
else LED_A_OFF();
if (LIGHT_SCHEME[i] & 0x4) LED_B_ON();
else LED_B_OFF();
if (LIGHT_SCHEME[i] & 0x8) LED_D_ON();
else LED_D_OFF();
break;
}
}
@ -625,15 +650,16 @@ void ListenReaderField(int limit) {
}
}
void UsbPacketReceived(uint8_t *packet, int len) {
void UsbPacketReceived(uint8_t *packet, int len)
{
UsbCommand *c = (UsbCommand *)packet;
//Dbprintf("received %d bytes, with command: 0x%04x and args: %d %d %d", len, c->cmd, c->arg[0], c->arg[1], c->arg[2]);
switch(c->cmd) {
switch (c->cmd) {
#ifdef WITH_LF
case CMD_SET_LF_T55XX_CONFIG:
setT55xxConfig( c->arg[0], (t55xx_config *) c->d.asBytes);
setT55xxConfig(c->arg[0], (t55xx_config *) c->d.asBytes);
break;
case CMD_SET_LF_SAMPLING_CONFIG:
setSamplingConfig((sample_config *) c->d.asBytes);
@ -692,7 +718,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
ReadTItag();
break;
case CMD_WRITE_TI_TYPE:
WriteTItag(c->arg[0],c->arg[1],c->arg[2]);
WriteTItag(c->arg[0], c->arg[1], c->arg[2]);
break;
case CMD_SIMULATE_TAG_125K:
LED_A_ON();
@ -765,25 +791,25 @@ void UsbPacketReceived(uint8_t *packet, int len) {
SnoopHitag(c->arg[0]);
break;
case CMD_SIMULATE_HITAG: // Simulate Hitag tag, args = memory content
SimulateHitagTag((bool)c->arg[0],(byte_t*)c->d.asBytes);
SimulateHitagTag((bool)c->arg[0], (byte_t *)c->d.asBytes);
break;
case CMD_READER_HITAG: // Reader for Hitag tags, args = type and function
ReaderHitag((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes);
ReaderHitag((hitag_function)c->arg[0], (hitag_data *)c->d.asBytes);
break;
case CMD_SIMULATE_HITAG_S:// Simulate Hitag s tag, args = memory content
SimulateHitagSTag((bool)c->arg[0],(byte_t*)c->d.asBytes);
SimulateHitagSTag((bool)c->arg[0], (byte_t *)c->d.asBytes);
break;
case CMD_TEST_HITAGS_TRACES:// Tests every challenge within the given file
check_challenges((bool)c->arg[0],(byte_t*)c->d.asBytes);
check_challenges((bool)c->arg[0], (byte_t *)c->d.asBytes);
break;
case CMD_READ_HITAG_S: //Reader for only Hitag S tags, args = key or challenge
ReadHitagS((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes);
ReadHitagS((hitag_function)c->arg[0], (hitag_data *)c->d.asBytes);
break;
case CMD_WR_HITAG_S: //writer for Hitag tags args=data to write,page and key or challenge
if ((hitag_function)c->arg[0] < 10) {
WritePageHitagS((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes,c->arg[2]);
WritePageHitagS((hitag_function)c->arg[0], (hitag_data *)c->d.asBytes, c->arg[2]);
} else if ((hitag_function)c->arg[0] >= 10) {
WriterHitag((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes, c->arg[2]);
WriterHitag((hitag_function)c->arg[0], (hitag_data *)c->d.asBytes, c->arg[2]);
}
break;
#endif
@ -892,10 +918,10 @@ void UsbPacketReceived(uint8_t *packet, int len) {
MifareReadBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
break;
case CMD_MIFAREU_READBL:
MifareUReadBlock(c->arg[0],c->arg[1], c->d.asBytes);
MifareUReadBlock(c->arg[0], c->arg[1], c->d.asBytes);
break;
case CMD_MIFAREUC_AUTH:
MifareUC_Auth(c->arg[0],c->d.asBytes);
MifareUC_Auth(c->arg[0], c->d.asBytes);
break;
case CMD_MIFAREU_READCARD:
MifareUReadCard(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
@ -1050,11 +1076,11 @@ void UsbPacketReceived(uint8_t *packet, int len) {
SmartCardAtr();
break;
}
case CMD_SMART_SETBAUD:{
case CMD_SMART_SETBAUD: {
SmartCardSetBaud(c->arg[0]);
break;
}
case CMD_SMART_SETCLOCK:{
case CMD_SMART_SETCLOCK: {
SmartCardSetClock(c->arg[0]);
break;
}
@ -1065,8 +1091,8 @@ void UsbPacketReceived(uint8_t *packet, int len) {
case CMD_SMART_UPLOAD: {
// upload file from client
uint8_t *mem = BigBuf_get_addr();
memcpy( mem + c->arg[0], c->d.asBytes, USB_CMD_DATA_SIZE);
cmd_send(CMD_ACK,1,0,0,0,0);
memcpy(mem + c->arg[0], c->d.asBytes, USB_CMD_DATA_SIZE);
cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
break;
}
case CMD_SMART_UPGRADE: {
@ -1101,7 +1127,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
char dest[USB_CMD_DATA_SIZE] = { '\0' };
static const char* welcome = "Proxmark3 Serial interface via FPC ready\n";
static const char *welcome = "Proxmark3 Serial interface via FPC ready\n";
strncat(dest, welcome, sizeof(dest) - strlen(dest) - 1);
sprintf(dest + strlen(dest) - 1, "| bytes 0x%02x 0x%02x 0x%02x 0x%02x \n"
, c->d.asBytes[0]
@ -1116,7 +1142,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
LED_A_ON();
usart_init();
usart_writebuffer((uint8_t*)&txcmd, sizeof(UsbCommand));
usart_writebuffer((uint8_t *)&txcmd, sizeof(UsbCommand));
//usb
cmd_send(CMD_DEBUG_PRINT_STRING, strlen(dest), 0, 0, dest, strlen(dest));
@ -1140,7 +1166,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
//cmd_send(CMD_DEBUG_PRINT_STRING, strlen(dest), 0, 0, dest, strlen(dest));
cmd_send(CMD_ACK,0,0,0,0,0);
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
StopTicks();
break;
}
@ -1180,11 +1206,11 @@ void UsbPacketReceived(uint8_t *packet, int len) {
// arg2 = BigBuf tracelen
//Dbprintf("transfer to client parameters: %" PRIu32 " | %" PRIu32 " | %" PRIu32, startidx, numofbytes, c->arg[2]);
for(size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) {
len = MIN( (numofbytes - i), USB_CMD_DATA_SIZE);
for (size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) {
len = MIN((numofbytes - i), USB_CMD_DATA_SIZE);
isok = cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K, i, len, BigBuf_get_traceLen(), mem + startidx + i, len);
if (isok != 0)
Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i+len, len);
Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i + len, len);
}
// Trigger a finish downloading signal with an ACK frame
// iceman, when did sending samplingconfig array got attached here?!?
@ -1202,15 +1228,15 @@ void UsbPacketReceived(uint8_t *packet, int len) {
// to be able to use this one for uploading data to device
// arg1 = 0 upload for LF usage
// 1 upload for HF usage
#define FPGA_LF 1
if ( c->arg[1] == FPGA_LF )
#define FPGA_LF 1
if (c->arg[1] == FPGA_LF)
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
else
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
uint8_t *mem = BigBuf_get_addr();
memcpy( mem + c->arg[0], c->d.asBytes, USB_CMD_DATA_SIZE);
cmd_send(CMD_ACK,1,0,0,0,0);
memcpy(mem + c->arg[0], c->d.asBytes, USB_CMD_DATA_SIZE);
cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
break;
}
case CMD_DOWNLOAD_EML_BIGBUF: {
@ -1229,7 +1255,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
len = MIN((numofbytes - i), USB_CMD_DATA_SIZE);
isok = cmd_send(CMD_DOWNLOADED_EML_BIGBUF, i, len, 0, mem + startidx + i, len);
if (isok != 0)
Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i+len, len);
Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i + len, len);
}
// Trigger a finish downloading signal with an ACK frame
cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
@ -1259,12 +1285,12 @@ void UsbPacketReceived(uint8_t *packet, int len) {
uint8_t *mem = BigBuf_malloc(size);
for(size_t i = 0; i < len; i += size) {
for (size_t i = 0; i < len; i += size) {
len = MIN((len - i), size);
Dbprintf("FlashMem reading | %d | %d | %d |", startidx + i, i, len);
isok = Flash_ReadDataCont(startidx + i, mem, len);
if ( isok == len ) {
if (isok == len) {
print_result("Chunk: ", mem, len);
} else {
Dbprintf("FlashMem reading failed | %d | %d", len, isok);
@ -1282,7 +1308,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
uint16_t res = 0;
uint32_t startidx = c->arg[0];
uint16_t len = c->arg[1];
uint8_t* data = c->d.asBytes;
uint8_t *data = c->d.asBytes;
uint32_t tmp = startidx + len;
@ -1293,9 +1319,9 @@ void UsbPacketReceived(uint8_t *packet, int len) {
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
if ( startidx == DEFAULT_T55XX_KEYS_OFFSET )
if (startidx == DEFAULT_T55XX_KEYS_OFFSET)
Flash_Erase4k(3, 0xC);
else if (startidx == DEFAULT_MF_KEYS_OFFSET )
else if (startidx == DEFAULT_MF_KEYS_OFFSET)
Flash_Erase4k(3, 0xB);
else if (startidx == DEFAULT_ICLASS_KEYS_OFFSET)
Flash_Erase4k(3, 0xA);
@ -1304,16 +1330,16 @@ void UsbPacketReceived(uint8_t *packet, int len) {
Flash_WriteEnable();
// inside 256b page?
if ( (tmp & 0xFF) != 0) {
if ((tmp & 0xFF) != 0) {
// is offset+len larger than a page
tmp = (startidx & 0xFF ) + len;
if (tmp > 0xFF ) {
tmp = (startidx & 0xFF) + len;
if (tmp > 0xFF) {
// data spread over two pages.
// offset xxxx10,
uint8_t first_len = (~startidx & 0xFF)+1;
uint8_t first_len = (~startidx & 0xFF) + 1;
// first mem page
res = Flash_WriteDataCont(startidx, data, first_len);
@ -1342,13 +1368,13 @@ void UsbPacketReceived(uint8_t *packet, int len) {
uint8_t page = c->arg[0];
uint8_t initalwipe = c->arg[1];
bool isok = false;
if ( initalwipe ) {
if (initalwipe) {
isok = Flash_WipeMemory();
cmd_send(CMD_ACK, isok, 0, 0, 0, 0);
LED_B_OFF();
break;
}
if ( page < 3)
if (page < 3)
isok = Flash_WipeMemoryPage(page);
cmd_send(CMD_ACK, isok, 0, 0, 0, 0);
@ -1375,7 +1401,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
len = MIN((numofbytes - i), USB_CMD_DATA_SIZE);
isok = Flash_ReadDataCont(startidx + i, mem, len);
if (!isok )
if (!isok)
Dbprintf("reading flash memory failed :: | bytes between %d - %d", i, len);
isok = cmd_send(CMD_FLASHMEM_DOWNLOADED, i, len, 0, mem, len);
@ -1391,12 +1417,12 @@ void UsbPacketReceived(uint8_t *packet, int len) {
case CMD_FLASHMEM_INFO: {
LED_B_ON();
rdv40_validation_t *info = (rdv40_validation_t*)BigBuf_malloc( sizeof(rdv40_validation_t) );
rdv40_validation_t *info = (rdv40_validation_t *)BigBuf_malloc(sizeof(rdv40_validation_t));
bool isok = Flash_ReadData(FLASH_MEM_SIGNATURE_OFFSET, info->signature, FLASH_MEM_SIGNATURE_LEN);
if (FlashInit()) {
Flash_UniqueID( info->flashid);
Flash_UniqueID(info->flashid);
FlashStop();
}
cmd_send(CMD_ACK, isok, 0, 0, info, sizeof(rdv40_validation_t));
@ -1412,12 +1438,20 @@ void UsbPacketReceived(uint8_t *packet, int len) {
break;
case CMD_SET_ADC_MUX:
switch(c->arg[0]) {
case 0: SetAdcMuxFor(GPIO_MUXSEL_LOPKD); break;
case 2: SetAdcMuxFor(GPIO_MUXSEL_HIPKD); break;
switch (c->arg[0]) {
case 0:
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
break;
case 2:
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
break;
#ifndef WITH_FPC
case 1: SetAdcMuxFor(GPIO_MUXSEL_LORAW); break;
case 3: SetAdcMuxFor(GPIO_MUXSEL_HIRAW); break;
case 1:
SetAdcMuxFor(GPIO_MUXSEL_LORAW);
break;
case 3:
SetAdcMuxFor(GPIO_MUXSEL_HIRAW);
break;
#endif
}
break;
@ -1429,7 +1463,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
SendStatus();
break;
case CMD_PING:
cmd_send(CMD_ACK,0,0,0,0,0);
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
break;
#ifdef WITH_LCD
case CMD_LCD_RESET:
@ -1448,17 +1482,17 @@ void UsbPacketReceived(uint8_t *packet, int len) {
SpinDelay(1000);
AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
// We're going to reset, and the bootrom will take control.
for(;;) {}
for (;;) {}
break;
case CMD_START_FLASH:
if(common_area.flags.bootrom_present) {
if (common_area.flags.bootrom_present) {
common_area.command = COMMON_AREA_COMMAND_ENTER_FLASH_MODE;
}
usb_disable();
AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
// We're going to flash, and the bootrom will take control.
for(;;) {}
for (;;) {}
break;
case CMD_DEVICE_INFO: {
@ -1466,21 +1500,22 @@ void UsbPacketReceived(uint8_t *packet, int len) {
if (common_area.flags.bootrom_present) {
dev_info |= DEVICE_INFO_FLAG_BOOTROM_PRESENT;
}
cmd_send(CMD_DEVICE_INFO,dev_info,0,0,0,0);
cmd_send(CMD_DEVICE_INFO, dev_info, 0, 0, 0, 0);
break;
}
default:
Dbprintf("%s: 0x%04x","unknown command:", c->cmd);
Dbprintf("%s: 0x%04x", "unknown command:", c->cmd);
break;
}
}
void __attribute__((noreturn)) AppMain(void) {
void __attribute__((noreturn)) AppMain(void)
{
SpinDelay(100);
clear_trace();
if(common_area.magic != COMMON_AREA_MAGIC || common_area.version != 1) {
if (common_area.magic != COMMON_AREA_MAGIC || common_area.version != 1) {
/* Initialize common area */
memset(&common_area, 0, sizeof(common_area));
common_area.magic = COMMON_AREA_MAGIC;
@ -1537,12 +1572,12 @@ void __attribute__((noreturn)) AppMain(void) {
uint8_t rx[sizeof(UsbCommand)];
for(;;) {
for (;;) {
WDT_HIT();
// Check if there is a usb packet available
if (usb_poll_validate_length()) {
if (usb_read(rx, sizeof(rx)) )
if (usb_read(rx, sizeof(rx)))
UsbPacketReceived(rx, sizeof(rx));
}
#ifdef WITH_FPC
@ -1558,11 +1593,11 @@ void __attribute__((noreturn)) AppMain(void) {
// Press button for one second to enter a possible standalone mode
if (BUTTON_HELD(1000) > 0) {
/*
* So this is the trigger to execute a standalone mod. Generic entrypoint by following the standalone/standalone.h headerfile
* All standalone mod "main loop" should be the RunMod() function.
* Since the standalone is either LF or HF, the somewhat bisarr defines below exists.
*/
/*
* So this is the trigger to execute a standalone mod. Generic entrypoint by following the standalone/standalone.h headerfile
* All standalone mod "main loop" should be the RunMod() function.
* Since the standalone is either LF or HF, the somewhat bisarr defines below exists.
*/
#if defined (WITH_LF) && ( defined (WITH_LF_SAMYRUN) || defined (WITH_LF_HIDBRUTE) || defined (WITH_LF_PROXBRUTE) )
RunMod();
#endif

View file

@ -110,7 +110,7 @@ void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd);
void EM4xWriteWord(uint32_t flag, uint32_t data, uint32_t pwd);
void Cotag(uint32_t arg0);
void setT55xxConfig(uint8_t arg0, t55xx_config *c);
t55xx_config * getT55xxConfig(void);
t55xx_config *getT55xxConfig(void);
void printT55xxConfig(void);
void loadT55xxConfig(void);
@ -133,11 +133,11 @@ void ReaderIso14443a(UsbCommand *c);
void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *parity);
void iso14a_set_trigger(bool enable);
// also used in emv
bool prepare_allocated_tag_modulation(tag_response_info_t * response_info);
bool prepare_allocated_tag_modulation(tag_response_info_t *response_info);
int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len);
// epa.h
void EPA_PACE_Collect_Nonce(UsbCommand * c);
void EPA_PACE_Collect_Nonce(UsbCommand *c);
void EPA_PACE_Replay(UsbCommand *c);
// mifarecmd.h
@ -169,35 +169,35 @@ void OnSuccessMagic();
void OnErrorMagic(uint8_t reason);
int32_t dist_nt(uint32_t nt1, uint32_t nt2);
void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype );
void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype);
//void RAMFUNC SniffMifare(uint8_t param);
//desfire
void Mifare_DES_Auth1(uint8_t arg0,uint8_t *datain);
void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain);
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
// mifaredesfire.h
bool InitDesfireCard();
void MifareSendCommand(uint8_t arg0,uint8_t arg1, uint8_t *datain);
void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain);
void MifareDesfireGetInformation();
void MifareDES_Auth1(uint8_t arg0,uint8_t arg1,uint8_t arg2, uint8_t *datain);
void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t * datain);
void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t *datain);
int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout);
size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout);
size_t CreateAPDU(uint8_t *datain, size_t len, uint8_t *dataout);
void OnSuccess();
void OnError(uint8_t reason);
// desfire_crypto.h
void *mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes, size_t offset, int communication_settings);
void *mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbytes, int communication_settings);
void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size);
void mifare_cypher_blocks_chained (desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation);
size_t key_block_size (const desfirekey_t key);
size_t padded_data_length (const size_t nbytes, const size_t block_size);
size_t maced_data_length (const desfirekey_t key, const size_t nbytes);
size_t enciphered_data_length (const desfiretag_t tag, const size_t nbytes, int communication_settings);
void cmac_generate_subkeys (desfirekey_t key);
void cmac (const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac);
void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes, size_t offset, int communication_settings);
void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes, int communication_settings);
void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size);
void mifare_cypher_blocks_chained(desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation);
size_t key_block_size(const desfirekey_t key);
size_t padded_data_length(const size_t nbytes, const size_t block_size);
size_t maced_data_length(const desfirekey_t key, const size_t nbytes);
size_t enciphered_data_length(const desfiretag_t tag, const size_t nbytes, int communication_settings);
void cmac_generate_subkeys(desfirekey_t key);
void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac);
// iso15693.h
void RecordRawAdcSamplesIso15693(void);
@ -205,14 +205,14 @@ void AcquireRawAdcSamplesIso15693(void);
void ReaderIso15693(uint32_t parameter); // Simulate an ISO15693 reader - greg
void SimTagIso15693(uint32_t parameter, uint8_t *uid); // simulate an ISO15693 tag - greg
void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag - atrox
void DirectTag15693Command(uint32_t datalen,uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI - atrox
void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI - atrox
void Iso15693InitReader(void);
// iclass.h
void RAMFUNC SniffIClass(void);
void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void ReaderIClass(uint8_t arg0);
void ReaderIClass_Replay(uint8_t arg0,uint8_t *MAC);
void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC);
void iClass_Authentication(uint8_t *MAC);
void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain);
void iClass_WriteBlock(uint8_t blockNo, uint8_t *data);
@ -224,22 +224,22 @@ void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType);
// hitag2.h
void SnoopHitag(uint32_t type);
void SimulateHitagTag(bool tag_mem_supplied, byte_t* data);
void ReaderHitag(hitag_function htf, hitag_data* htd);
void WriterHitag(hitag_function htf, hitag_data* htd, int page);
void SimulateHitagTag(bool tag_mem_supplied, byte_t *data);
void ReaderHitag(hitag_function htf, hitag_data *htd);
void WriterHitag(hitag_function htf, hitag_data *htd, int page);
//hitagS.h
void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data);
void ReadHitagS(hitag_function htf, hitag_data* htd);
void WritePageHitagS(hitag_function htf, hitag_data* htd,int page);
void check_challenges(bool file_given, byte_t* data);
void SimulateHitagSTag(bool tag_mem_supplied, byte_t *data);
void ReadHitagS(hitag_function htf, hitag_data *htd);
void WritePageHitagS(hitag_function htf, hitag_data *htd, int page);
void check_challenges(bool file_given, byte_t *data);
// cmd.h
uint8_t cmd_receive(UsbCommand* cmd);
uint8_t cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void* data, size_t len);
uint8_t cmd_receive(UsbCommand *cmd);
uint8_t cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len);
// util.h
void HfSnoop(int , int);
void HfSnoop(int, int);
//felica.c
extern void felica_sendraw(UsbCommand *c);

View file

@ -1,23 +1,27 @@
#include "buzzer.h"
void Ring_BEE_ONCE(uint16_t music_note) {
void Ring_BEE_ONCE(uint16_t music_note)
{
BEE_ON();
SpinDelayUs(music_note);
BEE_OFF();
SpinDelayUs(music_note);
}
void ring_2_7khz(uint16_t count) {
Ring_BEE_TIME(n_2_7khz,count);
void ring_2_7khz(uint16_t count)
{
Ring_BEE_TIME(n_2_7khz, count);
}
void Ring_BEE_TIME(uint16_t music_note,uint16_t count) {
for(uint16_t i=0 ; i < count; i++)
void Ring_BEE_TIME(uint16_t music_note, uint16_t count)
{
for (uint16_t i = 0 ; i < count; i++)
Ring_BEE_ONCE(music_note);
SpinDelay(9);
}
void Ring_ALL(uint16_t count) {
void Ring_ALL(uint16_t count)
{
Ring_BEE_TIME(note_1, count);
Ring_BEE_TIME(note_2, count);
Ring_BEE_TIME(note_3, count);
@ -28,14 +32,15 @@ void Ring_ALL(uint16_t count) {
SpinDelay(10);
}
void Ring_Little_Star(uint16_t count) {
Ring_BEE_TIME(note_1,count);
Ring_BEE_TIME(note_1,count);
Ring_BEE_TIME(note_5,count);
Ring_BEE_TIME(note_5,count);
Ring_BEE_TIME(note_6,count);
Ring_BEE_TIME(note_6,count);
Ring_BEE_TIME(note_5,2*count);
void Ring_Little_Star(uint16_t count)
{
Ring_BEE_TIME(note_1, count);
Ring_BEE_TIME(note_1, count);
Ring_BEE_TIME(note_5, count);
Ring_BEE_TIME(note_5, count);
Ring_BEE_TIME(note_6, count);
Ring_BEE_TIME(note_6, count);
Ring_BEE_TIME(note_5, 2 * count);
LED_A_ON();
/*
Ring_BEE_TIME(note_4,count);

View file

@ -21,7 +21,7 @@
#define note_8 0
extern void Ring_BEE_ONCE(uint16_t music_note);
extern void Ring_BEE_TIME(uint16_t music_note,uint16_t count);
extern void Ring_BEE_TIME(uint16_t music_note, uint16_t count);
extern void ring_2_7khz(uint16_t count);
extern void Ring_ALL(uint16_t count);
extern void Ring_Little_Star(uint16_t count);

View file

@ -71,7 +71,7 @@ const uint8_t sbox[256] = {
0x21, 0xE7, 0x4A, 0x8D, 0xFC, 0x90, 0x35, 0x6B
};
const uint8_t e_permtab[] ={
const uint8_t e_permtab[] = {
4, 6, /* 4 bytes in 6 bytes out*/
32, 1, 2, 3, 4, 5,
4, 5, 6, 7, 8, 9,
@ -83,7 +83,7 @@ const uint8_t e_permtab[] ={
28, 29, 30, 31, 32, 1
};
const uint8_t p_permtab[] ={
const uint8_t p_permtab[] = {
4, 4, /* 32 bit -> 32 bit */
16, 7, 20, 21,
29, 12, 28, 17,
@ -95,7 +95,7 @@ const uint8_t p_permtab[] ={
22, 11, 4, 25
};
const uint8_t ip_permtab[] ={
const uint8_t ip_permtab[] = {
8, 8, /* 64 bit -> 64 bit */
58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
@ -107,7 +107,7 @@ const uint8_t ip_permtab[] ={
63, 55, 47, 39, 31, 23, 15, 7
};
const uint8_t inv_ip_permtab[] ={
const uint8_t inv_ip_permtab[] = {
8, 8, /* 64 bit -> 64 bit */
40, 8, 48, 16, 56, 24, 64, 32,
39, 7, 47, 15, 55, 23, 63, 31,
@ -119,7 +119,7 @@ const uint8_t inv_ip_permtab[] ={
33, 1, 41, 9, 49, 17, 57, 25
};
const uint8_t pc1_permtab[] ={
const uint8_t pc1_permtab[] = {
8, 7, /* 64 bit -> 56 bit*/
57, 49, 41, 33, 25, 17, 9,
1, 58, 50, 42, 34, 26, 18,
@ -131,7 +131,7 @@ const uint8_t pc1_permtab[] ={
21, 13, 5, 28, 20, 12, 4
};
const uint8_t pc2_permtab[] ={
const uint8_t pc2_permtab[] = {
7, 6, /* 56 bit -> 48 bit */
14, 17, 11, 24, 1, 5,
3, 28, 15, 6, 21, 10,
@ -202,27 +202,29 @@ const uint8_t shiftkeyinv_permtab[] = {
#define ROTTABLE_INV 0x3F7E
/******************************************************************************/
void permute(const uint8_t *ptable, const uint8_t *in, uint8_t *out){
void permute(const uint8_t *ptable, const uint8_t *in, uint8_t *out)
{
uint8_t ob; /* in-bytes and out-bytes */
uint8_t byte, bit; /* counter for bit and byte */
ob = ptable[1];
ptable = &(ptable[2]);
for(byte=0; byte<ob; ++byte){
uint8_t x,t=0;
for(bit=0; bit<8; ++bit){
for (byte = 0; byte < ob; ++byte) {
uint8_t x, t = 0;
for (bit = 0; bit < 8; ++bit) {
x = *ptable++ - 1;
t<<=1;
if((in[x/8]) & (0x80>>(x%8)) ){
t|=0x01;
t <<= 1;
if ((in[x / 8]) & (0x80 >> (x % 8))) {
t |= 0x01;
}
}
out[byte]=t;
out[byte] = t;
}
}
/******************************************************************************/
void changeendian32(uint32_t * a){
void changeendian32(uint32_t *a)
{
*a = (*a & 0x000000FF) << 24 |
(*a & 0x0000FF00) << 8 |
(*a & 0x00FF0000) >> 8 |
@ -231,65 +233,70 @@ void changeendian32(uint32_t * a){
/******************************************************************************/
static inline
void shiftkey(uint8_t *key){
void shiftkey(uint8_t *key)
{
uint8_t k[7];
memcpy(k, key, 7);
permute((uint8_t*)shiftkey_permtab, k, key);
permute((uint8_t *)shiftkey_permtab, k, key);
}
/******************************************************************************/
static inline
void shiftkey_inv(uint8_t *key){
void shiftkey_inv(uint8_t *key)
{
uint8_t k[7];
memcpy(k, key, 7);
permute((uint8_t*)shiftkeyinv_permtab, k, key);
permute((uint8_t *)shiftkeyinv_permtab, k, key);
}
/******************************************************************************/
static inline
uint64_t splitin6bitwords(uint64_t a){
uint64_t ret=0;
uint64_t splitin6bitwords(uint64_t a)
{
uint64_t ret = 0;
a &= 0x0000ffffffffffffLL;
permute((uint8_t*)splitin6bitword_permtab, (uint8_t*)&a, (uint8_t*)&ret);
permute((uint8_t *)splitin6bitword_permtab, (uint8_t *)&a, (uint8_t *)&ret);
return ret;
}
/******************************************************************************/
static inline
uint8_t substitute(uint8_t a, uint8_t * sbp){
uint8_t substitute(uint8_t a, uint8_t *sbp)
{
uint8_t x;
x = sbp[a>>1];
x = (a&1)?x&0x0F:x>>4;
x = sbp[a >> 1];
x = (a & 1) ? x & 0x0F : x >> 4;
return x;
}
/******************************************************************************/
uint32_t des_f(uint32_t r, uint8_t* kr){
uint32_t des_f(uint32_t r, uint8_t *kr)
{
uint8_t i;
uint32_t t=0,ret;
uint32_t t = 0, ret;
uint64_t data;
uint8_t *sbp; /* sboxpointer */
permute((uint8_t*)e_permtab, (uint8_t*)&r, (uint8_t*)&data);
for(i=0; i<6; ++i)
((uint8_t*)&data)[i] ^= kr[i];
permute((uint8_t *)e_permtab, (uint8_t *)&r, (uint8_t *)&data);
for (i = 0; i < 6; ++i)
((uint8_t *)&data)[i] ^= kr[i];
/* Sbox substitution */
data = splitin6bitwords(data);
sbp=(uint8_t*)sbox;
for(i=0; i<8; ++i){
sbp = (uint8_t *)sbox;
for (i = 0; i < 8; ++i) {
uint8_t x;
x = substitute(((uint8_t*)&data)[i], sbp);
t<<=4;
x = substitute(((uint8_t *)&data)[i], sbp);
t <<= 4;
t |= x;
sbp += 32;
}
changeendian32(&t);
permute((uint8_t*)p_permtab,(uint8_t*)&t, (uint8_t*)&ret);
permute((uint8_t *)p_permtab, (uint8_t *)&t, (uint8_t *)&ret);
return ret;
}
@ -305,26 +312,27 @@ typedef struct {
#define R (data.d.v32[1])
#define L (data.d.v32[0])
void des_enc(void* out, const void* in, const void* key){
void des_enc(void *out, const void *in, const void *key)
{
uint8_t kr[6], k[7];
uint8_t i;
data_t data;
permute((uint8_t*)ip_permtab, (uint8_t*)in, data.d.v8);
permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k);
permute((uint8_t *)ip_permtab, (uint8_t *)in, data.d.v8);
permute((uint8_t *)pc1_permtab, (const uint8_t *)key, k);
for(i=0; i<8; ++i){
for (i = 0; i < 8; ++i) {
shiftkey(k);
if(ROTTABLE&((1<<((i<<1)+0))) )
if (ROTTABLE & ((1 << ((i << 1) + 0))))
shiftkey(k);
permute((uint8_t*)pc2_permtab, k, kr);
permute((uint8_t *)pc2_permtab, k, kr);
L ^= des_f(R, kr);
shiftkey(k);
if(ROTTABLE&((1<<((i<<1)+1))) )
if (ROTTABLE & ((1 << ((i << 1) + 1))))
shiftkey(k);
permute((uint8_t*)pc2_permtab, k, kr);
permute((uint8_t *)pc2_permtab, k, kr);
R ^= des_f(L, kr);
}
@ -333,32 +341,33 @@ void des_enc(void* out, const void* in, const void* key){
L ^= R;
R ^= L;
permute((uint8_t*)inv_ip_permtab, data.d.v8, (uint8_t*)out);
permute((uint8_t *)inv_ip_permtab, data.d.v8, (uint8_t *)out);
}
/******************************************************************************/
void des_dec(void* out, const void* in, const uint8_t* key){
void des_dec(void *out, const void *in, const uint8_t *key)
{
uint8_t kr[6],k[7];
uint8_t kr[6], k[7];
int8_t i;
data_t data;
permute((uint8_t*)ip_permtab, (uint8_t*)in, data.d.v8);
permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k);
for(i=7; i>=0; --i){
permute((uint8_t *)ip_permtab, (uint8_t *)in, data.d.v8);
permute((uint8_t *)pc1_permtab, (const uint8_t *)key, k);
for (i = 7; i >= 0; --i) {
permute((uint8_t*)pc2_permtab, k, kr);
permute((uint8_t *)pc2_permtab, k, kr);
L ^= des_f(R, kr);
shiftkey_inv(k);
if(ROTTABLE&((1<<((i<<1)+1))) ){
if (ROTTABLE & ((1 << ((i << 1) + 1)))) {
shiftkey_inv(k);
}
permute((uint8_t*)pc2_permtab, k, kr);
permute((uint8_t *)pc2_permtab, k, kr);
R ^= des_f(L, kr);
shiftkey_inv(k);
if(ROTTABLE&((1<<((i<<1)+0))) ){
if (ROTTABLE & ((1 << ((i << 1) + 0)))) {
shiftkey_inv(k);
}
@ -368,77 +377,79 @@ void des_dec(void* out, const void* in, const uint8_t* key){
L ^= R;
R ^= L;
permute((uint8_t*)inv_ip_permtab, data.d.v8, (uint8_t*)out);
permute((uint8_t *)inv_ip_permtab, data.d.v8, (uint8_t *)out);
}
/******************************************************************************/
void tdes_enc(void* out, void* in, const void* key){
des_enc(out, in, (uint8_t*)key + 0);
des_dec(out, out, (uint8_t*)key + 8);
des_enc(out, out, (uint8_t*)key +16);
void tdes_enc(void *out, void *in, const void *key)
{
des_enc(out, in, (uint8_t *)key + 0);
des_dec(out, out, (uint8_t *)key + 8);
des_enc(out, out, (uint8_t *)key + 16);
}
/******************************************************************************/
void tdes_dec(void* out, void* in, const uint8_t* key){
des_dec(out, in, (uint8_t*)key +16);
des_enc(out, out, (uint8_t*)key + 8);
des_dec(out, out, (uint8_t*)key + 0);
void tdes_dec(void *out, void *in, const uint8_t *key)
{
des_dec(out, in, (uint8_t *)key + 16);
des_enc(out, out, (uint8_t *)key + 8);
des_dec(out, out, (uint8_t *)key + 0);
}
void tdes_2key_enc(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]){
void tdes_2key_enc(void *out, const void *in, size_t length, const void *key, unsigned char iv[8])
{
if( length % 8 ) return;
if (length % 8) return;
uint8_t i;
uint8_t* tin = (uint8_t*) in;
uint8_t* tout = (uint8_t*) out;
uint8_t *tin = (uint8_t *) in;
uint8_t *tout = (uint8_t *) out;
while( length > 0 )
{
for( i = 0; i < 8; i++ )
tout[i] = (unsigned char)( tin[i] ^ iv[i] );
while (length > 0) {
for (i = 0; i < 8; i++)
tout[i] = (unsigned char)(tin[i] ^ iv[i]);
des_enc(tout, tin, (uint8_t*)key + 0);
des_dec(tout, tout, (uint8_t*)key + 8);
des_enc(tout, tout, (uint8_t*)key + 0);
des_enc(tout, tin, (uint8_t *)key + 0);
des_dec(tout, tout, (uint8_t *)key + 8);
des_enc(tout, tout, (uint8_t *)key + 0);
memcpy( iv, tout, 8 );
memcpy(iv, tout, 8);
tin += 8;
tout += 8;
length -= 8;
}
}
}
void tdes_2key_dec(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]){
void tdes_2key_dec(void *out, const void *in, size_t length, const void *key, unsigned char iv[8])
{
if( length % 8 ) return;
if (length % 8) return;
uint8_t i;
unsigned char temp[8];
uint8_t* tin = (uint8_t*) in;
uint8_t* tout = (uint8_t*) out;
uint8_t *tin = (uint8_t *) in;
uint8_t *tout = (uint8_t *) out;
while( length > 0 )
{
memcpy( temp, tin, 8 );
while (length > 0) {
memcpy(temp, tin, 8);
des_dec(tout, tin, (uint8_t*)key + 0);
des_enc(tout, tout, (uint8_t*)key + 8);
des_dec(tout, tout, (uint8_t*)key + 0);
des_dec(tout, tin, (uint8_t *)key + 0);
des_enc(tout, tout, (uint8_t *)key + 8);
des_dec(tout, tout, (uint8_t *)key + 0);
for( i = 0; i < 8; i++ )
tout[i] = (unsigned char)( tout[i] ^ iv[i] );
for (i = 0; i < 8; i++)
tout[i] = (unsigned char)(tout[i] ^ iv[i]);
memcpy( iv, temp, 8 );
memcpy(iv, temp, 8);
tin += 8;
tout += 8;
length -= 8;
}
}
}
/******************************************************************************/

View file

@ -56,7 +56,7 @@
* \param in pointer to the block (64 bit = 8 byte) where the plaintext is read from
* \param key pointer to the key (64 bit = 8 byte)
*/
void des_enc(void* out, const void* in, const void* key);
void des_enc(void *out, const void *in, const void *key);
/** \fn void des_dec(void* out, const void* in, const void* key)
* \brief decrypt a block with DES
@ -71,7 +71,7 @@ void des_enc(void* out, const void* in, const void* key);
* \param key pointer to the key (64 bit = 8 byte)
*/
//void des_dec(void* out, const void* in, const void* key);
void des_dec(void* out, const void* in, const uint8_t* key);
void des_dec(void *out, const void *in, const uint8_t *key);
/** \fn void tdes_enc(void* out, const void* in, const void* key)
* \brief encrypt a block with Tripple-DES
@ -86,7 +86,7 @@ void des_dec(void* out, const void* in, const uint8_t* key);
* \param key pointer to the key (192 bit = 24 byte)
*/
//void tdes_enc(void* out, const void* in, const void* key);
void tdes_enc(void* out, void* in, const void* key);
void tdes_enc(void *out, void *in, const void *key);
/** \fn void tdes_dec(void* out, const void* in, const void* key)
* \brief decrypt a block with Tripple-DES
@ -100,11 +100,11 @@ void tdes_enc(void* out, void* in, const void* key);
* \param in pointer to the block (64 bit = 8 byte) where the ciphertext is read from
* \param key pointer to the key (192 bit = 24 byte)
*/
//void tdes_dec(void* out, const void* in, const void* key);
void tdes_dec(void* out, void* in, const uint8_t* key);
//void tdes_dec(void* out, const void* in, const void* key);
void tdes_dec(void *out, void *in, const uint8_t *key);
void tdes_2key_enc(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]);
void tdes_2key_dec(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]);
void tdes_2key_enc(void *out, const void *in, size_t length, const void *key, unsigned char iv[8]);
void tdes_2key_dec(void *out, const void *in, size_t length, const void *key, unsigned char iv[8]);
// Copied from des.h in desfire imp.
typedef unsigned long DES_KS[16][2]; /* Single-key DES key schedule */

View file

@ -27,68 +27,72 @@
*/
#include "desfire_crypto.h"
static void xor (const uint8_t *ivect, uint8_t *data, const size_t len);
static size_t key_macing_length (desfirekey_t key);
static void xor(const uint8_t *ivect, uint8_t *data, const size_t len);
static size_t key_macing_length(desfirekey_t key);
// iceman, see memxor inside string.c, dest/src swapped..
static void xor (const uint8_t *ivect, uint8_t *data, const size_t len) {
static void xor(const uint8_t *ivect, uint8_t *data, const size_t len)
{
for (size_t i = 0; i < len; i++) {
data[i] ^= ivect[i];
}
}
void cmac_generate_subkeys ( desfirekey_t key) {
int kbs = key_block_size (key);
void cmac_generate_subkeys(desfirekey_t key)
{
int kbs = key_block_size(key);
const uint8_t R = (kbs == 8) ? 0x1B : 0x87;
uint8_t l[kbs];
memset (l, 0, kbs);
memset(l, 0, kbs);
uint8_t ivect[kbs];
memset (ivect, 0, kbs);
memset(ivect, 0, kbs);
mifare_cypher_blocks_chained (NULL, key, ivect, l, kbs, MCD_RECEIVE, MCO_ENCYPHER);
mifare_cypher_blocks_chained(NULL, key, ivect, l, kbs, MCD_RECEIVE, MCO_ENCYPHER);
bool xor = false;
// Used to compute CMAC on complete blocks
memcpy (key->cmac_sk1, l, kbs);
memcpy(key->cmac_sk1, l, kbs);
xor = l[0] & 0x80;
lsl (key->cmac_sk1, kbs);
lsl(key->cmac_sk1, kbs);
if (xor)
key->cmac_sk1[kbs-1] ^= R;
key->cmac_sk1[kbs - 1] ^= R;
// Used to compute CMAC on the last block if non-complete
memcpy (key->cmac_sk2, key->cmac_sk1, kbs);
memcpy(key->cmac_sk2, key->cmac_sk1, kbs);
xor = key->cmac_sk1[0] & 0x80;
lsl (key->cmac_sk2, kbs);
lsl(key->cmac_sk2, kbs);
if (xor)
key->cmac_sk2[kbs-1] ^= R;
key->cmac_sk2[kbs - 1] ^= R;
}
void cmac (const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac) {
int kbs = key_block_size (key);
uint8_t *buffer = malloc (padded_data_length (len, kbs));
void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac)
{
int kbs = key_block_size(key);
uint8_t *buffer = malloc(padded_data_length(len, kbs));
memcpy (buffer, data, len);
memcpy(buffer, data, len);
if ((!len) || (len % kbs)) {
buffer[len++] = 0x80;
while (len % kbs) {
buffer[len++] = 0x00;
}
xor (key->cmac_sk2, buffer + len - kbs, kbs);
xor(key->cmac_sk2, buffer + len - kbs, kbs);
} else {
xor (key->cmac_sk1, buffer + len - kbs, kbs);
xor(key->cmac_sk1, buffer + len - kbs, kbs);
}
mifare_cypher_blocks_chained (NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER);
mifare_cypher_blocks_chained(NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER);
memcpy (cmac, ivect, kbs);
memcpy(cmac, ivect, kbs);
free(buffer);
}
size_t key_block_size (const desfirekey_t key) {
size_t key_block_size(const desfirekey_t key)
{
size_t block_size = 8;
switch (key->type) {
case T_DES:
@ -106,7 +110,8 @@ size_t key_block_size (const desfirekey_t key) {
/*
* Size of MACing produced with the key.
*/
static size_t key_macing_length (const desfirekey_t key) {
static size_t key_macing_length(const desfirekey_t key)
{
size_t mac_length = MAC_LENGTH;
switch (key->type) {
case T_DES:
@ -124,7 +129,8 @@ static size_t key_macing_length (const desfirekey_t key) {
/*
* Size required to store nbytes of data in a buffer of size n*block_size.
*/
size_t padded_data_length (const size_t nbytes, const size_t block_size) {
size_t padded_data_length(const size_t nbytes, const size_t block_size)
{
if ((!nbytes) || (nbytes % block_size))
return ((nbytes / block_size) + 1) * block_size;
else
@ -134,13 +140,15 @@ size_t padded_data_length (const size_t nbytes, const size_t block_size) {
/*
* Buffer size required to MAC nbytes of data
*/
size_t maced_data_length (const desfirekey_t key, const size_t nbytes) {
return nbytes + key_macing_length (key);
size_t maced_data_length(const desfirekey_t key, const size_t nbytes)
{
return nbytes + key_macing_length(key);
}
/*
* Buffer size required to encipher nbytes of data and a two bytes CRC.
*/
size_t enciphered_data_length (const desfiretag_t tag, const size_t nbytes, int communication_settings) {
size_t enciphered_data_length(const desfiretag_t tag, const size_t nbytes, int communication_settings)
{
size_t crc_length = 0;
if (!(communication_settings & NO_CRC)) {
switch (DESFIRE(tag)->authentication_scheme) {
@ -153,12 +161,13 @@ size_t enciphered_data_length (const desfiretag_t tag, const size_t nbytes, int
}
}
size_t block_size = DESFIRE(tag)->session_key ? key_block_size (DESFIRE(tag)->session_key) : 1;
size_t block_size = DESFIRE(tag)->session_key ? key_block_size(DESFIRE(tag)->session_key) : 1;
return padded_data_length (nbytes + crc_length, block_size);
return padded_data_length(nbytes + crc_length, block_size);
}
void* mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes, size_t offset, int communication_settings) {
void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes, size_t offset, int communication_settings)
{
uint8_t *res = data;
uint8_t mac[4];
size_t edl;
@ -193,40 +202,40 @@ void* mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes
break;
/* pass through */
edl = padded_data_length (*nbytes - offset, key_block_size (DESFIRE(tag)->session_key)) + offset;
edl = padded_data_length(*nbytes - offset, key_block_size(DESFIRE(tag)->session_key)) + offset;
// Fill in the crypto buffer with data ...
memcpy (res, data, *nbytes);
memcpy(res, data, *nbytes);
// ... and 0 padding
memset (res + *nbytes, 0, edl - *nbytes);
memset(res + *nbytes, 0, edl - *nbytes);
mifare_cypher_blocks_chained (tag, NULL, NULL, res + offset, edl - offset, MCD_SEND, MCO_ENCYPHER);
mifare_cypher_blocks_chained(tag, NULL, NULL, res + offset, edl - offset, MCD_SEND, MCO_ENCYPHER);
memcpy (mac, res + edl - 8, 4);
memcpy(mac, res + edl - 8, 4);
// Copy again provided data (was overwritten by mifare_cypher_blocks_chained)
memcpy (res, data, *nbytes);
memcpy(res, data, *nbytes);
if (!(communication_settings & MAC_COMMAND))
break;
// Append MAC
size_t bla = maced_data_length (DESFIRE(tag)->session_key, *nbytes - offset) + offset;
size_t bla = maced_data_length(DESFIRE(tag)->session_key, *nbytes - offset) + offset;
bla++;
memcpy (res + *nbytes, mac, 4);
memcpy(res + *nbytes, mac, 4);
*nbytes += 4;
break;
case AS_NEW:
if (!(communication_settings & CMAC_COMMAND))
break;
cmac (key, DESFIRE (tag)->ivect, res, *nbytes, DESFIRE (tag)->cmac);
cmac(key, DESFIRE(tag)->ivect, res, *nbytes, DESFIRE(tag)->cmac);
if (append_mac) {
size_t len = maced_data_length (key, *nbytes);
size_t len = maced_data_length(key, *nbytes);
++len;
memcpy (res, data, *nbytes);
memcpy (res + *nbytes, DESFIRE (tag)->cmac, CMAC_LENGTH);
memcpy(res, data, *nbytes);
memcpy(res + *nbytes, DESFIRE(tag)->cmac, CMAC_LENGTH);
*nbytes += CMAC_LENGTH;
}
break;
@ -251,29 +260,29 @@ void* mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes
if (!(communication_settings & ENC_COMMAND))
break;
edl = enciphered_data_length (tag, *nbytes - offset, communication_settings) + offset;
edl = enciphered_data_length(tag, *nbytes - offset, communication_settings) + offset;
// Fill in the crypto buffer with data ...
memcpy (res, data, *nbytes);
memcpy(res, data, *nbytes);
if (!(communication_settings & NO_CRC)) {
// ... CRC ...
switch (DESFIRE (tag)->authentication_scheme) {
switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY:
AddCrc14A(res + offset, *nbytes - offset);
*nbytes += 2;
break;
case AS_NEW:
crc32_append (res, *nbytes);
crc32_append(res, *nbytes);
*nbytes += 4;
break;
}
}
// ... and padding
memset (res + *nbytes, 0, edl - *nbytes);
memset(res + *nbytes, 0, edl - *nbytes);
*nbytes = edl;
mifare_cypher_blocks_chained (tag, NULL, NULL, res + offset, *nbytes - offset, MCD_SEND, (AS_NEW == DESFIRE(tag)->authentication_scheme) ? MCO_ENCYPHER : MCO_DECYPHER);
mifare_cypher_blocks_chained(tag, NULL, NULL, res + offset, *nbytes - offset, MCD_SEND, (AS_NEW == DESFIRE(tag)->authentication_scheme) ? MCO_ENCYPHER : MCO_DECYPHER);
break;
default:
@ -286,7 +295,7 @@ void* mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes
}
void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbytes, int communication_settings)
void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes, int communication_settings)
{
void *res = data;
size_t edl;
@ -310,34 +319,34 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
/* pass through */
case MDCM_MACED:
switch (DESFIRE (tag)->authentication_scheme) {
switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY:
if (communication_settings & MAC_VERIFY) {
*nbytes -= key_macing_length (key);
*nbytes -= key_macing_length(key);
if (*nbytes <= 0) {
*nbytes = -1;
res = NULL;
#ifdef WITH_DEBUG
Dbprintf ("No room for MAC!");
Dbprintf("No room for MAC!");
#endif
break;
}
edl = enciphered_data_length (tag, *nbytes - 1, communication_settings);
edata = malloc (edl);
edl = enciphered_data_length(tag, *nbytes - 1, communication_settings);
edata = malloc(edl);
memcpy (edata, data, *nbytes - 1);
memset ((uint8_t *)edata + *nbytes - 1, 0, edl - *nbytes + 1);
memcpy(edata, data, *nbytes - 1);
memset((uint8_t *)edata + *nbytes - 1, 0, edl - *nbytes + 1);
mifare_cypher_blocks_chained (tag, NULL, NULL, edata, edl, MCD_SEND, MCO_ENCYPHER);
mifare_cypher_blocks_chained(tag, NULL, NULL, edata, edl, MCD_SEND, MCO_ENCYPHER);
if (0 != memcmp ((uint8_t *)data + *nbytes - 1, (uint8_t *)edata + edl - 8, 4)) {
if (0 != memcmp((uint8_t *)data + *nbytes - 1, (uint8_t *)edata + edl - 8, 4)) {
#ifdef WITH_DEBUG
Dbprintf ("MACing not verified");
hexdump ((uint8_t *)data + *nbytes - 1, key_macing_length (key), "Expect ", 0);
hexdump ((uint8_t *)edata + edl - 8, key_macing_length (key), "Actual ", 0);
Dbprintf("MACing not verified");
hexdump((uint8_t *)data + *nbytes - 1, key_macing_length(key), "Expect ", 0);
hexdump((uint8_t *)edata + edl - 8, key_macing_length(key), "Actual ", 0);
#endif
DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
*nbytes = -1;
res = NULL;
}
@ -353,21 +362,21 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
break;
}
first_cmac_byte = ((uint8_t *)data)[*nbytes - 9];
((uint8_t *)data)[*nbytes - 9] = ((uint8_t *)data)[*nbytes-1];
((uint8_t *)data)[*nbytes - 9] = ((uint8_t *)data)[*nbytes - 1];
}
int n = (communication_settings & CMAC_VERIFY) ? 8 : 0;
cmac (key, DESFIRE (tag)->ivect, ((uint8_t *)data), *nbytes - n, DESFIRE (tag)->cmac);
cmac(key, DESFIRE(tag)->ivect, ((uint8_t *)data), *nbytes - n, DESFIRE(tag)->cmac);
if (communication_settings & CMAC_VERIFY) {
((uint8_t *)data)[*nbytes - 9] = first_cmac_byte;
if (0 != memcmp (DESFIRE (tag)->cmac, (uint8_t *)data + *nbytes - 9, 8)) {
if (0 != memcmp(DESFIRE(tag)->cmac, (uint8_t *)data + *nbytes - 9, 8)) {
#ifdef WITH_DEBUG
Dbprintf ("CMAC NOT verified :-(");
hexdump ((uint8_t *)data + *nbytes - 9, 8, "Expect ", 0);
hexdump (DESFIRE (tag)->cmac, 8, "Actual ", 0);
Dbprintf("CMAC NOT verified :-(");
hexdump((uint8_t *)data + *nbytes - 9, 8, "Expect ", 0);
hexdump(DESFIRE(tag)->cmac, 8, "Actual ", 0);
#endif
DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
*nbytes = -1;
res = NULL;
} else {
@ -377,7 +386,7 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
break;
}
free (edata);
free(edata);
break;
case MDCM_ENCIPHERED:
@ -409,14 +418,14 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
* `------------------'
*/
mifare_cypher_blocks_chained (tag, NULL, NULL, res, *nbytes, MCD_RECEIVE, MCO_DECYPHER);
mifare_cypher_blocks_chained(tag, NULL, NULL, res, *nbytes, MCD_RECEIVE, MCO_DECYPHER);
/*
* Look for the CRC and ensure it is followed by NULL padding. We
* can't start by the end because the CRC is supposed to be 0 when
* verified, and accumulating 0's in it should not change it.
*/
switch (DESFIRE (tag)->authentication_scheme) {
switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY:
crc_pos = *nbytes - 8 - 1; // The CRC can be over two blocks
if (crc_pos < 0) {
@ -426,15 +435,15 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
break;
case AS_NEW:
/* Move status between payload and CRC */
res = DESFIRE (tag)->crypto_buffer;
memcpy (res, data, *nbytes);
res = DESFIRE(tag)->crypto_buffer;
memcpy(res, data, *nbytes);
crc_pos = (*nbytes) - 16 - 3;
if (crc_pos < 0) {
/* Single block */
crc_pos = 0;
}
memcpy ((uint8_t *)res + crc_pos + 1, (uint8_t *)res + crc_pos, *nbytes - crc_pos);
memcpy((uint8_t *)res + crc_pos + 1, (uint8_t *)res + crc_pos, *nbytes - crc_pos);
((uint8_t *)res)[crc_pos] = 0x00;
crc_pos++;
*nbytes += 1;
@ -442,11 +451,11 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
}
do {
uint16_t crc16 =0x00;
uint16_t crc16 = 0x00;
uint32_t crc;
switch (DESFIRE (tag)->authentication_scheme) {
switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY:
AddCrc14A( (uint8_t*)res, end_crc_pos);
AddCrc14A((uint8_t *)res, end_crc_pos);
end_crc_pos = crc_pos + 2;
//
@ -455,20 +464,20 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
break;
case AS_NEW:
end_crc_pos = crc_pos + 4;
crc32_ex (res, end_crc_pos, (uint8_t *)&crc);
crc32_ex(res, end_crc_pos, (uint8_t *)&crc);
break;
}
if (!crc) {
verified = true;
for (int n = end_crc_pos; n < *nbytes - 1; n++) {
uint8_t byte = ((uint8_t *)res)[n];
if (!( (0x00 == byte) || ((0x80 == byte) && (n == end_crc_pos)) ))
if (!((0x00 == byte) || ((0x80 == byte) && (n == end_crc_pos))))
verified = false;
}
}
if (verified) {
*nbytes = crc_pos;
switch (DESFIRE (tag)->authentication_scheme) {
switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY:
((uint8_t *)data)[(*nbytes)++] = 0x00;
break;
@ -477,7 +486,7 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
break;
}
} else {
switch (DESFIRE (tag)->authentication_scheme) {
switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY:
break;
case AS_NEW:
@ -495,7 +504,7 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
/* FIXME In some configurations, the file is transmitted PLAIN */
Dbprintf("CRC not verified in decyphered stream");
#endif
DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
*nbytes = -1;
res = NULL;
}
@ -512,14 +521,14 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
}
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_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size)
{
uint8_t ovect[MAX_CRYPTO_BLOCK_SIZE];
if (direction == MCD_SEND) {
xor (ivect, data, block_size);
xor(ivect, data, block_size);
} else {
memcpy (ovect, data, block_size);
memcpy(ovect, data, block_size);
}
uint8_t edata[MAX_CRYPTO_BLOCK_SIZE];
@ -543,7 +552,7 @@ void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
tdes_enc(edata,data, key->data);
tdes_enc(edata, data, key->data);
break;
case MCO_DECYPHER:
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
@ -556,7 +565,7 @@ void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect
case T_3K3DES:
switch (operation) {
case MCO_ENCYPHER:
tdes_enc(edata,data, key->data);
tdes_enc(edata, data, key->data);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_ENCRYPT);
@ -570,19 +579,16 @@ void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect
}
break;
case T_AES:
switch (operation)
{
case MCO_ENCYPHER:
{
switch (operation) {
case MCO_ENCYPHER: {
AesCtx ctx;
AesCtxIni(&ctx, ivect, key->data, KEY128,CBC);
AesEncrypt(&ctx, data, edata, sizeof(edata) );
AesCtxIni(&ctx, ivect, key->data, KEY128, CBC);
AesEncrypt(&ctx, data, edata, sizeof(edata));
break;
}
case MCO_DECYPHER:
{
case MCO_DECYPHER: {
AesCtx ctx;
AesCtxIni(&ctx, ivect, key->data, KEY128,CBC);
AesCtxIni(&ctx, ivect, key->data, KEY128, CBC);
AesDecrypt(&ctx, edata, data, sizeof(edata));
break;
}
@ -590,13 +596,13 @@ void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect
break;
}
memcpy (data, edata, block_size);
memcpy(data, edata, block_size);
if (direction == MCD_SEND) {
memcpy (ivect, data, block_size);
memcpy(ivect, data, block_size);
} else {
xor (ivect, data, block_size);
memcpy (ivect, ovect, block_size);
xor(ivect, data, block_size);
memcpy(ivect, ovect, block_size);
}
}
@ -610,29 +616,30 @@ void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect
* Because the tag may contain additional data, one may need to call this
* function with tag, key and ivect defined.
*/
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) {
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 block_size;
if (tag) {
if (!key)
key = DESFIRE (tag)->session_key;
key = DESFIRE(tag)->session_key;
if (!ivect)
ivect = DESFIRE (tag)->ivect;
ivect = DESFIRE(tag)->ivect;
switch (DESFIRE (tag)->authentication_scheme) {
switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY:
memset (ivect, 0, MAX_CRYPTO_BLOCK_SIZE);
memset(ivect, 0, MAX_CRYPTO_BLOCK_SIZE);
break;
case AS_NEW:
break;
}
}
block_size = key_block_size (key);
block_size = key_block_size(key);
size_t offset = 0;
while (offset < data_size) {
mifare_cypher_single_block (key, data + offset, ivect, direction, operation, block_size);
mifare_cypher_single_block(key, data + offset, ivect, direction, operation, block_size);
offset += block_size;
}
}

View file

@ -19,9 +19,10 @@
#include "desfire_key.h"
static inline void update_key_schedules (desfirekey_t key);
static inline void update_key_schedules(desfirekey_t key);
static inline void update_key_schedules (desfirekey_t key) {
static inline void update_key_schedules(desfirekey_t key)
{
// DES_set_key ((DES_cblock *)key->data, &(key->ks1));
// DES_set_key ((DES_cblock *)(key->data + 8), &(key->ks2));
// if (T_3K3DES == key->type) {
@ -29,72 +30,81 @@ static inline void update_key_schedules (desfirekey_t key) {
// }
}
void Desfire_des_key_new (const uint8_t value[8], desfirekey_t key) {
void Desfire_des_key_new(const uint8_t value[8], desfirekey_t key)
{
uint8_t data[8];
memcpy (data, value, 8);
for (int n=0; n < 8; n++)
memcpy(data, value, 8);
for (int n = 0; n < 8; n++)
data[n] &= 0xfe;
Desfire_des_key_new_with_version (data, key);
Desfire_des_key_new_with_version(data, key);
}
void Desfire_des_key_new_with_version (const uint8_t value[8], desfirekey_t key) {
if ( key != NULL) {
void Desfire_des_key_new_with_version(const uint8_t value[8], desfirekey_t key)
{
if (key != NULL) {
key->type = T_DES;
memcpy (key->data, value, 8);
memcpy (key->data+8, value, 8);
update_key_schedules (key);
memcpy(key->data, value, 8);
memcpy(key->data + 8, value, 8);
update_key_schedules(key);
}
}
void Desfire_3des_key_new (const uint8_t value[16], desfirekey_t key) {
void Desfire_3des_key_new(const uint8_t value[16], desfirekey_t key)
{
uint8_t data[16];
memcpy (data, value, 16);
for (int n=0; n < 8; n++)
memcpy(data, value, 16);
for (int n = 0; n < 8; n++)
data[n] &= 0xfe;
for (int n=8; n < 16; n++)
for (int n = 8; n < 16; n++)
data[n] |= 0x01;
Desfire_3des_key_new_with_version (data, key);
Desfire_3des_key_new_with_version(data, key);
}
void Desfire_3des_key_new_with_version (const uint8_t value[16], desfirekey_t key) {
if ( key != NULL ){
void Desfire_3des_key_new_with_version(const uint8_t value[16], desfirekey_t key)
{
if (key != NULL) {
key->type = T_3DES;
memcpy (key->data, value, 16);
memcpy (key->data + 16, value, 8);
update_key_schedules (key);
memcpy(key->data, value, 16);
memcpy(key->data + 16, value, 8);
update_key_schedules(key);
}
}
void Desfire_3k3des_key_new (const uint8_t value[24], desfirekey_t key) {
void Desfire_3k3des_key_new(const uint8_t value[24], desfirekey_t key)
{
uint8_t data[24];
memcpy (data, value, 24);
for (int n=0; n < 8; n++)
memcpy(data, value, 24);
for (int n = 0; n < 8; n++)
data[n] &= 0xfe;
Desfire_3k3des_key_new_with_version (data, key);
Desfire_3k3des_key_new_with_version(data, key);
}
void Desfire_3k3des_key_new_with_version (const uint8_t value[24], desfirekey_t key) {
if ( key != NULL){
void Desfire_3k3des_key_new_with_version(const uint8_t value[24], desfirekey_t key)
{
if (key != NULL) {
key->type = T_3K3DES;
memcpy (key->data, value, 24);
update_key_schedules (key);
memcpy(key->data, value, 24);
update_key_schedules(key);
}
}
void Desfire_aes_key_new (const uint8_t value[16], desfirekey_t key) {
Desfire_aes_key_new_with_version (value, 0, key);
void Desfire_aes_key_new(const uint8_t value[16], desfirekey_t key)
{
Desfire_aes_key_new_with_version(value, 0, key);
}
void Desfire_aes_key_new_with_version (const uint8_t value[16], uint8_t version, desfirekey_t key) {
void Desfire_aes_key_new_with_version(const uint8_t value[16], uint8_t version, desfirekey_t key)
{
if (key != NULL) {
memcpy (key->data, value, 16);
memcpy(key->data, value, 16);
key->type = T_AES;
key->aes_version = version;
}
}
uint8_t Desfire_key_get_version (desfirekey_t key) {
uint8_t Desfire_key_get_version(desfirekey_t key)
{
uint8_t version = 0;
for (int n = 0; n < 8; n++) {
@ -103,54 +113,55 @@ uint8_t Desfire_key_get_version (desfirekey_t key) {
return version;
}
void Desfire_key_set_version (desfirekey_t key, uint8_t version)
void Desfire_key_set_version(desfirekey_t key, uint8_t version)
{
for (int n = 0; n < 8; n++) {
uint8_t version_bit = ((version & (1 << (7-n))) >> (7-n));
uint8_t version_bit = ((version & (1 << (7 - n))) >> (7 - n));
key->data[n] &= 0xfe;
key->data[n] |= version_bit;
if (key->type == T_DES) {
key->data[n+8] = key->data[n];
key->data[n + 8] = key->data[n];
} else {
// Write ~version to avoid turning a 3DES key into a DES key
key->data[n+8] &= 0xfe;
key->data[n+8] |= ~version_bit;
key->data[n + 8] &= 0xfe;
key->data[n + 8] |= ~version_bit;
}
}
}
void Desfire_session_key_new (const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key) {
void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key)
{
uint8_t buffer[24];
switch (authkey->type) {
case T_DES:
memcpy (buffer, rnda, 4);
memcpy (buffer+4, rndb, 4);
Desfire_des_key_new_with_version (buffer, key);
memcpy(buffer, rnda, 4);
memcpy(buffer + 4, rndb, 4);
Desfire_des_key_new_with_version(buffer, key);
break;
case T_3DES:
memcpy (buffer, rnda, 4);
memcpy (buffer+4, rndb, 4);
memcpy (buffer+8, rnda+4, 4);
memcpy (buffer+12, rndb+4, 4);
Desfire_3des_key_new_with_version (buffer, key);
memcpy(buffer, rnda, 4);
memcpy(buffer + 4, rndb, 4);
memcpy(buffer + 8, rnda + 4, 4);
memcpy(buffer + 12, rndb + 4, 4);
Desfire_3des_key_new_with_version(buffer, key);
break;
case T_3K3DES:
memcpy (buffer, rnda, 4);
memcpy (buffer+4, rndb, 4);
memcpy (buffer+8, rnda+6, 4);
memcpy (buffer+12, rndb+6, 4);
memcpy (buffer+16, rnda+12, 4);
memcpy (buffer+20, rndb+12, 4);
Desfire_3k3des_key_new (buffer, key);
memcpy(buffer, rnda, 4);
memcpy(buffer + 4, rndb, 4);
memcpy(buffer + 8, rnda + 6, 4);
memcpy(buffer + 12, rndb + 6, 4);
memcpy(buffer + 16, rnda + 12, 4);
memcpy(buffer + 20, rndb + 12, 4);
Desfire_3k3des_key_new(buffer, key);
break;
case T_AES:
memcpy (buffer, rnda, 4);
memcpy (buffer+4, rndb, 4);
memcpy (buffer+8, rnda+12, 4);
memcpy (buffer+12, rndb+12, 4);
Desfire_aes_key_new (buffer, key);
memcpy(buffer, rnda, 4);
memcpy(buffer + 4, rndb, 4);
memcpy(buffer + 8, rnda + 12, 4);
memcpy(buffer + 12, rndb + 12, 4);
Desfire_aes_key_new(buffer, key);
break;
}
}

View file

@ -6,15 +6,15 @@
#include "iso14443a.h"
#include "desfire.h"
//#include "mifare.h" // iso14a_card_select_t struct
void Desfire_des_key_new (const uint8_t value[8], desfirekey_t key);
void Desfire_3des_key_new (const uint8_t value[16], desfirekey_t key);
void Desfire_des_key_new_with_version (const uint8_t value[8], desfirekey_t key);
void Desfire_3des_key_new_with_version (const uint8_t value[16], desfirekey_t key);
void Desfire_3k3des_key_new (const uint8_t value[24], desfirekey_t key);
void Desfire_3k3des_key_new_with_version (const uint8_t value[24], desfirekey_t key);
void Desfire_aes_key_new (const uint8_t value[16], desfirekey_t key);
void Desfire_aes_key_new_with_version (const uint8_t value[16], uint8_t version,desfirekey_t key);
uint8_t Desfire_key_get_version (desfirekey_t key);
void Desfire_key_set_version (desfirekey_t key, uint8_t version);
void Desfire_session_key_new (const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key);
void Desfire_des_key_new(const uint8_t value[8], desfirekey_t key);
void Desfire_3des_key_new(const uint8_t value[16], desfirekey_t key);
void Desfire_des_key_new_with_version(const uint8_t value[8], desfirekey_t key);
void Desfire_3des_key_new_with_version(const uint8_t value[16], desfirekey_t key);
void Desfire_3k3des_key_new(const uint8_t value[24], desfirekey_t key);
void Desfire_3k3des_key_new_with_version(const uint8_t value[24], desfirekey_t key);
void Desfire_aes_key_new(const uint8_t value[16], desfirekey_t key);
void Desfire_aes_key_new_with_version(const uint8_t value[16], uint8_t version, desfirekey_t key);
uint8_t Desfire_key_get_version(desfirekey_t key);
void Desfire_key_set_version(desfirekey_t key, uint8_t version);
void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key);
#endif

View file

@ -105,8 +105,7 @@ static char iso_type = 0;
//-----------------------------------------------------------------------------
int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response)
{
switch(iso_type)
{
switch (iso_type) {
case 'a':
return iso14_apdu(apdu, (uint16_t) length, false, response, NULL);
break;
@ -156,7 +155,7 @@ size_t EPA_Parse_CardAccess(uint8_t *data,
index += 2;
// check for extended length
if ((data[index - 1] & 0x80) != 0) {
index += (data[index-1] & 0x7F);
index += (data[index - 1] & 0x7F);
}
}
// OID
@ -166,8 +165,7 @@ size_t EPA_Parse_CardAccess(uint8_t *data,
&& memcmp(data + index + 2,
oid_pace_start,
sizeof(oid_pace_start)) == 0 // content matches
&& pace_info != NULL)
{
&& pace_info != NULL) {
// first, clear the pace_info struct
memset(pace_info, 0, sizeof(pace_version_info_t));
memcpy(pace_info->oid, data + index + 2, sizeof(pace_info->oid));
@ -176,8 +174,7 @@ size_t EPA_Parse_CardAccess(uint8_t *data,
if (data[index] == 02 && data[index + 1] == 01) {
pace_info->version = data[index + 2];
index += 3;
}
else {
} else {
return index;
}
// after that there might(!) be the parameter ID
@ -185,8 +182,7 @@ size_t EPA_Parse_CardAccess(uint8_t *data,
pace_info->parameter_id = data[index + 2];
index += 3;
}
}
else {
} else {
// skip this OID
index += 2 + data[index + 1];
}
@ -195,8 +191,7 @@ size_t EPA_Parse_CardAccess(uint8_t *data,
// TODO: This needs to be extended to support long tags
else if (data[index + 1] == 0) {
return index;
}
else {
} else {
// skip this part
// TODO: This needs to be extended to support long tags
// TODO: This needs to be extended to support unknown elements with
@ -229,8 +224,7 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length)
response_apdu);
if (rapdu_length < 6
|| response_apdu[rapdu_length - 4] != 0x90
|| response_apdu[rapdu_length - 3] != 0x00)
{
|| response_apdu[rapdu_length - 3] != 0x00) {
DbpString("Failed to select EF.CardAccess!");
return -1;
}
@ -241,8 +235,7 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length)
response_apdu);
if (rapdu_length <= 6
|| response_apdu[rapdu_length - 4] != 0x90
|| response_apdu[rapdu_length - 3] != 0x00)
{
|| response_apdu[rapdu_length - 3] != 0x00) {
Dbprintf("Failed to read EF.CardAccess!");
return -1;
}
@ -251,7 +244,7 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length)
// length of data available: apdu_length - 4 (ISO frame) - 2 (SW)
size_t to_copy = rapdu_length - 6;
to_copy = to_copy < max_length ? to_copy : max_length;
memcpy(buffer, response_apdu+2, to_copy);
memcpy(buffer, response_apdu + 2, to_copy);
return to_copy;
}
@ -265,7 +258,7 @@ static void EPA_PACE_Collect_Nonce_Abort(uint8_t step, int func_return)
EPA_Finish();
// send the USB packet
cmd_send(CMD_ACK,step,func_return,0,0,0);
cmd_send(CMD_ACK, step, func_return, 0, 0, 0);
}
//-----------------------------------------------------------------------------
@ -324,8 +317,7 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
uint8_t requested_size = (uint8_t)c->arg[0];
func_return = EPA_PACE_Get_Nonce(requested_size, nonce);
// check if the command succeeded
if (func_return < 0)
{
if (func_return < 0) {
EPA_PACE_Collect_Nonce_Abort(4, func_return);
return;
}
@ -334,7 +326,7 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
EPA_Finish();
// save received information
cmd_send(CMD_ACK,0,func_return,0,nonce,func_return);
cmd_send(CMD_ACK, 0, func_return, 0, nonce, func_return);
}
//-----------------------------------------------------------------------------
@ -364,21 +356,18 @@ int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce)
// check if the command succeeded
if (send_return < 6
|| response_apdu[send_return - 4] != 0x90
|| response_apdu[send_return - 3] != 0x00)
{
|| response_apdu[send_return - 3] != 0x00) {
return -1;
}
// if there is no nonce in the RAPDU, return here
if (send_return < 10)
{
if (send_return < 10) {
// no error
return 0;
}
// get the actual length of the nonce
uint8_t nonce_length = response_apdu[5];
if (nonce_length > send_return - 10)
{
if (nonce_length > send_return - 10) {
nonce_length = send_return - 10;
}
// copy the nonce
@ -435,8 +424,7 @@ int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password)
// check if the command succeeded
if (send_return != 6
|| response_apdu[send_return - 4] != 0x90
|| response_apdu[send_return - 3] != 0x00)
{
|| response_apdu[send_return - 3] != 0x00) {
return 1;
}
return 0;
@ -452,8 +440,7 @@ void EPA_PACE_Replay(UsbCommand *c)
// if an APDU has been passed, save it
if (c->arg[0] != 0) {
// make sure it's not too big
if(c->arg[2] > apdus_replay[c->arg[0] - 1].len)
{
if (c->arg[2] > apdus_replay[c->arg[0] - 1].len) {
cmd_send(CMD_ACK, 1, 0, 0, NULL, 0);
}
memcpy(apdus_replay[c->arg[0] - 1].data + c->arg[1],
@ -497,15 +484,14 @@ void EPA_PACE_Replay(UsbCommand *c)
if (i < sizeof(apdu_lengths_replay) - 1
&& (func_return < 6
|| response_apdu[func_return - 4] != 0x90
|| response_apdu[func_return - 3] != 0x00))
{
|| response_apdu[func_return - 3] != 0x00)) {
EPA_Finish();
cmd_send(CMD_ACK, 3 + i, func_return, 0, timings, 20);
return;
}
}
EPA_Finish();
cmd_send(CMD_ACK,0,0,0,timings,20);
cmd_send(CMD_ACK, 0, 0, 0, timings, 20);
return;
}
@ -543,7 +529,7 @@ int EPA_Setup()
// power up the field
iso14443b_setup();
// select the card
return_code = iso14443b_select_card( &card_b_info );
return_code = iso14443b_select_card(&card_b_info);
if (return_code == 0) {
Dbprintf("ISO 14443 Type B");
iso_type = 'b';

View file

@ -31,23 +31,25 @@ static uint32_t felica_lasttime_prox2air_start;
static void iso18092_setup(uint8_t fpga_minor_mode);
static uint8_t felica_select_card(felica_card_select_t *card);
static void TransmitFor18092_AsReader(uint8_t * frame, int len, uint32_t *timing, uint8_t power, uint8_t highspeed);
static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing, uint8_t power, uint8_t highspeed);
bool WaitForFelicaReply(uint16_t maxbytes);
void iso18092_set_timeout(uint32_t timeout) {
felica_timeout = timeout + (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/(16*8) + 2;
void iso18092_set_timeout(uint32_t timeout)
{
felica_timeout = timeout + (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / (16 * 8) + 2;
}
uint32_t iso18092_get_timeout(void) {
return felica_timeout - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/(16*8) - 2;
uint32_t iso18092_get_timeout(void)
{
return felica_timeout - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / (16 * 8) - 2;
}
#ifndef FELICA_MAX_FRAME_SIZE
#define FELICA_MAX_FRAME_SIZE 260
#define FELICA_MAX_FRAME_SIZE 260
#endif
//structure to hold outgoing NFC frame
static uint8_t frameSpace[FELICA_MAX_FRAME_SIZE+4];
static uint8_t frameSpace[FELICA_MAX_FRAME_SIZE + 4];
//structure to hold incoming NFC frame, used for ISO/IEC 18092-compatible frames
static struct {
@ -67,8 +69,8 @@ static struct {
uint16_t len;
uint8_t byte_offset;
uint8_t *framebytes;
//should be enough. maxlen is 255, 254 for data, 2 for sync, 2 for crc
// 0,1 -> SYNC, 2 - len, 3-(len+1)->data, then crc
//should be enough. maxlen is 255, 254 for data, 2 for sync, 2 for crc
// 0,1 -> SYNC, 2 - len, 3-(len+1)->data, then crc
} FelicaFrame;
//b2 4d is SYNC, 45645 in 16-bit notation, 10110010 01001101 binary. Frame will not start filling until this is shifted in
@ -77,33 +79,37 @@ static struct {
# define SYNC_16BIT 0xB24D
#endif
static void FelicaFrameReset() {
static void FelicaFrameReset()
{
FelicaFrame.state = STATE_UNSYNCD;
FelicaFrame.posCnt = 0;
FelicaFrame.crc_ok = false;
FelicaFrame.byte_offset = 0;
}
static void FelicaFrameinit(uint8_t *data) {
static void FelicaFrameinit(uint8_t *data)
{
FelicaFrame.framebytes = data;
FelicaFrameReset();
}
//shift byte into frame, reversing it at the same time
static void shiftInByte(uint8_t bt) {
static void shiftInByte(uint8_t bt)
{
uint8_t j;
for(j=0; j < FelicaFrame.byte_offset; j++) {
FelicaFrame.framebytes[FelicaFrame.posCnt] = ( FelicaFrame.framebytes[FelicaFrame.posCnt]<<1 ) + (bt & 1);
for (j = 0; j < FelicaFrame.byte_offset; j++) {
FelicaFrame.framebytes[FelicaFrame.posCnt] = (FelicaFrame.framebytes[FelicaFrame.posCnt] << 1) + (bt & 1);
bt >>= 1;
}
FelicaFrame.posCnt++;
FelicaFrame.rem_len--;
for(j = FelicaFrame.byte_offset; j<8; j++) {
FelicaFrame.framebytes[FelicaFrame.posCnt] = (FelicaFrame.framebytes[FelicaFrame.posCnt]<<1 ) + (bt & 1);
for (j = FelicaFrame.byte_offset; j < 8; j++) {
FelicaFrame.framebytes[FelicaFrame.posCnt] = (FelicaFrame.framebytes[FelicaFrame.posCnt] << 1) + (bt & 1);
bt >>= 1;
}
}
static void Process18092Byte(uint8_t bt) {
static void Process18092Byte(uint8_t bt)
{
switch (FelicaFrame.state) {
case STATE_UNSYNCD: {
//almost any nonzero byte can be start of SYNC. SYNC should be preceded by zeros, but that is not alsways the case
@ -119,7 +125,7 @@ static void Process18092Byte(uint8_t bt) {
FelicaFrame.shiftReg = bt;
FelicaFrame.state = STATE_UNSYNCD;
} else {
for (uint8_t i=0; i<8; i++) {
for (uint8_t i = 0; i < 8; i++) {
if (FelicaFrame.shiftReg == SYNC_16BIT) {
//SYNC done!
@ -128,13 +134,13 @@ static void Process18092Byte(uint8_t bt) {
FelicaFrame.framebytes[1] = 0x4d;
FelicaFrame.byte_offset = i;
//shift in remaining byte, slowly...
for(uint8_t j=i; j<8; j++) {
for (uint8_t j = i; j < 8; j++) {
FelicaFrame.framebytes[2] = (FelicaFrame.framebytes[2] << 1) + (bt & 1);
bt >>= 1;
}
FelicaFrame.posCnt = 2;
if (i==0)
if (i == 0)
break;
}
FelicaFrame.shiftReg = (FelicaFrame.shiftReg << 1) + (bt & 1);
@ -171,12 +177,12 @@ static void Process18092Byte(uint8_t bt) {
case STATE_GET_CRC: {
shiftInByte(bt);
if ( FelicaFrame.rem_len <= 0 ) {
if (FelicaFrame.rem_len <= 0) {
// skip sync 2bytes. IF ok, residue should be 0x0000
FelicaFrame.crc_ok = check_crc(CRC_FELICA, FelicaFrame.framebytes+2, FelicaFrame.len-2);
FelicaFrame.crc_ok = check_crc(CRC_FELICA, FelicaFrame.framebytes + 2, FelicaFrame.len - 2);
FelicaFrame.state = STATE_FULL;
FelicaFrame.rem_len = 0;
if (MF_DBGLEVEL > 3) Dbprintf("[+] got 2 crc bytes [%s]", (FelicaFrame.crc_ok) ? "OK" : "No" );
if (MF_DBGLEVEL > 3) Dbprintf("[+] got 2 crc bytes [%s]", (FelicaFrame.crc_ok) ? "OK" : "No");
}
break;
}
@ -190,7 +196,8 @@ static void Process18092Byte(uint8_t bt) {
* Currently does NOT do any collision handling.
* It expects 0-1 cards in the device's range.
*/
static uint8_t felica_select_card(felica_card_select_t *card) {
static uint8_t felica_select_card(felica_card_select_t *card)
{
// POLL command
// 0xB2 0x4B = sync code
@ -205,7 +212,7 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
// b0 = fc/64 (212kbps)
// 0x00 = timeslot
// 0x09 0x21 = crc
static uint8_t poll[10] = {0xb2,0x4d,0x06,FELICA_POLL_REQ,0xFF,0xFF,0x00,0x00,0x09,0x21};
static uint8_t poll[10] = {0xb2, 0x4d, 0x06, FELICA_POLL_REQ, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x21};
int len = 20;
@ -225,7 +232,7 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
} while (--len);
// timed-out
if ( len == 0 )
if (len == 0)
return 1;
// wrong answer
@ -233,7 +240,7 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
return 2;
// VALIDATE CRC residue is 0, hence if crc is a value it failed.
if (!check_crc(CRC_FELICA, FelicaFrame.framebytes+2, FelicaFrame.len-2))
if (!check_crc(CRC_FELICA, FelicaFrame.framebytes + 2, FelicaFrame.len - 2))
return 3;
// copy UID
@ -245,7 +252,7 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
memcpy(card->code, card->IDm, 2);
memcpy(card->uid, card->IDm + 2, 6);
memcpy(card->iccode, card->PMm, 2);
memcpy(card->mrt, card->PMm+2, 6);
memcpy(card->mrt, card->PMm + 2, 6);
}
// more status bytes?
@ -264,7 +271,8 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
// Felica standard has a different file system, AFAIK,
// 8-byte IDm, number of blocks, blocks numbers
// number of blocks limited to 4 for FelicaLite(S)
static void BuildFliteRdblk(uint8_t* idm, int blocknum, uint16_t *blocks ) {
static void BuildFliteRdblk(uint8_t *idm, int blocknum, uint16_t *blocks)
{
if (blocknum > 4 || blocknum <= 0)
Dbprintf("Invalid number of blocks, %d != 4", blocknum);
@ -298,7 +306,7 @@ static void BuildFliteRdblk(uint8_t* idm, int blocknum, uint16_t *blocks ) {
//number of blocks
frameSpace[c++] = blocknum;
for (i=0; i < blocknum; i++) {
for (i = 0; i < blocknum; i++) {
//3-byte block
if (blocks[i] >= 256) {
@ -312,15 +320,16 @@ static void BuildFliteRdblk(uint8_t* idm, int blocknum, uint16_t *blocks ) {
}
//set length
frameSpace[2] = c-2;
AddCrc(frameSpace, c-2);
frameSpace[2] = c - 2;
AddCrc(frameSpace, c - 2);
}
static void TransmitFor18092_AsReader(uint8_t * frame, int len, uint32_t *timing, uint8_t power, uint8_t highspeed) {
static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing, uint8_t power, uint8_t highspeed)
{
uint8_t flags = FPGA_MAJOR_MODE_ISO18092;
if ( power )
if (power)
flags |= FPGA_HF_ISO18092_FLAG_READER;
if (highspeed)
flags |= FPGA_HF_ISO18092_FLAG_424K;
@ -356,31 +365,32 @@ static void TransmitFor18092_AsReader(uint8_t * frame, int len, uint32_t *timing
}
}
/**/
/**/
while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {};
AT91C_BASE_SSC->SSC_THR = 0x00; //minimum delay
while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {};
AT91C_BASE_SSC->SSC_THR = 0x00; //spin
/**/
/**/
// log
LogTrace(
frame,
len,
(felica_lasttime_prox2air_start<<4) + DELAY_ARM2AIR_AS_READER,
((felica_lasttime_prox2air_start + felica_lasttime_prox2air_start)<<4) + DELAY_ARM2AIR_AS_READER,
(felica_lasttime_prox2air_start << 4) + DELAY_ARM2AIR_AS_READER,
((felica_lasttime_prox2air_start + felica_lasttime_prox2air_start) << 4) + DELAY_ARM2AIR_AS_READER,
NULL,
true
);
felica_nexttransfertime = MAX(felica_nexttransfertime ,felica_lasttime_prox2air_start + FELICA_REQUEST_GUARD_TIME);
felica_nexttransfertime = MAX(felica_nexttransfertime, felica_lasttime_prox2air_start + FELICA_REQUEST_GUARD_TIME);
}
// Wait for tag reply
// stop when button is pressed
// or return TRUE when command is captured
bool WaitForFelicaReply(uint16_t maxbytes) {
bool WaitForFelicaReply(uint16_t maxbytes)
{
uint32_t c = 0;
@ -393,7 +403,7 @@ bool WaitForFelicaReply(uint16_t maxbytes) {
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
uint32_t timeout = iso18092_get_timeout();
for(;;) {
for (;;) {
WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
@ -403,15 +413,15 @@ bool WaitForFelicaReply(uint16_t maxbytes) {
felica_nexttransfertime =
MAX(
felica_nexttransfertime,
(GetCountSspClk() & 0xfffffff8) - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/16 + FELICA_FRAME_DELAY_TIME
(GetCountSspClk() & 0xfffffff8) - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FELICA_FRAME_DELAY_TIME
)
;
LogTrace(
FelicaFrame.framebytes,
FelicaFrame.len,
((GetCountSspClk() & 0xfffffff8)<<4) - DELAY_AIR2ARM_AS_READER - timeout,
((GetCountSspClk() & 0xfffffff8)<<4) - DELAY_AIR2ARM_AS_READER,
((GetCountSspClk() & 0xfffffff8) << 4) - DELAY_AIR2ARM_AS_READER - timeout,
((GetCountSspClk() & 0xfffffff8) << 4) - DELAY_AIR2ARM_AS_READER,
NULL,
false
);
@ -430,13 +440,15 @@ bool WaitForFelicaReply(uint16_t maxbytes) {
// Set up FeliCa communication (similar to iso14443a_setup)
// field is setup for "Sending as Reader"
static void iso18092_setup(uint8_t fpga_minor_mode) {
static void iso18092_setup(uint8_t fpga_minor_mode)
{
LEDsoff();
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// allocate command receive buffer
BigBuf_free(); BigBuf_Clear_ext(false);
BigBuf_free();
BigBuf_Clear_ext(false);
// Initialize Demod and Uart structs
//DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
@ -473,7 +485,8 @@ static void iso18092_setup(uint8_t fpga_minor_mode) {
// arg0 FeliCa flags
// arg1 len of commandbytes
// d.asBytes command bytes to send
void felica_sendraw(UsbCommand *c) {
void felica_sendraw(UsbCommand *c)
{
if (MF_DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Enter");
@ -494,10 +507,10 @@ void felica_sendraw(UsbCommand *c) {
// notify client selecting status.
// if failed selecting, turn off antenna and quite.
if( !(param & FELICA_NO_SELECT) ) {
if (!(param & FELICA_NO_SELECT)) {
arg0 = felica_select_card(&card);
cmd_send(CMD_ACK, arg0, sizeof(card.uid), 0, &card, sizeof(felica_card_select_t));
if ( arg0 > 0 )
if (arg0 > 0)
goto OUT;
}
}
@ -505,26 +518,26 @@ void felica_sendraw(UsbCommand *c) {
if ((param & FELICA_RAW)) {
// 2 sync, 1 len, 2crc == 5
uint8_t *buf = BigBuf_malloc(len+5);
uint8_t *buf = BigBuf_malloc(len + 5);
// add sync bits
buf[0] = 0xb2;
buf[1] = 0x4d;
buf[2] = len;
// copy command
memcpy(buf+2, cmd, len);
memcpy(buf + 2, cmd, len);
if ((param & FELICA_APPEND_CRC)) {
// Don't append crc on empty bytearray...
if ( len > 0 ) {
if (len > 0) {
AddCrc(buf, len);
len += 2;
}
}
TransmitFor18092_AsReader(buf, buf[2]+4, NULL, 1, 0);
TransmitFor18092_AsReader(buf, buf[2] + 4, NULL, 1, 0);
arg0 = !WaitForFelicaReply(1024);
cmd_send(CMD_ACK, arg0, 0, 0, FelicaFrame.framebytes+2, FelicaFrame.len-2);
cmd_send(CMD_ACK, arg0, 0, 0, FelicaFrame.framebytes + 2, FelicaFrame.len - 2);
}
if ((param & FELICA_NO_DISCONNECT))
@ -539,25 +552,26 @@ OUT:
if (MF_DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Exit");
}
void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip)
{
int remFrames = (samplesToSkip) ? samplesToSkip : 0;
Dbprintf("Snoop FelicaLiteS: Getting first %d frames, Skipping %d triggers.\n", samplesToSkip, triggersToSkip);
iso18092_setup( FPGA_HF_ISO18092_FLAG_NOMOD);
iso18092_setup(FPGA_HF_ISO18092_FLAG_NOMOD);
//the frame bits are slow enough.
int n = BigBuf_max_traceLen() / sizeof(uint8_t); // take all memory
int numbts = 0;
uint8_t *dest = (uint8_t *)BigBuf_get_addr();
uint8_t *destend = dest + n-2;
uint8_t *destend = dest + n - 2;
uint32_t endframe = GetCountSspClk();
while (dest <= destend) {
WDT_HIT();
if( BUTTON_PRESS()) break;
if (BUTTON_PRESS()) break;
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR);
@ -566,7 +580,7 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
//to be sure we are in frame
if (FelicaFrame.state == STATE_GET_LENGTH) {
//length is after 48 (PRE)+16 (SYNC) - 64 ticks +maybe offset? not 100%
uint16_t distance = GetCountSspClk() - endframe - 64 + (FelicaFrame.byte_offset > 0 ? (8-FelicaFrame.byte_offset) : 0);
uint16_t distance = GetCountSspClk() - endframe - 64 + (FelicaFrame.byte_offset > 0 ? (8 - FelicaFrame.byte_offset) : 0);
*dest = distance >> 8;
dest++;
*dest = (distance & 0xff);
@ -577,16 +591,16 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
endframe = GetCountSspClk();
//*dest = FelicaFrame.crc_ok; //kind of wasteful
dest++;
for(int i=0; i < FelicaFrame.len; i++) {
for (int i = 0; i < FelicaFrame.len; i++) {
*dest = FelicaFrame.framebytes[i];
dest++;
if (dest >= destend ) break;
if (dest >= destend) break;
}
remFrames--;
if (remFrames <= 0) break;
if (dest >= destend ) break;
if (dest >= destend) break;
numbts += FelicaFrame.len;
@ -602,7 +616,7 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
set_tracelen(numbts);
Dbprintf("Felica sniffing done, tracelen: %i, use hf list felica for annotations", BigBuf_get_traceLen());
cmd_send(CMD_ACK,1, numbts,0,0,0);
cmd_send(CMD_ACK, 1, numbts, 0, 0, 0);
}
#define R_POLL0_LEN 0x16
@ -610,7 +624,8 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
#define R_READBLK_LEN 0x21
//simulate NFC Tag3 card - for now only poll response works
// second half (4 bytes) of NDEF2 goes into nfcid2_0, first into nfcid2_1
void felica_sim_lite(uint64_t nfcid) {
void felica_sim_lite(uint64_t nfcid)
{
int i, curlen = 0;
uint8_t *curresp = 0;
@ -619,9 +634,9 @@ void felica_sim_lite(uint64_t nfcid) {
num_to_bytes(nfcid, 8, ndef);
//prepare our 3 responses...
uint8_t resp_poll0[R_POLL0_LEN] = { 0xb2,0x4d,0x12,FELICA_POLL_ACK,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f};
uint8_t resp_poll1[R_POLL1_LEN] = { 0xb2,0x4d,0x14,FELICA_POLL_ACK,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00, 0x88,0xb4,0xb3,0x7f};
uint8_t resp_readblk[R_READBLK_LEN] = { 0xb2,0x4d,0x1d,FELICA_RDBLK_ACK,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x04,0x01,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x23,0xcb,0x6e};
uint8_t resp_poll0[R_POLL0_LEN] = { 0xb2, 0x4d, 0x12, FELICA_POLL_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0xb3, 0x7f};
uint8_t resp_poll1[R_POLL1_LEN] = { 0xb2, 0x4d, 0x14, FELICA_POLL_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0x88, 0xb4, 0xb3, 0x7f};
uint8_t resp_readblk[R_READBLK_LEN] = { 0xb2, 0x4d, 0x1d, FELICA_RDBLK_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x04, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x23, 0xcb, 0x6e};
//NFC tag 3/ ISo technically. Many overlapping standards
DbpString("Felica Lite-S sim start");
@ -630,10 +645,10 @@ void felica_sim_lite(uint64_t nfcid) {
);
//fill in blanks
for( i=0; i<8; i++) {
resp_poll0[i+4] = ndef[i];
resp_poll1[i+4] = ndef[i];
resp_readblk[i+4] = ndef[i];
for (i = 0; i < 8; i++) {
resp_poll0[i + 4] = ndef[i];
resp_poll1[i + 4] = ndef[i];
resp_readblk[i + 4] = ndef[i];
}
//calculate and set CRC
@ -641,12 +656,12 @@ void felica_sim_lite(uint64_t nfcid) {
AddCrc(resp_poll1, resp_poll1[2]);
AddCrc(resp_readblk, resp_readblk[2]);
iso18092_setup( FPGA_HF_ISO18092_FLAG_NOMOD);
iso18092_setup(FPGA_HF_ISO18092_FLAG_NOMOD);
bool listenmode = true;
//uint32_t frtm = GetCountSspClk();
for(;;) {
if( BUTTON_PRESS()) break;
for (;;) {
if (BUTTON_PRESS()) break;
WDT_HIT();
if (listenmode) {
@ -716,11 +731,12 @@ void felica_sim_lite(uint64_t nfcid) {
DbpString("Felica Lite-S sim end");
}
void felica_dump_lite_s() {
void felica_dump_lite_s()
{
uint8_t ndef[8];
uint8_t poll[10] = { 0xb2,0x4d,0x06,FELICA_POLL_REQ,0xff,0xff,0x00,0x00,0x09,0x21};
uint16_t liteblks[28] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x90,0x91,0x92,0xa0};
uint8_t poll[10] = { 0xb2, 0x4d, 0x06, FELICA_POLL_REQ, 0xff, 0xff, 0x00, 0x00, 0x09, 0x21};
uint16_t liteblks[28] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x90, 0x91, 0x92, 0xa0};
// setup device.
iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD);
@ -745,13 +761,13 @@ void felica_dump_lite_s() {
// for (c=0; c < 8; c++)
// ndef[c] = FelicaFrame.framebytes[c+4];
for (blknum=0; blknum < sizeof(liteblks); ) {
for (blknum = 0; blknum < sizeof(liteblks);) {
// block to read.
BuildFliteRdblk(ndef, 1, &liteblks[blknum]);
//TransmitFor18092_AsReader(frameSpace, frameSpace[2]+4, GetCountSspClk()+512, 1, 0);
TransmitFor18092_AsReader(frameSpace, frameSpace[2]+4, NULL, 1, 0);
TransmitFor18092_AsReader(frameSpace, frameSpace[2] + 4, NULL, 1, 0);
// read block
if (WaitForFelicaReply(1024) && FelicaFrame.framebytes[3] == FELICA_RDBLK_ACK) {
@ -764,15 +780,15 @@ void felica_dump_lite_s() {
//memcpy(dest+cnt, FelicaFrame.framebytes + 15, 16);
//cnt += 16;
for(uint8_t j=0; j < 16; j++)
dest[cnt++] = fb[15+j];
for (uint8_t j = 0; j < 16; j++)
dest[cnt++] = fb[15 + j];
blknum++;
cntfails = 0;
// // print raw log.
// Dbprintf("LEN %u | Dump bytes count %u ", FelicaFrame.len, cnt);
Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes+15, 0);
Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes + 15, 0);
} else {
cntfails++;
if (cntfails > 12) {

View file

@ -13,13 +13,15 @@
uint32_t FLASHMEM_SPIBAUDRATE = FLASH_BAUD;
void FlashmemSetSpiBaudrate(uint32_t baudrate){
void FlashmemSetSpiBaudrate(uint32_t baudrate)
{
FLASHMEM_SPIBAUDRATE = baudrate;
Dbprintf("Spi Baudrate : %dMhz", FLASHMEM_SPIBAUDRATE/1000000);
Dbprintf("Spi Baudrate : %dMhz", FLASHMEM_SPIBAUDRATE / 1000000);
}
// initialize
bool FlashInit() {
bool FlashInit()
{
FlashSetup(FLASHMEM_SPIBAUDRATE);
StartTicks();
@ -32,7 +34,8 @@ bool FlashInit() {
return true;
}
void FlashSetup(uint32_t baudrate){
void FlashSetup(uint32_t baudrate)
{
//WDT_DISABLE
AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS;
@ -71,10 +74,10 @@ void FlashSetup(uint32_t baudrate){
// If DLYBCS is less than or equal to six, six MCK periods
// will be inserted by default.
SPI_PCS(SPI_CSR_NUM) | // Peripheral Chip Select (selects SPI_NCS2 or PA10)
( 0 << 7) | // Disable LLB (1=MOSI2MISO test mode)
( 1 << 4) | // Disable ModeFault Protection
( 0 << 3) | // makes spi operate at MCK (1 is MCK/2)
( 0 << 2) | // Chip selects connected directly to peripheral
(0 << 7) | // Disable LLB (1=MOSI2MISO test mode)
(1 << 4) | // Disable ModeFault Protection
(0 << 3) | // makes spi operate at MCK (1 is MCK/2)
(0 << 2) | // Chip selects connected directly to peripheral
AT91C_SPI_PS_FIXED | // Fixed Peripheral Select
AT91C_SPI_MSTR; // Master Mode
@ -87,9 +90,9 @@ void FlashSetup(uint32_t baudrate){
}
AT91C_BASE_SPI->SPI_CSR[2] =
SPI_DLYBCT(dlybct,MCK)| // Delay between Consecutive Transfers (32 MCK periods)
SPI_DLYBS(0,MCK) | // Delay Beforce SPCK CLock
SPI_SCBR(baudrate,MCK)| // SPI Baudrate Selection
SPI_DLYBCT(dlybct, MCK) | // Delay between Consecutive Transfers (32 MCK periods)
SPI_DLYBS(0, MCK) | // Delay Beforce SPCK CLock
SPI_SCBR(baudrate, MCK) | // SPI Baudrate Selection
AT91C_SPI_BITS_8 | // Bits per Transfer (8 bits)
//AT91C_SPI_CSAAT | // Chip Select inactive after transfer
// 40.4.6.2 SPI: Bad tx_ready Behavior when CSAAT = 1 and SCBR = 1
@ -97,7 +100,7 @@ void FlashSetup(uint32_t baudrate){
// the same slave with an IDLE state between them, the tx_ready signal does not rise after the second data has been
// transferred in the shifter. This can imply for example, that the second data is sent twice.
// COLIN :: For now we STILL use CSAAT=1 to avoid having to (de)assert NPCS manually via PIO lines and we deal with delay
( csaat << 3) |
(csaat << 3) |
/* Spi modes:
Mode CPOL CPHA NCPHA
0 0 0 1 clock normally low read on rising edge
@ -120,14 +123,15 @@ void FlashSetup(uint32_t baudrate){
2 1 0 0 clock normally high read on falling edge
3 1 1 1 clock normally high read on rising edge
*/
( 0 << 1) | // Clock Phase data captured on leading edge, changes on following edge
( 0 << 0); // Clock Polarity inactive state is logic 0
(0 << 1) | // Clock Phase data captured on leading edge, changes on following edge
(0 << 0); // Clock Polarity inactive state is logic 0
// read first, empty buffer
if (AT91C_BASE_SPI->SPI_RDR == 0) {};
}
void FlashStop(void) {
void FlashStop(void)
{
//Bof
//* Reset all the Chip Select register
AT91C_BASE_SPI->SPI_CSR[0] = 0;
@ -144,13 +148,14 @@ void FlashStop(void) {
// SPI disable
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS;
if ( MF_DBGLEVEL > 3 ) Dbprintf("FlashStop");
if (MF_DBGLEVEL > 3) Dbprintf("FlashStop");
StopTicks();
}
// send one byte over SPI
uint16_t FlashSendByte(uint32_t data) {
uint16_t FlashSendByte(uint32_t data)
{
// wait until SPI is ready for transfer
//if you are checking for incoming data returned then the TXEMPTY flag is redundant
@ -162,19 +167,21 @@ uint16_t FlashSendByte(uint32_t data) {
//while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TDRE) == 0){};
// wait recive transfer is complete
while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0){};
while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0) {};
// reading incoming data
return ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF);
}
// send last byte over SPI
uint16_t FlashSendLastByte(uint32_t data) {
uint16_t FlashSendLastByte(uint32_t data)
{
return FlashSendByte(data | AT91C_SPI_LASTXFER);
}
// read state register 1
uint8_t Flash_ReadStat1(void) {
uint8_t Flash_ReadStat1(void)
{
FlashSendByte(READSTAT1);
return FlashSendLastByte(0xFF);
}
@ -185,18 +192,15 @@ bool Flash_CheckBusy(uint32_t timeout)
StartCountUS();
uint32_t _time = GetCountUS();
if ( MF_DBGLEVEL > 3 ) Dbprintf("Checkbusy in...");
if (MF_DBGLEVEL > 3) Dbprintf("Checkbusy in...");
do
{
if (!(Flash_ReadStat1() & BUSY))
{
do {
if (!(Flash_ReadStat1() & BUSY)) {
return false;
}
} while ((GetCountUS() - _time) < timeout);
if (timeout <= (GetCountUS() - _time))
{
if (timeout <= (GetCountUS() - _time)) {
return true;
}
@ -204,7 +208,8 @@ bool Flash_CheckBusy(uint32_t timeout)
}
// read ID out
uint8_t Flash_ReadID(void) {
uint8_t Flash_ReadID(void)
{
if (Flash_CheckBusy(BUSY_TIMEOUT)) return 0;
@ -217,16 +222,17 @@ uint8_t Flash_ReadID(void) {
uint8_t man_id = FlashSendByte(0xFF);
uint8_t dev_id = FlashSendLastByte(0xFF);
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash ReadID | Man ID %02x | Device ID %02x", man_id, dev_id);
if (MF_DBGLEVEL > 3) Dbprintf("Flash ReadID | Man ID %02x | Device ID %02x", man_id, dev_id);
if ( (man_id == WINBOND_MANID ) && (dev_id == WINBOND_DEVID) )
if ((man_id == WINBOND_MANID) && (dev_id == WINBOND_DEVID))
return dev_id;
return 0;
}
// read unique id for chip.
void Flash_UniqueID(uint8_t *uid) {
void Flash_UniqueID(uint8_t *uid)
{
if (Flash_CheckBusy(BUSY_TIMEOUT)) return;
@ -247,7 +253,8 @@ void Flash_UniqueID(uint8_t *uid) {
uid[0] = FlashSendLastByte(0xFF);
}
uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) {
uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len)
{
if (!FlashInit()) return 0;
@ -259,7 +266,7 @@ uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) {
FlashSendByte(cmd);
Flash_TransferAdresse(address);
if (FASTFLASH){
if (FASTFLASH) {
FlashSendByte(DUMMYBYTE);
}
@ -272,14 +279,16 @@ uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) {
return len;
}
void Flash_TransferAdresse(uint32_t address){
void Flash_TransferAdresse(uint32_t address)
{
FlashSendByte((address >> 16) & 0xFF);
FlashSendByte((address >> 8) & 0xFF);
FlashSendByte((address >> 0) & 0xFF);
}
/* This ensure we can ReadData without having to cycle through initialization everytime */
uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) {
uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len)
{
// length should never be zero
if (!len) return 0;
@ -289,7 +298,7 @@ uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) {
FlashSendByte(cmd);
Flash_TransferAdresse(address);
if (FASTFLASH){
if (FASTFLASH) {
FlashSendByte(DUMMYBYTE);
}
@ -305,7 +314,8 @@ uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) {
////////////////////////////////////////
// Write data can only program one page. A page has 256 bytes.
// if len > 256, it might wrap around and overwrite pos 0.
uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len)
{
// length should never be zero
if (!len)
@ -313,18 +323,18 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
// Max 256 bytes write
if (((address & 0xFF) + len) > 256) {
Dbprintf("Flash_WriteData 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF)+len, len );
Dbprintf("Flash_WriteData 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF) + len, len);
return 0;
}
// out-of-range
if ( (( address >> 16 ) & 0xFF ) > MAX_BLOCKS) {
if (((address >> 16) & 0xFF) > MAX_BLOCKS) {
Dbprintf("Flash_WriteData, block out-of-range");
return 0;
}
if (!FlashInit()) {
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail");
if (MF_DBGLEVEL > 3) Dbprintf("Flash_WriteData init fail");
return 0;
}
@ -351,17 +361,18 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
// length should never be zero
// Max 256 bytes write
// out-of-range
uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) {
uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len)
{
if (!len)
return 0;
if (((address & 0xFF) + len) > 256) {
Dbprintf("Flash_WriteDataCont 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF)+len, len );
Dbprintf("Flash_WriteDataCont 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF) + len, len);
return 0;
}
if ( (( address >> 16 ) & 0xFF ) > MAX_BLOCKS) {
if (((address >> 16) & 0xFF) > MAX_BLOCKS) {
Dbprintf("Flash_WriteDataCont, block out-of-range");
return 0;
}
@ -381,7 +392,8 @@ uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) {
// assumes valid start 256 based 00 address
//
uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len) {
uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len)
{
bool isok;
uint16_t res, bytes_sent = 0, bytes_remaining = len;
@ -412,47 +424,61 @@ out:
}
bool Flash_WipeMemoryPage(uint8_t page) {
bool Flash_WipeMemoryPage(uint8_t page)
{
if (!FlashInit()) {
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail");
if (MF_DBGLEVEL > 3) Dbprintf("Flash_WriteData init fail");
return false;
}
Flash_ReadStat1();
// Each block is 64Kb. One block erase takes 1s ( 1000ms )
Flash_WriteEnable(); Flash_Erase64k(page); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase64k(page);
Flash_CheckBusy(BUSY_TIMEOUT);
FlashStop();
return true;
}
// Wipes flash memory completely, fills with 0xFF
bool Flash_WipeMemory() {
bool Flash_WipeMemory()
{
if (!FlashInit()) {
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail");
if (MF_DBGLEVEL > 3) Dbprintf("Flash_WriteData init fail");
return false;
}
Flash_ReadStat1();
// Each block is 64Kb. Four blocks
// one block erase takes 1s ( 1000ms )
Flash_WriteEnable(); Flash_Erase64k(0); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable(); Flash_Erase64k(1); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable(); Flash_Erase64k(2); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable(); Flash_Erase64k(3); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase64k(0);
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase64k(1);
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase64k(2);
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase64k(3);
Flash_CheckBusy(BUSY_TIMEOUT);
FlashStop();
return true;
}
// enable the flash write
void Flash_WriteEnable() {
void Flash_WriteEnable()
{
FlashSendLastByte(WRITEENABLE);
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash Write enabled");
if (MF_DBGLEVEL > 3) Dbprintf("Flash Write enabled");
}
// erase 4K at one time
// execution time: 0.8ms / 800us
bool Flash_Erase4k(uint8_t block, uint8_t sector) {
bool Flash_Erase4k(uint8_t block, uint8_t sector)
{
if (block > MAX_BLOCKS || sector > MAX_SECTORS) return false;
@ -487,7 +513,8 @@ bool Flash_Erase32k(uint32_t address) {
// 0x01 00 00 -- 0x 01 FF FF == block 1
// 0x02 00 00 -- 0x 02 FF FF == block 2
// 0x03 00 00 -- 0x 03 FF FF == block 3
bool Flash_Erase64k(uint8_t block) {
bool Flash_Erase64k(uint8_t block)
{
if (block > MAX_BLOCKS) return false;
@ -499,13 +526,15 @@ bool Flash_Erase64k(uint8_t block) {
}
// Erase chip
void Flash_EraseChip(void) {
void Flash_EraseChip(void)
{
FlashSendLastByte(CHIPERASE);
}
void Flashmem_print_status(void) {
void Flashmem_print_status(void)
{
DbpString("Flash memory");
Dbprintf(" Baudrate................%dMHz",FLASHMEM_SPIBAUDRATE/1000000);
Dbprintf(" Baudrate................%dMHz", FLASHMEM_SPIBAUDRATE / 1000000);
if (!FlashInit()) {
DbpString(" Init....................FAIL");
@ -529,7 +558,7 @@ void Flashmem_print_status(void) {
break;
}
uint8_t uid[8] = {0,0,0,0,0,0,0,0};
uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0};
Flash_UniqueID(uid);
Dbprintf(" Unique ID...............0x%02x%02x%02x%02x%02x%02x%02x%02x",
uid[7], uid[6], uid[5], uid[4],

View file

@ -7,103 +7,103 @@
//-----------------------------------------------------------------------------
const char FONT6x8[97][8] = {
{0x06,0x08,0x08,0x00,0x00,0x00,0x00,0x00}, // columns, rows, bytes per char
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space
{0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00}, // !
{0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00}, // "
{0x50,0x50,0xF8,0x50,0xF8,0x50,0x50,0x00}, // #
{0x20,0x78,0xA0,0x70,0x28,0xF0,0x20,0x00}, // $
{0xC0,0xC8,0x10,0x20,0x40,0x98,0x18,0x00}, // %
{0x40,0xA0,0xA0,0x40,0xA8,0x90,0x68,0x00}, // &
{0x30,0x30,0x20,0x40,0x00,0x00,0x00,0x00}, // '
{0x10,0x20,0x40,0x40,0x40,0x20,0x10,0x00}, // (
{0x40,0x20,0x10,0x10,0x10,0x20,0x40,0x00}, // )
{0x00,0x20,0xA8,0x70,0x70,0xA8,0x20,0x00}, // *
{0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0x00}, // +
{0x00,0x00,0x00,0x00,0x30,0x30,0x20,0x40}, // ,
{0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00}, // -
{0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00}, // .
{0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00}, // /
{0x70,0x88,0x88,0xA8,0x88,0x88,0x70,0x00}, // 0
{0x20,0x60,0x20,0x20,0x20,0x20,0x70,0x00}, // 1
{0x70,0x88,0x08,0x70,0x80,0x80,0xF8,0x00}, // 2
{0xF8,0x08,0x10,0x30,0x08,0x88,0x70,0x00}, // 3
{0x10,0x30,0x50,0x90,0xF8,0x10,0x10,0x00}, // 4
{0xF8,0x80,0xF0,0x08,0x08,0x88,0x70,0x00}, // 5
{0x38,0x40,0x80,0xF0,0x88,0x88,0x70,0x00}, // 6
{0xF8,0x08,0x08,0x10,0x20,0x40,0x80,0x00}, // 7
{0x70,0x88,0x88,0x70,0x88,0x88,0x70,0x00}, // 8
{0x70,0x88,0x88,0x78,0x08,0x10,0xE0,0x00}, // 9
{0x00,0x00,0x20,0x00,0x20,0x00,0x00,0x00}, // :
{0x00,0x00,0x20,0x00,0x20,0x20,0x40,0x00}, // ;
{0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x00}, // <
{0x00,0x00,0xF8,0x00,0xF8,0x00,0x00,0x00}, // =
{0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x00}, // >
{0x70,0x88,0x08,0x30,0x20,0x00,0x20,0x00}, // ?
{0x70,0x88,0xA8,0xB8,0xB0,0x80,0x78,0x00}, // @
{0x20,0x50,0x88,0x88,0xF8,0x88,0x88,0x00}, // A
{0xF0,0x88,0x88,0xF0,0x88,0x88,0xF0,0x00}, // B
{0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x00}, // C
{0xF0,0x88,0x88,0x88,0x88,0x88,0xF0,0x00}, // D
{0xF8,0x80,0x80,0xF0,0x80,0x80,0xF8,0x00}, // E
{0xF8,0x80,0x80,0xF0,0x80,0x80,0x80,0x00}, // F
{0x78,0x88,0x80,0x80,0x98,0x88,0x78,0x00}, // G
{0x88,0x88,0x88,0xF8,0x88,0x88,0x88,0x00}, // H
{0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00}, // I
{0x38,0x10,0x10,0x10,0x10,0x90,0x60,0x00}, // J
{0x88,0x90,0xA0,0xC0,0xA0,0x90,0x88,0x00}, // K
{0x80,0x80,0x80,0x80,0x80,0x80,0xF8,0x00}, // L
{0x88,0xD8,0xA8,0xA8,0xA8,0x88,0x88,0x00}, // M
{0x88,0x88,0xC8,0xA8,0x98,0x88,0x88,0x00}, // N
{0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00}, // O
{0xF0,0x88,0x88,0xF0,0x80,0x80,0x80,0x00}, // P
{0x70,0x88,0x88,0x88,0xA8,0x90,0x68,0x00}, // Q
{0xF0,0x88,0x88,0xF0,0xA0,0x90,0x88,0x00}, // R
{0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x00}, // S
{0xF8,0xA8,0x20,0x20,0x20,0x20,0x20,0x00}, // T
{0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00}, // U
{0x88,0x88,0x88,0x88,0x88,0x50,0x20,0x00}, // V
{0x88,0x88,0x88,0xA8,0xA8,0xA8,0x50,0x00}, // W
{0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x00}, // X
{0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x00}, // Y
{0xF8,0x08,0x10,0x70,0x40,0x80,0xF8,0x00}, // Z
{0x78,0x40,0x40,0x40,0x40,0x40,0x78,0x00}, // [
{0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00}, // backslash
{0x78,0x08,0x08,0x08,0x08,0x08,0x78,0x00}, // ]
{0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00}, // ^
{0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00}, // _
{0x60,0x60,0x20,0x10,0x00,0x00,0x00,0x00}, // `
{0x00,0x00,0x60,0x10,0x70,0x90,0x78,0x00}, // a
{0x80,0x80,0xB0,0xC8,0x88,0xC8,0xB0,0x00}, // b
{0x00,0x00,0x70,0x88,0x80,0x88,0x70,0x00}, // c
{0x08,0x08,0x68,0x98,0x88,0x98,0x68,0x00}, // d
{0x00,0x00,0x70,0x88,0xF8,0x80,0x70,0x00}, // e
{0x10,0x28,0x20,0x70,0x20,0x20,0x20,0x00}, // f
{0x00,0x00,0x70,0x98,0x98,0x68,0x08,0x70}, // g
{0x80,0x80,0xB0,0xC8,0x88,0x88,0x88,0x00}, // h
{0x20,0x00,0x60,0x20,0x20,0x20,0x70,0x00}, // i
{0x10,0x00,0x10,0x10,0x10,0x90,0x60,0x00}, // j
{0x80,0x80,0x90,0xA0,0xC0,0xA0,0x90,0x00}, // k
{0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00}, // l
{0x00,0x00,0xD0,0xA8,0xA8,0xA8,0xA8,0x00}, // m
{0x00,0x00,0xB0,0xC8,0x88,0x88,0x88,0x00}, // n
{0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00}, // o
{0x00,0x00,0xB0,0xC8,0xC8,0xB0,0x80,0x80}, // p
{0x00,0x00,0x68,0x98,0x98,0x68,0x08,0x08}, // q
{0x00,0x00,0xB0,0xC8,0x80,0x80,0x80,0x00}, // r
{0x00,0x00,0x78,0x80,0x70,0x08,0xF0,0x00}, // s
{0x20,0x20,0xF8,0x20,0x20,0x28,0x10,0x00}, // t
{0x00,0x00,0x88,0x88,0x88,0x98,0x68,0x00}, // u
{0x00,0x00,0x88,0x88,0x88,0x50,0x20,0x00}, // v
{0x00,0x00,0x88,0x88,0xA8,0xA8,0x50,0x00}, // w
{0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x00}, // x
{0x00,0x00,0x88,0x88,0x78,0x08,0x88,0x70}, // y
{0x00,0x00,0xF8,0x10,0x20,0x40,0xF8,0x00}, // z
{0x10,0x20,0x20,0x40,0x20,0x20,0x10,0x00}, // {
{0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x00}, // |
{0x40,0x20,0x20,0x10,0x20,0x20,0x40,0x00}, // }
{0x40,0xA8,0x10,0x00,0x00,0x00,0x00,0x00}, // ~
{0x70,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00} // DEL
{0x06, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}, // columns, rows, bytes per char
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // space
{0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 0x00}, // !
{0x50, 0x50, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00}, // "
{0x50, 0x50, 0xF8, 0x50, 0xF8, 0x50, 0x50, 0x00}, // #
{0x20, 0x78, 0xA0, 0x70, 0x28, 0xF0, 0x20, 0x00}, // $
{0xC0, 0xC8, 0x10, 0x20, 0x40, 0x98, 0x18, 0x00}, // %
{0x40, 0xA0, 0xA0, 0x40, 0xA8, 0x90, 0x68, 0x00}, // &
{0x30, 0x30, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00}, // '
{0x10, 0x20, 0x40, 0x40, 0x40, 0x20, 0x10, 0x00}, // (
{0x40, 0x20, 0x10, 0x10, 0x10, 0x20, 0x40, 0x00}, // )
{0x00, 0x20, 0xA8, 0x70, 0x70, 0xA8, 0x20, 0x00}, // *
{0x00, 0x20, 0x20, 0xF8, 0x20, 0x20, 0x00, 0x00}, // +
{0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x20, 0x40}, // ,
{0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00}, // -
{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00}, // .
{0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00}, // /
{0x70, 0x88, 0x88, 0xA8, 0x88, 0x88, 0x70, 0x00}, // 0
{0x20, 0x60, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00}, // 1
{0x70, 0x88, 0x08, 0x70, 0x80, 0x80, 0xF8, 0x00}, // 2
{0xF8, 0x08, 0x10, 0x30, 0x08, 0x88, 0x70, 0x00}, // 3
{0x10, 0x30, 0x50, 0x90, 0xF8, 0x10, 0x10, 0x00}, // 4
{0xF8, 0x80, 0xF0, 0x08, 0x08, 0x88, 0x70, 0x00}, // 5
{0x38, 0x40, 0x80, 0xF0, 0x88, 0x88, 0x70, 0x00}, // 6
{0xF8, 0x08, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00}, // 7
{0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x70, 0x00}, // 8
{0x70, 0x88, 0x88, 0x78, 0x08, 0x10, 0xE0, 0x00}, // 9
{0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00}, // :
{0x00, 0x00, 0x20, 0x00, 0x20, 0x20, 0x40, 0x00}, // ;
{0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x00}, // <
{0x00, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0x00, 0x00}, // =
{0x40, 0x20, 0x10, 0x08, 0x10, 0x20, 0x40, 0x00}, // >
{0x70, 0x88, 0x08, 0x30, 0x20, 0x00, 0x20, 0x00}, // ?
{0x70, 0x88, 0xA8, 0xB8, 0xB0, 0x80, 0x78, 0x00}, // @
{0x20, 0x50, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x00}, // A
{0xF0, 0x88, 0x88, 0xF0, 0x88, 0x88, 0xF0, 0x00}, // B
{0x70, 0x88, 0x80, 0x80, 0x80, 0x88, 0x70, 0x00}, // C
{0xF0, 0x88, 0x88, 0x88, 0x88, 0x88, 0xF0, 0x00}, // D
{0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0xF8, 0x00}, // E
{0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0x80, 0x00}, // F
{0x78, 0x88, 0x80, 0x80, 0x98, 0x88, 0x78, 0x00}, // G
{0x88, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x88, 0x00}, // H
{0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00}, // I
{0x38, 0x10, 0x10, 0x10, 0x10, 0x90, 0x60, 0x00}, // J
{0x88, 0x90, 0xA0, 0xC0, 0xA0, 0x90, 0x88, 0x00}, // K
{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xF8, 0x00}, // L
{0x88, 0xD8, 0xA8, 0xA8, 0xA8, 0x88, 0x88, 0x00}, // M
{0x88, 0x88, 0xC8, 0xA8, 0x98, 0x88, 0x88, 0x00}, // N
{0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00}, // O
{0xF0, 0x88, 0x88, 0xF0, 0x80, 0x80, 0x80, 0x00}, // P
{0x70, 0x88, 0x88, 0x88, 0xA8, 0x90, 0x68, 0x00}, // Q
{0xF0, 0x88, 0x88, 0xF0, 0xA0, 0x90, 0x88, 0x00}, // R
{0x70, 0x88, 0x80, 0x70, 0x08, 0x88, 0x70, 0x00}, // S
{0xF8, 0xA8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00}, // T
{0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00}, // U
{0x88, 0x88, 0x88, 0x88, 0x88, 0x50, 0x20, 0x00}, // V
{0x88, 0x88, 0x88, 0xA8, 0xA8, 0xA8, 0x50, 0x00}, // W
{0x88, 0x88, 0x50, 0x20, 0x50, 0x88, 0x88, 0x00}, // X
{0x88, 0x88, 0x50, 0x20, 0x20, 0x20, 0x20, 0x00}, // Y
{0xF8, 0x08, 0x10, 0x70, 0x40, 0x80, 0xF8, 0x00}, // Z
{0x78, 0x40, 0x40, 0x40, 0x40, 0x40, 0x78, 0x00}, // [
{0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00}, // backslash
{0x78, 0x08, 0x08, 0x08, 0x08, 0x08, 0x78, 0x00}, // ]
{0x20, 0x50, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00}, // ^
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00}, // _
{0x60, 0x60, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00}, // `
{0x00, 0x00, 0x60, 0x10, 0x70, 0x90, 0x78, 0x00}, // a
{0x80, 0x80, 0xB0, 0xC8, 0x88, 0xC8, 0xB0, 0x00}, // b
{0x00, 0x00, 0x70, 0x88, 0x80, 0x88, 0x70, 0x00}, // c
{0x08, 0x08, 0x68, 0x98, 0x88, 0x98, 0x68, 0x00}, // d
{0x00, 0x00, 0x70, 0x88, 0xF8, 0x80, 0x70, 0x00}, // e
{0x10, 0x28, 0x20, 0x70, 0x20, 0x20, 0x20, 0x00}, // f
{0x00, 0x00, 0x70, 0x98, 0x98, 0x68, 0x08, 0x70}, // g
{0x80, 0x80, 0xB0, 0xC8, 0x88, 0x88, 0x88, 0x00}, // h
{0x20, 0x00, 0x60, 0x20, 0x20, 0x20, 0x70, 0x00}, // i
{0x10, 0x00, 0x10, 0x10, 0x10, 0x90, 0x60, 0x00}, // j
{0x80, 0x80, 0x90, 0xA0, 0xC0, 0xA0, 0x90, 0x00}, // k
{0x60, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00}, // l
{0x00, 0x00, 0xD0, 0xA8, 0xA8, 0xA8, 0xA8, 0x00}, // m
{0x00, 0x00, 0xB0, 0xC8, 0x88, 0x88, 0x88, 0x00}, // n
{0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70, 0x00}, // o
{0x00, 0x00, 0xB0, 0xC8, 0xC8, 0xB0, 0x80, 0x80}, // p
{0x00, 0x00, 0x68, 0x98, 0x98, 0x68, 0x08, 0x08}, // q
{0x00, 0x00, 0xB0, 0xC8, 0x80, 0x80, 0x80, 0x00}, // r
{0x00, 0x00, 0x78, 0x80, 0x70, 0x08, 0xF0, 0x00}, // s
{0x20, 0x20, 0xF8, 0x20, 0x20, 0x28, 0x10, 0x00}, // t
{0x00, 0x00, 0x88, 0x88, 0x88, 0x98, 0x68, 0x00}, // u
{0x00, 0x00, 0x88, 0x88, 0x88, 0x50, 0x20, 0x00}, // v
{0x00, 0x00, 0x88, 0x88, 0xA8, 0xA8, 0x50, 0x00}, // w
{0x00, 0x00, 0x88, 0x50, 0x20, 0x50, 0x88, 0x00}, // x
{0x00, 0x00, 0x88, 0x88, 0x78, 0x08, 0x88, 0x70}, // y
{0x00, 0x00, 0xF8, 0x10, 0x20, 0x40, 0xF8, 0x00}, // z
{0x10, 0x20, 0x20, 0x40, 0x20, 0x20, 0x10, 0x00}, // {
{0x20, 0x20, 0x20, 0x00, 0x20, 0x20, 0x20, 0x00}, // |
{0x40, 0x20, 0x20, 0x10, 0x20, 0x20, 0x40, 0x00}, // }
{0x40, 0xA8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, // ~
{0x70, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00} // DEL
};
/*
const char FONT8x8F[97][8] = {

View file

@ -28,7 +28,8 @@ static uint32_t uncompressed_bytes_cnt;
// Used to write the FPGA config word
// May also be used to write to other SPI attached devices like an LCD
//-----------------------------------------------------------------------------
static void DisableSpi(void) {
static void DisableSpi(void)
{
//* Reset all the Chip Select register
AT91C_BASE_SPI->SPI_CSR[0] = 0;
AT91C_BASE_SPI->SPI_CSR[1] = 0;
@ -45,7 +46,8 @@ static void DisableSpi(void) {
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS;
}
void SetupSpi(int mode) {
void SetupSpi(int mode)
{
// PA1 -> SPI_NCS3 chip select (MEM)
// PA10 -> SPI_NCS2 chip select (LCD)
// PA11 -> SPI_NCS0 chip select (FPGA)
@ -70,24 +72,24 @@ void SetupSpi(int mode) {
switch (mode) {
case SPI_FPGA_MODE:
AT91C_BASE_SPI->SPI_MR =
( 0 << 24) | // Delay between chip selects (take default: 6 MCK periods)
(0 << 24) | // Delay between chip selects (take default: 6 MCK periods)
(0xE << 16) | // Peripheral Chip Select (selects FPGA SPI_NCS0 or PA11)
( 0 << 7) | // Local Loopback Disabled
(0 << 7) | // Local Loopback Disabled
AT91C_SPI_MODFDIS | // Mode Fault Detection disabled
( 0 << 2) | // Chip selects connected directly to peripheral
(0 << 2) | // Chip selects connected directly to peripheral
AT91C_SPI_PS_FIXED | // Fixed Peripheral Select
AT91C_SPI_MSTR; // Master Mode
AT91C_BASE_SPI->SPI_CSR[0] =
( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
( 1 << 16) | // Delay Before SPCK (1 MCK period)
( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud
(1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
(1 << 16) | // Delay Before SPCK (1 MCK period)
(6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud
AT91C_SPI_BITS_16 | // Bits per Transfer (16 bits)
( 0 << 3) | // Chip Select inactive after transfer
(0 << 3) | // Chip Select inactive after transfer
AT91C_SPI_NCPHA | // Clock Phase data captured on leading edge, changes on following edge
( 0 << 0); // Clock Polarity inactive state is logic 0
(0 << 0); // Clock Polarity inactive state is logic 0
break;
/*
/*
case SPI_LCD_MODE:
AT91C_BASE_SPI->SPI_MR =
( 0 << 24) | // Delay between chip selects (take default: 6 MCK periods)
@ -107,7 +109,7 @@ void SetupSpi(int mode) {
( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge
( 0 << 0); // Clock Polarity inactive state is logic 0
break;
*/
*/
default:
DisableSpi();
break;
@ -118,7 +120,8 @@ void SetupSpi(int mode) {
// Set up the synchronous serial port, with the one set of options that we
// always use when we are talking to the FPGA. Both RX and TX are enabled.
//-----------------------------------------------------------------------------
void FpgaSetupSsc(void) {
void FpgaSetupSsc(void)
{
// First configure the GPIOs, and get ourselves a clock.
AT91C_BASE_PIOA->PIO_ASR =
GPIO_SSC_FRAME |
@ -156,7 +159,8 @@ void FpgaSetupSsc(void) {
// ourselves, not to another buffer). The stuff to manipulate those buffers
// is in apps.h, because it should be inlined, for speed.
//-----------------------------------------------------------------------------
bool FpgaSetupSscDma(uint8_t *buf, int len) {
bool FpgaSetupSscDma(uint8_t *buf, int len)
{
if (buf == NULL) return false;
FpgaDisableSscDma();
@ -172,7 +176,8 @@ bool FpgaSetupSscDma(uint8_t *buf, int len) {
// Uncompress (inflate) the FPGA data. Returns one decompressed byte with
// each call.
//----------------------------------------------------------------------------
static int get_from_fpga_combined_stream(z_streamp compressed_fpga_stream, uint8_t *output_buffer) {
static int get_from_fpga_combined_stream(z_streamp compressed_fpga_stream, uint8_t *output_buffer)
{
if (fpga_image_ptr == compressed_fpga_stream->next_out) { // need more data
compressed_fpga_stream->next_out = output_buffer;
compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN;
@ -194,8 +199,9 @@ static int get_from_fpga_combined_stream(z_streamp compressed_fpga_stream, uint8
// are combined into one big file:
// 288 bytes from FPGA file 1, followed by 288 bytes from FGPA file 2, etc.
//----------------------------------------------------------------------------
static int get_from_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer) {
while((uncompressed_bytes_cnt / FPGA_INTERLEAVE_SIZE) % fpga_bitstream_num != (bitstream_version - 1)) {
static int get_from_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer)
{
while ((uncompressed_bytes_cnt / FPGA_INTERLEAVE_SIZE) % fpga_bitstream_num != (bitstream_version - 1)) {
// skip undesired data belonging to other bitstream_versions
get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer);
}
@ -203,19 +209,23 @@ static int get_from_fpga_stream(int bitstream_version, z_streamp compressed_fpga
return get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer);
}
static voidpf fpga_inflate_malloc(voidpf opaque, uInt items, uInt size) {
return BigBuf_malloc(items*size);
static voidpf fpga_inflate_malloc(voidpf opaque, uInt items, uInt size)
{
return BigBuf_malloc(items * size);
}
// free eventually allocated BigBuf memory
static void fpga_inflate_free(voidpf opaque, voidpf address) {
BigBuf_free(); BigBuf_Clear_ext(false);
static void fpga_inflate_free(voidpf opaque, voidpf address)
{
BigBuf_free();
BigBuf_Clear_ext(false);
}
//----------------------------------------------------------------------------
// Initialize decompression of the respective (HF or LF) FPGA stream
//----------------------------------------------------------------------------
static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer) {
static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer)
{
uint8_t header[FPGA_BITSTREAM_FIXED_HEADER_SIZE];
uncompressed_bytes_cnt = 0;
@ -242,7 +252,8 @@ static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_s
return false;
}
static void DownloadFPGA_byte( uint8_t w) {
static void DownloadFPGA_byte(uint8_t w)
{
#define SEND_BIT(x) { if(w & (1<<x) ) HIGH(GPIO_FPGA_DIN); else LOW(GPIO_FPGA_DIN); HIGH(GPIO_FPGA_CCLK); LOW(GPIO_FPGA_CCLK); }
SEND_BIT(7);
SEND_BIT(6);
@ -255,7 +266,8 @@ static void DownloadFPGA_byte( uint8_t w) {
}
// Download the fpga image starting at current stream position with length FpgaImageLen bytes
static void DownloadFPGA(int bitstream_version, int FpgaImageLen, z_streamp compressed_fpga_stream, uint8_t *output_buffer) {
static void DownloadFPGA(int bitstream_version, int FpgaImageLen, z_streamp compressed_fpga_stream, uint8_t *output_buffer)
{
int i = 0;
AT91C_BASE_PIOA->PIO_OER = GPIO_FPGA_ON;
@ -296,12 +308,12 @@ static void DownloadFPGA(int bitstream_version, int FpgaImageLen, z_streamp comp
i = 100000;
// wait for FPGA ready to accept data signal
while ((i) && ( !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_NINIT ) ) ) {
while ((i) && (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_NINIT))) {
i--;
}
// crude error indicator, leave both red LEDs on and return
if (i==0){
if (i == 0) {
LED_C_ON();
LED_D_ON();
return;
@ -318,12 +330,12 @@ static void DownloadFPGA(int bitstream_version, int FpgaImageLen, z_streamp comp
// continue to clock FPGA until ready signal goes high
i = 100000;
while ( (i--) && ( !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_DONE ) ) ) {
while ((i--) && (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_DONE))) {
HIGH(GPIO_FPGA_CCLK);
LOW(GPIO_FPGA_CCLK);
}
// crude error indicator, leave both red LEDs on and return
if (i==0){
if (i == 0) {
LED_C_ON();
LED_D_ON();
return;
@ -337,11 +349,12 @@ static void DownloadFPGA(int bitstream_version, int FpgaImageLen, z_streamp comp
* (big endian), <length> bytes content. Except for section 'e' which has 4 bytes
* length.
*/
static int bitparse_find_section(int bitstream_version, char section_name, uint32_t *section_length, z_streamp compressed_fpga_stream, uint8_t *output_buffer) {
static int bitparse_find_section(int bitstream_version, char section_name, uint32_t *section_length, z_streamp compressed_fpga_stream, uint8_t *output_buffer)
{
int result = 0;
#define MAX_FPGA_BIT_STREAM_HEADER_SEARCH 100 // maximum number of bytes to search for the requested section
#define MAX_FPGA_BIT_STREAM_HEADER_SEARCH 100 // maximum number of bytes to search for the requested section
uint16_t numbytes = 0;
while(numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH) {
while (numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH) {
char current_name = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
numbytes++;
uint32_t current_length = 0;
@ -386,7 +399,8 @@ static int bitparse_find_section(int bitstream_version, char section_name, uint3
// Check which FPGA image is currently loaded (if any). If necessary
// decompress and load the correct (HF or LF) image to the FPGA
//----------------------------------------------------------------------------
void FpgaDownloadAndGo(int bitstream_version) {
void FpgaDownloadAndGo(int bitstream_version)
{
// check whether or not the bitstream is already loaded
if (downloaded_bitstream == bitstream_version)
@ -398,7 +412,8 @@ void FpgaDownloadAndGo(int bitstream_version) {
bool verbose = (MF_DBGLEVEL > 3);
// make sure that we have enough memory to decompress
BigBuf_free(); BigBuf_Clear_ext(verbose);
BigBuf_free();
BigBuf_Clear_ext(verbose);
if (!reset_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer))
return;
@ -415,7 +430,8 @@ void FpgaDownloadAndGo(int bitstream_version) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
// free eventually allocated BigBuf memory
BigBuf_free(); BigBuf_Clear_ext(false);
BigBuf_free();
BigBuf_Clear_ext(false);
}
//-----------------------------------------------------------------------------
@ -423,7 +439,8 @@ void FpgaDownloadAndGo(int bitstream_version) {
// The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
// where C is the 4 bit command and D is the 12 bit data
//-----------------------------------------------------------------------------
void FpgaSendCommand(uint16_t cmd, uint16_t v) {
void FpgaSendCommand(uint16_t cmd, uint16_t v)
{
SetupSpi(SPI_FPGA_MODE);
while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); // wait for the transfer to complete
AT91C_BASE_SPI->SPI_TDR = AT91C_SPI_LASTXFER | cmd | v; // send the data
@ -434,7 +451,8 @@ void FpgaSendCommand(uint16_t cmd, uint16_t v) {
// vs. clone vs. etc.). This is now a special case of FpgaSendCommand() to
// avoid changing this function's occurence everywhere in the source code.
//-----------------------------------------------------------------------------
void FpgaWriteConfWord(uint8_t v) {
void FpgaWriteConfWord(uint8_t v)
{
FpgaSendCommand(FPGA_CMD_SET_CONFREG, v);
}
@ -443,7 +461,8 @@ void FpgaWriteConfWord(uint8_t v) {
// closable, but should only close one at a time. Not an FPGA thing, but
// the samples from the ADC always flow through the FPGA.
//-----------------------------------------------------------------------------
void SetAdcMuxFor(uint32_t whichGpio) {
void SetAdcMuxFor(uint32_t whichGpio)
{
AT91C_BASE_PIOA->PIO_OER =
GPIO_MUXSEL_HIPKD |
GPIO_MUXSEL_LOPKD |
@ -466,12 +485,14 @@ void SetAdcMuxFor(uint32_t whichGpio) {
HIGH(whichGpio);
}
void Fpga_print_status(void) {
void Fpga_print_status(void)
{
Dbprintf("Currently loaded FPGA image");
Dbprintf(" mode....................%s", fpga_version_information[downloaded_bitstream-1]);
Dbprintf(" mode....................%s", fpga_version_information[downloaded_bitstream - 1]);
}
int FpgaGetCurrent(void) {
int FpgaGetCurrent(void)
{
return downloaded_bitstream;
}
@ -479,10 +500,11 @@ int FpgaGetCurrent(void) {
// log message
// if HF, Disable SSC DMA
// turn off trace and leds off.
void switch_off(void) {
void switch_off(void)
{
if (MF_DBGLEVEL > 3) Dbprintf("switch_off");
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
if (downloaded_bitstream == FPGA_BITSTREAM_HF )
if (downloaded_bitstream == FPGA_BITSTREAM_HF)
FpgaDisableSscDma();
set_tracing(false);
LEDsoff();

View file

@ -11,22 +11,23 @@ static void RAMFUNC optimizedSnoop(void)
int n = BigBuf_max_traceLen() / sizeof(uint16_t); // take all memory
uint16_t *dest = (uint16_t *)BigBuf_get_addr();
uint16_t *destend = dest + n-1;
uint16_t *destend = dest + n - 1;
// Reading data loop
while(dest <= destend) {
if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
while (dest <= destend) {
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
*dest = (uint16_t)(AT91C_BASE_SSC->SSC_RHR);
dest++;
}
}
//setting tracelen - important! it was set by buffer overflow before
set_tracelen( BigBuf_max_traceLen());
set_tracelen(BigBuf_max_traceLen());
}
void HfSnoop(int samplesToSkip, int triggersToSkip)
{
BigBuf_free(); BigBuf_Clear();
BigBuf_free();
BigBuf_Clear();
Dbprintf("Skipping first %d sample pairs, Skipping %d triggers.\n", samplesToSkip, triggersToSkip);
int trigger_cnt = 0;
@ -47,7 +48,7 @@ void HfSnoop(int samplesToSkip, int triggersToSkip)
SpinDelay(100);
uint16_t r = 0;
while (!BUTTON_PRESS() && !usb_poll_validate_length() ) {
while (!BUTTON_PRESS() && !usb_poll_validate_length()) {
WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
@ -62,9 +63,9 @@ void HfSnoop(int samplesToSkip, int triggersToSkip)
if (!BUTTON_PRESS()) {
int waitcount = samplesToSkip; // lets wait 40000 ticks of pck0
while(waitcount != 0) {
while (waitcount != 0) {
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY))
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY))
waitcount--;
}
optimizedSnoop();

File diff suppressed because it is too large Load diff

View file

@ -53,7 +53,7 @@ static byte_t pwdh0, pwdl0, pwdl1; //password bytes
static uint32_t rnd = 0x74124485; //randomnumber
static int test = 0;
size_t blocknr;
bool end=false;
bool end = false;
// Single bit Hitag2 functions:
#define i4(x,a,b,c,d) ((u32)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8))
@ -65,7 +65,8 @@ static const u32 ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0
#define ht2bs_5c(a,b,c,d,e) (~((((((c^e)|d)&a)^b)&(c^b))^(((d^e)|a)&((d^b)|c))))
#define uf20bs u32
static u32 f20(const u64 x) {
static u32 f20(const u64 x)
{
u32 i5;
i5 = ((ht2_f4a >> i4(x, 1, 2, 4, 5)) & 1) * 1
@ -76,7 +77,8 @@ static u32 f20(const u64 x) {
return (ht2_f5c >> i5) & 1;
}
static u64 hitag2_round(u64 *state) {
static u64 hitag2_round(u64 *state)
{
u64 x = *state;
x = (x >> 1)
@ -88,16 +90,18 @@ static u64 hitag2_round(u64 *state) {
*state = x;
return f20(x);
}
static u64 hitag2_init(const u64 key, const u32 serial, const u32 IV) {
static u64 hitag2_init(const u64 key, const u32 serial, const u32 IV)
{
u32 i;
u64 x = ((key & 0xFFFF) << 32) + serial;
for (i = 0; i < 32; i++) {
x >>= 1;
x += (u64) (f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47;
x += (u64)(f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47;
}
return x;
}
static u32 hitag2_byte(u64 *x) {
static u32 hitag2_byte(u64 *x)
{
u32 i, c;
for (i = 0, c = 0; i < 8; i++)
@ -144,11 +148,11 @@ static u32 hitag2_byte(u64 *x) {
* Implementation of the crc8 calculation from Hitag S
* from http://www.proxmark.org/files/Documents/125%20kHz%20-%20Hitag/HitagS.V11.pdf
*/
void calc_crc(unsigned char * crc, unsigned char data, unsigned char Bitcount) {
void calc_crc(unsigned char *crc, unsigned char data, unsigned char Bitcount)
{
*crc ^= data; // crc = crc (exor) data
do {
if (*crc & 0x80) // if (MSB-CRC == 1)
{
if (*crc & 0x80) { // if (MSB-CRC == 1)
*crc <<= 1; // CRC = CRC Bit-shift left
*crc ^= CRC_POLYNOM; // CRC = CRC (exor) CRC_POLYNOM
} else {
@ -157,7 +161,8 @@ void calc_crc(unsigned char * crc, unsigned char data, unsigned char Bitcount) {
} while (--Bitcount);
}
static void hitag_send_bit(int bit) {
static void hitag_send_bit(int bit)
{
LED_A_ON();
// Reset clock for the next bit
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
@ -259,7 +264,8 @@ static void hitag_send_bit(int bit) {
}
}
static void hitag_send_frame(const byte_t* frame, size_t frame_len) {
static void hitag_send_frame(const byte_t *frame, size_t frame_len)
{
// Send start of frame
for (size_t i = 0; i < sof_bits; i++) {
@ -274,7 +280,8 @@ static void hitag_send_frame(const byte_t* frame, size_t frame_len) {
LOW(GPIO_SSC_DOUT);
}
static void hitag_reader_send_bit(int bit) {
static void hitag_reader_send_bit(int bit)
{
//Dbprintf("BIT: %d",bit);
LED_A_ON();
// Reset clock for the next bit
@ -330,7 +337,8 @@ 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) {
static void hitag_reader_send_frame(const byte_t *frame, size_t frame_len)
{
// Send the content of the frame
for (size_t i = 0; i < frame_len; i++) {
if (frame[0] == 0xf8) {
@ -352,7 +360,8 @@ static void hitag_reader_send_frame(const byte_t* frame, size_t frame_len) {
/*
* to check if the right uid was selected
*/
static int check_select(byte_t* rx, uint32_t uid) {
static int check_select(byte_t *rx, uint32_t uid)
{
unsigned char resp[48];
int i;
uint32_t ans = 0x0;
@ -372,8 +381,9 @@ static int check_select(byte_t* rx, uint32_t uid) {
/*
* handles all commands from a reader
*/
static void hitagS_handle_reader_command(byte_t* rx, const size_t rxlen,
byte_t* tx, size_t* txlen) {
static void hitagS_handle_reader_command(byte_t *rx, const size_t rxlen,
byte_t *tx, size_t *txlen)
{
byte_t rx_air[HITAG_FRAME_LEN];
byte_t page;
int i;
@ -565,8 +575,7 @@ static void hitagS_handle_reader_command(byte_t* rx, const size_t rxlen,
break;
case 20: {
//write page, write block, read page or read block command received
if ((rx[0] & 0xf0) == 0xc0) //read page
{
if ((rx[0] & 0xf0) == 0xc0) { //read page
//send page data
page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16);
*txlen = 32;
@ -608,8 +617,7 @@ static void hitagS_handle_reader_command(byte_t* rx, const size_t rxlen,
sof_bits = 0;
*txlen = 0;
}
} else if ((rx[0] & 0xf0) == 0xd0) //read block
{
} else if ((rx[0] & 0xf0) == 0xd0) { //read block
page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16);
*txlen = 32 * 4;
//send page,...,page+3 data
@ -651,8 +659,7 @@ static void hitagS_handle_reader_command(byte_t* rx, const size_t rxlen,
sof_bits = 0;
*txlen = 0;
}
} else if ((rx[0] & 0xf0) == 0x80) //write page
{
} else if ((rx[0] & 0xf0) == 0x80) { //write page
page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16);
switch (tag.mode) {
@ -683,8 +690,7 @@ static void hitagS_handle_reader_command(byte_t* rx, const size_t rxlen,
tag.tstate = HT_WRITING_PAGE_DATA;
}
} else if ((rx[0] & 0xf0) == 0x90) //write block
{
} else if ((rx[0] & 0xf0) == 0x90) { //write block
page = ((rx[0] & 0x0f) * 6) + ((rx[1] & 0xf0) / 16);
switch (tag.mode) {
case HT_STANDARD:
@ -725,8 +731,9 @@ static void hitagS_handle_reader_command(byte_t* rx, const size_t rxlen,
/*
* to autenticate to a tag with the given key or challenge
*/
static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr, byte_t* rx, const size_t rxlen, byte_t* tx,
size_t* txlen) {
static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrAr, byte_t *rx, const size_t rxlen, byte_t *tx,
size_t *txlen)
{
byte_t rx_air[HITAG_FRAME_LEN];
int response_bit[200];
int i, j, z, k;
@ -742,7 +749,7 @@ static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr
if (tag.pstate == HT_READY && rxlen >= 67) {
//received uid
if(end==true) {
if (end == true) {
Dbprintf("authentication failed!");
return -1;
}
@ -857,8 +864,8 @@ static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr
if (tag.auth == 1) {
//if the tag is in authentication mode try the key or challenge
*txlen = 64;
if(end!=true){
if(htf==02||htf==04){ //RHTS_KEY //WHTS_KEY
if (end != true) {
if (htf == 02 || htf == 04) { //RHTS_KEY //WHTS_KEY
state = hitag2_init(rev64(key), rev32(tag.uid),
rev32(rnd));
@ -878,11 +885,11 @@ static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr
if (DEBUG)
Dbprintf("%02X %02X %02X %02X %02X %02X %02X %02X", tx[0],
tx[1], tx[2], tx[3], tx[4], tx[5], tx[6], tx[7]);
} else if(htf==01 || htf==03) { //RHTS_CHALLENGE //WHTS_CHALLENGE
} else if (htf == 01 || htf == 03) { //RHTS_CHALLENGE //WHTS_CHALLENGE
for (i = 0; i < 8; i++)
tx[i]=((NrAr>>(56-(i*8)))&0xff);
tx[i] = ((NrAr >> (56 - (i * 8))) & 0xff);
}
end=true;
end = true;
tag.pstate = HT_AUTHENTICATE;
} else {
Dbprintf("authentication failed!");
@ -906,10 +913,10 @@ static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr
}
//decrypt password
pwdh0=0;
pwdl0=0;
pwdl1=0;
if(htf==02 || htf==04){ //RHTS_KEY //WHTS_KEY
pwdh0 = 0;
pwdl0 = 0;
pwdl1 = 0;
if (htf == 02 || htf == 04) { //RHTS_KEY //WHTS_KEY
{
state = hitag2_init(rev64(key), rev32(tag.uid), rev32(rnd));
for (i = 0; i < 5; i++)
@ -938,7 +945,8 @@ static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr
/*
* Emulates a Hitag S Tag with the given data from the .hts file
*/
void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) {
void SimulateHitagSTag(bool tag_mem_supplied, byte_t *data)
{
int frame_count;
int response;
int overflow;
@ -948,10 +956,11 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) {
//bool bQuitTraceFull = false;
bQuiet = false;
byte_t txbuf[HITAG_FRAME_LEN];
byte_t* tx = txbuf;
byte_t *tx = txbuf;
size_t txlen = 0;
// free eventually allocated BigBuf memory
BigBuf_free(); BigBuf_Clear_ext(false);
BigBuf_free();
BigBuf_Clear_ext(false);
// Clean up trace and prepare it for storing frames
set_tracing(true);
@ -968,58 +977,58 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) {
//read tag data into memory
if (tag_mem_supplied) {
DbpString("Loading hitagS memory...");
memcpy((byte_t*)tag.pages,data,4*64);
memcpy((byte_t *)tag.pages, data, 4 * 64);
}
tag.uid=(uint32_t)tag.pages[0];
tag.uid = (uint32_t)tag.pages[0];
Dbprintf("Hitag S simulation started");
tag.key=(intptr_t)tag.pages[3];
tag.key<<=16;
tag.key+=((tag.pages[2][0])<<8)+tag.pages[2][1];
tag.pwdl0=tag.pages[2][3];
tag.pwdl1=tag.pages[2][2];
tag.pwdh0=tag.pages[1][0];
tag.key = (intptr_t)tag.pages[3];
tag.key <<= 16;
tag.key += ((tag.pages[2][0]) << 8) + tag.pages[2][1];
tag.pwdl0 = tag.pages[2][3];
tag.pwdl1 = tag.pages[2][2];
tag.pwdh0 = tag.pages[1][0];
//con0
tag.max_page=64;
if((tag.pages[1][3]&0x2)==0 && (tag.pages[1][3]&0x1)==1)
tag.max_page=8;
if((tag.pages[1][3]&0x2)==0 && (tag.pages[1][3]&0x1)==0)
tag.max_page=0;
tag.max_page = 64;
if ((tag.pages[1][3] & 0x2) == 0 && (tag.pages[1][3] & 0x1) == 1)
tag.max_page = 8;
if ((tag.pages[1][3] & 0x2) == 0 && (tag.pages[1][3] & 0x1) == 0)
tag.max_page = 0;
//con1
tag.auth=0;
if((tag.pages[1][2]&0x80) == 0x80)
tag.auth=1;
tag.LCON=0;
if((tag.pages[1][2]&0x2) == 0x02)
tag.LCON=1;
tag.LKP=0;
if((tag.pages[1][2]&0x1) == 0x01)
tag.LKP=1;
tag.auth = 0;
if ((tag.pages[1][2] & 0x80) == 0x80)
tag.auth = 1;
tag.LCON = 0;
if ((tag.pages[1][2] & 0x2) == 0x02)
tag.LCON = 1;
tag.LKP = 0;
if ((tag.pages[1][2] & 0x1) == 0x01)
tag.LKP = 1;
//con2
//0=read write 1=read only
tag.LCK7=0;
if((tag.pages[1][1]&0x80) == 0x80)
tag.LCK7=1;
tag.LCK6=0;
if((tag.pages[1][1]&0x40) == 0x040)
tag.LCK6=1;
tag.LCK5=0;
if((tag.pages[1][1]&0x20) == 0x20)
tag.LCK5=1;
tag.LCK4=0;
if((tag.pages[1][1]&0x10) == 0x10)
tag.LCK4=1;
tag.LCK3=0;
if((tag.pages[1][1]&0x8) == 0x08)
tag.LCK3=1;
tag.LCK2=0;
if((tag.pages[1][1]&0x4) == 0x04)
tag.LCK2=1;
tag.LCK1=0;
if((tag.pages[1][1]&0x2) == 0x02)
tag.LCK1=1;
tag.LCK0=0;
if((tag.pages[1][1]&0x1) == 0x01)
tag.LCK0=1;
tag.LCK7 = 0;
if ((tag.pages[1][1] & 0x80) == 0x80)
tag.LCK7 = 1;
tag.LCK6 = 0;
if ((tag.pages[1][1] & 0x40) == 0x040)
tag.LCK6 = 1;
tag.LCK5 = 0;
if ((tag.pages[1][1] & 0x20) == 0x20)
tag.LCK5 = 1;
tag.LCK4 = 0;
if ((tag.pages[1][1] & 0x10) == 0x10)
tag.LCK4 = 1;
tag.LCK3 = 0;
if ((tag.pages[1][1] & 0x8) == 0x08)
tag.LCK3 = 1;
tag.LCK2 = 0;
if ((tag.pages[1][1] & 0x4) == 0x04)
tag.LCK2 = 1;
tag.LCK1 = 0;
if ((tag.pages[1][1] & 0x2) == 0x02)
tag.LCK1 = 1;
tag.LCK0 = 0;
if ((tag.pages[1][1] & 0x1) == 0x01)
tag.LCK0 = 1;
// Set up simulator mode, frequency divisor which will drive the FPGA
// and analog mux selection.
@ -1163,7 +1172,8 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) {
* If the key was given the password will be decrypted.
* Reads every page of a hitag S transpoder.
*/
void ReadHitagS(hitag_function htf, hitag_data* htd) {
void ReadHitagS(hitag_function htf, hitag_data *htd)
{
int i, j, z, k;
int frame_count;
int response_bit[200];
@ -1171,7 +1181,7 @@ void ReadHitagS(hitag_function htf, hitag_data* htd) {
byte_t rx[HITAG_FRAME_LEN];
size_t rxlen = 0;
byte_t txbuf[HITAG_FRAME_LEN];
byte_t* tx = txbuf;
byte_t *tx = txbuf;
size_t txlen = 0;
int lastbit;
bool bSkip;
@ -1197,18 +1207,21 @@ void ReadHitagS(hitag_function htf, hitag_data* htd) {
memcpy(NrAr_, htd->auth.NrAr, 8);
Dbhexdump(8, NrAr_, false);
NrAr = NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 |
((uint64_t)NrAr_[2]) << 40| ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56;
} break;
((uint64_t)NrAr_[2]) << 40 | ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56;
}
break;
case 02: { //RHTS_KEY
DbpString("Authenticating using key:");
memcpy(key_, htd->crypto.key, 6);
Dbhexdump(6, key_, false);
key = key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40;
} break;
}
break;
default: {
Dbprintf("Error , unknown function: %d",htf);
Dbprintf("Error , unknown function: %d", htf);
return;
} break;
}
break;
}
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
@ -1304,7 +1317,7 @@ void ReadHitagS(hitag_function htf, hitag_data* htd) {
tag.pstate = HT_READY;
tag.tstate = HT_NO_OP;
} else if (tag.pstate != HT_SELECTED) {
if (hitagS_handle_tag_auth(htf, key,NrAr,rx, rxlen, tx, &txlen) == -1)
if (hitagS_handle_tag_auth(htf, key, NrAr, rx, rxlen, tx, &txlen) == -1)
bStop = !false;
}
if (tag.pstate == HT_SELECTED && tag.tstate == HT_NO_OP && rxlen > 0) {
@ -1505,13 +1518,14 @@ void ReadHitagS(hitag_function htf, hitag_data* htd) {
* Authenticates to the Tag with the given Key or Challenge.
* Writes the given 32Bit data into page_
*/
void WritePageHitagS(hitag_function htf, hitag_data* htd,int page_) {
void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_)
{
int frame_count;
int response;
byte_t rx[HITAG_FRAME_LEN];
size_t rxlen = 0;
byte_t txbuf[HITAG_FRAME_LEN];
byte_t* tx = txbuf;
byte_t *tx = txbuf;
size_t txlen = 0;
int lastbit;
bool bSkip;
@ -1522,36 +1536,39 @@ void WritePageHitagS(hitag_function htf, hitag_data* htd,int page_) {
bool bQuitTraceFull = false;
int page = page_;
unsigned char crc;
byte_t data[4]= {0,0,0,0};
byte_t data[4] = {0, 0, 0, 0};
//read given key/challenge, the page and the data
byte_t NrAr_[8];
uint64_t key=0;
uint64_t NrAr=0;
uint64_t key = 0;
uint64_t NrAr = 0;
byte_t key_[6];
switch(htf) {
switch (htf) {
case 03: { //WHTS_CHALLENGE
memcpy(data,htd->auth.data,4);
memcpy(data, htd->auth.data, 4);
DbpString("Authenticating using nr,ar pair:");
memcpy(NrAr_,htd->auth.NrAr,8);
Dbhexdump(8,NrAr_,false);
NrAr=NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 |
((uint64_t)NrAr_[2]) << 40| ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56;
} break;
memcpy(NrAr_, htd->auth.NrAr, 8);
Dbhexdump(8, NrAr_, false);
NrAr = NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 |
((uint64_t)NrAr_[2]) << 40 | ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56;
}
break;
case 04: { //WHTS_KEY
memcpy(data,htd->crypto.data,4);
memcpy(data, htd->crypto.data, 4);
DbpString("Authenticating using key:");
memcpy(key_,htd->crypto.key,6);
Dbhexdump(6,key_,false);
key=key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40;
} break;
memcpy(key_, htd->crypto.key, 6);
Dbhexdump(6, key_, false);
key = key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40;
}
break;
default: {
Dbprintf("Error , unknown function: %d",htf);
Dbprintf("Error , unknown function: %d", htf);
return;
} break;
}
break;
}
Dbprintf("Page: %d",page_);
Dbprintf("Page: %d", page_);
Dbprintf("DATA: %02X %02X %02X %02X", data[0], data[1], data[2], data[3]);
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
// Reset the return status
@ -1659,7 +1676,7 @@ void WritePageHitagS(hitag_function htf, hitag_data* htd,int page_) {
tag.tstate = HT_NO_OP;
} else if (tag.pstate != HT_SELECTED) {
//try to authenticate with the given key or challenge
if (hitagS_handle_tag_auth(htf,key,NrAr,rx, rxlen, tx, &txlen) == -1)
if (hitagS_handle_tag_auth(htf, key, NrAr, rx, rxlen, tx, &txlen) == -1)
bStop = !false;
}
if (tag.pstate == HT_SELECTED && tag.tstate == HT_NO_OP && rxlen > 0) {
@ -1802,7 +1819,7 @@ void WritePageHitagS(hitag_function htf, hitag_data* htd,int page_) {
}
}
}
end=false;
end = false;
LED_B_OFF();
LED_D_OFF();
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
@ -1818,7 +1835,8 @@ void WritePageHitagS(hitag_function htf, hitag_data* htd,int page_) {
* is not received correctly due to Antenna problems. This function
* detects these challenges.
*/
void check_challenges(bool file_given, byte_t* data) {
void check_challenges(bool file_given, byte_t *data)
{
int i, j, z, k;
byte_t uid_byte[4];
int frame_count;
@ -1828,7 +1846,7 @@ void check_challenges(bool file_given, byte_t* data) {
int u1 = 0;
size_t rxlen = 0;
byte_t txbuf[HITAG_FRAME_LEN];
byte_t* tx = txbuf;
byte_t *tx = txbuf;
size_t txlen = 0;
int lastbit;
bool bSkip;
@ -1906,7 +1924,7 @@ void check_challenges(bool file_given, byte_t* data) {
if (file_given) {
DbpString("Loading challenges...");
memcpy((byte_t*)unlocker,data,60*8);
memcpy((byte_t *)unlocker, data, 60 * 8);
}
while (file_given && !bStop && !BUTTON_PRESS()) {

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -95,10 +95,10 @@ typedef struct {
extern void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par);
extern tDemod* GetDemod(void);
extern tDemod *GetDemod(void);
extern void DemodReset(void);
extern void DemodInit(uint8_t *data, uint8_t *parity);
extern tUart* GetUart(void);
extern tUart *GetUart(void);
extern void UartReset(void);
extern void UartInit(uint8_t *data, uint8_t *parity);
extern RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time);
@ -133,7 +133,7 @@ bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_Start
//extern bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_t **buffer, size_t *buffer_size);
void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype );
void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype);
void DetectNACKbug();
#ifdef __cplusplus

View file

@ -38,7 +38,7 @@
// 4sample
#define SEND4STUFFBIT(x) ToSendStuffBit(x);ToSendStuffBit(x);ToSendStuffBit(x);ToSendStuffBit(x);
//#define SEND4STUFFBIT(x) ToSendStuffBit(x);
// iceman, this threshold value, what makes 8 a good amplitude for this IQ values?
// iceman, this threshold value, what makes 8 a good amplitude for this IQ values?
#ifndef SUBCARRIER_DETECT_THRESHOLD
# define SUBCARRIER_DETECT_THRESHOLD 8
#endif
@ -77,7 +77,8 @@ static struct {
uint8_t *output;
} Uart;
static void UartReset() {
static void UartReset()
{
Uart.state = STATE_UNSYNCD;
Uart.shiftReg = 0;
Uart.bitCnt = 0;
@ -86,7 +87,8 @@ static void UartReset() {
Uart.posCnt = 0;
}
static void UartInit(uint8_t *data) {
static void UartInit(uint8_t *data)
{
Uart.output = data;
UartReset();
// memset(Uart.output, 0x00, MAX_FRAME_SIZE);
@ -107,10 +109,10 @@ static struct {
uint16_t bitCount;
int posCount;
int thisBit;
/* this had been used to add RSSI (Received Signal Strength Indication) to traces. Currently not implemented.
/* this had been used to add RSSI (Received Signal Strength Indication) to traces. Currently not implemented.
int metric;
int metricN;
*/
*/
uint16_t shiftReg;
uint8_t *output;
uint16_t len;
@ -120,7 +122,8 @@ static struct {
} Demod;
// Clear out the state of the "UART" that receives from the tag.
static void DemodReset() {
static void DemodReset()
{
Demod.state = DEMOD_UNSYNCD;
Demod.bitCount = 0;
Demod.posCount = 0;
@ -133,7 +136,8 @@ static void DemodReset() {
Demod.endTime = 0;
}
static void DemodInit(uint8_t *data) {
static void DemodInit(uint8_t *data)
{
Demod.output = data;
DemodReset();
// memset(Demod.output, 0x00, MAX_FRAME_SIZE);
@ -153,20 +157,22 @@ static void DemodInit(uint8_t *data) {
* 13560000000 / 384000 = 35312 FWT
* @param timeout is in frame wait time, fwt, measured in ETUs
*/
static void iso14b_set_timeout(uint32_t timeout) {
#define MAX_TIMEOUT 40542464 // 13560000Hz * 1000ms / (2^32-1) * (8*16)
if(timeout > MAX_TIMEOUT)
static void iso14b_set_timeout(uint32_t timeout)
{
#define MAX_TIMEOUT 40542464 // 13560000Hz * 1000ms / (2^32-1) * (8*16)
if (timeout > MAX_TIMEOUT)
timeout = MAX_TIMEOUT;
iso14b_timeout = timeout;
if(MF_DBGLEVEL >= 3) Dbprintf("ISO14443B Timeout set to %ld fwt", iso14b_timeout);
if (MF_DBGLEVEL >= 3) Dbprintf("ISO14443B Timeout set to %ld fwt", iso14b_timeout);
}
static void iso14b_set_maxframesize(uint16_t size) {
static void iso14b_set_maxframesize(uint16_t size)
{
if (size > 256)
size = MAX_FRAME_SIZE;
Uart.byteCntMax = size;
if(MF_DBGLEVEL >= 3) Dbprintf("ISO14443B Max frame size set to %d bytes", Uart.byteCntMax);
if (MF_DBGLEVEL >= 3) Dbprintf("ISO14443B Max frame size set to %d bytes", Uart.byteCntMax);
}
//-----------------------------------------------------------------------------
@ -174,7 +180,8 @@ static void iso14b_set_maxframesize(uint16_t size) {
// that here) so that they can be transmitted to the reader. Doesn't transmit
// them yet, just leaves them ready to send in ToSend[].
//-----------------------------------------------------------------------------
static void CodeIso14443bAsTag(const uint8_t *cmd, int len) {
static void CodeIso14443bAsTag(const uint8_t *cmd, int len)
{
/* ISO 14443 B
*
* Reader to card | ASK - Amplitude Shift Keying Modulation (PCD to PICC for Type B) (NRZ-L encodig)
@ -237,7 +244,7 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) {
*
*/
int i,j;
int i, j;
uint8_t b;
ToSendReset();
@ -252,15 +259,15 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) {
// Send SOF.
// 10-11 ETU * 4times samples ZEROS
for(i = 0; i < 10; i++) { SEND4STUFFBIT(0); }
for (i = 0; i < 10; i++) { SEND4STUFFBIT(0); }
//for(i = 0; i < 10; i++) { ToSendStuffBit(0); }
// 2-3 ETU * 4times samples ONES
for(i = 0; i < 3; i++) { SEND4STUFFBIT(1); }
for (i = 0; i < 3; i++) { SEND4STUFFBIT(1); }
//for(i = 0; i < 3; i++) { ToSendStuffBit(1); }
// data
for(i = 0; i < len; ++i) {
for (i = 0; i < len; ++i) {
// Start bit
SEND4STUFFBIT(0);
@ -268,7 +275,7 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) {
// Data bits
b = cmd[i];
for(j = 0; j < 8; ++j) {
for (j = 0; j < 8; ++j) {
// if(b & 1) {
// SEND4STUFFBIT(1);
// //ToSendStuffBit(1);
@ -276,7 +283,7 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) {
// SEND4STUFFBIT(0);
// //ToSendStuffBit(0);
// }
SEND4STUFFBIT( b & 1 );
SEND4STUFFBIT(b & 1);
b >>= 1;
}
@ -292,11 +299,11 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) {
// Send EOF.
// 10-11 ETU * 4 sample rate = ZEROS
for(i = 0; i < 10; i++) { SEND4STUFFBIT(0); }
for (i = 0; i < 10; i++) { SEND4STUFFBIT(0); }
//for(i = 0; i < 10; i++) { ToSendStuffBit(0); }
// why this?
for(i = 0; i < 40; i++) { SEND4STUFFBIT(1); }
for (i = 0; i < 40; i++) { SEND4STUFFBIT(1); }
//for(i = 0; i < 40; i++) { ToSendStuffBit(1); }
// Convert from last byte pos to length
@ -316,7 +323,8 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) {
* Returns: true if we received a EOF
* false if we are still waiting for some more
*/
static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) {
static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit)
{
switch (Uart.state) {
case STATE_UNSYNCD:
if (!bit) {
@ -358,7 +366,7 @@ static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) {
case STATE_AWAITING_START_BIT:
Uart.posCnt++;
if (bit) {
if (Uart.posCnt > 50/2) { // max 57us between characters = 49 1/fs, max 3 etus after low phase of SOF = 24 1/fs
if (Uart.posCnt > 50 / 2) { // max 57us between characters = 49 1/fs, max 3 etus after low phase of SOF = 24 1/fs
// stayed high for too long between characters, error
Uart.state = STATE_UNSYNCD;
}
@ -385,8 +393,7 @@ static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) {
Uart.posCnt = 0;
}
if (Uart.bitCnt == 10) {
if ((Uart.shiftReg & 0x200) && !(Uart.shiftReg & 0x001))
{
if ((Uart.shiftReg & 0x200) && !(Uart.shiftReg & 0x001)) {
// this is a data byte, with correct
// start and stop bits
Uart.output[Uart.byteCnt] = (Uart.shiftReg >> 1) & 0xff;
@ -433,7 +440,8 @@ static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) {
// Assume that we're called with the SSC (to the FPGA) and ADC path set
// correctly.
//-----------------------------------------------------------------------------
static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) {
static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len)
{
// Set FPGA mode to "simulated ISO 14443B tag", no modulation (listen
// only, since we are receiving, not transmitting).
// Signal field is off with the appropriate LED
@ -447,7 +455,7 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) {
// clear receiving shift register and holding register
// What does this loop do? Is it TR1?
// loop is a wait/delay ?
/*
/*
for(uint8_t c = 0; c < 10;) {
// keep tx buffer in a defined state anyway.
@ -461,7 +469,7 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) {
UartInit(received);
uint8_t mask;
while( !BUTTON_PRESS() ) {
while (!BUTTON_PRESS()) {
WDT_HIT();
// keep tx buffer in a defined state anyway.
@ -470,12 +478,12 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) {
}
// Wait for byte be become available in rx holding register
if ( AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY ) {
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
b = (uint8_t) AT91C_BASE_SSC->SSC_RHR;
for ( mask = 0x80; mask != 0; mask >>= 1) {
if ( Handle14443bReaderUartBit(b & mask)) {
for (mask = 0x80; mask != 0; mask >>= 1) {
if (Handle14443bReaderUartBit(b & mask)) {
*len = Uart.byteCnt;
return true;
}
@ -485,18 +493,21 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) {
return false;
}
void ClearFpgaShiftingRegisters(void){
void ClearFpgaShiftingRegisters(void)
{
volatile uint8_t b;
// clear receiving shift register and holding register
while(!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {};
while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {};
b = AT91C_BASE_SSC->SSC_RHR; (void) b;
b = AT91C_BASE_SSC->SSC_RHR;
(void) b;
while(!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {};
while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {};
b = AT91C_BASE_SSC->SSC_RHR; (void) b;
b = AT91C_BASE_SSC->SSC_RHR;
(void) b;
// wait for the FPGA to signal fdt_indicator == 1 (the FPGA is ready to queue new data in its delay line)
for (uint8_t j = 0; j < 5; j++) { // allow timeout - better late than never
@ -508,18 +519,20 @@ void ClearFpgaShiftingRegisters(void){
//AT91C_BASE_SSC->SSC_THR = 0xFF;
}
void WaitForFpgaDelayQueueIsEmpty( uint16_t delay ){
void WaitForFpgaDelayQueueIsEmpty(uint16_t delay)
{
// Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN again:
uint8_t fpga_queued_bits = delay >> 3; // twich /8 ?? >>3,
for (uint8_t i = 0; i <= fpga_queued_bits/8 + 1; ) {
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
for (uint8_t i = 0; i <= fpga_queued_bits / 8 + 1;) {
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = 0xFF;
i++;
}
}
}
static void TransmitFor14443b_AsTag( uint8_t *response, uint16_t len) {
static void TransmitFor14443b_AsTag(uint8_t *response, uint16_t len)
{
volatile uint32_t b;
@ -536,16 +549,17 @@ static void TransmitFor14443b_AsTag( uint8_t *response, uint16_t len) {
FpgaSetupSsc();
// Transmit the response.
for(uint16_t i = 0; i < len;) {
for (uint16_t i = 0; i < len;) {
// Put byte into tx holding register as soon as it is ready
if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
AT91C_BASE_SSC->SSC_THR = response[++i];
}
// Prevent rx holding register from overflowing
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
b = AT91C_BASE_SSC->SSC_RHR;(void)b;
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
b = AT91C_BASE_SSC->SSC_RHR;
(void)b;
}
}
@ -556,7 +570,8 @@ static void TransmitFor14443b_AsTag( uint8_t *response, uint16_t len) {
// Main loop of simulated tag: receive commands from reader, decide what
// response to send, and send it.
//-----------------------------------------------------------------------------
void SimulateIso14443bTag(uint32_t pupi) {
void SimulateIso14443bTag(uint32_t pupi)
{
// setup device.
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
@ -566,7 +581,8 @@ void SimulateIso14443bTag(uint32_t pupi) {
FpgaSetupSsc();
// allocate command receive buffer
BigBuf_free(); BigBuf_Clear_ext(false);
BigBuf_free();
BigBuf_Clear_ext(false);
clear_trace(); //sim
set_tracing(true);
@ -590,14 +606,15 @@ void SimulateIso14443bTag(uint32_t pupi) {
// supports only 106kBit/s in both directions, max frame size = 32Bytes,
// supports ISO14443-4, FWI=8 (77ms), NAD supported, CID not supported:
uint8_t respATQB[] = { 0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19,
0x22, 0x00, 0x21, 0x85, 0x5e, 0xd7 };
0x22, 0x00, 0x21, 0x85, 0x5e, 0xd7
};
// response to HLTB and ATTRIB
static const uint8_t respOK[] = {0x00, 0x78, 0xF0};
// ...PUPI/UID supplied from user. Adjust ATQB response accordingly
if ( pupi > 0 ) {
num_to_bytes(pupi, 4, respATQB+1);
if (pupi > 0) {
num_to_bytes(pupi, 4, respATQB + 1);
AddCrc14B(respATQB, 12);
}
@ -621,7 +638,7 @@ void SimulateIso14443bTag(uint32_t pupi) {
// find reader field
if (cardSTATE == SIM_NOFIELD) {
vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
if ( vHf > MF_MINFIELDV ) {
if (vHf > MF_MINFIELDV) {
cardSTATE = SIM_IDLE;
LED_A_ON();
}
@ -637,9 +654,9 @@ void SimulateIso14443bTag(uint32_t pupi) {
// ISO14443-B protocol states:
// REQ or WUP request in ANY state
// WUP in HALTED state
if (len == 5 ) {
if ( (receivedCmd[0] == ISO14443B_REQB && (receivedCmd[2] & 0x8)== 0x8 && cardSTATE == SIM_HALTED) ||
receivedCmd[0] == ISO14443B_REQB ){
if (len == 5) {
if ((receivedCmd[0] == ISO14443B_REQB && (receivedCmd[2] & 0x8) == 0x8 && cardSTATE == SIM_HALTED) ||
receivedCmd[0] == ISO14443B_REQB) {
LogTrace(receivedCmd, len, 0, 0, NULL, true);
cardSTATE = SIM_SELECTING;
}
@ -663,27 +680,27 @@ void SimulateIso14443bTag(uint32_t pupi) {
break;
}
case SIM_SELECTING: {
TransmitFor14443b_AsTag( encodedATQB, encodedATQBLen );
TransmitFor14443b_AsTag(encodedATQB, encodedATQBLen);
LogTrace(respATQB, sizeof(respATQB), 0, 0, NULL, false);
cardSTATE = SIM_WORK;
break;
}
case SIM_HALTING: {
TransmitFor14443b_AsTag( encodedOK, encodedOKLen );
TransmitFor14443b_AsTag(encodedOK, encodedOKLen);
LogTrace(respOK, sizeof(respOK), 0, 0, NULL, false);
cardSTATE = SIM_HALTED;
break;
}
case SIM_ACKNOWLEDGE: {
TransmitFor14443b_AsTag( encodedOK, encodedOKLen );
TransmitFor14443b_AsTag(encodedOK, encodedOKLen);
LogTrace(respOK, sizeof(respOK), 0, 0, NULL, false);
cardSTATE = SIM_IDLE;
break;
}
case SIM_WORK: {
if ( len == 7 && receivedCmd[0] == ISO14443B_HALT ) {
if (len == 7 && receivedCmd[0] == ISO14443B_HALT) {
cardSTATE = SIM_HALTED;
} else if ( len == 11 && receivedCmd[0] == ISO14443B_ATTRIB ) {
} else if (len == 11 && receivedCmd[0] == ISO14443B_ATTRIB) {
cardSTATE = SIM_ACKNOWLEDGE;
} else {
// Todo:
@ -693,7 +710,7 @@ void SimulateIso14443bTag(uint32_t pupi) {
Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsReceived);
// CRC Check
if (len >= 3){ // if crc exists
if (len >= 3) { // if crc exists
if (!check_crc(CRC_14443_B, receivedCmd, len))
DbpString("+++CRC fail");
@ -704,7 +721,8 @@ void SimulateIso14443bTag(uint32_t pupi) {
}
break;
}
default: break;
default:
break;
}
++cmdsReceived;
@ -735,7 +753,8 @@ void SimulateIso14443bTag(uint32_t pupi) {
* false if we are still waiting for some more
*
*/
static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) {
static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq)
{
int v = 0, myI = ABS(ci), myQ = ABS(cq);
// The soft decision on the bit uses an estimate of just the
@ -790,7 +809,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) {
//note: couldn't we just use MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2) from common.h - marshmellow
#define CHECK_FOR_SUBCARRIER() { v = MAX(myI, myQ) + (MIN(myI, myQ) >> 1); }
switch(Demod.state) {
switch (Demod.state) {
case DEMOD_UNSYNCD:
CHECK_FOR_SUBCARRIER();
@ -834,7 +853,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) {
Demod.posCount = 0; // start of SOF sequence
} else {
// maximum length of TR1 = 200 1/fs
if (Demod.posCount > 200/4) Demod.state = DEMOD_UNSYNCD;
if (Demod.posCount > 200 / 4) Demod.state = DEMOD_UNSYNCD;
}
Demod.posCount++;
break;
@ -846,7 +865,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) {
if (v > 0) {
// low phase of SOF too short (< 9 etu). Note: spec is >= 10, but FPGA tends to "smear" edges
if (Demod.posCount < 9*2) {
if (Demod.posCount < 9 * 2) {
Demod.state = DEMOD_UNSYNCD;
} else {
LED_C_ON(); // Got SOF
@ -856,7 +875,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) {
}
} else {
// low phase of SOF too long (> 12 etu)
if (Demod.posCount > 14*2) {
if (Demod.posCount > 14 * 2) {
Demod.state = DEMOD_UNSYNCD;
LED_C_OFF();
}
@ -869,7 +888,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) {
MAKE_SOFT_DECISION();
if (v > 0) {
if (Demod.posCount > 6*2) { // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs
if (Demod.posCount > 6 * 2) { // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs
Demod.state = DEMOD_UNSYNCD;
LED_C_OFF();
}
@ -907,7 +926,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) {
uint16_t s = Demod.shiftReg;
// stop bit == '1', start bit == '0'
if ((s & 0x200) && (s & 0x001) == 0 ) {
if ((s & 0x200) && (s & 0x001) == 0) {
// left shift to drop the startbit
uint8_t b = (s >> 1);
Demod.output[Demod.len] = b;
@ -939,7 +958,8 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) {
* Demodulate the samples we received from the tag, also log to tracebuffer
* quiet: set to 'TRUE' to disable debug output
*/
static void GetTagSamplesFor14443bDemod() {
static void GetTagSamplesFor14443bDemod()
{
bool gotFrame = false, finished = false;
int lastRxCounter = ISO14443B_DMA_BUFFER_SIZE;
int ci = 0, cq = 0;
@ -951,11 +971,11 @@ static void GetTagSamplesFor14443bDemod() {
DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
// The DMA buffer, used to stream samples from the FPGA
int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE);
int8_t *dmaBuf = (int8_t *) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE);
int8_t *upTo = dmaBuf;
// Setup and start DMA.
if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE) ){
if (!FpgaSetupSscDma((uint8_t *) dmaBuf, ISO14443B_DMA_BUFFER_SIZE)) {
if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting");
return;
}
@ -967,7 +987,7 @@ static void GetTagSamplesFor14443bDemod() {
time_0 = GetCountSspClk();
// rx counter - dma counter? (how much?) & (mod) mask > 2. (since 2bytes at the time is read)
while ( !finished ) {
while (!finished) {
LED_A_INV();
WDT_HIT();
@ -979,7 +999,7 @@ static void GetTagSamplesFor14443bDemod() {
lastRxCounter -= 2;
// restart DMA buffer to receive again.
if(upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) {
if (upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) {
upTo = dmaBuf;
lastRxCounter = ISO14443B_DMA_BUFFER_SIZE;
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo;
@ -995,17 +1015,18 @@ static void GetTagSamplesFor14443bDemod() {
FpgaDisableSscDma();
if ( upTo )
if (upTo)
upTo = NULL;
if ( Demod.len > 0 )
if (Demod.len > 0)
LogTrace(Demod.output, Demod.len, time_0, time_stop, NULL, false);
}
//-----------------------------------------------------------------------------
// Transmit the command (to the tag) that was placed in ToSend[].
//-----------------------------------------------------------------------------
static void TransmitFor14443b_AsReader(void) {
static void TransmitFor14443b_AsReader(void)
{
int c;
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);
@ -1016,16 +1037,16 @@ static void TransmitFor14443b_AsReader(void) {
// loop 10 * 8 = 80 ETU of delay, with a non modulated signal. why?
// 80*9 = 720us.
for(c = 0; c < 50;) {
for (c = 0; c < 50;) {
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = 0xFF;
c++;
}
}
// Send frame loop
for(c = 0; c < ToSendMax;) {
for (c = 0; c < ToSendMax;) {
// Put byte into tx holding register as soon as it is ready
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
@ -1039,7 +1060,8 @@ static void TransmitFor14443b_AsReader(void) {
// Code a layer 2 command (string of octets, including CRC) into ToSend[],
// so that it is ready to transmit to the tag using TransmitFor14443b().
//-----------------------------------------------------------------------------
static void CodeIso14443bAsReader(const uint8_t *cmd, int len) {
static void CodeIso14443bAsReader(const uint8_t *cmd, int len)
{
/*
* Reader data transmission:
* - no modulation ONES
@ -1061,7 +1083,7 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) {
// Send SOF
// 10-11 ETUs of ZERO
for(i = 0; i < 10; ++i) ToSendStuffBit(0);
for (i = 0; i < 10; ++i) ToSendStuffBit(0);
// 2-3 ETUs of ONE
ToSendStuffBit(1);
@ -1070,7 +1092,7 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) {
// Sending cmd, LSB
// from here we add BITS
for(i = 0; i < len; ++i) {
for (i = 0; i < len; ++i) {
// Start bit
ToSendStuffBit(0);
// Data bits
@ -1084,14 +1106,14 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) {
// if ( (b>>6) & 1) ToSendStuffBit(1); else ToSendStuffBit(0);
// if ( (b>>7) & 1) ToSendStuffBit(1); else ToSendStuffBit(0);
ToSendStuffBit( b & 1);
ToSendStuffBit( (b>>1) & 1);
ToSendStuffBit( (b>>2) & 1);
ToSendStuffBit( (b>>3) & 1);
ToSendStuffBit( (b>>4) & 1);
ToSendStuffBit( (b>>5) & 1);
ToSendStuffBit( (b>>6) & 1);
ToSendStuffBit( (b>>7) & 1);
ToSendStuffBit(b & 1);
ToSendStuffBit((b >> 1) & 1);
ToSendStuffBit((b >> 2) & 1);
ToSendStuffBit((b >> 3) & 1);
ToSendStuffBit((b >> 4) & 1);
ToSendStuffBit((b >> 5) & 1);
ToSendStuffBit((b >> 6) & 1);
ToSendStuffBit((b >> 7) & 1);
// Stop bit
ToSendStuffBit(1);
@ -1104,13 +1126,13 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) {
// Send EOF
// 10-11 ETUs of ZERO
for(i = 0; i < 10; ++i) ToSendStuffBit(0);
for (i = 0; i < 10; ++i) ToSendStuffBit(0);
// Transition time. TR0 - guard time
// 8ETUS minum?
// Per specification, Subcarrier must be stopped no later than 2 ETUs after EOF.
// I'm guessing this is for the FPGA to be able to send all bits before we switch to listening mode
for(i = 0; i < 24 ; ++i) ToSendStuffBit(1);
for (i = 0; i < 24 ; ++i) ToSendStuffBit(1);
// TR1 - Synchronization time
// Convert from last character reference to length
@ -1120,7 +1142,8 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) {
/*
* Convenience function to encode, transmit and trace iso 14443b comms
*/
static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len) {
static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len)
{
uint32_t time_start = GetCountSspClk();
@ -1128,15 +1151,16 @@ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len) {
TransmitFor14443b_AsReader();
if(trigger) LED_A_ON();
if (trigger) LED_A_ON();
LogTrace(cmd, len, time_start, GetCountSspClk()-time_start, NULL, true);
LogTrace(cmd, len, time_start, GetCountSspClk() - time_start, NULL, true);
}
/* Sends an APDU to the tag
* TODO: check CRC and preamble
*/
uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response) {
uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response)
{
uint8_t message_frame[message_length + 4];
// PCB
@ -1152,16 +1176,16 @@ uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *r
CodeAndTransmit14443bAsReader(message_frame, message_length + 4); //no
// get response
GetTagSamplesFor14443bDemod(); //no
if(Demod.len < 3)
if (Demod.len < 3)
return 0;
// VALIDATE CRC
if (!check_crc(CRC_14443_B, Demod.output, Demod.len)){
if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) {
if (MF_DBGLEVEL > 3) Dbprintf("crc fail ICE");
return 0;
}
// copy response contents
if(response != NULL)
if (response != NULL)
memcpy(response, Demod.output, Demod.len);
return Demod.len;
@ -1170,7 +1194,8 @@ uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *r
/**
* SRx Initialise.
*/
uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card ) {
uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card)
{
// INITIATE command: wake up the tag using the INITIATE
static const uint8_t init_srx[] = { ISO14443B_INITIATE, 0x00, 0x97, 0x5b };
// SELECT command (with space for CRC)
@ -1230,7 +1255,8 @@ uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card ) {
* TODO: Support multiple cards (perform anticollision)
* TODO: Verify CRC checksums
*/
uint8_t iso14443b_select_card(iso14b_card_select_t *card ) {
uint8_t iso14443b_select_card(iso14b_card_select_t *card)
{
// WUPB command (including CRC)
// Note: WUPB wakes up all tags, REQB doesn't wake up tags in HALT state
static const uint8_t wupb[] = { ISO14443B_REQB, 0x00, 0x08, 0x39, 0x73 };
@ -1251,8 +1277,8 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card ) {
if (card) {
card->uidlen = 4;
memcpy(card->uid, Demod.output+1, 4);
memcpy(card->atqb, Demod.output+5, 7);
memcpy(card->uid, Demod.output + 1, 4);
memcpy(card->atqb, Demod.output + 5, 7);
}
// copy the PUPI to ATTRIB ( PUPI == UID )
@ -1266,11 +1292,11 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card ) {
GetTagSamplesFor14443bDemod();//select_card
// Answer to ATTRIB too short?
if(Demod.len < 3)
if (Demod.len < 3)
return 2;
// VALIDATE CRC
if (!check_crc(CRC_14443_B, Demod.output, Demod.len) )
if (!check_crc(CRC_14443_B, Demod.output, Demod.len))
return 3;
if (card) {
@ -1290,9 +1316,9 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card ) {
// FWT
uint8_t fwt = card->atqb[6] >> 4;
if ( fwt < 16 ){
if (fwt < 16) {
uint32_t fwt_time = (302 << fwt);
iso14b_set_timeout( fwt_time);
iso14b_set_timeout(fwt_time);
}
}
// reset PCB block number
@ -1302,7 +1328,8 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card ) {
// Set up ISO 14443 Type B communication (similar to iso14443a_setup)
// field is setup for "Sending as Reader"
void iso14443b_setup() {
void iso14443b_setup()
{
LEDsoff();
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
@ -1335,7 +1362,8 @@ void iso14443b_setup() {
//
// I tried to be systematic and check every answer of the tag, every CRC, etc...
//-----------------------------------------------------------------------------
static bool ReadSTBlock(uint8_t block) {
static bool ReadSTBlock(uint8_t block)
{
uint8_t cmd[] = {ISO14443B_READ_BLK, block, 0x00, 0x00};
AddCrc14B(cmd, 2);
CodeAndTransmit14443bAsReader(cmd, sizeof(cmd));
@ -1353,7 +1381,8 @@ static bool ReadSTBlock(uint8_t block) {
}
return true;
}
void ReadSTMemoryIso14443b(uint8_t numofblocks) {
void ReadSTMemoryIso14443b(uint8_t numofblocks)
{
// Make sure that we start from off, since the tags are stateful;
// confusing things will happen if we don't reset them between reads.
//switch_off();
@ -1363,11 +1392,11 @@ void ReadSTMemoryIso14443b(uint8_t numofblocks) {
iso14443b_setup();
iso14b_card_select_t *card = (iso14b_card_select_t*)buf;
iso14b_card_select_t *card = (iso14b_card_select_t *)buf;
uint8_t res = iso14443b_select_srx_card(card);
// 0: OK 2: attrib fail, 3:crc fail,
if ( res > 0 ) goto out;
if (res > 0) goto out;
Dbprintf("[+] Tag memory dump, block 0 to %d", numofblocks);
@ -1390,8 +1419,8 @@ void ReadSTMemoryIso14443b(uint8_t numofblocks) {
// Now print out the memory location:
Dbprintf("Address=%02x, Contents=%08x, CRC=%04x", i,
(Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0],
(Demod.output[4]<<8)+Demod.output[5]);
(Demod.output[3] << 24) + (Demod.output[2] << 16) + (Demod.output[1] << 8) + Demod.output[0],
(Demod.output[4] << 8) + Demod.output[5]);
if (i == 0xff) break;
++i;
@ -1402,7 +1431,8 @@ out:
SpinDelay(20);
}
static void iso1444b_setup_sniff(void){
static void iso1444b_setup_sniff(void)
{
LEDsoff();
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
@ -1455,7 +1485,8 @@ static void iso1444b_setup_sniff(void){
* DMA Buffer - ISO14443B_DMA_BUFFER_SIZE
* Demodulated samples received - all the rest
*/
void RAMFUNC SniffIso14443b(void) {
void RAMFUNC SniffIso14443b(void)
{
uint32_t time_0 = 0, time_start = 0, time_stop = 0;
int ci = 0, cq = 0;
@ -1469,11 +1500,11 @@ void RAMFUNC SniffIso14443b(void) {
iso1444b_setup_sniff();
// The DMA buffer, used to stream samples from the FPGA
int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE);
int8_t *dmaBuf = (int8_t *) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE);
int8_t *data = dmaBuf;
// Setup and start DMA.
if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE) ){
if (!FpgaSetupSscDma((uint8_t *) dmaBuf, ISO14443B_DMA_BUFFER_SIZE)) {
if (MF_DBGLEVEL > 1) Dbprintf("[!] FpgaSetupSscDma failed. Exiting");
BigBuf_free();
return;
@ -1547,7 +1578,8 @@ void RAMFUNC SniffIso14443b(void) {
switch_off();
}
void iso14b_set_trigger(bool enable) {
void iso14b_set_trigger(bool enable)
{
trigger = enable;
}
@ -1562,7 +1594,8 @@ void iso14b_set_trigger(bool enable) {
* none
*
*/
void SendRawCommand14443B_Ex(UsbCommand *c) {
void SendRawCommand14443B_Ex(UsbCommand *c)
{
iso14b_command_t param = c->arg[0];
size_t len = c->arg[1] & 0xffff;
uint8_t *cmd = c->d.asBytes;
@ -1570,7 +1603,7 @@ void SendRawCommand14443B_Ex(UsbCommand *c) {
uint32_t sendlen = sizeof(iso14b_card_select_t);
uint8_t buf[USB_CMD_DATA_SIZE] = {0x00};
if (MF_DBGLEVEL > 3) Dbprintf("14b raw: param, %04x", param );
if (MF_DBGLEVEL > 3) Dbprintf("14b raw: param, %04x", param);
// turn on trigger (LED_A)
if ((param & ISO14B_REQUEST_TRIGGER) == ISO14B_REQUEST_TRIGGER)
@ -1584,19 +1617,19 @@ void SendRawCommand14443B_Ex(UsbCommand *c) {
set_tracing(true);
if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) {
iso14b_card_select_t *card = (iso14b_card_select_t*)buf;
iso14b_card_select_t *card = (iso14b_card_select_t *)buf;
status = iso14443b_select_card(card);
cmd_send(CMD_ACK, status, sendlen, 0, buf, sendlen);
// 0: OK 2: attrib fail, 3:crc fail,
if ( status > 0 ) goto out;
if (status > 0) goto out;
}
if ((param & ISO14B_SELECT_SR) == ISO14B_SELECT_SR) {
iso14b_card_select_t *card = (iso14b_card_select_t*)buf;
iso14b_card_select_t *card = (iso14b_card_select_t *)buf;
status = iso14443b_select_srx_card(card);
cmd_send(CMD_ACK, status, sendlen, 0, buf, sendlen);
// 0: OK 2: demod fail, 3:crc fail,
if ( status > 0 ) goto out;
if (status > 0) goto out;
}
if ((param & ISO14B_APDU) == ISO14B_APDU) {
@ -1605,7 +1638,7 @@ void SendRawCommand14443B_Ex(UsbCommand *c) {
}
if ((param & ISO14B_RAW) == ISO14B_RAW) {
if((param & ISO14B_APPEND_CRC) == ISO14B_APPEND_CRC) {
if ((param & ISO14B_APPEND_CRC) == ISO14B_APPEND_CRC) {
AddCrc14B(cmd, len);
len += 2;
}

View file

@ -37,11 +37,11 @@ extern "C" {
extern void SendRawCommand14443B_Ex(UsbCommand *c);
extern void iso14443b_setup();
extern uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response);
extern uint8_t iso14443b_select_card(iso14b_card_select_t* card);
extern uint8_t iso14443b_select_card_srx(iso14b_card_select_t* card);
extern uint8_t iso14443b_select_card(iso14b_card_select_t *card);
extern uint8_t iso14443b_select_card_srx(iso14b_card_select_t *card);
// testfunctions
extern void WaitForFpgaDelayQueueIsEmpty( uint16_t delay );
extern void WaitForFpgaDelayQueueIsEmpty(uint16_t delay);
extern void ClearFpgaShiftingRegisters(void);
// States for 14B SIM command

View file

@ -99,13 +99,14 @@ static void BuildInventoryResponse(uint8_t *cmdout, uint8_t *uid);
// resulting data rate is 26,48 kbit/s (fc/512)
// cmd ... data
// n ... length of data
static void CodeIso15693AsReader(uint8_t *cmd, int n) {
static void CodeIso15693AsReader(uint8_t *cmd, int n)
{
int i, j;
ToSendReset();
// Give it a bit of slack at the beginning
for(i = 0; i < 24; i++)
for (i = 0; i < 24; i++)
ToSendStuffBit(1);
// SOF for 1of4
@ -117,10 +118,10 @@ static void CodeIso15693AsReader(uint8_t *cmd, int n) {
ToSendStuffBit(0);
ToSendStuffBit(1);
ToSendStuffBit(1);
for(i = 0; i < n; i++) {
for(j = 0; j < 8; j += 2) {
for (i = 0; i < n; i++) {
for (j = 0; j < 8; j += 2) {
int these = (cmd[i] >> j) & 3;
switch(these) {
switch (these) {
case 0:
ToSendStuffBit(1);
ToSendStuffBit(0);
@ -171,20 +172,21 @@ static void CodeIso15693AsReader(uint8_t *cmd, int n) {
ToSendStuffBit(1);
// And slack at the end, too.
for(i = 0; i < 24; i++)
for (i = 0; i < 24; i++)
ToSendStuffBit(1);
}
// encode data using "1 out of 256" sheme
// data rate is 1,66 kbit/s (fc/8192)
// is designed for more robust communication over longer distances
static void CodeIso15693AsReader256(uint8_t *cmd, int n) {
static void CodeIso15693AsReader256(uint8_t *cmd, int n)
{
int i, j;
ToSendReset();
// Give it a bit of slack at the beginning
for(i = 0; i < 24; i++)
for (i = 0; i < 24; i++)
ToSendStuffBit(1);
// SOF for 1of256
@ -197,7 +199,7 @@ static void CodeIso15693AsReader256(uint8_t *cmd, int n) {
ToSendStuffBit(1);
ToSendStuffBit(0);
for(i = 0; i < n; i++) {
for (i = 0; i < n; i++) {
for (j = 0; j <= 255; j++) {
if (cmd[i] == j) {
ToSendStuffBit(1);
@ -215,12 +217,13 @@ static void CodeIso15693AsReader256(uint8_t *cmd, int n) {
ToSendStuffBit(1);
// And slack at the end, too.
for(i = 0; i < 24; i++)
for (i = 0; i < 24; i++)
ToSendStuffBit(1);
}
// Transmit the command (to the tag) that was placed in ToSend[].
static void TransmitTo15693Tag(const uint8_t *cmd, int len, int *samples, int *wait) {
static void TransmitTo15693Tag(const uint8_t *cmd, int len, int *samples, int *wait)
{
int c;
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
@ -236,10 +239,10 @@ static void TransmitTo15693Tag(const uint8_t *cmd, int len, int *samples, int *w
}
c = 0;
for(;;) {
for (;;) {
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = cmd[c];
if( ++c >= len) break;
if (++c >= len) break;
}
WDT_HIT();
}
@ -255,7 +258,8 @@ static void TransmitTo15693Tag(const uint8_t *cmd, int len, int *samples, int *w
//-----------------------------------------------------------------------------
// Transmit the command (to the reader) that was placed in ToSend[].
//-----------------------------------------------------------------------------
static void TransmitTo15693Reader(const uint8_t *cmd, int len, int *samples, int *wait) {
static void TransmitTo15693Reader(const uint8_t *cmd, int len, int *samples, int *wait)
{
int c = 0;
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_424K);
@ -270,10 +274,10 @@ static void TransmitTo15693Reader(const uint8_t *cmd, int len, int *samples, int
}
c = 0;
for(;;) {
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
for (;;) {
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = cmd[c];
if( ++c >= len) break;
if (++c >= len) break;
}
WDT_HIT();
}
@ -288,7 +292,8 @@ static void TransmitTo15693Reader(const uint8_t *cmd, int len, int *samples, int
//-----------------------------------------------------------------------------
// DEMODULATE tag answer
//-----------------------------------------------------------------------------
static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) {
static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount)
{
int i, j;
int max = 0, maxPos = 0, skip = 4;
@ -297,8 +302,8 @@ static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) {
// First, correlate for SOF
for (i = 0; i < samplecount; i++) {
int corr = 0;
for ( j = 0; j < ARRAYLEN(FrameSOF); j += skip) {
corr += FrameSOF[j] * dest[i+(j/skip)];
for (j = 0; j < ARRAYLEN(FrameSOF); j += skip) {
corr += FrameSOF[j] * dest[i + (j / skip)];
}
if (corr > max) {
max = corr;
@ -308,7 +313,7 @@ static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) {
// DbpString("SOF at %d, correlation %d", maxPos,max/(ARRAYLEN(FrameSOF)/skip));
// greg - If correlation is less than 1 then there's little point in continuing
if ((max / (ARRAYLEN(FrameSOF)/skip) ) < 1)
if ((max / (ARRAYLEN(FrameSOF) / skip)) < 1)
return k;
i = maxPos + ARRAYLEN(FrameSOF) / skip;
@ -316,16 +321,16 @@ static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) {
uint8_t outBuf[ISO15_MAX_FRAME];
memset(outBuf, 0, sizeof(outBuf));
uint8_t mask = 0x01;
for(;;) {
for (;;) {
int corr0 = 0, corr1 = 0, corrEOF = 0;
for (j = 0; j < ARRAYLEN(Logic0); j += skip) {
corr0 += Logic0[j] * dest[i+(j/skip)];
corr0 += Logic0[j] * dest[i + (j / skip)];
}
for (j = 0; j < ARRAYLEN(Logic1); j += skip) {
corr1 += Logic1[j] * dest[i+(j/skip)];
corr1 += Logic1[j] * dest[i + (j / skip)];
}
for (j = 0; j < ARRAYLEN(FrameEOF); j += skip) {
corrEOF += FrameEOF[j] * dest[i+(j/skip)];
corrEOF += FrameEOF[j] * dest[i + (j / skip)];
}
// Even things out by the length of the target waveform.
corr0 *= 4;
@ -350,7 +355,7 @@ static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) {
mask = 0x01;
}
if ( ( i + (int)ARRAYLEN(FrameEOF)) >= samplecount-1) {
if ((i + (int)ARRAYLEN(FrameEOF)) >= samplecount - 1) {
//Dbprintf("[!] ran off end! %d | %d",( i + (int)ARRAYLEN(FrameEOF)), samplecount-1);
break;
}
@ -366,7 +371,7 @@ static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) {
// 0x08 is an assumption - but works quite often
}
for(i = 0; i < k; i++)
for (i = 0; i < k; i++)
received[i] = outBuf[i];
// return the number of bytes demodulated
@ -381,7 +386,8 @@ static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) {
// returns:
// number of decoded bytes
// logging enabled
static int GetIso15693AnswerFromTag(uint8_t *received, int *elapsed) {
static int GetIso15693AnswerFromTag(uint8_t *received, int *elapsed)
{
#define SIGNAL_BUFF_SIZE 15000
// get current clock
@ -395,13 +401,13 @@ static int GetIso15693AnswerFromTag(uint8_t *received, int *elapsed) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
for(;;) {
for (;;) {
WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = 0x00; //0x43;
// To make use of exact timing of next command from reader!!
if (elapsed) (*elapsed)++;
if (elapsed)(*elapsed)++;
}
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
@ -415,7 +421,7 @@ static int GetIso15693AnswerFromTag(uint8_t *received, int *elapsed) {
// iceman 2016, amplitude sqrt(abs(i) + abs(q))
if (getNext) {
buf[counter++] = (uint8_t)(MAX(ci,cq) + (MIN(ci, cq) >> 1));
buf[counter++] = (uint8_t)(MAX(ci, cq) + (MIN(ci, cq) >> 1));
if (counter >= SIGNAL_BUFF_SIZE)
break;
@ -435,7 +441,8 @@ static int GetIso15693AnswerFromTag(uint8_t *received, int *elapsed) {
// Now the GetISO15693 message from sniffing command
// logging enable,
static int GetIso15693AnswerFromSniff(uint8_t *received, int *samples, int *elapsed) {
static int GetIso15693AnswerFromSniff(uint8_t *received, int *samples, int *elapsed)
{
bool getNext = false;
int counter = 0, ci = 0, cq = 0;
@ -447,7 +454,7 @@ static int GetIso15693AnswerFromSniff(uint8_t *received, int *samples, int *elap
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
for(;;) {
for (;;) {
WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
@ -461,9 +468,9 @@ static int GetIso15693AnswerFromSniff(uint8_t *received, int *samples, int *elap
// close to what we want.
if (getNext) {
buf[counter++] = (uint8_t)(MAX(ci,cq) + (MIN(ci, cq) >> 1));
buf[counter++] = (uint8_t)(MAX(ci, cq) + (MIN(ci, cq) >> 1));
if(counter >= 20000)
if (counter >= 20000)
break;
} else {
cq = ci;
@ -483,7 +490,8 @@ static int GetIso15693AnswerFromSniff(uint8_t *received, int *samples, int *elap
// for the response. The response is not demodulated, just left in the buffer
// so that it can be downloaded to a PC and processed there.
//-----------------------------------------------------------------------------
void AcquireRawAdcSamplesIso15693(void) {
void AcquireRawAdcSamplesIso15693(void)
{
int c = 0, getNext = false;
int ci = 0, cq = 0;
@ -503,13 +511,13 @@ void AcquireRawAdcSamplesIso15693(void) {
// sending command
c = 0;
for(;;) {
for (;;) {
WDT_HIT();
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = ToSend[c];
c++;
if(c == ToSendMax + 3) {
if (c == ToSendMax + 3) {
break;
}
}
@ -521,7 +529,7 @@ void AcquireRawAdcSamplesIso15693(void) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
c = 0;
for(;;) {
for (;;) {
WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
@ -536,7 +544,7 @@ void AcquireRawAdcSamplesIso15693(void) {
// iceman 2016, amplitude sqrt(abs(i) + abs(q))
if (getNext) {
buf[c++] = (uint8_t)(MAX(ci,cq) + (MIN(ci, cq) >> 1));
buf[c++] = (uint8_t)(MAX(ci, cq) + (MIN(ci, cq) >> 1));
if (c >= 7000) break;
@ -549,7 +557,8 @@ void AcquireRawAdcSamplesIso15693(void) {
}
// switch_off, initreader, no logging
void RecordRawAdcSamplesIso15693(void) {
void RecordRawAdcSamplesIso15693(void)
{
int c = 0, getNext = false;
int ci = 0, cq = 0;
@ -558,7 +567,7 @@ void RecordRawAdcSamplesIso15693(void) {
uint8_t *buf = BigBuf_get_addr();
for(;;) {
for (;;) {
WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
@ -571,9 +580,9 @@ void RecordRawAdcSamplesIso15693(void) {
// close to what we want.
if (getNext) {
buf[c++] = (uint8_t)(MAX(ci,cq) + (MIN(ci, cq) >> 1));
buf[c++] = (uint8_t)(MAX(ci, cq) + (MIN(ci, cq) >> 1));
if(c >= 7000)
if (c >= 7000)
break;
} else {
cq = ci;
@ -589,7 +598,8 @@ void RecordRawAdcSamplesIso15693(void) {
// Initialize the proxmark as iso15k reader
// (this might produces glitches that confuse some tags
void Iso15693InitReader(void) {
void Iso15693InitReader(void)
{
LEDsoff();
clear_trace();
set_tracing(true);
@ -621,7 +631,8 @@ void Iso15693InitReader(void) {
// Encode (into the ToSend buffers) an identify request, which is the first
// thing that you must send to a tag to get a response.
static void BuildIdentifyRequest(uint8_t *out) {
static void BuildIdentifyRequest(uint8_t *out)
{
uint8_t cmd[CMD_ID_RESP] = {0, ISO15_CMD_INVENTORY, 0, 0, 0};
// flags
@ -665,9 +676,10 @@ static void BuildReadBlockRequest(uint8_t **out, uint8_t *uid, uint8_t blockNumb
*/
// Now the VICC>VCD responses when we are simulating a tag
static void BuildInventoryResponse(uint8_t *out, uint8_t *uid) {
static void BuildInventoryResponse(uint8_t *out, uint8_t *uid)
{
uint8_t cmd[CMD_INV_RESP] = {0,0,0,0,0,0,0,0,0,0,0,0};
uint8_t cmd[CMD_INV_RESP] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
// one sub-carrier, inventory, 1 slot, fast rate
// AFI is at bit 5 (1<<4) when doing an INVENTORY
@ -696,7 +708,8 @@ static void BuildInventoryResponse(uint8_t *out, uint8_t *uid) {
// If you do not need the answer use NULL for *recv[]
// return: lenght of received data
// logging enabled
int SendDataTag(uint8_t *send, int sendlen, bool init, int speed, uint8_t *outdata) {
int SendDataTag(uint8_t *send, int sendlen, bool init, int speed, uint8_t *outdata)
{
int t_samples = 0, wait = 0, elapsed = 0, answer_len = 0;
@ -734,11 +747,12 @@ int SendDataTag(uint8_t *send, int sendlen, bool init, int speed, uint8_t *outda
// Decodes a message from a tag and displays its metadata and content
#define DBD15STATLEN 48
void DbdecodeIso15693Answer(int len, uint8_t *d) {
char status[DBD15STATLEN+1] = {0};
void DbdecodeIso15693Answer(int len, uint8_t *d)
{
char status[DBD15STATLEN + 1] = {0};
if (len > 3) {
if (d[0] & ( 1 << 3 ))
if (d[0] & (1 << 3))
strncat(status, "ProtExt ", DBD15STATLEN);
if (d[0] & 1) {
// error
@ -774,9 +788,9 @@ void DbdecodeIso15693Answer(int len, uint8_t *d) {
default:
strncat(status, "unknown error", DBD15STATLEN);
}
strncat(status ," " ,DBD15STATLEN);
strncat(status, " ", DBD15STATLEN);
} else {
strncat(status ,"No error ", DBD15STATLEN);
strncat(status, "No error ", DBD15STATLEN);
}
if (CheckCrc(d, len))
@ -784,7 +798,7 @@ void DbdecodeIso15693Answer(int len, uint8_t *d) {
else
strncat(status, "[!] crc fail", DBD15STATLEN);
if ( MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("%s", status);
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("%s", status);
}
}
@ -798,11 +812,12 @@ void DbdecodeIso15693Answer(int len, uint8_t *d) {
//-----------------------------------------------------------------------------
// ok
// parameter is unused !?!
void ReaderIso15693(uint32_t parameter) {
void ReaderIso15693(uint32_t parameter)
{
int answerLen1 = 0;
int tsamples = 0, wait = 0, elapsed = 0;
uint8_t uid[8] = {0,0,0,0,0,0,0,0};
uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0};
// set up device/fpga
Iso15693InitReader();
@ -819,7 +834,7 @@ void ReaderIso15693(uint32_t parameter) {
// THIS MEANS WE CAN PRE-BUILD REQUESTS TO SAVE CPU TIME
uint32_t time_start = GetCountSspClk();
uint8_t cmd[CMD_ID_RESP] = {0};
BuildIdentifyRequest( cmd );
BuildIdentifyRequest(cmd);
TransmitTo15693Tag(ToSend, ToSendMax, &tsamples, &wait);
LogTrace(cmd, CMD_ID_RESP, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true);
@ -837,7 +852,7 @@ void ReaderIso15693(uint32_t parameter) {
uid[6] = answer1[3];
uid[7] = answer1[2];
if ( MF_DBGLEVEL >= MF_DBG_EXTENDED) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
Dbprintf("[+] UID = %02X%02X%02X%02X%02X%02X%02X%02X",
uid[0], uid[1], uid[2], uid[3],
uid[4], uid[5], uid[5], uid[6]
@ -851,7 +866,7 @@ void ReaderIso15693(uint32_t parameter) {
cmd_send(CMD_ACK, 1, sizeof(uid), 0, uid, sizeof(uid));
}
if ( MF_DBGLEVEL >= MF_DBG_EXTENDED) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
Dbprintf("[+] %d octets read from IDENTIFY request:", answerLen1);
DbdecodeIso15693Answer(answerLen1, answer1);
Dbhexdump(answerLen1, answer1, true);
@ -862,7 +877,8 @@ void ReaderIso15693(uint32_t parameter) {
// Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands
// all demodulation performed in arm rather than host. - greg
void SimTagIso15693(uint32_t parameter, uint8_t *uid) {
void SimTagIso15693(uint32_t parameter, uint8_t *uid)
{
LEDsoff();
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
@ -890,14 +906,14 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid) {
uint8_t cmd[CMD_INV_RESP] = {0};
BuildInventoryResponse(cmd, uid);
while (!BUTTON_PRESS() && !usb_poll_validate_length() ) {
while (!BUTTON_PRESS() && !usb_poll_validate_length()) {
WDT_HIT();
// Listen to reader
ans = GetIso15693AnswerFromSniff(buf, &samples, &elapsed) ;
// we should do a better check than this
if (ans >= 1 ) {
if (ans >= 1) {
time_start = GetCountSspClk();
TransmitTo15693Reader(ToSend, ToSendMax, &tsamples, &wait);
@ -916,9 +932,10 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid) {
// Since there is no standardized way of reading the AFI out of a tag, we will brute force it
// (some manufactures offer a way to read the AFI, though)
void BruteforceIso15693Afi(uint32_t speed) {
void BruteforceIso15693Afi(uint32_t speed)
{
uint8_t data[7] = {0,0,0,0,0,0,0};
uint8_t data[7] = {0, 0, 0, 0, 0, 0, 0};
uint8_t buf[ISO15_MAX_FRAME];
memset(buf, 0x00, sizeof(buf));
int datalen = 0, recvlen = 0;
@ -939,7 +956,7 @@ void BruteforceIso15693Afi(uint32_t speed) {
WDT_HIT();
if (recvlen >= 12) {
Dbprintf("NoAFI UID = %s", sprintUID(NULL, buf + 2) );
Dbprintf("NoAFI UID = %s", sprintUID(NULL, buf + 2));
}
// now with AFI
@ -955,7 +972,7 @@ void BruteforceIso15693Afi(uint32_t speed) {
recvlen = SendDataTag(data, datalen, false, speed, buf);
WDT_HIT();
if (recvlen >= 12) {
Dbprintf("AFI = %i UID = %s", i, sprintUID(NULL, buf + 2) );
Dbprintf("AFI = %i UID = %s", i, sprintUID(NULL, buf + 2));
}
if (BUTTON_PRESS()) {
@ -970,7 +987,8 @@ void BruteforceIso15693Afi(uint32_t speed) {
// Allows to directly send commands to the tag via the client
// Has to increase dialog between device and client.
void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t *data) {
void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t *data)
{
bool init = true;
int buflen = 0;
@ -997,6 +1015,6 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint
Dbhexdump(buflen, buf, true);
}
} else {
cmd_send(CMD_ACK,1,0,0,0,0);
cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
}
}

View file

@ -16,7 +16,7 @@
#include "legic_prng.h" /* legic PRNG impl */
#include "legic.h" /* legic_card_select_t struct */
static uint8_t* legic_mem; /* card memory, used for read, write */
static uint8_t *legic_mem; /* card memory, used for read, write */
static legic_card_select_t card;/* metadata of currently selected card */
static crc_t legic_crc;
@ -50,14 +50,15 @@ static uint32_t last_frame_end; /* ts of last bit of previews rx or tx frame */
#define WRITE_LOWERLIMIT 4 /* UID and MCC are not writable */
#define INPUT_THRESHOLD 8 /* heuristically determined, lower values */
/* lead to detecting false ack during write */
/* lead to detecting false ack during write */
//-----------------------------------------------------------------------------
// I/O interface abstraction (FPGA -> ARM)
//-----------------------------------------------------------------------------
static inline uint8_t rx_byte_from_fpga() {
for(;;) {
static inline uint8_t rx_byte_from_fpga()
{
for (;;) {
WDT_HIT();
// wait for byte be become available in rx holding register
@ -83,9 +84,12 @@ static inline uint8_t rx_byte_from_fpga() {
//
// Note: The SSC receiver is never synchronized the calculation may be performed
// on a i/q pair from two subsequent correlations, but does not matter.
static inline int32_t sample_power() {
int32_t q = (int8_t)rx_byte_from_fpga(); q = ABS(q);
int32_t i = (int8_t)rx_byte_from_fpga(); i = ABS(i);
static inline int32_t sample_power()
{
int32_t q = (int8_t)rx_byte_from_fpga();
q = ABS(q);
int32_t i = (int8_t)rx_byte_from_fpga();
i = ABS(i);
return MAX(i, q) + (MIN(i, q) >> 1);
}
@ -97,10 +101,11 @@ static inline int32_t sample_power() {
//
// Note: The demodulator would be drifting (18.9us * 5 != 100us), rx_frame
// has a delay loop that aligns rx_bit calls to the TAG tx timeslots.
static inline bool rx_bit() {
static inline bool rx_bit()
{
int32_t power;
for (size_t i = 0; i<5; ++i) {
for (size_t i = 0; i < 5; ++i) {
power = sample_power();
}
@ -116,7 +121,8 @@ static inline bool rx_bit() {
// be circumvented, but the adventage over bitbang would be little.
//-----------------------------------------------------------------------------
static inline void tx_bit(bool bit) {
static inline void tx_bit(bool bit)
{
// insert pause
LOW(GPIO_SSC_DOUT);
last_frame_end += RWD_TIME_PAUSE;
@ -138,7 +144,8 @@ static inline void tx_bit(bool bit) {
// present.
//-----------------------------------------------------------------------------
static void tx_frame(uint32_t frame, uint8_t len) {
static void tx_frame(uint32_t frame, uint8_t len)
{
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
// wait for next tx timeslot
@ -166,7 +173,8 @@ static void tx_frame(uint32_t frame, uint8_t len) {
LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, true);
}
static uint32_t rx_frame(uint8_t len) {
static uint32_t rx_frame(uint8_t len)
{
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
| FPGA_HF_READER_RX_XCORR_848_KHZ
| FPGA_HF_READER_RX_XCORR_QUARTER);
@ -195,7 +203,8 @@ static uint32_t rx_frame(uint8_t len) {
return frame;
}
static bool rx_ack() {
static bool rx_ack()
{
// change fpga into rx mode
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
| FPGA_HF_READER_RX_XCORR_848_KHZ
@ -235,10 +244,11 @@ static bool rx_ack() {
// Legic Reader
//-----------------------------------------------------------------------------
static int init_card(uint8_t cardtype, legic_card_select_t *p_card) {
static int init_card(uint8_t cardtype, legic_card_select_t *p_card)
{
p_card->tagtype = cardtype;
switch(p_card->tagtype) {
switch (p_card->tagtype) {
case 0x0d:
p_card->cmdsize = 6;
p_card->addrsize = 5;
@ -263,7 +273,8 @@ static int init_card(uint8_t cardtype, legic_card_select_t *p_card) {
return 0;
}
static void init_reader(bool clear_mem) {
static void init_reader(bool clear_mem)
{
// configure FPGA
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
@ -303,7 +314,8 @@ static void init_reader(bool clear_mem) {
// - Transmit initialisation vector 7 bits
// - Receive card type 6 bits
// - Transmit Acknowledge 6 bits
static uint32_t setup_phase(uint8_t iv) {
static uint32_t setup_phase(uint8_t iv)
{
// init coordination timestamp
last_frame_end = GET_TICKS;
@ -336,13 +348,15 @@ static uint32_t setup_phase(uint8_t iv) {
return card_type;
}
static uint8_t calc_crc4(uint16_t cmd, uint8_t cmd_sz, uint8_t value) {
static uint8_t calc_crc4(uint16_t cmd, uint8_t cmd_sz, uint8_t value)
{
crc_clear(&legic_crc);
crc_update(&legic_crc, (value << cmd_sz) | cmd, 8 + cmd_sz);
return crc_finish(&legic_crc);
}
static int16_t read_byte(uint16_t index, uint8_t cmd_sz) {
static int16_t read_byte(uint16_t index, uint8_t cmd_sz)
{
uint16_t cmd = (index << 1) | LEGIC_READ;
// read one byte
@ -371,7 +385,8 @@ static int16_t read_byte(uint16_t index, uint8_t cmd_sz) {
// Transmit write command, wait until (3.6ms) the tag sends back an unencrypted
// ACK ('1' bit) and forward the prng time based.
bool write_byte(uint16_t index, uint8_t byte, uint8_t addr_sz) {
bool write_byte(uint16_t index, uint8_t byte, uint8_t addr_sz)
{
uint32_t cmd = index << 1 | LEGIC_WRITE; // prepare command
uint8_t crc = calc_crc4(cmd, addr_sz + 1, byte); // calculate crc
cmd |= byte << (addr_sz + 1); // append value
@ -393,7 +408,8 @@ bool write_byte(uint16_t index, uint8_t byte, uint8_t addr_sz) {
//
// Only this functions are public / called from appmain.c
//-----------------------------------------------------------------------------
void LegicRfInfo(void) {
void LegicRfInfo(void)
{
// configure ARM and FPGA
init_reader(false);
@ -423,14 +439,15 @@ void LegicRfInfo(void) {
}
// OK
cmd_send(CMD_ACK, 1, 0, 0, (uint8_t*)&card, sizeof(legic_card_select_t));
cmd_send(CMD_ACK, 1, 0, 0, (uint8_t *)&card, sizeof(legic_card_select_t));
OUT:
switch_off();
StopTicks();
}
void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) {
void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv)
{
// configure ARM and FPGA
init_reader(false);
@ -463,7 +480,8 @@ OUT:
StopTicks();
}
void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) {
void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data)
{
// configure ARM and FPGA
init_reader(false);

View file

@ -16,7 +16,7 @@
#include "legic_prng.h" /* legic PRNG impl */
#include "legic.h" /* legic_card_select_t struct */
static uint8_t* legic_mem; /* card memory, used for sim */
static uint8_t *legic_mem; /* card memory, used for sim */
static legic_card_select_t card;/* metadata of currently selected card */
static crc_t legic_crc;
@ -58,7 +58,8 @@ static uint32_t last_frame_end; /* ts of last bit of previews rx or tx frame */
//-----------------------------------------------------------------------------
// Returns true if a pulse/pause is received within timeout
static inline bool wait_for(bool value, const uint32_t timeout) {
static inline bool wait_for(bool value, const uint32_t timeout)
{
while ((bool)(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_DIN) != value) {
if (GetCountSspClk() > timeout) {
return false;
@ -76,17 +77,18 @@ static inline bool wait_for(bool value, const uint32_t timeout) {
// - A bit length >80.2us is a 1
// - A bit length <80.2us is a 0
// - A bit length >148.6us is a code violation
static inline int8_t rx_bit() {
static inline int8_t rx_bit()
{
// backup ts for threshold calculation
uint32_t bit_start = last_frame_end;
// wait for pause to end
if (!wait_for(RWD_PULSE, bit_start + RWD_TIME_1*3/2)) {
if (!wait_for(RWD_PULSE, bit_start + RWD_TIME_1 * 3 / 2)) {
return -1;
}
// wait for next pause
if (!wait_for(RWD_PAUSE, bit_start + RWD_TIME_1*3/2)) {
if (!wait_for(RWD_PAUSE, bit_start + RWD_TIME_1 * 3 / 2)) {
return -1;
}
@ -119,7 +121,8 @@ static inline int8_t rx_bit() {
// Note: The Subcarrier is not disabled during bits to prevent glitches. This is
// not mandatory but results in a cleaner signal. tx_frame will disable
// the subcarrier when the frame is done.
static inline void tx_bit(bool bit) {
static inline void tx_bit(bool bit)
{
LED_C_ON();
if (bit) {
@ -146,10 +149,11 @@ static inline void tx_bit(bool bit) {
// and depends only the command received (IV, ACK, READ or WRITE).
//-----------------------------------------------------------------------------
static void tx_frame(uint32_t frame, uint8_t len) {
static void tx_frame(uint32_t frame, uint8_t len)
{
// wait for next tx timeslot
last_frame_end += TAG_FRAME_WAIT;
legic_prng_forward(TAG_FRAME_WAIT/TAG_BIT_PERIOD - 1);
legic_prng_forward(TAG_FRAME_WAIT / TAG_BIT_PERIOD - 1);
while (GetCountSspClk() < last_frame_end) { };
// backup ts for trace log
@ -170,10 +174,11 @@ static void tx_frame(uint32_t frame, uint8_t len) {
LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, false);
}
static void tx_ack() {
static void tx_ack()
{
// wait for ack timeslot
last_frame_end += TAG_ACK_WAIT;
legic_prng_forward(TAG_ACK_WAIT/TAG_BIT_PERIOD - 1);
legic_prng_forward(TAG_ACK_WAIT / TAG_BIT_PERIOD - 1);
while (GetCountSspClk() < last_frame_end) { };
// backup ts for trace log
@ -198,7 +203,8 @@ static void tx_ack() {
// - forward prng based on ts/TAG_BIT_PERIOD
// - receive the frame
// - detect end of frame (last pause)
static int32_t rx_frame(uint8_t *len) {
static int32_t rx_frame(uint8_t *len)
{
int32_t frame = 0;
// add 2 SSP clock cycles (1 for tx and 1 for rx pipeline delay)
@ -263,7 +269,8 @@ static int32_t rx_frame(uint8_t *len) {
// Legic Simulator
//-----------------------------------------------------------------------------
static int32_t init_card(uint8_t cardtype, legic_card_select_t *p_card) {
static int32_t init_card(uint8_t cardtype, legic_card_select_t *p_card)
{
p_card->tagtype = cardtype;
switch (p_card->tagtype) {
@ -291,7 +298,8 @@ static int32_t init_card(uint8_t cardtype, legic_card_select_t *p_card) {
return 0;
}
static void init_tag() {
static void init_tag()
{
// configure FPGA
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR
@ -326,7 +334,8 @@ static void init_tag() {
// - Receive initialisation vector 7 bits
// - Transmit card type 6 bits
// - Receive Acknowledge 6 bits
static int32_t setup_phase(legic_card_select_t *p_card) {
static int32_t setup_phase(legic_card_select_t *p_card)
{
uint8_t len = 0;
// init coordination timestamp
@ -366,13 +375,13 @@ static int32_t setup_phase(legic_card_select_t *p_card) {
// validate data
switch (p_card->tagtype) {
case 0:
if(ack != 0x19) return -1;
if (ack != 0x19) return -1;
break;
case 1:
if(ack != 0x39) return -1;
if (ack != 0x39) return -1;
break;
case 2:
if(ack != 0x39) return -1;
if (ack != 0x39) return -1;
break;
}
@ -387,13 +396,15 @@ static int32_t setup_phase(legic_card_select_t *p_card) {
return 0;
}
static uint8_t calc_crc4(uint16_t cmd, uint8_t cmd_sz, uint8_t value) {
static uint8_t calc_crc4(uint16_t cmd, uint8_t cmd_sz, uint8_t value)
{
crc_clear(&legic_crc);
crc_update(&legic_crc, (value << cmd_sz) | cmd, 8 + cmd_sz);
return crc_finish(&legic_crc);
}
static int32_t connected_phase(legic_card_select_t *p_card) {
static int32_t connected_phase(legic_card_select_t *p_card)
{
uint8_t len = 0;
// wait for command
@ -447,7 +458,8 @@ static int32_t connected_phase(legic_card_select_t *p_card) {
// Only this function is public / called from appmain.c
//-----------------------------------------------------------------------------
void LegicRfSimulate(uint8_t cardtype) {
void LegicRfSimulate(uint8_t cardtype)
{
// configure ARM and FPGA
init_tag();

File diff suppressed because it is too large Load diff

View file

@ -18,9 +18,10 @@ Default LF config is set to:
*/
sample_config config = { 1, 8, 1, 95, 0 } ;
void printConfig() {
void printConfig()
{
Dbprintf("LF Sampling config");
Dbprintf(" [q] divisor.............%d (%d KHz)", config.divisor, 12000 / (config.divisor+1));
Dbprintf(" [q] divisor.............%d (%d KHz)", config.divisor, 12000 / (config.divisor + 1));
Dbprintf(" [b] bps.................%d", config.bits_per_sample);
Dbprintf(" [d] decimation..........%d", config.decimation);
Dbprintf(" [a] averaging...........%s", (config.averaging) ? "Yes" : "No");
@ -38,24 +39,26 @@ void printConfig() {
* @brief setSamplingConfig
* @param sc
*/
void setSamplingConfig(sample_config *sc) {
if(sc->divisor != 0) config.divisor = sc->divisor;
if(sc->bits_per_sample != 0) config.bits_per_sample = sc->bits_per_sample;
if(sc->trigger_threshold != -1) config.trigger_threshold = sc->trigger_threshold;
void setSamplingConfig(sample_config *sc)
{
if (sc->divisor != 0) config.divisor = sc->divisor;
if (sc->bits_per_sample != 0) config.bits_per_sample = sc->bits_per_sample;
if (sc->trigger_threshold != -1) config.trigger_threshold = sc->trigger_threshold;
config.decimation = (sc->decimation != 0) ? sc->decimation : 1;
config.averaging = sc->averaging;
if(config.bits_per_sample > 8) config.bits_per_sample = 8;
if (config.bits_per_sample > 8) config.bits_per_sample = 8;
printConfig();
}
sample_config* getSamplingConfig() {
sample_config *getSamplingConfig()
{
return &config;
}
struct BitstreamOut {
uint8_t * buffer;
uint8_t *buffer;
uint32_t numbits;
uint32_t position;
};
@ -65,10 +68,11 @@ struct BitstreamOut {
* @param stream
* @param bit
*/
void pushBit( BitstreamOut* stream, uint8_t bit) {
void pushBit(BitstreamOut *stream, uint8_t bit)
{
int bytepos = stream->position >> 3; // divide by 8
int bitpos = stream->position & 7;
*(stream->buffer+bytepos) |= (bit > 0) << (7 - bitpos);
*(stream->buffer + bytepos) |= (bit > 0) << (7 - bitpos);
stream->position++;
stream->numbits++;
}
@ -80,9 +84,10 @@ void pushBit( BitstreamOut* stream, uint8_t bit) {
* 0 or 95 ==> 125 KHz
*
**/
void LFSetupFPGAForADC(int divisor, bool lf_field) {
void LFSetupFPGAForADC(int divisor, bool lf_field)
{
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
if ( (divisor == 1) || (divisor < 0) || (divisor > 255) )
if ((divisor == 1) || (divisor < 0) || (divisor > 255))
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
else if (divisor == 0)
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
@ -116,7 +121,8 @@ void LFSetupFPGAForADC(int divisor, bool lf_field) {
* @param silent - is true, now outputs are made. If false, dbprints the status
* @return the number of bits occupied by the samples.
*/
uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold, bool silent, int bufsize, uint32_t cancel_after) {
uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold, bool silent, int bufsize, uint32_t cancel_after)
{
uint8_t *dest = BigBuf_get_addr();
bufsize = (bufsize > 0 && bufsize < BigBuf_max_traceLen()) ? bufsize : BigBuf_max_traceLen();
@ -127,17 +133,17 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag
if (decimation < 1) decimation = 1;
// use a bit stream to handle the output
BitstreamOut data = { dest , 0, 0};
BitstreamOut data = { dest, 0, 0};
int sample_counter = 0;
uint8_t sample = 0;
// if we want to do averaging
uint32_t sample_sum =0 ;
uint32_t sample_sum = 0 ;
uint32_t sample_total_numbers = 0;
uint32_t sample_total_saved = 0;
uint32_t cancel_counter = 0;
while (!BUTTON_PRESS() && !usb_poll_validate_length() ) {
while (!BUTTON_PRESS() && !usb_poll_validate_length()) {
WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
@ -172,13 +178,13 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag
// averaging
if (averaging && decimation > 1) {
sample = sample_sum / decimation;
sample_sum =0;
sample_sum = 0;
}
// store the sample
sample_total_saved ++;
if (bits_per_sample == 8) {
dest[sample_total_saved-1] = sample;
dest[sample_total_saved - 1] = sample;
// Get the return value correct
data.numbits = sample_total_saved << 3;
@ -218,24 +224,28 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag
* @param silent
* @return number of bits sampled
*/
uint32_t DoAcquisition_default(int trigger_threshold, bool silent) {
return DoAcquisition(1, 8, 0,trigger_threshold, silent, 0, 0);
uint32_t DoAcquisition_default(int trigger_threshold, bool silent)
{
return DoAcquisition(1, 8, 0, trigger_threshold, silent, 0, 0);
}
uint32_t DoAcquisition_config( bool silent, int sample_size) {
uint32_t DoAcquisition_config(bool silent, int sample_size)
{
return DoAcquisition(config.decimation
,config.bits_per_sample
,config.averaging
,config.trigger_threshold
,silent
,sample_size
,0);
, config.bits_per_sample
, config.averaging
, config.trigger_threshold
, silent
, sample_size
, 0);
}
uint32_t DoPartialAcquisition(int trigger_threshold, bool silent, int sample_size, uint32_t cancel_after) {
uint32_t DoPartialAcquisition(int trigger_threshold, bool silent, int sample_size, uint32_t cancel_after)
{
return DoAcquisition(1, 8, 0, trigger_threshold, silent, sample_size, cancel_after);
}
uint32_t ReadLF(bool activeField, bool silent, int sample_size) {
uint32_t ReadLF(bool activeField, bool silent, int sample_size)
{
if (!silent)
printConfig();
LFSetupFPGAForADC(config.divisor, activeField);
@ -246,7 +256,8 @@ uint32_t ReadLF(bool activeField, bool silent, int sample_size) {
* Initializes the FPGA for reader-mode (field on), and acquires the samples.
* @return number of bits sampled
**/
uint32_t SampleLF(bool printCfg, int sample_size) {
uint32_t SampleLF(bool printCfg, int sample_size)
{
BigBuf_Clear_ext(false);
uint32_t ret = ReadLF(true, printCfg, sample_size);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
@ -256,7 +267,8 @@ uint32_t SampleLF(bool printCfg, int sample_size) {
* Initializes the FPGA for snoop-mode (field off), and acquires the samples.
* @return number of bits sampled
**/
uint32_t SnoopLF() {
uint32_t SnoopLF()
{
BigBuf_Clear_ext(false);
uint32_t ret = ReadLF(false, true, 0);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
@ -267,16 +279,17 @@ uint32_t SnoopLF() {
* acquisition of T55x7 LF signal. Similar to other LF, but adjusted with @marshmellows thresholds
* the data is collected in BigBuf.
**/
void doT55x7Acquisition(size_t sample_size) {
void doT55x7Acquisition(size_t sample_size)
{
#define T55xx_READ_UPPER_THRESHOLD 128+60 // 60 grph
#define T55xx_READ_LOWER_THRESHOLD 128-60 // -60 grph
#define T55xx_READ_TOL 5
#define T55xx_READ_UPPER_THRESHOLD 128+60 // 60 grph
#define T55xx_READ_LOWER_THRESHOLD 128-60 // -60 grph
#define T55xx_READ_TOL 5
uint8_t *dest = BigBuf_get_addr();
uint16_t bufsize = BigBuf_max_traceLen();
if ( bufsize > sample_size )
if (bufsize > sample_size)
bufsize = sample_size;
uint8_t curSample = 0, lastSample = 0;
@ -285,7 +298,7 @@ void doT55x7Acquisition(size_t sample_size) {
bool highFound = false;
bool lowFound = false;
while(!BUTTON_PRESS() && !usb_poll_validate_length() && skipCnt < 1000 && (i < bufsize) ) {
while (!BUTTON_PRESS() && !usb_poll_validate_length() && skipCnt < 1000 && (i < bufsize)) {
WDT_HIT();
@ -313,7 +326,7 @@ void doT55x7Acquisition(size_t sample_size) {
}
// skip until first high samples begin to change
if (startFound || curSample > T55xx_READ_LOWER_THRESHOLD + T55xx_READ_TOL){
if (startFound || curSample > T55xx_READ_LOWER_THRESHOLD + T55xx_READ_TOL) {
// if just found start - recover last sample
if (!startFound) {
dest[i++] = lastSample;
@ -337,12 +350,13 @@ void doT55x7Acquisition(size_t sample_size) {
#ifndef COTAG_BITS
#define COTAG_BITS 264
#endif
void doCotagAcquisition(size_t sample_size) {
void doCotagAcquisition(size_t sample_size)
{
uint8_t *dest = BigBuf_get_addr();
uint16_t bufsize = BigBuf_max_traceLen();
if ( bufsize > sample_size )
if (bufsize > sample_size)
bufsize = sample_size;
dest[0] = 0;
@ -350,7 +364,7 @@ void doCotagAcquisition(size_t sample_size) {
uint16_t i = 0;
uint16_t noise_counter = 0;
while (!BUTTON_PRESS() && !usb_poll_validate_length() && (i < bufsize) && (noise_counter < (COTAG_T1 << 1)) ) {
while (!BUTTON_PRESS() && !usb_poll_validate_length() && (i < bufsize) && (noise_counter < (COTAG_T1 << 1))) {
WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
@ -358,7 +372,7 @@ void doCotagAcquisition(size_t sample_size) {
LED_D_OFF();
// find first peak
if ( !firsthigh ) {
if (!firsthigh) {
if (sample < COTAG_ONE_THRESHOLD) {
noise_counter++;
continue;
@ -366,8 +380,8 @@ void doCotagAcquisition(size_t sample_size) {
noise_counter = 0;
firsthigh = 1;
}
if ( !firstlow ){
if (sample > COTAG_ZERO_THRESHOLD ) {
if (!firstlow) {
if (sample > COTAG_ZERO_THRESHOLD) {
noise_counter++;
continue;
}
@ -377,22 +391,23 @@ void doCotagAcquisition(size_t sample_size) {
++i;
if ( sample > COTAG_ONE_THRESHOLD)
if (sample > COTAG_ONE_THRESHOLD)
dest[i] = 255;
else if ( sample < COTAG_ZERO_THRESHOLD)
else if (sample < COTAG_ZERO_THRESHOLD)
dest[i] = 0;
else
dest[i] = dest[i-1];
dest[i] = dest[i - 1];
}
}
}
uint32_t doCotagAcquisitionManchester() {
uint32_t doCotagAcquisitionManchester()
{
uint8_t *dest = BigBuf_get_addr();
uint16_t bufsize = BigBuf_max_traceLen();
if ( bufsize > COTAG_BITS )
if (bufsize > COTAG_BITS)
bufsize = COTAG_BITS;
dest[0] = 0;
@ -401,7 +416,7 @@ uint32_t doCotagAcquisitionManchester() {
uint8_t curr = 0, prev = 0;
uint16_t noise_counter = 0;
while (!BUTTON_PRESS() && !usb_poll_validate_length() && (sample_counter < bufsize) && (noise_counter < (COTAG_T1 << 1)) ) {
while (!BUTTON_PRESS() && !usb_poll_validate_length() && (sample_counter < bufsize) && (noise_counter < (COTAG_T1 << 1))) {
WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
@ -409,7 +424,7 @@ uint32_t doCotagAcquisitionManchester() {
LED_D_OFF();
// find first peak
if ( !firsthigh ) {
if (!firsthigh) {
if (sample < COTAG_ONE_THRESHOLD) {
noise_counter++;
continue;
@ -418,8 +433,8 @@ uint32_t doCotagAcquisitionManchester() {
firsthigh = 1;
}
if ( !firstlow ){
if (sample > COTAG_ZERO_THRESHOLD ) {
if (!firstlow) {
if (sample > COTAG_ZERO_THRESHOLD) {
noise_counter++;
continue;
}
@ -428,20 +443,18 @@ uint32_t doCotagAcquisitionManchester() {
}
// set sample 255, 0, or previous
if ( sample > COTAG_ONE_THRESHOLD){
if (sample > COTAG_ONE_THRESHOLD) {
prev = curr;
curr = 1;
}
else if ( sample < COTAG_ZERO_THRESHOLD) {
} else if (sample < COTAG_ZERO_THRESHOLD) {
prev = curr;
curr = 0;
}
else {
} else {
curr = prev;
}
// full T1 periods,
if ( period > 0 ) {
if (period > 0) {
--period;
continue;
}

View file

@ -78,7 +78,7 @@ void LFSetupFPGAForADC(int divisor, bool lf_field);
*/
void setSamplingConfig(sample_config *sc);
sample_config * getSamplingConfig();
sample_config *getSamplingConfig();
void printConfig();

File diff suppressed because it is too large Load diff

View file

@ -10,13 +10,14 @@
// the block number for the ISO14443-4 PCB
uint8_t pcb_blocknum = 0;
// Deselect card by sending a s-block. the crc is precalced for speed
static uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4};
static uint8_t deselect_cmd[] = {0xc2, 0xe0, 0xb4};
//static uint8_t __msg[MAX_FRAME_SIZE] = { 0x0A, 0x00, 0x00, /* ..., */ 0x00 };
/* PCB CID CMD PAYLOAD */
//static uint8_t __res[MAX_FRAME_SIZE];
bool InitDesfireCard(){
bool InitDesfireCard()
{
iso14a_card_select_t card;
@ -40,7 +41,8 @@ enum {
BAR = 0x08,
} CmdOptions ;
void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){
void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain)
{
/* ARG0 contains flags.
0x01 = init card.
@ -50,7 +52,7 @@ void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){
uint8_t flags = arg0;
size_t datalen = arg1;
uint8_t resp[RECEIVE_SIZE];
memset(resp,0,sizeof(resp));
memset(resp, 0, sizeof(resp));
if (MF_DBGLEVEL >= 4) {
Dbprintf(" flags : %02X", flags);
@ -58,11 +60,11 @@ void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){
print_result(" RX : ", datain, datalen);
}
if ( flags & CLEARTRACE )
if (flags & CLEARTRACE)
clear_trace();
if ( flags & INIT ){
if ( !InitDesfireCard() )
if (flags & INIT) {
if (!InitDesfireCard())
return;
}
@ -70,7 +72,7 @@ void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){
if (MF_DBGLEVEL >= 4)
print_result("ERR <--: ", resp, len);
if ( !len ) {
if (!len) {
OnError(2);
return;
}
@ -78,13 +80,14 @@ void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){
// reset the pcb_blocknum,
pcb_blocknum = 0;
if ( flags & DISCONNECT )
if (flags & DISCONNECT)
OnSuccess();
cmd_send(CMD_ACK,1,len,0,resp,len);
cmd_send(CMD_ACK, 1, len, 0, resp, len);
}
void MifareDesfireGetInformation(){
void MifareDesfireGetInformation()
{
int len = 0;
iso14a_card_select_t card;
@ -105,13 +108,13 @@ void MifareDesfireGetInformation(){
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
// card select - information
if ( !iso14443a_select_card(NULL, &card, NULL, true, 0, false) ) {
if (!iso14443a_select_card(NULL, &card, NULL, true, 0, false)) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) DbpString("Can't select card");
OnError(1);
return;
}
if ( card.uidlen != 7 ) {
if (card.uidlen != 7) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Wrong UID size. Expected 7byte got %d", card.uidlen);
OnError(2);
return;
@ -127,7 +130,7 @@ void MifareDesfireGetInformation(){
size_t cmd_len = sizeof(cmd);
len = DesfireAPDU(cmd, cmd_len, resp);
if ( !len ) {
if (!len) {
print_result("ERROR <--: ", resp, len);
OnError(3);
return;
@ -135,12 +138,12 @@ void MifareDesfireGetInformation(){
LED_A_OFF();
LED_B_ON();
memcpy(dataout+7,resp+3,7);
memcpy(dataout + 7, resp + 3, 7);
// ADDITION_FRAME 1
cmd[0] = ADDITIONAL_FRAME;
len = DesfireAPDU(cmd, cmd_len, resp);
if ( !len ) {
if (!len) {
print_result("ERROR <--: ", resp, len);
OnError(3);
return;
@ -148,30 +151,31 @@ void MifareDesfireGetInformation(){
LED_B_OFF();
LED_C_ON();
memcpy(dataout+7+7,resp+3,7);
memcpy(dataout + 7 + 7, resp + 3, 7);
// ADDITION_FRAME 2
len = DesfireAPDU(cmd, cmd_len, resp);
if ( !len ) {
if (!len) {
print_result("ERROR <--: ", resp, len);
OnError(3);
return;
}
memcpy(dataout+7+7+7,resp+3,14);
memcpy(dataout + 7 + 7 + 7, resp + 3, 14);
cmd_send(CMD_ACK,1,0,0,dataout,sizeof(dataout));
cmd_send(CMD_ACK, 1, 0, 0, dataout, sizeof(dataout));
// reset the pcb_blocknum,
pcb_blocknum = 0;
OnSuccess();
}
void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain){
void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain)
{
int len = 0;
//uint8_t PICC_MASTER_KEY8[8] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47};
uint8_t PICC_MASTER_KEY16[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f };
uint8_t PICC_MASTER_KEY16[16] = { 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f };
uint8_t null_key_data8[8] = {0x00};
//uint8_t null_key_data16[16] = {0x00};
//uint8_t new_key_data8[8] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
@ -200,24 +204,24 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
// 3 olika kommunikations sätt, PLAIN,MAC,CRYPTO
// des, nyckel 0,
switch (mode){
case 1:{
switch (mode) {
case 1: {
uint8_t keybytes[16];
uint8_t RndA[8] = {0x00};
uint8_t RndB[8] = {0x00};
if (algo == 2) {
if (datain[1] == 0xff){
memcpy(keybytes,PICC_MASTER_KEY16,16);
if (datain[1] == 0xff) {
memcpy(keybytes, PICC_MASTER_KEY16, 16);
} else {
memcpy(keybytes, datain+1, datalen);
memcpy(keybytes, datain + 1, datalen);
}
} else {
if (algo == 1) {
if (datain[1] == 0xff){
memcpy(keybytes,null_key_data8,8);
} else{
memcpy(keybytes, datain+1, datalen);
if (datain[1] == 0xff) {
memcpy(keybytes, null_key_data8, 8);
} else {
memcpy(keybytes, datain + 1, datalen);
}
}
}
@ -227,13 +231,13 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
if (algo == 2)
Desfire_3des_key_new_with_version(keybytes, key);
else if (algo ==1)
else if (algo == 1)
Desfire_des_key_new(keybytes, key);
cmd[0] = AUTHENTICATE;
cmd[1] = keyno; //keynumber
len = DesfireAPDU(cmd, 2, resp);
if ( !len ) {
if (!len) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) {
DbpString("Authentication failed. Card timeout.");
}
@ -241,21 +245,21 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
return;
}
if ( resp[2] == 0xaf ){
if (resp[2] == 0xaf) {
} else {
DbpString("Authentication failed. Invalid key number.");
OnError(3);
return;
}
memcpy( encRndB, resp+3, 8);
memcpy(encRndB, resp + 3, 8);
if (algo == 2)
tdes_dec(&decRndB, &encRndB, key->data);
else if (algo == 1)
des_dec(&decRndB, &encRndB, key->data);
memcpy(RndB, decRndB, 8);
rol(decRndB,8);
rol(decRndB, 8);
// This should be random
uint8_t decRndA[8] = {0x00};
@ -282,10 +286,10 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
memcpy(both + 8, encRndB, 8);
cmd[0] = ADDITIONAL_FRAME;
memcpy(cmd+1, both, 16 );
memcpy(cmd + 1, both, 16);
len = DesfireAPDU(cmd, 17, resp);
if ( !len ) {
if (!len) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) {
DbpString("Authentication failed. Card timeout.");
}
@ -293,21 +297,21 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
return;
}
if ( resp[2] == 0x00 ){
if (resp[2] == 0x00) {
struct desfire_key sessionKey = {0};
desfirekey_t skey = &sessionKey;
Desfire_session_key_new( RndA, RndB , key, skey );
Desfire_session_key_new(RndA, RndB, key, skey);
//print_result("SESSION : ", skey->data, 8);
memcpy(encRndA, resp+3, 8);
memcpy(encRndA, resp + 3, 8);
if (algo == 2)
tdes_dec(&encRndA, &encRndA, key->data);
else if (algo == 1)
des_dec(&encRndA, &encRndA, key->data);
rol(decRndA,8);
rol(decRndA, 8);
for (int x = 0; x < 8; x++) {
if (decRndA[x] != encRndA[x]) {
DbpString("Authentication failed. Cannot varify PICC.");
@ -407,9 +411,9 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
OnSuccess();
if (algo == 2)
cmd_send(CMD_ACK,1,0,0,skey->data,16);
cmd_send(CMD_ACK, 1, 0, 0, skey->data, 16);
else if (algo == 1)
cmd_send(CMD_ACK,1,0,0,skey->data,8);
cmd_send(CMD_ACK, 1, 0, 0, skey->data, 8);
} else {
DbpString("Authentication failed.");
OnError(6);
@ -420,23 +424,23 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
case 2:
//SendDesfireCommand(AUTHENTICATE_ISO, &keyno, resp);
break;
case 3:{
case 3: {
//defaultkey
uint8_t keybytes[16] = {0x00};
if (datain[1] == 0xff){
memcpy(keybytes,PICC_MASTER_KEY16,16);
} else{
memcpy(keybytes, datain+1, datalen);
if (datain[1] == 0xff) {
memcpy(keybytes, PICC_MASTER_KEY16, 16);
} else {
memcpy(keybytes, datain + 1, datalen);
}
struct desfire_key defaultkey = {0x00};
desfirekey_t key = &defaultkey;
Desfire_aes_key_new( keybytes, key);
Desfire_aes_key_new(keybytes, key);
AesCtx ctx;
if ( AesCtxIni(&ctx, IV, key->data, KEY128, CBC) < 0 ){
if( MF_DBGLEVEL >= 4) {
if (AesCtxIni(&ctx, IV, key->data, KEY128, CBC) < 0) {
if (MF_DBGLEVEL >= 4) {
DbpString("AES context failed to init");
}
OnError(7);
@ -446,7 +450,7 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
cmd[0] = AUTHENTICATE_AES;
cmd[1] = 0x00; //keynumber
len = DesfireAPDU(cmd, 2, resp);
if ( !len ) {
if (!len) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) {
DbpString("Authentication failed. Card timeout.");
}
@ -454,20 +458,20 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
return;
}
memcpy( encRndB, resp+3, 16);
memcpy(encRndB, resp + 3, 16);
// dekryptera tagnonce.
AesDecrypt(&ctx, encRndB, decRndB, 16);
rol(decRndB,16);
memcpy(both, nonce,16);
memcpy(both+16, decRndB ,16 );
AesEncrypt(&ctx, both, encBoth, 32 );
rol(decRndB, 16);
memcpy(both, nonce, 16);
memcpy(both + 16, decRndB, 16);
AesEncrypt(&ctx, both, encBoth, 32);
cmd[0] = ADDITIONAL_FRAME;
memcpy(cmd+1, encBoth, 32 );
memcpy(cmd + 1, encBoth, 32);
len = DesfireAPDU(cmd, 33, resp); // 1 + 32 == 33
if ( !len ) {
if (!len) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) {
DbpString("Authentication failed. Card timeout.");
}
@ -475,11 +479,11 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
return;
}
if ( resp[2] == 0x00 ){
if (resp[2] == 0x00) {
// Create AES Session key
struct desfire_key sessionKey = {0};
desfirekey_t skey = &sessionKey;
Desfire_session_key_new( nonce, decRndB , key, skey );
Desfire_session_key_new(nonce, decRndB, key, skey);
print_result("SESSION : ", skey->data, 16);
} else {
DbpString("Authentication failed.");
@ -492,14 +496,15 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
}
OnSuccess();
cmd_send(CMD_ACK,1,len,0,resp,len);
cmd_send(CMD_ACK, 1, len, 0, resp, len);
}
// 3 olika ISO sätt att skicka data till DESFIRE (direkt, inkapslat, inkapslat ISO)
// cmd = cmd bytes to send
// cmd_len = length of cmd
// dataout = pointer to response data array
int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){
int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout)
{
size_t len = 0;
size_t wrappedLen = 0;
@ -507,15 +512,15 @@ int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){
uint8_t resp[MAX_FRAME_SIZE];
uint8_t par[MAX_PARITY_SIZE];
wrappedLen = CreateAPDU( cmd, cmd_len, wCmd);
wrappedLen = CreateAPDU(cmd, cmd_len, wCmd);
if (MF_DBGLEVEL >= 4)
print_result("WCMD <--: ", wCmd, wrappedLen);
ReaderTransmit( wCmd, wrappedLen, NULL);
ReaderTransmit(wCmd, wrappedLen, NULL);
len = ReaderReceive(resp, par);
if ( !len ) {
if (!len) {
if (MF_DBGLEVEL >= 4) Dbprintf("fukked");
return false; //DATA LINK ERROR
}
@ -524,8 +529,7 @@ int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){
else if (len >= 4 // PCB+CID+CRC = 4 bytes
&& ((resp[0] & 0xC0) == 0 // I-Block
|| (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
&& (resp[0] & 0x01) == pcb_blocknum) // equal block numbers
{
&& (resp[0] & 0x01) == pcb_blocknum) { // equal block numbers
pcb_blocknum ^= 1; //toggle next block
}
@ -534,9 +538,10 @@ int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){
}
// CreateAPDU
size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout){
size_t CreateAPDU(uint8_t *datain, size_t len, uint8_t *dataout)
{
size_t cmdlen = MIN(len+4, USB_CMD_DATA_SIZE-1);
size_t cmdlen = MIN(len + 4, USB_CMD_DATA_SIZE - 1);
uint8_t cmd[cmdlen];
memset(cmd, 0, cmdlen);
@ -545,27 +550,29 @@ size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout){
cmd[0] |= pcb_blocknum; // OR the block number into the PCB
cmd[1] = 0x00; // CID: 0x00 //TODO: allow multiple selected cards
memcpy(cmd+2, datain, len);
AddCrc14A(cmd, len+2);
memcpy(cmd + 2, datain, len);
AddCrc14A(cmd, len + 2);
memcpy(dataout, cmd, cmdlen);
return cmdlen;
}
// crc_update(&desfire_crc32, 0, 1); /* CMD_WRITE */
// crc_update(&desfire_crc32, addr, addr_sz);
// crc_update(&desfire_crc32, byte, 8);
// uint32_t crc = crc_finish(&desfire_crc32);
// crc_update(&desfire_crc32, 0, 1); /* CMD_WRITE */
// crc_update(&desfire_crc32, addr, addr_sz);
// crc_update(&desfire_crc32, byte, 8);
// uint32_t crc = crc_finish(&desfire_crc32);
void OnSuccess(){
void OnSuccess()
{
pcb_blocknum = 0;
ReaderTransmit(deselect_cmd, 3 , NULL);
ReaderTransmit(deselect_cmd, 3, NULL);
mifare_ultra_halt();
switch_off();
}
void OnError(uint8_t reason){
cmd_send(CMD_ACK,0,reason,0,0,0);
void OnError(uint8_t reason)
{
cmd_send(CMD_ACK, 0, reason, 0, 0, 0);
OnSuccess();
}

View file

@ -12,8 +12,8 @@
//static int sniffState = SNF_INIT;
static uint8_t sniffUIDType = 0;
static uint8_t sniffUID[10] = {0,0,0,0,0,0,0,0,0,0};
static uint8_t sniffATQA[2] = {0,0};
static uint8_t sniffUID[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static uint8_t sniffATQA[2] = {0, 0};
static uint8_t sniffSAK = 0;
static uint8_t sniffBuf[17];
static uint32_t timerData = 0;
@ -24,7 +24,8 @@ static uint32_t timerData = 0;
// if no activity for 2sec, it sends the collected data to the client.
//-----------------------------------------------------------------------------
// "hf mf sniff"
void RAMFUNC SniffMifare(uint8_t param) {
void RAMFUNC SniffMifare(uint8_t param)
{
// param:
// bit 0 - trigger from first card answer
// bit 1 - trigger from first reader 7-bit request
@ -35,7 +36,8 @@ void RAMFUNC SniffMifare(uint8_t param) {
// Allocate memory from BigBuf for some buffers
// free all previous allocations first
BigBuf_free(); BigBuf_Clear_ext(false);
BigBuf_free();
BigBuf_Clear_ext(false);
clear_trace();
set_tracing(true);
@ -71,13 +73,13 @@ void RAMFUNC SniffMifare(uint8_t param) {
// Setup and start DMA.
// set transfer address and number of bytes. Start transfer.
if ( !FpgaSetupSscDma(dmaBuf, DMA_BUFFER_SIZE) ){
if (!FpgaSetupSscDma(dmaBuf, DMA_BUFFER_SIZE)) {
if (MF_DBGLEVEL > 1) Dbprintf("[!] FpgaSetupSscDma failed. Exiting");
return;
}
tUart* uart = GetUart();
tDemod* demod = GetDemod();
tUart *uart = GetUart();
tDemod *demod = GetDemod();
MfSniffInit();
@ -86,7 +88,7 @@ void RAMFUNC SniffMifare(uint8_t param) {
while (!BUTTON_PRESS()) {
WDT_HIT();
LED_A_ON();
/*
/*
if ((sniffCounter & 0x0000FFFF) == 0) { // from time to time
// check if a transaction is completed (timeout after 2000ms).
// if yes, stop the DMA transfer and send what we have so far to the client
@ -143,7 +145,7 @@ void RAMFUNC SniffMifare(uint8_t param) {
// no need to try decoding tag data if the reader is sending
if (!TagIsActive) {
uint8_t readerbyte = (previous_data & 0xF0) | (*data >> 4);
if (MillerDecoding(readerbyte, (sniffCounter-1)*4)) {
if (MillerDecoding(readerbyte, (sniffCounter - 1) * 4)) {
LogTrace(receivedCmd, uart->len, 0, 0, NULL, true);
DemodReset();
UartReset();
@ -154,7 +156,7 @@ void RAMFUNC SniffMifare(uint8_t param) {
// no need to try decoding tag data if the reader is sending
if (!ReaderIsActive) {
uint8_t tagbyte = (previous_data << 4) | (*data & 0x0F);
if (ManchesterDecoding(tagbyte, 0, (sniffCounter-1)*4)) {
if (ManchesterDecoding(tagbyte, 0, (sniffCounter - 1) * 4)) {
LogTrace(receivedResp, demod->len, 0, 0, NULL, false);
DemodReset();
UartReset();
@ -175,7 +177,8 @@ void RAMFUNC SniffMifare(uint8_t param) {
switch_off();
}
void MfSniffInit(void){
void MfSniffInit(void)
{
memset(sniffUID, 0x00, sizeof(sniffUID));
memset(sniffATQA, 0x00, sizeof(sniffATQA));
memset(sniffBuf, 0x00, sizeof(sniffBuf));
@ -184,9 +187,10 @@ void MfSniffInit(void){
timerData = 0;
}
void MfSniffEnd(void){
void MfSniffEnd(void)
{
LED_B_ON();
cmd_send(CMD_ACK,0,0,0,0,0);
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
LED_B_OFF();
}
@ -304,7 +308,8 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui
}
*/
void RAMFUNC MfSniffSend() {
void RAMFUNC MfSniffSend()
{
uint16_t tracelen = BigBuf_get_traceLen();
uint16_t chunksize = 0;
int packlen = tracelen; // total number of bytes to send

View file

@ -13,7 +13,8 @@
int MF_DBGLEVEL = MF_DBG_ERROR;
// crypto1 helpers
void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out){
void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out)
{
uint8_t bt = 0;
int i;
@ -30,11 +31,13 @@ void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, u
return;
}
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len){
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len)
{
mf_crypto1_decryptEx(pcs, data, len, data);
}
void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par) {
void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par)
{
uint8_t bt = 0;
int i;
par[0] = 0;
@ -42,13 +45,14 @@ void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, u
for (i = 0; i < len; i++) {
bt = data[i];
data[i] = crypto1_byte(pcs, 0x00, 0) ^ data[i];
if ( ( i & 0x0007 ) == 0)
if ((i & 0x0007) == 0)
par[ i >> 3 ] = 0;
par[ i >> 3 ] |= (((filter(pcs->odd) ^ oddparity8(bt)) & 0x01)<<(7-(i&0x0007)));
par[ i >> 3 ] |= (((filter(pcs->odd) ^ oddparity8(bt)) & 0x01) << (7 - (i & 0x0007)));
}
}
uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data) {
uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data)
{
uint8_t bt = 0;
bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 0)) << 0;
bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 1)) << 1;
@ -58,22 +62,24 @@ uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data) {
}
// send X byte basic commands
int mifare_sendcmd(uint8_t cmd, uint8_t* data, uint8_t data_size, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing) {
uint8_t dcmd[data_size+3];
int mifare_sendcmd(uint8_t cmd, uint8_t *data, uint8_t data_size, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing)
{
uint8_t dcmd[data_size + 3];
dcmd[0] = cmd;
memcpy(dcmd+1, data, data_size);
AddCrc14A(dcmd, data_size+1);
memcpy(dcmd + 1, data, data_size);
AddCrc14A(dcmd, data_size + 1);
ReaderTransmit(dcmd, sizeof(dcmd), timing);
int len = ReaderReceive(answer, answer_parity);
if(!len) {
if (!len) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("%02X Cmd failed. Card timeout.", cmd);
len = ReaderReceive(answer,answer_parity);
len = ReaderReceive(answer, answer_parity);
}
return len;
}
// send 2 byte commands
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) {
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)
{
uint16_t pos, res;
uint8_t dcmd[4] = {cmd, data, 0x00, 0x00};
uint8_t ecmd[4] = {0x00, 0x00, 0x00, 0x00};
@ -85,7 +91,7 @@ int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd,
par[0] = 0;
for (pos = 0; pos < 4; pos++) {
ecmd[pos] = crypto1_byte(pcs, 0x00, 0) ^ dcmd[pos];
par[0] |= (((filter(pcs->odd) ^ oddparity8(dcmd[pos])) & 0x01) << (7-pos));
par[0] |= (((filter(pcs->odd) ^ oddparity8(dcmd[pos])) & 0x01) << (7 - pos));
}
ReaderTransmitPar(ecmd, sizeof(ecmd), par, timing);
} else {
@ -113,21 +119,23 @@ int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd,
}
// mifare classic commands
int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested) {
int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested)
{
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)
{
int len;
uint32_t pos, nt, ntpp; // Supplied tag nonce
uint8_t par[1] = {0x00};
uint8_t nr[4];
uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
uint8_t mf_nr_ar[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
// "random" reader nonce:
num_to_bytes( prng_successor( GetTickCount(), 32), 4, nr);
num_to_bytes(prng_successor(GetTickCount(), 32), 4, nr);
// Transmit MIFARE_CLASSIC_AUTH
len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing);
@ -163,7 +171,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
par[0] = 0;
for (pos = 0; pos < 4; pos++) {
mf_nr_ar[pos] = crypto1_byte(pcs, nr[pos], 0) ^ nr[pos];
par[0] |= (((filter(pcs->odd) ^ oddparity8(nr[pos])) & 0x01) << (7-pos));
par[0] |= (((filter(pcs->odd) ^ oddparity8(nr[pos])) & 0x01) << (7 - pos));
}
// Skip 32 bits in pseudo random generator
@ -171,9 +179,9 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
// ar+parity
for (pos = 4; pos < 8; pos++) {
nt = prng_successor(nt,8);
mf_nr_ar[pos] = crypto1_byte(pcs,0x00,0) ^ (nt & 0xff);
par[0] |= (((filter(pcs->odd) ^ oddparity8(nt & 0xff)) & 0x01) << (7-pos));
nt = prng_successor(nt, 8);
mf_nr_ar[pos] = crypto1_byte(pcs, 0x00, 0) ^ (nt & 0xff);
par[0] |= (((filter(pcs->odd) ^ oddparity8(nt & 0xff)) & 0x01) << (7 - pos));
}
// Transmit reader nonce and reader answer
@ -186,7 +194,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
return 2;
}
ntpp = prng_successor(nt, 32) ^ crypto1_word(pcs, 0,0);
ntpp = prng_successor(nt, 32) ^ crypto1_word(pcs, 0, 0);
if (ntpp != bytes_to_num(receivedAnswer, 4)) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication failed. Error card response.");
@ -195,7 +203,8 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
return 0;
}
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) {
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData)
{
int len;
uint8_t bt[2] = {0x00, 0x00};
@ -224,7 +233,8 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
}
// mifare ultralight commands
int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack){
int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack)
{
uint16_t len = 0;
uint8_t resp[4] = {0x00, 0x00, 0x00, 0x00};
@ -243,16 +253,17 @@ int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack){
}
if (MF_DBGLEVEL >= MF_DBG_EXTENDED)
Dbprintf("Auth Resp: %02x%02x%02x%02x", resp[0],resp[1],resp[2],resp[3]);
Dbprintf("Auth Resp: %02x%02x%02x%02x", resp[0], resp[1], resp[2], resp[3]);
memcpy(pack, resp, 4);
return 1;
}
int mifare_ultra_auth(uint8_t *keybytes){
int mifare_ultra_auth(uint8_t *keybytes)
{
/// 3des2k
uint8_t random_a[8] = {1,1,1,1,1,1,1,1};
uint8_t random_a[8] = {1, 1, 1, 1, 1, 1, 1, 1};
uint8_t random_b[8] = {0x00};
uint8_t enc_random_b[8] = {0x00};
uint8_t rnd_ab[16] = {0x00};
@ -262,36 +273,36 @@ int mifare_ultra_auth(uint8_t *keybytes){
uint16_t len = 0;
uint8_t resp[19] = {0x00};
uint8_t respPar[3] = {0,0,0};
uint8_t respPar[3] = {0, 0, 0};
// REQUEST AUTHENTICATION
len = mifare_sendcmd_short(NULL, 1, MIFARE_ULC_AUTH_1, 0x00, resp, respPar ,NULL);
len = mifare_sendcmd_short(NULL, 1, MIFARE_ULC_AUTH_1, 0x00, resp, respPar, NULL);
if (len != 11) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]);
return 0;
}
// tag nonce.
memcpy(enc_random_b,resp+1,8);
memcpy(enc_random_b, resp + 1, 8);
// decrypt nonce.
tdes_2key_dec((void*)random_b, (void*)enc_random_b, sizeof(random_b), (const void*)key, IV );
rol(random_b,8);
memcpy(rnd_ab ,random_a,8);
memcpy(rnd_ab+8,random_b,8);
tdes_2key_dec((void *)random_b, (void *)enc_random_b, sizeof(random_b), (const void *)key, IV);
rol(random_b, 8);
memcpy(rnd_ab, random_a, 8);
memcpy(rnd_ab + 8, random_b, 8);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
Dbprintf("enc_B: %02x %02x %02x %02x %02x %02x %02x %02x",
enc_random_b[0],enc_random_b[1],enc_random_b[2],enc_random_b[3],enc_random_b[4],enc_random_b[5],enc_random_b[6],enc_random_b[7]);
enc_random_b[0], enc_random_b[1], enc_random_b[2], enc_random_b[3], enc_random_b[4], enc_random_b[5], enc_random_b[6], enc_random_b[7]);
Dbprintf(" B: %02x %02x %02x %02x %02x %02x %02x %02x",
random_b[0],random_b[1],random_b[2],random_b[3],random_b[4],random_b[5],random_b[6],random_b[7]);
random_b[0], random_b[1], random_b[2], random_b[3], random_b[4], random_b[5], random_b[6], random_b[7]);
Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x",
rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3],rnd_ab[4],rnd_ab[5],rnd_ab[6],rnd_ab[7]);
rnd_ab[0], rnd_ab[1], rnd_ab[2], rnd_ab[3], rnd_ab[4], rnd_ab[5], rnd_ab[6], rnd_ab[7]);
Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x",
rnd_ab[8],rnd_ab[9],rnd_ab[10],rnd_ab[11],rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15] );
rnd_ab[8], rnd_ab[9], rnd_ab[10], rnd_ab[11], rnd_ab[12], rnd_ab[13], rnd_ab[14], rnd_ab[15]);
}
// encrypt out, in, length, key, iv
@ -303,38 +314,39 @@ int mifare_ultra_auth(uint8_t *keybytes){
return 0;
}
uint8_t enc_resp[8] = { 0,0,0,0,0,0,0,0 };
uint8_t resp_random_a[8] = { 0,0,0,0,0,0,0,0 };
memcpy(enc_resp, resp+1, 8);
uint8_t enc_resp[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
uint8_t resp_random_a[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
memcpy(enc_resp, resp + 1, 8);
// decrypt out, in, length, key, iv
tdes_2key_dec(resp_random_a, enc_resp, 8, key, enc_random_b);
if ( memcmp(resp_random_a, random_a, 8) != 0 ) {
if (memcmp(resp_random_a, random_a, 8) != 0) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("failed authentication");
return 0;
}
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x",
rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3],
rnd_ab[4],rnd_ab[5],rnd_ab[6],rnd_ab[7]);
rnd_ab[0], rnd_ab[1], rnd_ab[2], rnd_ab[3],
rnd_ab[4], rnd_ab[5], rnd_ab[6], rnd_ab[7]);
Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x",
rnd_ab[8],rnd_ab[9],rnd_ab[10],rnd_ab[11],
rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15]);
rnd_ab[8], rnd_ab[9], rnd_ab[10], rnd_ab[11],
rnd_ab[12], rnd_ab[13], rnd_ab[14], rnd_ab[15]);
Dbprintf("a: %02x %02x %02x %02x %02x %02x %02x %02x",
random_a[0],random_a[1],random_a[2],random_a[3],
random_a[4],random_a[5],random_a[6],random_a[7]);
random_a[0], random_a[1], random_a[2], random_a[3],
random_a[4], random_a[5], random_a[6], random_a[7]);
Dbprintf("b: %02x %02x %02x %02x %02x %02x %02x %02x",
resp_random_a[0],resp_random_a[1],resp_random_a[2],resp_random_a[3],
resp_random_a[4],resp_random_a[5],resp_random_a[6],resp_random_a[7]);
resp_random_a[0], resp_random_a[1], resp_random_a[2], resp_random_a[3],
resp_random_a[4], resp_random_a[5], resp_random_a[6], resp_random_a[7]);
}
return 1;
}
int mifare_ultra_readblockEx(uint8_t blockNo, uint8_t *blockData) {
int mifare_ultra_readblockEx(uint8_t blockNo, uint8_t *blockData)
{
uint16_t len = 0;
uint8_t bt[2] = {0x00, 0x00};
uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00};
@ -360,15 +372,16 @@ int mifare_ultra_readblockEx(uint8_t blockNo, uint8_t *blockData) {
memcpy(blockData, receivedAnswer, 14);
return 0;
}
int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData) {
#define MFU_MAX_RETRIES 5
int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData)
{
#define MFU_MAX_RETRIES 5
uint8_t res;
for (uint8_t retries = 0; retries < MFU_MAX_RETRIES; ++retries) {
res = mifare_ultra_readblockEx(blockNo, blockData);
// break if OK, or NACK.
switch ( res ) {
switch (res) {
case 0:
case 1:
return res;
@ -379,7 +392,8 @@ int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData) {
return res;
}
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) {
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData)
{
// variables
uint16_t len = 0;
uint32_t pos = 0;
@ -404,7 +418,7 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
// crypto
for (pos = 0; pos < 18; pos++) {
d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos];
par[pos>>3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos&0x0007)));
par[pos >> 3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos & 0x0007)));
}
ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL);
@ -457,25 +471,27 @@ int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData) {
}
*/
int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) {
int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData)
{
uint16_t len = 0;
uint8_t block[5] = {blockNo, 0x00, 0x00, 0x00, 0x00 };
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
// command MIFARE_CLASSIC_WRITEBLOCK
memcpy(block+1, blockData, 4);
memcpy(block + 1, blockData, 4);
len = mifare_sendcmd( MIFARE_ULC_WRITE, block, sizeof(block), receivedAnswer, receivedAnswerPar, NULL);
len = mifare_sendcmd(MIFARE_ULC_WRITE, block, sizeof(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);
Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0], len);
return 1;
}
return 0;
}
int mifare_classic_halt_ex(struct Crypto1State *pcs) {
int mifare_classic_halt_ex(struct Crypto1State *pcs)
{
uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00};
uint16_t len = mifare_sendcmd_short(pcs, (pcs == NULL) ? CRYPT_NONE : CRYPT_ALL, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL);
if (len != 0) {
@ -484,11 +500,13 @@ int mifare_classic_halt_ex(struct Crypto1State *pcs) {
}
return 0;
}
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) {
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
{
return mifare_classic_halt_ex(pcs);
}
int mifare_ultra_halt() {
int mifare_ultra_halt()
{
uint16_t len = 0;
uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00};
len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL);
@ -502,41 +520,48 @@ int mifare_ultra_halt() {
// 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)
uint8_t NumBlocksPerSector(uint8_t sectorNo) {
uint8_t NumBlocksPerSector(uint8_t sectorNo)
{
return (sectorNo < 32) ? 4 : 16;
}
uint8_t FirstBlockOfSector(uint8_t sectorNo) {
uint8_t FirstBlockOfSector(uint8_t sectorNo)
{
if (sectorNo < 32)
return sectorNo * 4;
else
return 32*4 + (sectorNo - 32) * 16;
return 32 * 4 + (sectorNo - 32) * 16;
}
// work with emulator memory
void emlSetMem(uint8_t *data, int blockNum, int blocksCount) {
void emlSetMem(uint8_t *data, int blockNum, int blocksCount)
{
emlSetMem_xt(data, blockNum, blocksCount, 16);
}
void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth) {
uint8_t* emCARD = BigBuf_get_EM_addr();
void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth)
{
uint8_t *emCARD = BigBuf_get_EM_addr();
memcpy(emCARD + blockNum * blockBtWidth, data, blocksCount * blockBtWidth);
}
void emlGetMem(uint8_t *data, int blockNum, int blocksCount) {
uint8_t* emCARD = BigBuf_get_EM_addr();
void emlGetMem(uint8_t *data, int blockNum, int blocksCount)
{
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 = BigBuf_get_EM_addr();
void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount)
{
uint8_t *emCARD = BigBuf_get_EM_addr();
memcpy(data, emCARD + bytePtr, byteCount);
}
int emlCheckValBl(int blockNum) {
uint8_t* emCARD = BigBuf_get_EM_addr();
uint8_t* data = emCARD + blockNum * 16;
int emlCheckValBl(int blockNum)
{
uint8_t *emCARD = BigBuf_get_EM_addr();
uint8_t *data = emCARD + blockNum * 16;
if ((data[0] != (data[4] ^ 0xff)) || (data[0] != data[8]) ||
(data[1] != (data[5] ^ 0xff)) || (data[1] != data[9]) ||
@ -549,9 +574,10 @@ int emlCheckValBl(int blockNum) {
return 0;
}
int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) {
uint8_t* emCARD = BigBuf_get_EM_addr();
uint8_t* data = emCARD + blockNum * 16;
int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum)
{
uint8_t *emCARD = BigBuf_get_EM_addr();
uint8_t *data = emCARD + blockNum * 16;
if (emlCheckValBl(blockNum))
return 1;
@ -561,9 +587,10 @@ int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) {
return 0;
}
int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) {
uint8_t* emCARD = BigBuf_get_EM_addr();
uint8_t* data = emCARD + blockNum * 16;
int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum)
{
uint8_t *emCARD = BigBuf_get_EM_addr();
uint8_t *data = emCARD + blockNum * 16;
memcpy(data + 0, &blReg, 4);
memcpy(data + 8, &blReg, 4);
@ -578,21 +605,23 @@ int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) {
return 0;
}
uint64_t emlGetKey(int sectorNum, int keyType) {
uint64_t emlGetKey(int sectorNum, int keyType)
{
uint8_t key[6] = {0x00};
uint8_t* emCARD = BigBuf_get_EM_addr();
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);
}
void emlClearMem(void) {
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 = BigBuf_get_EM_addr();
uint8_t *emCARD = BigBuf_get_EM_addr();
memset(emCARD, 0, CARD_MEMORY_SIZE);
// fill sectors trailer data
for(uint16_t b = 3; b < 256; ((b < 127) ? (b += 4) : (b += 16)))
for (uint16_t b = 3; b < 256; ((b < 127) ? (b += 4) : (b += 16)))
emlSetMem((uint8_t *)trailer, b, 1);
// uid
@ -602,43 +631,46 @@ void emlClearMem(void) {
// Mifare desfire commands
int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing) {
int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing)
{
uint8_t dcmd[5] = {cmd, data[0], data[1], 0x00, 0x00};
AddCrc14A(dcmd, 3);
ReaderTransmit(dcmd, sizeof(dcmd), NULL);
int len = ReaderReceive(answer, answer_parity);
if(!len) {
if (!len) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed. Card timeout.");
return 1;
}
return len;
}
int mifare_sendcmd_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer,uint8_t *answer_parity, uint32_t *timing) {
int mifare_sendcmd_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing)
{
uint8_t dcmd[20] = {0x00};
dcmd[0] = cmd;
memcpy(dcmd+1,data,17);
memcpy(dcmd + 1, data, 17);
AddCrc14A(dcmd, 18);
ReaderTransmit(dcmd, sizeof(dcmd), NULL);
int len = ReaderReceive(answer, answer_parity);
if(!len){
if (!len) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed. Card timeout.");
return 1;
}
return len;
}
int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData){
int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData)
{
int len;
// load key, keynumber
uint8_t data[2]={MFDES_AUTHENTICATE, 0x00};
uint8_t data[2] = {MFDES_AUTHENTICATE, 0x00};
uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00};
uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00};
len = mifare_sendcmd_special(NULL, 1, 0x02, data, receivedAnswer,receivedAnswerPar,NULL);
len = mifare_sendcmd_special(NULL, 1, 0x02, data, receivedAnswer, receivedAnswerPar, NULL);
if (len == 1) {
if (MF_DBGLEVEL >= MF_DBG_ERROR)
Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
@ -648,9 +680,9 @@ int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData){
if (len == 12) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
Dbprintf("Auth1 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4],
receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9],
receivedAnswer[10],receivedAnswer[11]);
receivedAnswer[0], receivedAnswer[1], receivedAnswer[2], receivedAnswer[3], receivedAnswer[4],
receivedAnswer[5], receivedAnswer[6], receivedAnswer[7], receivedAnswer[8], receivedAnswer[9],
receivedAnswer[10], receivedAnswer[11]);
}
memcpy(blockData, receivedAnswer, 12);
return 0;
@ -658,16 +690,17 @@ int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData){
return 1;
}
int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){
int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData)
{
int len;
uint8_t data[17] = {MFDES_AUTHENTICATION_FRAME};
memcpy(data+1,key,16);
memcpy(data + 1, key, 16);
uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00};
uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00};
len = mifare_sendcmd_special2(NULL, 1, 0x03, data, receivedAnswer, receivedAnswerPar ,NULL);
len = mifare_sendcmd_special2(NULL, 1, 0x03, data, receivedAnswer, receivedAnswerPar, NULL);
if ((receivedAnswer[0] == 0x03) && (receivedAnswer[1] == 0xae)) {
if (MF_DBGLEVEL >= MF_DBG_ERROR)
@ -675,12 +708,12 @@ int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){
return 1;
}
if (len == 12){
if (len == 12) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
Dbprintf("Auth2 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4],
receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9],
receivedAnswer[10],receivedAnswer[11]);
receivedAnswer[0], receivedAnswer[1], receivedAnswer[2], receivedAnswer[3], receivedAnswer[4],
receivedAnswer[5], receivedAnswer[6], receivedAnswer[7], receivedAnswer[8], receivedAnswer[9],
receivedAnswer[10], receivedAnswer[11]);
}
memcpy(blockData, receivedAnswer, 12);
return 0;

View file

@ -58,12 +58,12 @@
#define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF();
//functions
int mifare_sendcmd(uint8_t cmd, uint8_t *data, uint8_t data_size, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_sendcmd(uint8_t cmd, uint8_t *data, uint8_t data_size, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);
// mifare classic
int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested);
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing);
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing);
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid);
int mifare_classic_halt_ex(struct Crypto1State *pcs);
@ -78,8 +78,8 @@ int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData);
int mifare_ultra_halt();
// desfire
int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_sendcmd_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer,uint8_t *answer_parity, uint32_t *timing);
int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_sendcmd_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData);
int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData);

View file

@ -96,7 +96,8 @@ uint8_t xopt__select(bool x, bool y, uint8_t r)
}
*/
void opt_successor(const uint8_t* k, State *s, bool y, State* successor) {
void opt_successor(const uint8_t *k, State *s, bool y, State *successor)
{
uint8_t Tt = 1 & opt_T(s);
successor->t = (s->t >> 1);
@ -105,11 +106,12 @@ void opt_successor(const uint8_t* k, State *s, bool y, State* successor) {
successor->b = s->b >> 1;
successor->b |= (opt_B(s) ^ (s->r & 0x1)) << 7;
successor->r = (k[opt__select(Tt,y,s->r)] ^ successor->b) + s->l ;
successor->l = successor->r+s->r;
successor->r = (k[opt__select(Tt, y, s->r)] ^ successor->b) + s->l ;
successor->l = successor->r + s->r;
}
void opt_suc(const uint8_t* k,State* s, uint8_t *in, uint8_t length, bool add32Zeroes) {
void opt_suc(const uint8_t *k, State *s, uint8_t *in, uint8_t length, bool add32Zeroes)
{
State x2;
int i;
uint8_t head = 0;
@ -148,12 +150,13 @@ void opt_suc(const uint8_t* k,State* s, uint8_t *in, uint8_t length, bool add32Z
}
}
void opt_output(const uint8_t* k,State* s, uint8_t *buffer) {
void opt_output(const uint8_t *k, State *s, uint8_t *buffer)
{
uint8_t times = 0;
uint8_t bout = 0;
State temp = {0,0,0,0};
for ( ; times < 4; times++) {
bout =0;
State temp = {0, 0, 0, 0};
for (; times < 4; times++) {
bout = 0;
bout |= (s->r & 0x4) << 5;
opt_successor(k, s, 0, &temp);
bout |= (temp.r & 0x4) << 4;
@ -174,7 +177,8 @@ void opt_output(const uint8_t* k,State* s, uint8_t *buffer) {
}
}
void opt_MAC(uint8_t* k, uint8_t* input, uint8_t* out) {
void opt_MAC(uint8_t *k, uint8_t *input, uint8_t *out)
{
State _init = {
((k[0] ^ 0x4c) + 0xEC) & 0xFF,// l
((k[0] ^ 0x4c) + 0x21) & 0xFF,// r
@ -182,34 +186,38 @@ void opt_MAC(uint8_t* k, uint8_t* input, uint8_t* out) {
0xE012 // t
};
opt_suc(k,&_init,input,12, false);
opt_output(k,&_init, out);
opt_suc(k, &_init, input, 12, false);
opt_output(k, &_init, out);
}
uint8_t rev_byte(uint8_t b) {
uint8_t rev_byte(uint8_t b)
{
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
return b;
}
void opt_reverse_arraybytecpy(uint8_t* dest, uint8_t *src, size_t len) {
void opt_reverse_arraybytecpy(uint8_t *dest, uint8_t *src, size_t len)
{
uint8_t i;
for ( i =0; i< len ; i++)
for (i = 0; i < len ; i++)
dest[i] = rev_byte(src[i]);
}
void opt_doReaderMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]) {
void opt_doReaderMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4])
{
static uint8_t cc_nr[12];
opt_reverse_arraybytecpy(cc_nr, cc_nr_p, 12);
uint8_t dest [] = {0,0,0,0,0,0,0,0};
uint8_t dest [] = {0, 0, 0, 0, 0, 0, 0, 0};
opt_MAC(div_key_p, cc_nr, dest);
//The output MAC must also be reversed
opt_reverse_arraybytecpy(mac, dest, 4);
return;
}
void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]) {
static uint8_t cc_nr[8+4+4];
void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4])
{
static uint8_t cc_nr[8 + 4 + 4];
opt_reverse_arraybytecpy(cc_nr, cc_p, 12);
State _init = {
((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l
@ -218,10 +226,10 @@ void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]) {
0xE012 // t
};
opt_suc(div_key_p, &_init, cc_nr, 12, true);
uint8_t dest [] = {0,0,0,0};
uint8_t dest [] = {0, 0, 0, 0};
opt_output(div_key_p, &_init, dest);
//The output MAC must also be reversed
opt_reverse_arraybytecpy(mac, dest,4);
opt_reverse_arraybytecpy(mac, dest, 4);
return;
}
@ -233,7 +241,8 @@ void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]) {
* @param div_key_p
* @return the cipher state
*/
State opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p) {
State opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p)
{
static uint8_t cc_nr[8];
opt_reverse_arraybytecpy(cc_nr, cc_p, 8);
State _init = {
@ -254,14 +263,15 @@ State opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p) {
* @param mac - where to store the MAC
* @param div_key_p - the key to use
*/
void opt_doTagMAC_2(State _init, uint8_t* nr, uint8_t mac[4], const uint8_t* div_key_p) {
void opt_doTagMAC_2(State _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p)
{
static uint8_t _nr[4];
opt_reverse_arraybytecpy(_nr, nr, 4);
opt_suc(div_key_p, &_init,_nr, 4, true);
opt_suc(div_key_p, &_init, _nr, 4, true);
uint8_t dest [] = {0,0,0,0};
uint8_t dest [] = {0, 0, 0, 0};
opt_output(div_key_p, &_init, dest);
//The output MAC must also be reversed
opt_reverse_arraybytecpy(mac, dest,4);
opt_reverse_arraybytecpy(mac, dest, 4);
return;
}

View file

@ -46,6 +46,6 @@ State opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p);
* @param mac - where to store the MAC
* @param div_key_p - the key to use
*/
void opt_doTagMAC_2(State _init, uint8_t* nr, uint8_t mac[4], const uint8_t* div_key_p);
void opt_doTagMAC_2(State _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p);
#endif // OPTIMIZED_CIPHER_H

View file

@ -3,13 +3,14 @@
#define T0_PCF 8 //period for the pcf7931 in us
#define ALLOC 16
size_t DemodPCF7931(uint8_t **outBlocks) {
size_t DemodPCF7931(uint8_t **outBlocks)
{
uint8_t bits[256] = {0x00};
uint8_t blocks[8][16];
uint8_t *dest = BigBuf_get_addr();
int GraphTraceLen = BigBuf_max_traceLen();
if ( GraphTraceLen > 18000 )
if (GraphTraceLen > 18000)
GraphTraceLen = 18000;
int i, j, lastval, bitidx, half_switch;
@ -18,7 +19,7 @@ size_t DemodPCF7931(uint8_t **outBlocks) {
int pmc, block_done;
int lc, warnings = 0;
size_t num_blocks = 0;
int lmin=128, lmax=128;
int lmin = 128, lmax = 128;
uint8_t dir;
//clear read buffer
BigBuf_Clear_keep_EM();
@ -32,16 +33,16 @@ size_t DemodPCF7931(uint8_t **outBlocks) {
i = 2;
/* Find first local max/min */
if(dest[1] > dest[0]) {
while(i < GraphTraceLen) {
if( !(dest[i] > dest[i-1]) && dest[i] > lmax)
if (dest[1] > dest[0]) {
while (i < GraphTraceLen) {
if (!(dest[i] > dest[i - 1]) && dest[i] > lmax)
break;
i++;
}
dir = 0;
} else {
while(i < GraphTraceLen) {
if( !(dest[i] < dest[i-1]) && dest[i] < lmin)
while (i < GraphTraceLen) {
if (!(dest[i] < dest[i - 1]) && dest[i] < lmin)
break;
i++;
}
@ -54,38 +55,37 @@ size_t DemodPCF7931(uint8_t **outBlocks) {
block_done = 0;
for (bitidx = 0; i < GraphTraceLen; i++) {
if ((dest[i-1] > dest[i] && dir == 1 && dest[i] > lmax) || (dest[i-1] < dest[i] && dir == 0 && dest[i] < lmin)) {
if ((dest[i - 1] > dest[i] && dir == 1 && dest[i] > lmax) || (dest[i - 1] < dest[i] && dir == 0 && dest[i] < lmin)) {
lc = i - lastval;
lastval = i;
// Switch depending on lc length:
// Tolerance is 1/8 of clock rate (arbitrary)
if (ABS(lc-clock/4) < tolerance) {
if (ABS(lc - clock / 4) < tolerance) {
// 16T0
if((i - pmc) == lc) { /* 16T0 was previous one */
if ((i - pmc) == lc) { /* 16T0 was previous one */
/* It's a PMC ! */
i += (128+127+16+32+33+16)-1;
i += (128 + 127 + 16 + 32 + 33 + 16) - 1;
lastval = i;
pmc = 0;
block_done = 1;
} else {
pmc = i;
}
} else if (ABS(lc-clock/2) < tolerance) {
} else if (ABS(lc - clock / 2) < tolerance) {
// 32TO
if((i - pmc) == lc) { /* 16T0 was previous one */
if ((i - pmc) == lc) { /* 16T0 was previous one */
/* It's a PMC ! */
i += (128+127+16+32+33)-1;
i += (128 + 127 + 16 + 32 + 33) - 1;
lastval = i;
pmc = 0;
block_done = 1;
} else if(half_switch == 1) {
} else if (half_switch == 1) {
bits[bitidx++] = 0;
half_switch = 0;
}
else
} else
half_switch++;
} else if (ABS(lc-clock) < tolerance) {
} else if (ABS(lc - clock) < tolerance) {
// 64TO
bits[bitidx++] = 1;
} else {
@ -96,18 +96,18 @@ size_t DemodPCF7931(uint8_t **outBlocks) {
}
}
if(block_done == 1) {
if(bitidx == 128) {
for(j = 0; j < 16; ++j) {
if (block_done == 1) {
if (bitidx == 128) {
for (j = 0; j < 16; ++j) {
blocks[num_blocks][j] =
128 * bits[j*8 + 7]+
64*bits[j*8+6]+
32*bits[j*8+5]+
16*bits[j*8+4]+
8*bits[j*8+3]+
4*bits[j*8+2]+
2*bits[j*8+1]+
bits[j*8]
128 * bits[j * 8 + 7] +
64 * bits[j * 8 + 6] +
32 * bits[j * 8 + 5] +
16 * bits[j * 8 + 4] +
8 * bits[j * 8 + 3] +
4 * bits[j * 8 + 2] +
2 * bits[j * 8 + 1] +
bits[j * 8]
;
}
num_blocks++;
@ -116,44 +116,44 @@ size_t DemodPCF7931(uint8_t **outBlocks) {
block_done = 0;
half_switch = 0;
}
if(i < GraphTraceLen)
dir =(dest[i-1] > dest[i]) ? 0 : 1;
if (i < GraphTraceLen)
dir = (dest[i - 1] > dest[i]) ? 0 : 1;
}
if(bitidx==255)
bitidx=0;
if (bitidx == 255)
bitidx = 0;
warnings = 0;
if(num_blocks == 4) break;
if (num_blocks == 4) break;
}
memcpy(outBlocks, blocks, 16*num_blocks);
memcpy(outBlocks, blocks, 16 * num_blocks);
return num_blocks;
}
bool IsBlock0PCF7931(uint8_t *block) {
bool IsBlock0PCF7931(uint8_t *block)
{
// assuming all RFU bits are set to 0
// if PAC is enabled password is set to 0
if (block[7] == 0x01)
{
if (!memcmp(block, "\x00\x00\x00\x00\x00\x00\x00", 7) && !memcmp(block+9, "\x00\x00\x00\x00\x00\x00\x00", 7))
if (block[7] == 0x01) {
if (!memcmp(block, "\x00\x00\x00\x00\x00\x00\x00", 7) && !memcmp(block + 9, "\x00\x00\x00\x00\x00\x00\x00", 7))
return true;
}
else if (block[7] == 0x00)
{
if (!memcmp(block+9, "\x00\x00\x00\x00\x00\x00\x00", 7))
} else if (block[7] == 0x00) {
if (!memcmp(block + 9, "\x00\x00\x00\x00\x00\x00\x00", 7))
return true;
}
return false;
}
bool IsBlock1PCF7931(uint8_t *block) {
bool IsBlock1PCF7931(uint8_t *block)
{
// assuming all RFU bits are set to 0
if (block[10] == 0 && block[11] == 0 && block[12] == 0 && block[13] == 0)
if((block[14] & 0x7f) <= 9 && block[15] <= 9)
if ((block[14] & 0x7f) <= 9 && block[15] <= 9)
return true;
return false;
}
void ReadPCF7931() {
void ReadPCF7931()
{
int found_blocks = 0; // successfully read blocks
int max_blocks = 8; // readable blocks
uint8_t memory_blocks[8][17]; // PCF content
@ -168,17 +168,17 @@ void ReadPCF7931() {
int errors = 0; // error counter
int tries = 0; // tries counter
memset(memory_blocks, 0, 8*17*sizeof(uint8_t));
memset(single_blocks, 0, 8*17*sizeof(uint8_t));
memset(memory_blocks, 0, 8 * 17 * sizeof(uint8_t));
memset(single_blocks, 0, 8 * 17 * sizeof(uint8_t));
int i = 0, j = 0;
do {
i = 0;
memset(tmp_blocks, 0, 4*16*sizeof(uint8_t));
n = DemodPCF7931((uint8_t**)tmp_blocks);
if(!n)
memset(tmp_blocks, 0, 4 * 16 * sizeof(uint8_t));
n = DemodPCF7931((uint8_t **)tmp_blocks);
if (!n)
++errors;
// exit if no block is received
@ -187,7 +187,7 @@ void ReadPCF7931() {
return;
}
// exit if too many errors during reading
if (tries > 50 && (2*errors > tries)) {
if (tries > 50 && (2 * errors > tries)) {
Dbprintf("Error reading the tag");
Dbprintf("Here is the partial content");
goto end;
@ -218,12 +218,12 @@ void ReadPCF7931() {
Dbprintf("(dbg) got %d blocks (%d/%d found) (%d tries, %d errors)", n, found_blocks, (max_blocks == 0 ? found_blocks : max_blocks), tries, errors);
i = 0;
if(!found_0_1) {
if (!found_0_1) {
while (i < n - 1) {
if (IsBlock0PCF7931(tmp_blocks[i]) && IsBlock1PCF7931(tmp_blocks[i+1])) {
if (IsBlock0PCF7931(tmp_blocks[i]) && IsBlock1PCF7931(tmp_blocks[i + 1])) {
found_0_1 = 1;
memcpy(memory_blocks[0], tmp_blocks[i], 16);
memcpy(memory_blocks[1], tmp_blocks[i+1], 16);
memcpy(memory_blocks[1], tmp_blocks[i + 1], 16);
memory_blocks[0][ALLOC] = memory_blocks[1][ALLOC] = 1;
// block 1 tells how many blocks are going to be sent
max_blocks = MAX((memory_blocks[1][14] & 0x7f), memory_blocks[1][15]) + 1;
@ -244,26 +244,26 @@ void ReadPCF7931() {
} else {
// Trying to re-order blocks
// Look for identical block in memory blocks
while (i < n-1) {
while (i < n - 1) {
// skip all zeroes blocks
if (memcmp(tmp_blocks[i], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) {
for (j = 1; j < max_blocks - 1; ++j) {
if (!memcmp(tmp_blocks[i], memory_blocks[j], 16) && !memory_blocks[j+1][ALLOC]) {
memcpy(memory_blocks[j+1], tmp_blocks[i+1], 16);
memory_blocks[j+1][ALLOC] = 1;
if (!memcmp(tmp_blocks[i], memory_blocks[j], 16) && !memory_blocks[j + 1][ALLOC]) {
memcpy(memory_blocks[j + 1], tmp_blocks[i + 1], 16);
memory_blocks[j + 1][ALLOC] = 1;
if (++found_blocks >= max_blocks) goto end;
}
}
}
if (memcmp(tmp_blocks[i+1], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) {
if (memcmp(tmp_blocks[i + 1], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) {
for (j = 0; j < max_blocks; ++j) {
if (!memcmp(tmp_blocks[i+1], memory_blocks[j], 16) && !memory_blocks[(j == 0 ? max_blocks : j) -1][ALLOC]) {
if (!memcmp(tmp_blocks[i + 1], memory_blocks[j], 16) && !memory_blocks[(j == 0 ? max_blocks : j) - 1][ALLOC]) {
if (j == 0) {
memcpy(memory_blocks[max_blocks - 1], tmp_blocks[i], 16);
memory_blocks[max_blocks - 1][ALLOC] = 1;
} else {
memcpy(memory_blocks[j-1], tmp_blocks[i], 16);
memory_blocks[j-1][ALLOC] = 1;
memcpy(memory_blocks[j - 1], tmp_blocks[i], 16);
memory_blocks[j - 1][ALLOC] = 1;
}
if (++found_blocks >= max_blocks) goto end;
}
@ -277,10 +277,9 @@ void ReadPCF7931() {
Dbprintf("Button pressed, stopping.");
goto end;
}
}
while (found_blocks != max_blocks);
} while (found_blocks != max_blocks);
end:
end:
Dbprintf("-----------------------------------------");
Dbprintf("Memory content:");
Dbprintf("-----------------------------------------");
@ -301,10 +300,11 @@ void ReadPCF7931() {
Dbprintf("-----------------------------------------");
}
cmd_send(CMD_ACK,0,0,0,0,0);
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
}
static void RealWritePCF7931(uint8_t *pass, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) {
static void RealWritePCF7931(uint8_t *pass, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data)
{
uint32_t tab[1024] = {0}; // data times frame
uint32_t u = 0;
uint8_t parity = 0;
@ -312,8 +312,8 @@ static void RealWritePCF7931(uint8_t *pass, uint16_t init_delay, int32_t l, int3
//BUILD OF THE DATA FRAME
//alimentation of the tag (time for initializing)
AddPatternPCF7931(init_delay, 0, 8192/2*T0_PCF, tab);
AddPatternPCF7931(8192/2*T0_PCF + 319*T0_PCF+70, 3*T0_PCF, 29*T0_PCF, tab);
AddPatternPCF7931(init_delay, 0, 8192 / 2 * T0_PCF, tab);
AddPatternPCF7931(8192 / 2 * T0_PCF + 319 * T0_PCF + 70, 3 * T0_PCF, 29 * T0_PCF, tab);
//password indication bit
AddBitPCF7931(1, tab, l, p);
//password (on 56 bits)
@ -329,33 +329,29 @@ static void RealWritePCF7931(uint8_t *pass, uint16_t init_delay, int32_t l, int3
//block adress on 6 bits
for (u = 0; u < 6; ++u) {
if (address&(1<<u)) { // bit 1
if (address & (1 << u)) { // bit 1
++parity;
AddBitPCF7931(1, tab, l, p);
} else{ // bit 0
} else { // bit 0
AddBitPCF7931(0, tab, l, p);
}
}
//byte address on 4 bits
for (u = 0; u < 4; ++u)
{
if (byte&(1<<u)) { // bit 1
for (u = 0; u < 4; ++u) {
if (byte & (1 << u)) { // bit 1
parity++;
AddBitPCF7931(1, tab, l, p);
}
else // bit 0
} else // bit 0
AddBitPCF7931(0, tab, l, p);
}
//data on 8 bits
for (u=0; u<8; u++)
{
if (data&(1<<u)) { // bit 1
for (u = 0; u < 8; u++) {
if (data & (1 << u)) { // bit 1
parity++;
AddBitPCF7931(1, tab, l, p);
}
else //bit 0
} else //bit 0
AddBitPCF7931(0, tab, l, p);
}
@ -366,17 +362,17 @@ static void RealWritePCF7931(uint8_t *pass, uint16_t init_delay, int32_t l, int3
AddBitPCF7931(1, tab, l, p);//odd parity
//time access memory
AddPatternPCF7931(5120+2680, 0, 0, tab);
AddPatternPCF7931(5120 + 2680, 0, 0, tab);
//conversion of the scale time
for (u = 0; u < 500; ++u)
tab[u]=(tab[u] * 3)/2;
tab[u] = (tab[u] * 3) / 2;
//compensation of the counter reload
while (!comp){
while (!comp) {
comp = 1;
for (u = 0; tab[u] != 0; ++u)
if(tab[u] > 0xFFFF){
if (tab[u] > 0xFFFF) {
tab[u] -= 0xFFFF;
comp = 0;
}
@ -390,7 +386,8 @@ static void RealWritePCF7931(uint8_t *pass, uint16_t init_delay, int32_t l, int3
@param byte : address of the byte to write
@param data : data to write
*/
void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) {
void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data)
{
Dbprintf("Initialization delay : %d us", init_delay);
Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p);
Dbprintf("Password (LSB first on each byte): %02x %02x %02x %02x %02x %02x %02x", pass1, pass2, pass3, pass4, pass5, pass6, pass7);
@ -400,7 +397,7 @@ void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, ui
uint8_t password[7] = {pass1, pass2, pass3, pass4, pass5, pass6, pass7};
RealWritePCF7931 (password, init_delay, l, p, address, byte, data);
RealWritePCF7931(password, init_delay, l, p, address, byte, data);
}
@ -408,14 +405,15 @@ void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, ui
* @param tab : array of the data frame
*/
void SendCmdPCF7931(uint32_t * tab){
uint16_t u=0, tempo=0;
void SendCmdPCF7931(uint32_t *tab)
{
uint16_t u = 0, tempo = 0;
Dbprintf("Sending data frame...");
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU );
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);
LED_A_ON();
@ -432,7 +430,7 @@ void SendCmdPCF7931(uint32_t * tab){
AT91C_BASE_TCB->TCB_BCR = 1;
tempo = AT91C_BASE_TC0->TC_CV;
for( u = 0; tab[u] != 0; u += 3){
for (u = 0; tab[u] != 0; u += 3) {
// modulate antenna
HIGH(GPIO_SSC_DOUT);
while (tempo != tab[u])
@ -440,12 +438,12 @@ void SendCmdPCF7931(uint32_t * tab){
// stop modulating antenna
LOW(GPIO_SSC_DOUT);
while (tempo != tab[u+1])
while (tempo != tab[u + 1])
tempo = AT91C_BASE_TC0->TC_CV;
// modulate antenna
HIGH(GPIO_SSC_DOUT);
while (tempo != tab[u+2])
while (tempo != tab[u + 2])
tempo = AT91C_BASE_TC0->TC_CV;
}
@ -464,13 +462,14 @@ void SendCmdPCF7931(uint32_t * tab){
* @param l : offset on low pulse width
* @param p : offset on low pulse positioning
*/
bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p){
bool AddBytePCF7931(uint8_t byte, uint32_t *tab, int32_t l, int32_t p)
{
uint32_t u;
for (u = 0; u < 8; ++u) {
if (byte & (1 << u)) { //bit is 1
if( AddBitPCF7931(1, tab, l, p)==1) return 1;
if (AddBitPCF7931(1, tab, l, p) == 1) return 1;
} else { //bit is 0
if (AddBitPCF7931(0, tab, l, p)==1) return 1;
if (AddBitPCF7931(0, tab, l, p) == 1) return 1;
}
}
@ -483,30 +482,31 @@ bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p){
* @param l : offset on low pulse width
* @param p : offset on low pulse positioning
*/
bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p){
bool AddBitPCF7931(bool b, uint32_t *tab, int32_t l, int32_t p)
{
uint8_t u = 0;
//we put the cursor at the last value of the array
for ( u = 0; tab[u] != 0; u += 3 ) { }
for (u = 0; tab[u] != 0; u += 3) { }
if ( b == 1 ) { //add a bit 1
if ( u == 0 )
if (b == 1) { //add a bit 1
if (u == 0)
tab[u] = 34 * T0_PCF + p;
else
tab[u] = 34 * T0_PCF + tab[u-1] + p;
tab[u] = 34 * T0_PCF + tab[u - 1] + p;
tab[u+1] = 6 * T0_PCF + tab[u] + l;
tab[u+2] = 88 * T0_PCF + tab[u+1] - l - p;
tab[u + 1] = 6 * T0_PCF + tab[u] + l;
tab[u + 2] = 88 * T0_PCF + tab[u + 1] - l - p;
return 0;
} else { //add a bit 0
if ( u == 0 )
if (u == 0)
tab[u] = 98 * T0_PCF + p;
else
tab[u] = 98 * T0_PCF + tab[u-1] + p;
tab[u] = 98 * T0_PCF + tab[u - 1] + p;
tab[u+1] = 6 * T0_PCF + tab[u] + l;
tab[u+2] = 24 * T0_PCF + tab[u+1] - l - p;
tab[u + 1] = 6 * T0_PCF + tab[u] + l;
tab[u + 2] = 24 * T0_PCF + tab[u + 1] - l - p;
return 0;
}
return 1;
@ -518,13 +518,14 @@ bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p){
* @param c : delay of the last high pulse
* @param tab : array of the data frame
*/
bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab){
bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t *tab)
{
uint32_t u = 0;
for(u = 0; tab[u] != 0; u += 3){} //we put the cursor at the last value of the array
for (u = 0; tab[u] != 0; u += 3) {} //we put the cursor at the last value of the array
tab[u] = (u == 0) ? a : a + tab[u-1];
tab[u+1] = b + tab[u];
tab[u+2] = c + tab[u+1];
tab[u] = (u == 0) ? a : a + tab[u - 1];
tab[u + 1] = b + tab[u];
tab[u + 2] = c + tab[u + 1];
return 0;
}

View file

@ -11,10 +11,10 @@ size_t DemodPCF7931(uint8_t **outBlocks);
bool IsBlock0PCF7931(uint8_t *Block);
bool IsBlock1PCF7931(uint8_t *Block);
void ReadPCF7931();
void SendCmdPCF7931(uint32_t * tab);
bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p);
bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p);
bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab);
void SendCmdPCF7931(uint32_t *tab);
bool AddBytePCF7931(uint8_t byte, uint32_t *tab, int32_t l, int32_t p);
bool AddBitPCF7931(bool b, uint32_t *tab, int32_t l, int32_t p);
bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t *tab);
void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data);
#endif

View file

@ -128,16 +128,28 @@ kvsprintf(char const *fmt, void *arg, int radix, va_list ap)
for (;;) {
padc = ' ';
width = 0;
while ((ch = (u_char)*fmt++) != '%' || stop) {
while ((ch = (u_char) * fmt++) != '%' || stop) {
PCHAR(ch);
if (ch == '\0')
return (retval);
}
percent = fmt - 1;
qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
sign = 0; dot = 0; dwidth = 0; upper = 0;
cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
reswitch: switch (ch = (u_char)*fmt++) {
qflag = 0;
lflag = 0;
ladjust = 0;
sharpflag = 0;
neg = 0;
sign = 0;
dot = 0;
dwidth = 0;
upper = 0;
cflag = 0;
hflag = 0;
jflag = 0;
tflag = 0;
zflag = 0;
reswitch:
switch (ch = (u_char) * fmt++) {
case '.':
dot = 1;
goto reswitch;
@ -169,8 +181,15 @@ reswitch: switch (ch = (u_char)*fmt++) {
padc = '0';
goto reswitch;
}
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
for (n = 0;; ++fmt) {
n = n * 10 + ch - '0';
ch = *fmt;
@ -213,12 +232,12 @@ reswitch: switch (ch = (u_char)*fmt++) {
p = va_arg(ap, char *);
if (!width)
width = 16;
while(width--) {
while (width--) {
PCHAR(hex2ascii(*up >> 4));
PCHAR(hex2ascii(*up & 0x0f));
up++;
if (width)
for (q=p;*q;q++)
for (q = p; *q; q++)
PCHAR(*q);
}
break;
@ -282,7 +301,7 @@ reswitch: switch (ch = (u_char)*fmt++) {
if (p == NULL)
p = "(null)";
if (!dot)
n = strlen (p);
n = strlen(p);
else
for (n = 0; n < dwidth && p[n]; n++)
continue;

View file

@ -15,8 +15,8 @@
#include <stddef.h>
#include "string.h"
int kvsprintf(const char *format, void *arg, int radix, va_list ap) __attribute__ ((format (printf, 1, 0)));
int vsprintf(char *str, const char *format, va_list ap) __attribute__ ((format (printf, 2, 0)));
int sprintf(char *str, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
int kvsprintf(const char *format, void *arg, int radix, va_list ap) __attribute__((format(printf, 1, 0)));
int vsprintf(char *str, const char *format, va_list ap) __attribute__((format(printf, 2, 0)));
int sprintf(char *str, const char *format, ...) __attribute__((format(printf, 2, 3)));
#endif

View file

@ -26,7 +26,7 @@ static voidpf inflate_malloc(voidpf opaque, uInt items, uInt size)
uint8_t *allocated_memory;
allocated_memory = next_free_memory;
next_free_memory += items*size;
next_free_memory += items * size;
return allocated_memory;
}
@ -71,7 +71,7 @@ void __attribute__((section(".startos"))) Vector(void)
/* Set up (that is: clear) BSS. */
dst = &__bss_start__;
end = &__bss_end__;
while(dst < end) *dst++ = 0;
while (dst < end) *dst++ = 0;
// Set up data segment: Copy from flash to ram
// src = &__data_src_start__;

View file

@ -13,7 +13,7 @@ void *memcpy(void *dest, const void *src, int len)
{
uint8_t *d = dest;
const uint8_t *s = src;
while((len--) > 0) {
while ((len--) > 0) {
*d = *s;
d++;
s++;
@ -24,7 +24,7 @@ void *memcpy(void *dest, const void *src, int len)
void *memset(void *dest, int c, int len)
{
uint8_t *d = dest;
while((len--) > 0) {
while ((len--) > 0) {
*d = c;
d++;
}
@ -36,8 +36,8 @@ int memcmp(const void *av, const void *bv, int len)
const uint8_t *a = av;
const uint8_t *b = bv;
while((len--) > 0) {
if(*a != *b) {
while ((len--) > 0) {
if (*a != *b) {
return *a - *b;
}
a++;
@ -46,22 +46,23 @@ int memcmp(const void *av, const void *bv, int len)
return 0;
}
void memxor(uint8_t * dest, uint8_t * src, size_t len) {
for( ; len > 0; len--,dest++,src++)
void memxor(uint8_t *dest, uint8_t *src, size_t len)
{
for (; len > 0; len--, dest++, src++)
*dest ^= *src;
}
int strlen(const char *str)
{
int l = 0;
while(*str) {
while (*str) {
l++;
str++;
}
return l;
}
char* strncat(char *dest, const char *src, unsigned int n)
char *strncat(char *dest, const char *src, unsigned int n)
{
unsigned int dest_len = strlen(dest);
unsigned int i;
@ -73,7 +74,7 @@ char* strncat(char *dest, const char *src, unsigned int n)
return dest;
}
char* strcat(char *dest, const char *src)
char *strcat(char *dest, const char *src)
{
unsigned int dest_len = strlen(dest);
unsigned int i;
@ -91,7 +92,7 @@ void strreverse(char s[])
{
int c, i, j;
for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
for (i = 0, j = strlen(s) - 1; i < j; i++, j--) {
c = s[i];
s[i] = s[j];
s[j] = c;

View file

@ -18,7 +18,7 @@ int strlen(const char *str);
void *memcpy(void *dest, const void *src, int len);
void *memset(void *dest, int c, int len);
int memcmp(const void *av, const void *bv, int len);
void memxor(uint8_t * dest, uint8_t * src, size_t 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);
void strreverse(char s[]);

View file

@ -11,7 +11,8 @@
#include "ticks.h"
// attempt at high resolution microsecond timer
// beware: timer counts in 21.3uS increments (1024/48Mhz)
void SpinDelayUs(int us) {
void SpinDelayUs(int us)
{
int ticks = (48 * us) >> 10;
// Borrow a PWM unit for my real-time clock
@ -24,7 +25,7 @@ void SpinDelayUs(int us) {
uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
for(;;) {
for (;;) {
uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
if (now == (uint16_t)(start + ticks))
return;
@ -33,9 +34,10 @@ void SpinDelayUs(int us) {
}
}
void SpinDelay(int ms) {
void SpinDelay(int ms)
{
// convert to uS and call microsecond delay function
SpinDelayUs(ms*1000);
SpinDelayUs(ms * 1000);
}
// -------------------------------------------------------------------------
// timer lib
@ -46,26 +48,29 @@ void SpinDelay(int ms) {
// SpinDelay(1000);
// ti = GetTickCount() - ti;
// Dbprintf("timer(1s): %d t=%d", ti, GetTickCount());
void StartTickCount(void) {
void StartTickCount(void)
{
// This timer is based on the slow clock. The slow clock frequency is between 22kHz and 40kHz.
// We can determine the actual slow clock frequency by looking at the Main Clock Frequency Register.
uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & 0xffff; // = 16 * main clock frequency (16MHz) / slow clock frequency
// set RealTimeCounter divider to count at 1kHz:
AT91C_BASE_RTTC->RTTC_RTMR = AT91C_RTTC_RTTRST | ((256000 + (mainf/2)) / mainf);
AT91C_BASE_RTTC->RTTC_RTMR = AT91C_RTTC_RTTRST | ((256000 + (mainf / 2)) / mainf);
// note: worst case precision is approx 2.5%
}
/*
* Get the current count.
*/
uint32_t RAMFUNC GetTickCount(void){
uint32_t RAMFUNC GetTickCount(void)
{
return AT91C_BASE_RTTC->RTTC_RTVR;// was * 2;
}
// -------------------------------------------------------------------------
// microseconds timer
// -------------------------------------------------------------------------
void StartCountUS(void) {
void StartCountUS(void)
{
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1);
AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
@ -88,7 +93,8 @@ void StartCountUS(void) {
while (AT91C_BASE_TC1->TC_CV > 0);
}
uint32_t RAMFUNC GetCountUS(void){
uint32_t RAMFUNC GetCountUS(void)
{
//return (AT91C_BASE_TC1->TC_CV * 0x8000) + ((AT91C_BASE_TC0->TC_CV / 15) * 10);
// By suggestion from PwPiwi, http://www.proxmark.org/forum/viewtopic.php?pid=17548#p17548
return ((uint32_t)AT91C_BASE_TC1->TC_CV) * 0x8000 + (((uint32_t)AT91C_BASE_TC0->TC_CV) * 2) / 3;
@ -97,7 +103,8 @@ uint32_t RAMFUNC GetCountUS(void){
// -------------------------------------------------------------------------
// Timer for iso14443 commands. Uses ssp_clk from FPGA
// -------------------------------------------------------------------------
void StartCountSspClk(void) {
void StartCountSspClk(void)
{
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1) | (1 << AT91C_ID_TC2); // Enable Clock to all timers
AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_TIOA1 // XC0 Clock = TIOA1
| AT91C_TCB_TC1XC1S_NONE // XC1 Clock = none
@ -138,9 +145,9 @@ void StartCountSspClk(void) {
// synchronize the counter with the ssp_frame signal.
// Note: FPGA must be in any iso14443 mode, otherwise the frame signal would not be present
while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME)); // wait for ssp_frame to go high (start of frame)
while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME); // wait for ssp_frame to be low
while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)); // wait for ssp_clk to go high
while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME)); // wait for ssp_frame to go high (start of frame)
while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME); // wait for ssp_frame to be low
while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)); // wait for ssp_clk to go high
// note: up to now two ssp_clk rising edges have passed since the rising edge of ssp_frame
// it is now safe to assert a sync signal. This sets all timers to 0 on next active clock edge
@ -154,14 +161,16 @@ void StartCountSspClk(void) {
// Therefore need to wait quite some time before we can use the counter.
while (AT91C_BASE_TC2->TC_CV > 0);
}
void ResetSspClk(void) {
void ResetSspClk(void)
{
//enable clock of timer and software trigger
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
while (AT91C_BASE_TC2->TC_CV > 0);
}
uint32_t RAMFUNC GetCountSspClk(void) {
uint32_t RAMFUNC GetCountSspClk(void)
{
uint32_t tmp_count = (AT91C_BASE_TC2->TC_CV << 16) | AT91C_BASE_TC0->TC_CV;
if ((tmp_count & 0x0000ffff) == 0) //small chance that we may have missed an increment in TC2
return (AT91C_BASE_TC2->TC_CV << 16);
@ -172,7 +181,8 @@ uint32_t RAMFUNC GetCountSspClk(void) {
// Timer for bitbanging, or LF stuff when you need a very precis timer
// 1us = 1.5ticks
// -------------------------------------------------------------------------
void StartTicks(void){
void StartTicks(void)
{
// initialization of the timer
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1);
AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
@ -205,36 +215,41 @@ void StartTicks(void){
while (AT91C_BASE_TC0->TC_CV > 0);
}
uint32_t GetTicks(void) {
uint32_t GetTicks(void)
{
uint32_t hi, lo;
do {
hi = AT91C_BASE_TC1->TC_CV;
lo = AT91C_BASE_TC0->TC_CV;
} while(hi != AT91C_BASE_TC1->TC_CV);
} while (hi != AT91C_BASE_TC1->TC_CV);
return (hi << 16) | lo;
}
// Wait - Spindelay in ticks.
// if called with a high number, this will trigger the WDT...
void WaitTicks(uint32_t ticks){
if ( ticks == 0 ) return;
void WaitTicks(uint32_t ticks)
{
if (ticks == 0) return;
ticks += GetTicks();
while (GetTicks() < ticks);
}
// Wait / Spindelay in us (microseconds)
// 1us = 1.5ticks.
void WaitUS(uint16_t us){
WaitTicks( (uint32_t)us * 3/2 );
void WaitUS(uint16_t us)
{
WaitTicks((uint32_t)us * 3 / 2);
}
void WaitMS(uint16_t ms){
WaitTicks( (uint32_t)ms * 1500 );
void WaitMS(uint16_t ms)
{
WaitTicks((uint32_t)ms * 1500);
}
// stop clock
void StopTicks(void){
void StopTicks(void)
{
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
}

View file

@ -9,8 +9,9 @@
//-----------------------------------------------------------------------------
#include "util.h"
size_t nbytes(size_t nbits) {
return (nbits >> 3)+((nbits % 8) > 0);
size_t nbytes(size_t nbits)
{
return (nbits >> 3) + ((nbits % 8) > 0);
}
/*
@ -18,22 +19,25 @@ size_t nbytes(size_t nbits) {
Returns the value v with the bottom b [0,32] bits reflected.
Example: reflect(0x3e23L,3) == 0x3e26
*/
uint32_t reflect(uint32_t v, int b) {
uint32_t reflect(uint32_t v, int b)
{
uint32_t t = v;
for ( int i = 0; i < b; ++i) {
for (int i = 0; i < b; ++i) {
if (t & 1)
v |= BITMASK((b-1)-i);
v |= BITMASK((b - 1) - i);
else
v &= ~BITMASK((b-1)-i);
t>>=1;
v &= ~BITMASK((b - 1) - i);
t >>= 1;
}
return v;
}
uint8_t reflect8(uint8_t b) {
uint8_t reflect8(uint8_t b)
{
return ((b * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
}
uint16_t reflect16(uint16_t b) {
uint16_t reflect16(uint16_t b)
{
uint16_t v = 0;
v |= (b & 0x8000) >> 15;
v |= (b & 0x4000) >> 13;
@ -55,14 +59,16 @@ uint16_t reflect16(uint16_t b) {
return v;
}
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest) {
void num_to_bytes(uint64_t n, size_t len, uint8_t *dest)
{
while (len--) {
dest[len] = (uint8_t) n;
n >>= 8;
}
}
uint64_t bytes_to_num(uint8_t* src, size_t len) {
uint64_t bytes_to_num(uint8_t *src, size_t len)
{
uint64_t num = 0;
while (len--) {
num = (num << 8) | (*src);
@ -72,56 +78,93 @@ uint64_t bytes_to_num(uint8_t* src, size_t len) {
}
// RotateLeft - Ultralight, Desfire
void rol(uint8_t *data, const size_t len) {
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];
for (size_t i = 0; i < len - 1; i++) {
data[i] = data[i + 1];
}
data[len-1] = first;
data[len - 1] = first;
}
void lsl (uint8_t *data, size_t len) {
void lsl(uint8_t *data, size_t len)
{
for (size_t n = 0; n < len - 1; n++) {
data[n] = (data[n] << 1) | (data[n+1] >> 7);
data[n] = (data[n] << 1) | (data[n + 1] >> 7);
}
data[len - 1] <<= 1;
}
int32_t le24toh (uint8_t data[3]) {
int32_t le24toh(uint8_t data[3])
{
return (data[2] << 16) | (data[1] << 8) | data[0];
}
//convert hex digit to integer
uint8_t hex2int(char hexchar){
switch(hexchar){
case '0': return 0; break;
case '1': return 1; break;
case '2': return 2; break;
case '3': return 3; break;
case '4': return 4; break;
case '5': return 5; break;
case '6': return 6; break;
case '7': return 7; break;
case '8': return 8; break;
case '9': return 9; break;
uint8_t hex2int(char hexchar)
{
switch (hexchar) {
case '0':
return 0;
break;
case '1':
return 1;
break;
case '2':
return 2;
break;
case '3':
return 3;
break;
case '4':
return 4;
break;
case '5':
return 5;
break;
case '6':
return 6;
break;
case '7':
return 7;
break;
case '8':
return 8;
break;
case '9':
return 9;
break;
case 'a':
case 'A': return 10; break;
case 'A':
return 10;
break;
case 'b':
case 'B': return 11; break;
case 'B':
return 11;
break;
case 'c':
case 'C': return 12; break;
case 'C':
return 12;
break;
case 'd':
case 'D': return 13; break;
case 'D':
return 13;
break;
case 'e':
case 'E': return 14; break;
case 'E':
return 14;
break;
case 'f':
case 'F': return 15; break;
case 'F':
return 15;
break;
default:
return 0;
}
}
void LEDsoff() {
void LEDsoff()
{
LED_A_OFF();
LED_B_OFF();
LED_C_OFF();
@ -129,7 +172,8 @@ void LEDsoff() {
}
// LEDs: R(C) O(A) G(B) -- R(D) [1, 2, 4 and 8]
void LED(int led, int ms) {
void LED(int led, int ms)
{
if (led & LED_RED)
LED_C_ON();
if (led & LED_ORANGE)
@ -154,7 +198,8 @@ void LED(int led, int ms) {
LED_D_OFF();
}
void SpinOff(uint32_t pause) {
void SpinOff(uint32_t pause)
{
LED_A_OFF();
LED_B_OFF();
LED_C_OFF();
@ -163,10 +208,10 @@ void SpinOff(uint32_t pause) {
}
// 0=A, 1=B, 2=C, 3=D
void SpinErr(uint8_t led, uint32_t speed, uint8_t times) {
void SpinErr(uint8_t led, uint32_t speed, uint8_t times)
{
SpinOff(speed);
NTIME(times)
{
NTIME(times) {
switch (led) {
case 0:
LED_A_INV();
@ -185,7 +230,8 @@ void SpinErr(uint8_t led, uint32_t speed, uint8_t times) {
}
}
void SpinDown(uint32_t speed) {
void SpinDown(uint32_t speed)
{
SpinOff(speed);
LED_D_ON();
SpinDelay(speed);
@ -201,7 +247,8 @@ void SpinDown(uint32_t speed) {
LED_A_OFF();
}
void SpinUp(uint32_t speed) {
void SpinUp(uint32_t speed)
{
SpinOff(speed);
LED_A_ON();
SpinDelay(speed);
@ -222,7 +269,8 @@ void SpinUp(uint32_t speed) {
// not clicked, or held down (for ms || 1sec)
// In general, don't use this function unless you expect a
// double click, otherwise it will waste 500ms -- use BUTTON_HELD instead
int BUTTON_CLICKED(int ms) {
int BUTTON_CLICKED(int ms)
{
// Up to 500ms in between clicks to mean a double click
int ticks = (48000 * (ms ? ms : 1000)) >> 10;
@ -240,16 +288,13 @@ int BUTTON_CLICKED(int ms) {
uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
int letoff = 0;
for(;;)
{
for (;;) {
uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
// We haven't let off the button yet
if (!letoff)
{
if (!letoff) {
// We just let it off!
if (!BUTTON_PRESS())
{
if (!BUTTON_PRESS()) {
letoff = 1;
// reset our timer for 500ms
@ -271,8 +316,7 @@ int BUTTON_CLICKED(int ms) {
return BUTTON_DOUBLE_CLICK;
// Have we ran out of time to double click?
else
if (now == (uint16_t)(start + ticks))
else if (now == (uint16_t)(start + ticks))
// At least we did a single click
return BUTTON_SINGLE_CLICK;
@ -284,7 +328,8 @@ int BUTTON_CLICKED(int ms) {
}
// Determine if a button is held down
int BUTTON_HELD(int ms) {
int BUTTON_HELD(int ms)
{
// If button is held for one second
int ticks = (48000 * (ms ? ms : 1000)) >> 10;
@ -301,8 +346,7 @@ int BUTTON_HELD(int ms) {
uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
for(;;)
{
for (;;) {
uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
// As soon as our button let go, we didn't hold long enough
@ -310,8 +354,7 @@ int BUTTON_HELD(int ms) {
return BUTTON_SINGLE_CLICK;
// Have we waited the full second?
else
if (now == (uint16_t)(start + ticks))
else if (now == (uint16_t)(start + ticks))
return BUTTON_HOLD;
WDT_HIT();
@ -326,10 +369,11 @@ int BUTTON_HELD(int ms) {
* verifies the magic properties, then stores a formatted string, prefixed by
* prefix in dst.
*/
void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information) {
struct version_information *v = (struct version_information*)version_information;
void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information)
{
struct version_information *v = (struct version_information *)version_information;
dst[0] = 0;
strncat(dst, prefix, len-1);
strncat(dst, prefix, len - 1);
if (v->magic != VERSION_INFORMATION_MAGIC) {
strncat(dst, "Missing/Invalid version information\n", len - strlen(dst) - 1);
return;

View file

@ -49,11 +49,11 @@ extern uint32_t reflect(uint32_t v, int b); // used in crc.c ...
extern uint8_t reflect8(uint8_t b); // dedicated 8bit reversal
extern uint16_t reflect16(uint16_t b); // dedicated 16bit reversal
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
uint64_t bytes_to_num(uint8_t* src, size_t len);
void num_to_bytes(uint64_t n, size_t len, uint8_t *dest);
uint64_t bytes_to_num(uint8_t *src, size_t len);
void rol(uint8_t *data, const size_t len);
void lsl (uint8_t *data, size_t len);
int32_t le24toh (uint8_t data[3]);
void lsl(uint8_t *data, size_t len);
int32_t le24toh(uint8_t data[3]);
uint8_t hex2int(char hexchar);
void LED(int led, int ms);

View file

@ -37,13 +37,15 @@
//#define UART_WRITE(P, BUF, SIZ) (P)->uart_write(BUF, SIZ, (P)->extobj)
#define UART_WRITE(BUF) DbprintfEx(FLAG_RAWPRINT, "%s", BUF)
int vtsend_init(vtsend_t *p, VTSEND_SERIAL_WRITE uart_write, void *extobj) {
int vtsend_init(vtsend_t *p, VTSEND_SERIAL_WRITE uart_write, void *extobj)
{
p->uart_write = uart_write;
p->extobj = extobj;
return 0;
}
int vtsend_cursor_position(vtsend_t *p, const int column, const int line) {
int vtsend_cursor_position(vtsend_t *p, const int column, const int line)
{
char buf[1 + 8];
buf[0] = ESC;
buf[1] = '[';
@ -58,7 +60,8 @@ int vtsend_cursor_position(vtsend_t *p, const int column, const int line) {
return 0;
}
int vtsend_cursor_up(vtsend_t *p, const int n) {
int vtsend_cursor_up(vtsend_t *p, const int n)
{
char buf[1 + 5];
buf[0] = ESC;
buf[1] = '[';
@ -71,7 +74,8 @@ int vtsend_cursor_up(vtsend_t *p, const int n) {
return 0;
}
int vtsend_cursor_down(vtsend_t *p, const int n) {
int vtsend_cursor_down(vtsend_t *p, const int n)
{
char buf[1 + 5];
buf[0] = ESC;
buf[1] = '[';
@ -84,7 +88,8 @@ int vtsend_cursor_down(vtsend_t *p, const int n) {
return 0;
}
int vtsend_cursor_forward(vtsend_t *p, const int n) {
int vtsend_cursor_forward(vtsend_t *p, const int n)
{
char buf[1 + 5];
buf[0] = ESC;
buf[1] = '[';
@ -97,7 +102,8 @@ int vtsend_cursor_forward(vtsend_t *p, const int n) {
return 0;
}
int vtsend_cursor_backward(vtsend_t *p, const int n) {
int vtsend_cursor_backward(vtsend_t *p, const int n)
{
char buf[1 + 5];
buf[0] = ESC;
buf[1] = '[';
@ -110,7 +116,8 @@ int vtsend_cursor_backward(vtsend_t *p, const int n) {
return 0;
}
int vtsend_cursor_position_save(vtsend_t *p) {
int vtsend_cursor_position_save(vtsend_t *p)
{
char buf[1 + 3];
buf[0] = ESC;
buf[1] = '[';
@ -121,7 +128,8 @@ int vtsend_cursor_position_save(vtsend_t *p) {
return 0;
}
int vtsend_cursor_position_restore(vtsend_t *p) {
int vtsend_cursor_position_restore(vtsend_t *p)
{
char buf[1 + 3];
buf[0] = ESC;
buf[1] = '[';
@ -132,7 +140,8 @@ int vtsend_cursor_position_restore(vtsend_t *p) {
return 0;
}
int vtsend_erase_display(vtsend_t *p) {
int vtsend_erase_display(vtsend_t *p)
{
char buf[1 + 4];
buf[0] = ESC;
buf[1] = '[';
@ -144,7 +153,8 @@ int vtsend_erase_display(vtsend_t *p) {
return 0;
}
int vtsend_erase_line(vtsend_t *p) {
int vtsend_erase_line(vtsend_t *p)
{
char buf[1 + 4];
buf[0] = ESC;
buf[1] = '[';
@ -156,7 +166,8 @@ int vtsend_erase_line(vtsend_t *p) {
return 0;
}
int vtsend_set_color_foreground(vtsend_t *p, const int color) {
int vtsend_set_color_foreground(vtsend_t *p, const int color)
{
char buf[1 + 5];
buf[0] = ESC;
buf[1] = '[';
@ -169,7 +180,8 @@ int vtsend_set_color_foreground(vtsend_t *p, const int color) {
return 0;
}
int vtsend_set_color_background(vtsend_t *p, const int color) {
int vtsend_set_color_background(vtsend_t *p, const int color)
{
char buf[1 + 5];
buf[0] = ESC;
buf[1] = '[';
@ -182,7 +194,8 @@ int vtsend_set_color_background(vtsend_t *p, const int color) {
return 0;
}
int vtsend_set_attribute(vtsend_t *p, const int attr) {
int vtsend_set_attribute(vtsend_t *p, const int attr)
{
char buf[1 + 5];
buf[0] = ESC;
buf[1] = '[';
@ -195,7 +208,8 @@ int vtsend_set_attribute(vtsend_t *p, const int attr) {
return 0;
}
int vtsend_set_scroll_region(vtsend_t *p, const int top, const int bottom) {
int vtsend_set_scroll_region(vtsend_t *p, const int top, const int bottom)
{
char buf[1 + 8];
buf[0] = ESC;
buf[1] = '[';
@ -211,7 +225,8 @@ int vtsend_set_scroll_region(vtsend_t *p, const int top, const int bottom) {
return 0;
}
int vtsend_set_cursor(vtsend_t *p, const int visible) {
int vtsend_set_cursor(vtsend_t *p, const int visible)
{
if (visible) {
char buf[1 + 6];
buf[0] = ESC;
@ -238,7 +253,8 @@ int vtsend_set_cursor(vtsend_t *p, const int visible) {
return 0;
}
int vtsend_reset(vtsend_t *p) {
int vtsend_reset(vtsend_t *p)
{
char buf[1 + 2];
buf[0] = ESC;
buf[1] = 'c';
@ -248,7 +264,8 @@ int vtsend_reset(vtsend_t *p) {
return 0;
}
int vtsend_draw_box(vtsend_t *p, const int x1, const int y1, const int x2, const int y2) {
int vtsend_draw_box(vtsend_t *p, const int x1, const int y1, const int x2, const int y2)
{
int i;
vtsend_cursor_position(p, x1, y1);
@ -268,7 +285,8 @@ int vtsend_draw_box(vtsend_t *p, const int x1, const int y1, const int x2, const
return 0;
}
int vtsend_fill_box(vtsend_t *p, const int x1, const int y1, const int x2, const int y2) {
int vtsend_fill_box(vtsend_t *p, const int x1, const int y1, const int x2, const int y2)
{
int i, j;
for (i = y1; i <= y2; i++) {
vtsend_cursor_position(p, x1, i);

View file

@ -15,15 +15,17 @@ unsigned int start_addr, end_addr, bootrom_unlocked;
extern char _bootrom_start, _bootrom_end, _flash_start, _flash_end;
extern uint32_t _osimage_entry;
void DbpString(char *str) {
void DbpString(char *str)
{
byte_t len = 0;
while (str[len] != 0x00)
len++;
cmd_send(CMD_DEBUG_PRINT_STRING, len, 0, 0, (byte_t*)str, len);
cmd_send(CMD_DEBUG_PRINT_STRING, len, 0, 0, (byte_t *)str, len);
}
static void ConfigClocks(void) {
static void ConfigClocks(void)
{
// we are using a 16 MHz crystal as the basis for everything
// slow clock runs at 32Khz typical regardless of crystal
@ -32,12 +34,12 @@ static void ConfigClocks(void) {
// enable the clock to the following peripherals
AT91C_BASE_PMC->PMC_PCER =
(1<<AT91C_ID_PIOA) |
(1<<AT91C_ID_ADC) |
(1<<AT91C_ID_SPI) |
(1<<AT91C_ID_SSC) |
(1<<AT91C_ID_PWMC) |
(1<<AT91C_ID_UDP);
(1 << AT91C_ID_PIOA) |
(1 << AT91C_ID_ADC) |
(1 << AT91C_ID_SPI) |
(1 << AT91C_ID_SSC) |
(1 << AT91C_ID_PWMC) |
(1 << AT91C_ID_UDP);
// worst case scenario, with MAINCK = 16Mhz xtal, startup delay is 1.4ms
// if SLCK slow clock runs at its worst case (max) frequency of 42khz
@ -49,7 +51,7 @@ static void ConfigClocks(void) {
PMC_MAIN_OSC_STARTUP_DELAY(8);
// wait for main oscillator to stabilize
while ( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS) ) {};
while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS)) {};
// PLL output clock frequency in range 80 - 160 MHz needs CKGR_PLL = 00
// PLL output clock frequency in range 150 - 180 MHz needs CKGR_PLL = 10
@ -63,7 +65,7 @@ static void ConfigClocks(void) {
PMC_PLL_USB_DIVISOR(1);
// wait for PLL to lock
while ( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK) ) {};
while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK)) {};
// we want a master clock (MCK) to be PLL clock / 2 = 96Mhz / 2 = 48Mhz
// datasheet recommends that this register is programmed in two operations
@ -71,62 +73,66 @@ static void ConfigClocks(void) {
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2;
// wait for main clock ready signal
while ( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) ) {};
while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)) {};
// set the source to PLL
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2 | AT91C_PMC_CSS_PLL_CLK;
// wait for main clock ready signal
while ( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) ) {};
while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)) {};
}
static void Fatal(void) {
for(;;) {};
static void Fatal(void)
{
for (;;) {};
}
void UsbPacketReceived(uint8_t *packet, int len) {
void UsbPacketReceived(uint8_t *packet, int len)
{
int i, dont_ack = 0;
UsbCommand* c = (UsbCommand *)packet;
UsbCommand *c = (UsbCommand *)packet;
volatile uint32_t *p;
//if ( len != sizeof(UsbCommand)) Fatal();
uint32_t arg0 = (uint32_t)c->arg[0];
switch(c->cmd) {
switch (c->cmd) {
case CMD_DEVICE_INFO: {
dont_ack = 1;
arg0 = DEVICE_INFO_FLAG_BOOTROM_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM |
DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH;
if(common_area.flags.osimage_present)
if (common_area.flags.osimage_present)
arg0 |= DEVICE_INFO_FLAG_OSIMAGE_PRESENT;
cmd_send(CMD_DEVICE_INFO,arg0,1,2,0,0);
} break;
cmd_send(CMD_DEVICE_INFO, arg0, 1, 2, 0, 0);
}
break;
case CMD_SETUP_WRITE: {
/* The temporary write buffer of the embedded flash controller is mapped to the
* whole memory region, only the last 8 bits are decoded.
*/
p = (volatile uint32_t *)&_flash_start;
for(i = 0; i < 12; i++)
p[i+arg0] = c->d.asDwords[i];
} break;
for (i = 0; i < 12; i++)
p[i + arg0] = c->d.asDwords[i];
}
break;
case CMD_FINISH_WRITE: {
uint32_t* flash_mem = (uint32_t*)(&_flash_start);
for ( int j=0; j<2; j++) {
for(i = 0+(64*j); i < 64+(64*j); i++) {
uint32_t *flash_mem = (uint32_t *)(&_flash_start);
for (int j = 0; j < 2; j++) {
for (i = 0 + (64 * j); i < 64 + (64 * j); i++) {
flash_mem[i] = c->d.asDwords[i];
}
uint32_t flash_address = arg0 + (0x100*j);
uint32_t flash_address = arg0 + (0x100 * j);
/* Check that the address that we are supposed to write to is within our allowed region */
if( ((flash_address + AT91C_IFLASH_PAGE_SIZE - 1) >= end_addr) || (flash_address < start_addr) ) {
if (((flash_address + AT91C_IFLASH_PAGE_SIZE - 1) >= end_addr) || (flash_address < start_addr)) {
/* Disallow write */
dont_ack = 1;
cmd_send(CMD_NACK,0,0,0,0,0);
cmd_send(CMD_NACK, 0, 0, 0, 0, 0);
} else {
uint32_t page_n = (flash_address - ((uint32_t)flash_mem)) / AT91C_IFLASH_PAGE_SIZE;
/* Translate address to flash page and do flash, update here for the 512k part */
@ -137,18 +143,20 @@ void UsbPacketReceived(uint8_t *packet, int len) {
// Wait until flashing of page finishes
uint32_t sr;
while(!((sr = AT91C_BASE_EFC0->EFC_FSR) & AT91C_MC_FRDY));
if(sr & (AT91C_MC_LOCKE | AT91C_MC_PROGE)) {
while (!((sr = AT91C_BASE_EFC0->EFC_FSR) & AT91C_MC_FRDY));
if (sr & (AT91C_MC_LOCKE | AT91C_MC_PROGE)) {
dont_ack = 1;
cmd_send(CMD_NACK,sr,0,0,0,0);
cmd_send(CMD_NACK, sr, 0, 0, 0, 0);
}
}
} break;
}
break;
case CMD_HARDWARE_RESET: {
usb_disable();
AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
} break;
}
break;
case CMD_START_FLASH: {
if (c->arg[2] == START_FLASH_MAGIC)
@ -166,28 +174,31 @@ void UsbPacketReceived(uint8_t *packet, int len) {
/* Only allow command if the bootrom is unlocked, or the parameters are outside of the protected
* bootrom area. In any case they must be within the flash area.
*/
if( (bootrom_unlocked || ((cmd_start >= prot_end) || (cmd_end < prot_start))) &&
if ((bootrom_unlocked || ((cmd_start >= prot_end) || (cmd_end < prot_start))) &&
(cmd_start >= allow_start) &&
(cmd_end <= allow_end) ) {
(cmd_end <= allow_end)) {
start_addr = cmd_start;
end_addr = cmd_end;
} else {
start_addr = end_addr = 0;
dont_ack = 1;
cmd_send(CMD_NACK,0,0,0,0,0);
cmd_send(CMD_NACK, 0, 0, 0, 0, 0);
}
} break;
}
break;
default: {
Fatal();
} break;
}
break;
}
if (!dont_ack)
cmd_send(CMD_ACK,arg0,0,0,0,0);
cmd_send(CMD_ACK, arg0, 0, 0, 0, 0);
}
static void flash_mode(int externally_entered) {
static void flash_mode(int externally_entered)
{
start_addr = 0;
end_addr = 0;
bootrom_unlocked = 0;
@ -196,14 +207,14 @@ static void flash_mode(int externally_entered) {
usb_enable();
// wait for reset to be complete?
for (volatile size_t i=0; i<0x100000; i++) {};
for (volatile size_t i = 0; i < 0x100000; i++) {};
for(;;) {
for (;;) {
WDT_HIT();
// Check if there is a usb packet available
if (usb_poll_validate_length()) {
if (usb_read(rx, sizeof(rx)) )
if (usb_read(rx, sizeof(rx)))
UsbPacketReceived(rx, sizeof(rx));
}
@ -212,7 +223,7 @@ static void flash_mode(int externally_entered) {
usb_disable();
LED_B_ON();
AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
for(;;) {};
for (;;) {};
}
if (externally_entered && BUTTON_PRESS()) {
/* Let the user's button press override the automatic leave */
@ -221,7 +232,8 @@ static void flash_mode(int externally_entered) {
}
}
void BootROM(void) {
void BootROM(void)
{
//------------
// First set up all the I/O pins; GPIOs configured directly, other ones
// just need to be assigned to the appropriate peripheral.
@ -274,8 +286,8 @@ void BootROM(void) {
AT91C_BASE_EFC0->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48);
// 9 = 256, 10+ is 512kb
uint8_t id = ( *(AT91C_DBGU_CIDR) & 0xF00) >> 8;
if ( id > 9 )
uint8_t id = (*(AT91C_DBGU_CIDR) & 0xF00) >> 8;
if (id > 9)
AT91C_BASE_EFC1->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48);
// Initialize all system clocks
@ -289,19 +301,19 @@ void BootROM(void) {
case AT91C_RSTC_RSTTYP_SOFTWARE:
case AT91C_RSTC_RSTTYP_USER:
/* In these cases the common_area in RAM should be ok, retain it if it's there */
if(common_area.magic == COMMON_AREA_MAGIC && common_area.version == 1)
if (common_area.magic == COMMON_AREA_MAGIC && common_area.version == 1)
common_area_present = 1;
break;
default: /* Otherwise, initialize it from scratch */
break;
}
if (!common_area_present){
if (!common_area_present) {
/* Common area not ok, initialize it */
int i;
/* Makeshift memset, no need to drag util.c into this */
for(i=0; i<sizeof(common_area); i++)
((char*)&common_area)[i] = 0;
for (i = 0; i < sizeof(common_area); i++)
((char *)&common_area)[i] = 0;
common_area.magic = COMMON_AREA_MAGIC;
common_area.version = 1;
@ -318,6 +330,6 @@ void BootROM(void) {
flash_mode(1);
} else {
// jump to Flash address of the osimage entry point (LSBit set for thumb mode)
__asm("bx %0\n" : : "r" ( ((int)&_osimage_entry) | 0x1 ) );
__asm("bx %0\n" : : "r"(((int)&_osimage_entry) | 0x1));
}
}

View file

@ -12,7 +12,8 @@
#define HMAC_POS_DATA 0x008
#define HMAC_POS_TAG 0x1B4
void nfc3d_amiibo_calc_seed(const uint8_t * dump, uint8_t * key) {
void nfc3d_amiibo_calc_seed(const uint8_t *dump, uint8_t *key)
{
memcpy(key + 0x00, dump + 0x029, 0x02);
memset(key + 0x02, 0x00, 0x0E);
memcpy(key + 0x10, dump + 0x1D4, 0x08);
@ -20,24 +21,26 @@ void nfc3d_amiibo_calc_seed(const uint8_t * dump, uint8_t * key) {
memcpy(key + 0x20, dump + 0x1E8, 0x20);
}
void nfc3d_amiibo_keygen(const nfc3d_keygen_masterkeys * masterKeys, const uint8_t * dump, nfc3d_keygen_derivedkeys * derivedKeys) {
void nfc3d_amiibo_keygen(const nfc3d_keygen_masterkeys *masterKeys, const uint8_t *dump, nfc3d_keygen_derivedkeys *derivedKeys)
{
uint8_t seed[NFC3D_KEYGEN_SEED_SIZE];
nfc3d_amiibo_calc_seed(dump, seed);
nfc3d_keygen(masterKeys, seed, derivedKeys);
}
void nfc3d_amiibo_cipher(const nfc3d_keygen_derivedkeys * keys, const uint8_t * in, uint8_t * out) {
void nfc3d_amiibo_cipher(const nfc3d_keygen_derivedkeys *keys, const uint8_t *in, uint8_t *out)
{
mbedtls_aes_context aes;
size_t nc_off = 0;
unsigned char nonce_counter[16];
unsigned char stream_block[16];
mbedtls_aes_setkey_enc( &aes, keys->aesKey, 128 );
mbedtls_aes_setkey_enc(&aes, keys->aesKey, 128);
memset(nonce_counter, 0, sizeof(nonce_counter));
memset(stream_block, 0, sizeof(stream_block));
memcpy(nonce_counter, keys->aesIV, sizeof(nonce_counter));
mbedtls_aes_crypt_ctr( &aes, 0x188, &nc_off, nonce_counter, stream_block, in + 0x02C, out + 0x02C );
mbedtls_aes_crypt_ctr(&aes, 0x188, &nc_off, nonce_counter, stream_block, in + 0x02C, out + 0x02C);
memcpy(out + 0x000, in + 0x000, 0x008);
// Data signature NOT copied
@ -46,7 +49,8 @@ void nfc3d_amiibo_cipher(const nfc3d_keygen_derivedkeys * keys, const uint8_t *
memcpy(out + 0x1D4, in + 0x1D4, 0x034);
}
void nfc3d_amiibo_tag_to_internal(const uint8_t * tag, uint8_t * intl) {
void nfc3d_amiibo_tag_to_internal(const uint8_t *tag, uint8_t *intl)
{
memcpy(intl + 0x000, tag + 0x008, 0x008);
memcpy(intl + 0x008, tag + 0x080, 0x020);
memcpy(intl + 0x028, tag + 0x010, 0x024);
@ -56,7 +60,8 @@ void nfc3d_amiibo_tag_to_internal(const uint8_t * tag, uint8_t * intl) {
memcpy(intl + 0x1DC, tag + 0x054, 0x02C);
}
void nfc3d_amiibo_internal_to_tag(const uint8_t * intl, uint8_t * tag) {
void nfc3d_amiibo_internal_to_tag(const uint8_t *intl, uint8_t *tag)
{
memcpy(tag + 0x008, intl + 0x000, 0x008);
memcpy(tag + 0x080, intl + 0x008, 0x020);
memcpy(tag + 0x010, intl + 0x028, 0x024);
@ -66,7 +71,8 @@ void nfc3d_amiibo_internal_to_tag(const uint8_t * intl, uint8_t * tag) {
memcpy(tag + 0x054, intl + 0x1DC, 0x02C);
}
bool nfc3d_amiibo_unpack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * tag, uint8_t * plain) {
bool nfc3d_amiibo_unpack(const nfc3d_amiibo_keys *amiiboKeys, const uint8_t *tag, uint8_t *plain)
{
uint8_t internal[NFC3D_AMIIBO_SIZE];
nfc3d_keygen_derivedkeys dataKeys;
nfc3d_keygen_derivedkeys tagKeys;
@ -82,19 +88,20 @@ bool nfc3d_amiibo_unpack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * t
nfc3d_amiibo_cipher(&dataKeys, internal, plain);
// Regenerate tag HMAC. Note: order matters, data HMAC depends on tag HMAC!
mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey),
plain + 0x1D4, 0x34, plain + HMAC_POS_TAG );
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey),
plain + 0x1D4, 0x34, plain + HMAC_POS_TAG);
// Regenerate data HMAC
mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), dataKeys.hmacKey, sizeof(dataKeys.hmacKey),
plain + 0x029, 0x1DF, plain + HMAC_POS_DATA );
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), dataKeys.hmacKey, sizeof(dataKeys.hmacKey),
plain + 0x029, 0x1DF, plain + HMAC_POS_DATA);
return
memcmp(plain + HMAC_POS_DATA, internal + HMAC_POS_DATA, 32) == 0 &&
memcmp(plain + HMAC_POS_TAG, internal + HMAC_POS_TAG, 32) == 0;
}
void nfc3d_amiibo_pack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * plain, uint8_t * tag) {
void nfc3d_amiibo_pack(const nfc3d_amiibo_keys *amiiboKeys, const uint8_t *plain, uint8_t *tag)
{
uint8_t cipher[NFC3D_AMIIBO_SIZE];
nfc3d_keygen_derivedkeys tagKeys;
nfc3d_keygen_derivedkeys dataKeys;
@ -104,24 +111,24 @@ void nfc3d_amiibo_pack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * pla
nfc3d_amiibo_keygen(&amiiboKeys->data, plain, &dataKeys);
// Generate tag HMAC
mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey),
plain + 0x1D4, 0x34, cipher + HMAC_POS_TAG );
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey),
plain + 0x1D4, 0x34, cipher + HMAC_POS_TAG);
// Init mbedtls HMAC context
mbedtls_md_context_t ctx;
mbedtls_md_init( &ctx );
mbedtls_md_setup( &ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1 );
mbedtls_md_init(&ctx);
mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1);
// Generate data HMAC
mbedtls_md_hmac_starts( &ctx, dataKeys.hmacKey, sizeof(dataKeys.hmacKey) );
mbedtls_md_hmac_update( &ctx, plain + 0x029, 0x18B ); // Data
mbedtls_md_hmac_update( &ctx, cipher + HMAC_POS_TAG, 0x20 ); // Tag HMAC
mbedtls_md_hmac_update( &ctx, plain + 0x1D4, 0x34 ); // Here be dragons
mbedtls_md_hmac_starts(&ctx, dataKeys.hmacKey, sizeof(dataKeys.hmacKey));
mbedtls_md_hmac_update(&ctx, plain + 0x029, 0x18B); // Data
mbedtls_md_hmac_update(&ctx, cipher + HMAC_POS_TAG, 0x20); // Tag HMAC
mbedtls_md_hmac_update(&ctx, plain + 0x1D4, 0x34); // Here be dragons
mbedtls_md_hmac_finish( &ctx, cipher + HMAC_POS_DATA );
mbedtls_md_hmac_finish(&ctx, cipher + HMAC_POS_DATA);
// HMAC cleanup
mbedtls_md_free( &ctx );
mbedtls_md_free(&ctx);
// Encrypt
nfc3d_amiibo_cipher(&dataKeys, plain, cipher);
@ -130,8 +137,9 @@ void nfc3d_amiibo_pack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * pla
nfc3d_amiibo_internal_to_tag(cipher, tag);
}
bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys * amiiboKeys, const char * path) {
FILE * f = fopen(path, "rb");
bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys *amiiboKeys, const char *path)
{
FILE *f = fopen(path, "rb");
if (!f) {
return false;
}
@ -152,7 +160,8 @@ bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys * amiiboKeys, const char * path) {
return true;
}
void nfc3d_amiibo_copy_app_data(const uint8_t * src, uint8_t * dst) {
void nfc3d_amiibo_copy_app_data(const uint8_t *src, uint8_t *dst)
{
//uint16_t *ami_nb_wr = (uint16_t*)(dst + 0x29);

View file

@ -24,9 +24,9 @@ typedef struct {
} nfc3d_amiibo_keys;
#pragma pack()
bool nfc3d_amiibo_unpack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * tag, uint8_t * plain);
void nfc3d_amiibo_pack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * plain, uint8_t * tag);
bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys * amiiboKeys, const char * path);
void nfc3d_amiibo_copy_app_data(const uint8_t * src, uint8_t * dst);
bool nfc3d_amiibo_unpack(const nfc3d_amiibo_keys *amiiboKeys, const uint8_t *tag, uint8_t *plain);
void nfc3d_amiibo_pack(const nfc3d_amiibo_keys *amiiboKeys, const uint8_t *plain, uint8_t *tag);
bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys *amiiboKeys, const char *path);
void nfc3d_amiibo_copy_app_data(const uint8_t *src, uint8_t *dst);
#endif

View file

@ -12,9 +12,10 @@
#define NTAG215_SIZE 540
static char * self;
static char *self;
void amiitool_usage() {
void amiitool_usage()
{
fprintf(stderr,
"amiitool build %i (commit %s-%08x)\n"
"by Marcos Del Sol Vives <marcos@dracon.es>\n"
@ -32,7 +33,8 @@ void amiitool_usage() {
);
}
static bool LoadAmiikey(nfc3d_amiibo_keys keys, char* keyfile) {
static bool LoadAmiikey(nfc3d_amiibo_keys keys, char *keyfile)
{
if (!nfc3d_amiibo_load_keys(&keys, keyfile)) {
PrintAndLogEx(ERR, "Could not load keys from '%s'", keyfile);
@ -41,13 +43,14 @@ static bool LoadAmiikey(nfc3d_amiibo_keys keys, char* keyfile) {
return true;
}
int main(int argc, char ** argv) {
int main(int argc, char **argv)
{
self = argv[0];
char * infile = NULL;
char * savefile = NULL;
char * outfile = NULL;
char * keyfile = NULL;
char *infile = NULL;
char *savefile = NULL;
char *outfile = NULL;
char *keyfile = NULL;
char op = '\0';
bool lenient = false;
@ -88,7 +91,7 @@ int main(int argc, char ** argv) {
uint8_t original[NTAG215_SIZE];
uint8_t modified[NFC3D_AMIIBO_SIZE];
FILE * f = stdin;
FILE *f = stdin;
if (infile) {
f = fopen(infile, "rb");
if (!f) {

View file

@ -10,7 +10,8 @@
#include <string.h>
#include <mbedtls/md.h>
void nfc3d_drbg_init(nfc3d_drbg_ctx * ctx, const uint8_t * hmacKey, size_t hmacKeySize, const uint8_t * seed, size_t seedSize) {
void nfc3d_drbg_init(nfc3d_drbg_ctx *ctx, const uint8_t *hmacKey, size_t hmacKeySize, const uint8_t *seed, size_t seedSize)
{
assert(ctx != NULL);
assert(hmacKey != NULL);
assert(seed != NULL);
@ -30,7 +31,8 @@ void nfc3d_drbg_init(nfc3d_drbg_ctx * ctx, const uint8_t * hmacKey, size_t hmacK
mbedtls_md_hmac_starts(&ctx->hmacCtx, hmacKey, hmacKeySize);
}
void nfc3d_drbg_step(nfc3d_drbg_ctx * ctx, uint8_t * output) {
void nfc3d_drbg_step(nfc3d_drbg_ctx *ctx, uint8_t *output)
{
assert(ctx != NULL);
assert(output != NULL);
@ -51,12 +53,14 @@ void nfc3d_drbg_step(nfc3d_drbg_ctx * ctx, uint8_t * output) {
mbedtls_md_hmac_finish(&ctx->hmacCtx, output);
}
void nfc3d_drbg_cleanup(nfc3d_drbg_ctx * ctx) {
void nfc3d_drbg_cleanup(nfc3d_drbg_ctx *ctx)
{
assert(ctx != NULL);
mbedtls_md_free(&ctx->hmacCtx);
}
void nfc3d_drbg_generate_bytes(const uint8_t * hmacKey, size_t hmacKeySize, const uint8_t * seed, size_t seedSize, uint8_t * output, size_t outputSize) {
void nfc3d_drbg_generate_bytes(const uint8_t *hmacKey, size_t hmacKeySize, const uint8_t *seed, size_t seedSize, uint8_t *output, size_t outputSize)
{
uint8_t temp[NFC3D_DRBG_OUTPUT_SIZE];
nfc3d_drbg_ctx rngCtx;

View file

@ -24,10 +24,10 @@ typedef struct {
size_t bufferSize;
} nfc3d_drbg_ctx;
void nfc3d_drbg_init(nfc3d_drbg_ctx * ctx, const uint8_t * hmacKey, size_t hmacKeySize, const uint8_t * seed, size_t seedSize);
void nfc3d_drbg_step(nfc3d_drbg_ctx * ctx, uint8_t * output);
void nfc3d_drbg_cleanup(nfc3d_drbg_ctx * ctx);
void nfc3d_drbg_generate_bytes(const uint8_t * hmacKey, size_t hmacKeySize, const uint8_t * seed, size_t seedSize, uint8_t * output, size_t outputSize);
void nfc3d_drbg_init(nfc3d_drbg_ctx *ctx, const uint8_t *hmacKey, size_t hmacKeySize, const uint8_t *seed, size_t seedSize);
void nfc3d_drbg_step(nfc3d_drbg_ctx *ctx, uint8_t *output);
void nfc3d_drbg_cleanup(nfc3d_drbg_ctx *ctx);
void nfc3d_drbg_generate_bytes(const uint8_t *hmacKey, size_t hmacKeySize, const uint8_t *seed, size_t seedSize, uint8_t *output, size_t outputSize);
#endif

View file

@ -10,13 +10,14 @@
#include <stdio.h>
#include <string.h>
void nfc3d_keygen_prepare_seed(const nfc3d_keygen_masterkeys * baseKeys, const uint8_t * baseSeed, uint8_t * output, size_t * outputSize) {
void nfc3d_keygen_prepare_seed(const nfc3d_keygen_masterkeys *baseKeys, const uint8_t *baseSeed, uint8_t *output, size_t *outputSize)
{
assert(baseKeys != NULL);
assert(baseSeed != NULL);
assert(output != NULL);
assert(outputSize != NULL);
uint8_t * start = output;
uint8_t *start = output;
// 1: Copy whole type string
output = memccpy(output, baseKeys->typeString, '\0', sizeof(baseKeys->typeString));
@ -44,7 +45,8 @@ void nfc3d_keygen_prepare_seed(const nfc3d_keygen_masterkeys * baseKeys, const u
*outputSize = output - start;
}
void nfc3d_keygen(const nfc3d_keygen_masterkeys * baseKeys, const uint8_t * baseSeed, nfc3d_keygen_derivedkeys * derivedKeys) {
void nfc3d_keygen(const nfc3d_keygen_masterkeys *baseKeys, const uint8_t *baseSeed, nfc3d_keygen_derivedkeys *derivedKeys)
{
uint8_t preparedSeed[NFC3D_DRBG_MAX_SEED_SIZE];
size_t preparedSeedSize;

View file

@ -29,6 +29,6 @@ typedef struct {
} nfc3d_keygen_derivedkeys;
#pragma pack()
void nfc3d_keygen(const nfc3d_keygen_masterkeys * baseKeys, const uint8_t * baseSeed, nfc3d_keygen_derivedkeys * derivedKeys);
void nfc3d_keygen(const nfc3d_keygen_masterkeys *baseKeys, const uint8_t *baseSeed, nfc3d_keygen_derivedkeys *derivedKeys);
#endif

View file

@ -15,12 +15,11 @@
#define HANDLE_ERROR if (error_occured) { \
error_occured = 0;\
break;\
}
}
int main(int argc, char **argv)
{
if (argc != 3 && argc != 4)
{
if (argc != 3 && argc != 4) {
printf("\n\tusage: cli <command 1> <command 2> [logfile (default cli.log)]\n");
printf("\n");
printf("\texample: cli hi14asnoop hi14alist h14a.log\n");

File diff suppressed because it is too large Load diff

View file

@ -41,11 +41,10 @@ extern "C" {
#define ARG_REX_ICASE 1
/* bit masks for arg_hdr.flag */
enum
{
ARG_TERMINATOR=0x1,
ARG_HASVALUE=0x2,
ARG_HASOPTVALUE=0x4
enum {
ARG_TERMINATOR = 0x1,
ARG_HASVALUE = 0x2,
ARG_HASOPTVALUE = 0x4
};
typedef void (arg_resetfn)(void *parent);
@ -71,8 +70,7 @@ typedef void (arg_errorfn)(void *parent, FILE *fp, int error, const char *argval
* if desired, but the original intention is for them to be set by the
* constructor and left unaltered.
*/
struct arg_hdr
{
struct arg_hdr {
char flag; /* Modifier flags: ARG_TERMINATOR, ARG_HASVALUE. */
const char *shortopts; /* String defining the short options */
const char *longopts; /* String defiing the long options */
@ -88,47 +86,40 @@ struct arg_hdr
void *priv; /* Pointer to private header data for use by arg_xxx functions */
};
struct arg_rem
{
struct arg_rem {
struct arg_hdr hdr; /* The mandatory argtable header struct */
};
struct arg_lit
{
struct arg_lit {
struct arg_hdr hdr; /* The mandatory argtable header struct */
int count; /* Number of matching command line args */
};
struct arg_int
{
struct arg_int {
struct arg_hdr hdr; /* The mandatory argtable header struct */
int count; /* Number of matching command line args */
int *ival; /* Array of parsed argument values */
};
struct arg_dbl
{
struct arg_dbl {
struct arg_hdr hdr; /* The mandatory argtable header struct */
int count; /* Number of matching command line args */
double *dval; /* Array of parsed argument values */
};
struct arg_str
{
struct arg_str {
struct arg_hdr hdr; /* The mandatory argtable header struct */
int count; /* Number of matching command line args */
const char **sval; /* Array of parsed argument values */
};
struct arg_rex
{
struct arg_rex {
struct arg_hdr hdr; /* The mandatory argtable header struct */
int count; /* Number of matching command line args */
const char **sval; /* Array of parsed argument values */
};
struct arg_file
{
struct arg_file {
struct arg_hdr hdr; /* The mandatory argtable header struct */
int count; /* Number of matching command line args*/
const char **filename; /* Array of parsed filenames (eg: /home/foo.bar) */
@ -136,17 +127,15 @@ struct arg_file
const char **extension; /* Array of parsed extensions (eg: .bar) */
};
struct arg_date
{
struct arg_date {
struct arg_hdr hdr; /* The mandatory argtable header struct */
const char *format; /* strptime format string used to parse the date */
int count; /* Number of matching command line args */
struct tm *tmval; /* Array of parsed time values */
};
enum {ARG_ELIMIT=1, ARG_EMALLOC, ARG_ENOMATCH, ARG_ELONGOPT, ARG_EMISSARG};
struct arg_end
{
enum {ARG_ELIMIT = 1, ARG_EMALLOC, ARG_ENOMATCH, ARG_ELONGOPT, ARG_EMISSARG};
struct arg_end {
struct arg_hdr hdr; /* The mandatory argtable header struct */
int count; /* Number of errors encountered */
int *error; /* Array of error codes */
@ -157,132 +146,132 @@ struct arg_end
/**** arg_xxx constructor functions *********************************/
struct arg_rem* arg_rem(const char* datatype, const char* glossary);
struct arg_rem *arg_rem(const char *datatype, const char *glossary);
struct arg_lit* arg_lit0(const char* shortopts,
const char* longopts,
const char* glossary);
struct arg_lit* arg_lit1(const char* shortopts,
const char* longopts,
struct arg_lit *arg_lit0(const char *shortopts,
const char *longopts,
const char *glossary);
struct arg_lit* arg_litn(const char* shortopts,
const char* longopts,
struct arg_lit *arg_lit1(const char *shortopts,
const char *longopts,
const char *glossary);
struct arg_lit *arg_litn(const char *shortopts,
const char *longopts,
int mincount,
int maxcount,
const char *glossary);
struct arg_key* arg_key0(const char* keyword,
struct arg_key *arg_key0(const char *keyword,
int flags,
const char* glossary);
struct arg_key* arg_key1(const char* keyword,
const char *glossary);
struct arg_key *arg_key1(const char *keyword,
int flags,
const char* glossary);
struct arg_key* arg_keyn(const char* keyword,
const char *glossary);
struct arg_key *arg_keyn(const char *keyword,
int flags,
int mincount,
int maxcount,
const char* glossary);
struct arg_int* arg_int0(const char* shortopts,
const char* longopts,
const char* datatype,
const char* glossary);
struct arg_int* arg_int1(const char* shortopts,
const char* longopts,
const char* datatype,
const char *glossary);
struct arg_int* arg_intn(const char* shortopts,
const char* longopts,
struct arg_int *arg_int0(const char *shortopts,
const char *longopts,
const char *datatype,
const char *glossary);
struct arg_int *arg_int1(const char *shortopts,
const char *longopts,
const char *datatype,
const char *glossary);
struct arg_int *arg_intn(const char *shortopts,
const char *longopts,
const char *datatype,
int mincount,
int maxcount,
const char *glossary);
struct arg_dbl* arg_dbl0(const char* shortopts,
const char* longopts,
const char* datatype,
const char* glossary);
struct arg_dbl* arg_dbl1(const char* shortopts,
const char* longopts,
const char* datatype,
struct arg_dbl *arg_dbl0(const char *shortopts,
const char *longopts,
const char *datatype,
const char *glossary);
struct arg_dbl* arg_dbln(const char* shortopts,
const char* longopts,
struct arg_dbl *arg_dbl1(const char *shortopts,
const char *longopts,
const char *datatype,
const char *glossary);
struct arg_dbl *arg_dbln(const char *shortopts,
const char *longopts,
const char *datatype,
int mincount,
int maxcount,
const char *glossary);
struct arg_str* arg_str0(const char* shortopts,
const char* longopts,
const char* datatype,
const char* glossary);
struct arg_str* arg_str1(const char* shortopts,
const char* longopts,
const char* datatype,
struct arg_str *arg_str0(const char *shortopts,
const char *longopts,
const char *datatype,
const char *glossary);
struct arg_str* arg_strn(const char* shortopts,
const char* longopts,
const char* datatype,
struct arg_str *arg_str1(const char *shortopts,
const char *longopts,
const char *datatype,
const char *glossary);
struct arg_str *arg_strn(const char *shortopts,
const char *longopts,
const char *datatype,
int mincount,
int maxcount,
const char *glossary);
struct arg_rex* arg_rex0(const char* shortopts,
const char* longopts,
const char* pattern,
const char* datatype,
int flags,
const char* glossary);
struct arg_rex* arg_rex1(const char* shortopts,
const char* longopts,
const char* pattern,
const char* datatype,
struct arg_rex *arg_rex0(const char *shortopts,
const char *longopts,
const char *pattern,
const char *datatype,
int flags,
const char *glossary);
struct arg_rex* arg_rexn(const char* shortopts,
const char* longopts,
const char* pattern,
const char* datatype,
struct arg_rex *arg_rex1(const char *shortopts,
const char *longopts,
const char *pattern,
const char *datatype,
int flags,
const char *glossary);
struct arg_rex *arg_rexn(const char *shortopts,
const char *longopts,
const char *pattern,
const char *datatype,
int mincount,
int maxcount,
int flags,
const char *glossary);
struct arg_file* arg_file0(const char* shortopts,
const char* longopts,
const char* datatype,
const char* glossary);
struct arg_file* arg_file1(const char* shortopts,
const char* longopts,
const char* datatype,
struct arg_file *arg_file0(const char *shortopts,
const char *longopts,
const char *datatype,
const char *glossary);
struct arg_file* arg_filen(const char* shortopts,
const char* longopts,
const char* datatype,
struct arg_file *arg_file1(const char *shortopts,
const char *longopts,
const char *datatype,
const char *glossary);
struct arg_file *arg_filen(const char *shortopts,
const char *longopts,
const char *datatype,
int mincount,
int maxcount,
const char *glossary);
struct arg_date* arg_date0(const char* shortopts,
const char* longopts,
const char* format,
const char* datatype,
const char* glossary);
struct arg_date* arg_date1(const char* shortopts,
const char* longopts,
const char* format,
const char* datatype,
struct arg_date *arg_date0(const char *shortopts,
const char *longopts,
const char *format,
const char *datatype,
const char *glossary);
struct arg_date* arg_daten(const char* shortopts,
const char* longopts,
const char* format,
const char* datatype,
struct arg_date *arg_date1(const char *shortopts,
const char *longopts,
const char *format,
const char *datatype,
const char *glossary);
struct arg_date *arg_daten(const char *shortopts,
const char *longopts,
const char *format,
const char *datatype,
int mincount,
int maxcount,
const char *glossary);
struct arg_end* arg_end(int maxerrors);
struct arg_end *arg_end(int maxerrors);
/**** other functions *******************************************/
@ -293,7 +282,7 @@ void arg_print_syntax(FILE *fp, void **argtable, const char *suffix);
void arg_print_syntaxv(FILE *fp, void **argtable, const char *suffix);
void arg_print_glossary(FILE *fp, void **argtable, const char *format);
void arg_print_glossary_gnu(FILE *fp, void **argtable);
void arg_print_errors(FILE* fp, struct arg_end* end, const char* progname);
void arg_print_errors(FILE *fp, struct arg_end *end, const char *progname);
void arg_freetable(void **argtable, size_t n);
/**** deprecated functions, for back-compatibility only ********/

View file

@ -19,7 +19,8 @@ char *programHint = NULL;
char *programHelp = NULL;
char buf[500] = {0};
int CLIParserInit(char *vprogramName, char *vprogramHint, char *vprogramHelp) {
int CLIParserInit(char *vprogramName, char *vprogramHint, char *vprogramHelp)
{
argtable = NULL;
argtableLen = 0;
programName = vprogramName;
@ -30,7 +31,8 @@ int CLIParserInit(char *vprogramName, char *vprogramHint, char *vprogramHelp) {
return 0;
}
int CLIParserParseArg(int argc, char **argv, void* vargtable[], size_t vargtableLen, bool allowEmptyExec) {
int CLIParserParseArg(int argc, char **argv, void *vargtable[], size_t vargtableLen, bool allowEmptyExec)
{
int nerrors;
argtable = vargtable;
@ -46,7 +48,7 @@ int CLIParserParseArg(int argc, char **argv, void* vargtable[], size_t vargtable
nerrors = arg_parse(argc, argv, argtable);
/* special case: '--help' takes precedence over error reporting */
if ((argc < 2 && !allowEmptyExec) ||((struct arg_lit *)argtable[0])->count > 0) { // help must be the first record
if ((argc < 2 && !allowEmptyExec) || ((struct arg_lit *)argtable[0])->count > 0) { // help must be the first record
printf("Usage: %s", programName);
arg_print_syntaxv(stdout, argtable, "\n");
if (programHint)
@ -79,11 +81,13 @@ enum ParserState {
#define isSpace(c)(c == ' ' || c == '\t')
int CLIParserParseString(const char* str, void* vargtable[], size_t vargtableLen, bool allowEmptyExec) {
int CLIParserParseString(const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec)
{
return CLIParserParseStringEx(str, vargtable, vargtableLen, allowEmptyExec, false);
}
int CLIParserParseStringEx(const char* str, void* vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData) {
int CLIParserParseStringEx(const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData)
{
int argc = 0;
char *argv[200] = {NULL};
@ -101,9 +105,9 @@ int CLIParserParseStringEx(const char* str, void* vargtable[], size_t vargtableL
// parse params
for (int i = 0; i < len; i++) {
switch(state){
switch (state) {
case PS_FIRST: // first char
if (!clueData || str[i] == '-'){ // first char before space is '-' - next element - option OR not "clueData" for not-option fields
if (!clueData || str[i] == '-') { // first char before space is '-' - next element - option OR not "clueData" for not-option fields
state = PS_OPTION;
if (spaceptr) {
@ -125,7 +129,7 @@ int CLIParserParseStringEx(const char* str, void* vargtable[], size_t vargtableL
bufptr++;
break;
case PS_OPTION:
if (isSpace(str[i])){
if (isSpace(str[i])) {
state = PS_FIRST;
*bufptr = 0x00;
@ -143,7 +147,8 @@ int CLIParserParseStringEx(const char* str, void* vargtable[], size_t vargtableL
return CLIParserParseArg(argc, argv, vargtable, vargtableLen, allowEmptyExec);
}
void CLIParserFree() {
void CLIParserFree()
{
arg_freetable(argtable, argtableLen);
argtable = NULL;
@ -151,7 +156,8 @@ void CLIParserFree() {
}
// convertors
int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) {
int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen)
{
*datalen = 0;
int ibuf = 0;
@ -160,7 +166,7 @@ int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
if (res || !ibuf)
return res;
switch(param_gethex_to_eol((char *)buf, 0, data, maxdatalen, datalen)) {
switch (param_gethex_to_eol((char *)buf, 0, data, maxdatalen, datalen)) {
case 1:
printf("Parameter error: Invalid HEX value.\n");
return 1;
@ -175,7 +181,8 @@ int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
return 0;
}
int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) {
int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen)
{
*datalen = 0;
if (!argstr->count)
return 0;

View file

@ -32,9 +32,9 @@
#define CLIGetStrWithReturn(paramnum, data, datalen) if (CLIParamStrToBuf(arg_get_str(paramnum), data, sizeof(data), datalen)) {CLIParserFree();return 1;}
extern int CLIParserInit(char *vprogramName, char *vprogramHint, char *vprogramHelp);
extern int CLIParserParseString(const char* str, void* argtable[], size_t vargtableLen, bool allowEmptyExec);
extern int CLIParserParseStringEx(const char* str, void* vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData);
extern int CLIParserParseArg(int argc, char **argv, void* argtable[], size_t vargtableLen, bool allowEmptyExec);
extern int CLIParserParseString(const char *str, void *argtable[], size_t vargtableLen, bool allowEmptyExec);
extern int CLIParserParseStringEx(const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData);
extern int CLIParserParseArg(int argc, char **argv, void *argtable[], size_t vargtableLen, bool allowEmptyExec);
extern void CLIParserFree();
extern int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen);

View file

@ -60,13 +60,13 @@ struct option {
};
__BEGIN_DECLS
int getopt_long(int, char * const *, const char *,
int getopt_long(int, char *const *, const char *,
const struct option *, int *);
int getopt_long_only(int, char * const *, const char *,
int getopt_long_only(int, char *const *, const char *,
const struct option *, int *);
#ifndef _GETOPT_DECLARED
#define _GETOPT_DECLARED
int getopt(int, char * const [], const char *);
int getopt(int, char *const [], const char *);
extern char *optarg; /* getopt(3) external variables */
extern int optind, opterr, optopt;

View file

@ -11,7 +11,8 @@
static int CmdHelp(const char *Cmd);
int usage_analyse_lcr(void) {
int usage_analyse_lcr(void)
{
PrintAndLogEx(NORMAL, "Specifying the bytes of a UID with a known LRC will find the last byte value");
PrintAndLogEx(NORMAL, "needed to generate that LRC with a rolling XOR. All bytes should be specified in HEX.");
PrintAndLogEx(NORMAL, "");
@ -25,7 +26,8 @@ int usage_analyse_lcr(void) {
PrintAndLogEx(NORMAL, "expected output: Target (BA) requires final LRC XOR byte value: 5A");
return 0;
}
int usage_analyse_checksum(void) {
int usage_analyse_checksum(void)
{
PrintAndLogEx(NORMAL, "The bytes will be added with eachother and than limited with the applied mask");
PrintAndLogEx(NORMAL, "Finally compute ones' complement of the least significant bytes");
PrintAndLogEx(NORMAL, "");
@ -41,7 +43,8 @@ int usage_analyse_checksum(void) {
PrintAndLogEx(NORMAL, "expected output: 0x61");
return 0;
}
int usage_analyse_crc(void){
int usage_analyse_crc(void)
{
PrintAndLogEx(NORMAL, "A stub method to test different crc implementations inside the PM3 sourcecode. Just because you figured out the poly, doesn't mean you get the desired output");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: analyse crc [h] <bytes>");
@ -53,7 +56,8 @@ int usage_analyse_crc(void){
PrintAndLogEx(NORMAL, " analyse crc 137AF00A0A0D");
return 0;
}
int usage_analyse_nuid(void){
int usage_analyse_nuid(void)
{
PrintAndLogEx(NORMAL, "Generate 4byte NUID from 7byte UID");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: analyse hid [h] <bytes>");
@ -65,7 +69,8 @@ int usage_analyse_nuid(void){
PrintAndLogEx(NORMAL, " analyse nuid 11223344556677");
return 0;
}
int usage_analyse_a(void) {
int usage_analyse_a(void)
{
PrintAndLogEx(NORMAL, "Iceman's personal garbage test command");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: analyse a [h] d <bytes>");
@ -78,7 +83,8 @@ int usage_analyse_a(void) {
return 0;
}
static uint8_t calculateLRC( uint8_t* bytes, uint8_t len) {
static uint8_t calculateLRC(uint8_t *bytes, uint8_t len)
{
uint8_t LRC = 0;
for (uint8_t i = 0; i < len; i++)
LRC ^= bytes[i];
@ -102,7 +108,8 @@ static uint16_t shiftadd ( uint8_t* bytes, uint8_t len){
return 0;
}
*/
static uint16_t calcSumCrumbAdd( uint8_t* bytes, uint8_t len, uint32_t mask) {
static uint16_t calcSumCrumbAdd(uint8_t *bytes, uint8_t len, uint32_t mask)
{
uint16_t sum = 0;
for (uint8_t i = 0; i < len; i++) {
sum += CRUMB(bytes[i], 0);
@ -113,10 +120,12 @@ static uint16_t calcSumCrumbAdd( uint8_t* bytes, uint8_t len, uint32_t mask) {
sum &= mask;
return sum;
}
static uint16_t calcSumCrumbAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask) {
static uint16_t calcSumCrumbAddOnes(uint8_t *bytes, uint8_t len, uint32_t mask)
{
return (~calcSumCrumbAdd(bytes, len, mask) & mask);
}
static uint16_t calcSumNibbleAdd( uint8_t* bytes, uint8_t len, uint32_t mask) {
static uint16_t calcSumNibbleAdd(uint8_t *bytes, uint8_t len, uint32_t mask)
{
uint16_t sum = 0;
for (uint8_t i = 0; i < len; i++) {
sum += NIBBLE_LOW(bytes[i]);
@ -125,10 +134,12 @@ static uint16_t calcSumNibbleAdd( uint8_t* bytes, uint8_t len, uint32_t mask) {
sum &= mask;
return sum;
}
static uint16_t calcSumNibbleAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask){
static uint16_t calcSumNibbleAddOnes(uint8_t *bytes, uint8_t len, uint32_t mask)
{
return (~calcSumNibbleAdd(bytes, len, mask) & mask);
}
static uint16_t calcSumCrumbXor( uint8_t* bytes, uint8_t len, uint32_t mask) {
static uint16_t calcSumCrumbXor(uint8_t *bytes, uint8_t len, uint32_t mask)
{
uint16_t sum = 0;
for (uint8_t i = 0; i < len; i++) {
sum ^= CRUMB(bytes[i], 0);
@ -139,7 +150,8 @@ static uint16_t calcSumCrumbXor( uint8_t* bytes, uint8_t len, uint32_t mask) {
sum &= mask;
return sum;
}
static uint16_t calcSumNibbleXor( uint8_t* bytes, uint8_t len, uint32_t mask) {
static uint16_t calcSumNibbleXor(uint8_t *bytes, uint8_t len, uint32_t mask)
{
uint16_t sum = 0;
for (uint8_t i = 0; i < len; i++) {
sum ^= NIBBLE_LOW(bytes[i]);
@ -148,7 +160,8 @@ static uint16_t calcSumNibbleXor( uint8_t* bytes, uint8_t len, uint32_t mask) {
sum &= mask;
return sum;
}
static uint16_t calcSumByteXor( uint8_t* bytes, uint8_t len, uint32_t mask) {
static uint16_t calcSumByteXor(uint8_t *bytes, uint8_t len, uint32_t mask)
{
uint16_t sum = 0;
for (uint8_t i = 0; i < len; i++) {
sum ^= bytes[i];
@ -156,7 +169,8 @@ static uint16_t calcSumByteXor( uint8_t* bytes, uint8_t len, uint32_t mask) {
sum &= mask;
return sum;
}
static uint16_t calcSumByteAdd( uint8_t* bytes, uint8_t len, uint32_t mask) {
static uint16_t calcSumByteAdd(uint8_t *bytes, uint8_t len, uint32_t mask)
{
uint16_t sum = 0;
for (uint8_t i = 0; i < len; i++) {
sum += bytes[i];
@ -165,11 +179,13 @@ static uint16_t calcSumByteAdd( uint8_t* bytes, uint8_t len, uint32_t mask) {
return sum;
}
// Ones complement
static uint16_t calcSumByteAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask) {
static uint16_t calcSumByteAddOnes(uint8_t *bytes, uint8_t len, uint32_t mask)
{
return (~calcSumByteAdd(bytes, len, mask) & mask);
}
static uint16_t calcSumByteSub( uint8_t* bytes, uint8_t len, uint32_t mask) {
static uint16_t calcSumByteSub(uint8_t *bytes, uint8_t len, uint32_t mask)
{
uint8_t sum = 0;
for (uint8_t i = 0; i < len; i++) {
sum -= bytes[i];
@ -177,10 +193,12 @@ static uint16_t calcSumByteSub( uint8_t* bytes, uint8_t len, uint32_t mask) {
sum &= mask;
return sum;
}
static uint16_t calcSumByteSubOnes( uint8_t* bytes, uint8_t len, uint32_t mask){
static uint16_t calcSumByteSubOnes(uint8_t *bytes, uint8_t len, uint32_t mask)
{
return (~calcSumByteSub(bytes, len, mask) & mask);
}
static uint16_t calcSumNibbleSub( uint8_t* bytes, uint8_t len, uint32_t mask) {
static uint16_t calcSumNibbleSub(uint8_t *bytes, uint8_t len, uint32_t mask)
{
uint8_t sum = 0;
for (uint8_t i = 0; i < len; i++) {
sum -= NIBBLE_LOW(bytes[i]);
@ -189,14 +207,16 @@ static uint16_t calcSumNibbleSub( uint8_t* bytes, uint8_t len, uint32_t mask) {
sum &= mask;
return sum;
}
static uint16_t calcSumNibbleSubOnes( uint8_t* bytes, uint8_t len, uint32_t mask) {
static uint16_t calcSumNibbleSubOnes(uint8_t *bytes, uint8_t len, uint32_t mask)
{
return (~calcSumNibbleSub(bytes, len, mask) & mask);
}
// BSD shift checksum 8bit version
static uint16_t calcBSDchecksum8( uint8_t* bytes, uint8_t len, uint32_t mask){
static uint16_t calcBSDchecksum8(uint8_t *bytes, uint8_t len, uint32_t mask)
{
uint16_t sum = 0;
for(uint8_t i = 0; i < len; i++){
for (uint8_t i = 0; i < len; i++) {
sum = ((sum & 0xFF) >> 1) | ((sum & 0x1) << 7); // rotate accumulator
sum += bytes[i]; // add next byte
sum &= 0xFF; //
@ -205,9 +225,10 @@ static uint16_t calcBSDchecksum8( uint8_t* bytes, uint8_t len, uint32_t mask){
return sum;
}
// BSD shift checksum 4bit version
static uint16_t calcBSDchecksum4( uint8_t* bytes, uint8_t len, uint32_t mask){
static uint16_t calcBSDchecksum4(uint8_t *bytes, uint8_t len, uint32_t mask)
{
uint16_t sum = 0;
for(uint8_t i = 0; i < len; i++){
for (uint8_t i = 0; i < len; i++) {
sum = ((sum & 0xF) >> 1) | ((sum & 0x1) << 3); // rotate accumulator
sum += NIBBLE_HIGH(bytes[i]); // add high nibble
sum &= 0xF; //
@ -220,7 +241,8 @@ static uint16_t calcBSDchecksum4( uint8_t* bytes, uint8_t len, uint32_t mask){
}
// measuring LFSR maximum length
int CmdAnalyseLfsr(const char *Cmd){
int CmdAnalyseLfsr(const char *Cmd)
{
uint16_t start_state = 0; /* Any nonzero start state will work. */
uint16_t lfsr = start_state;
@ -230,7 +252,7 @@ int CmdAnalyseLfsr(const char *Cmd){
uint8_t find = param_get8ex(Cmd, 1, 0, 16);
PrintAndLogEx(NORMAL, "LEGIC LFSR IV 0x%02X: \n", iv);
PrintAndLogEx(NORMAL, " bit# | lfsr | ^0x40 | 0x%02X ^ lfsr \n",find);
PrintAndLogEx(NORMAL, " bit# | lfsr | ^0x40 | 0x%02X ^ lfsr \n", find);
for (uint8_t i = 0x01; i < 0x30; i += 1) {
//period = 0;
@ -238,14 +260,15 @@ int CmdAnalyseLfsr(const char *Cmd){
legic_prng_forward(i);
lfsr = legic_prng_get_bits(12);
PrintAndLogEx(NORMAL, " %02X | %03X | %03X | %03X \n",i, lfsr, 0x40 ^ lfsr, find ^ lfsr);
PrintAndLogEx(NORMAL, " %02X | %03X | %03X | %03X \n", i, lfsr, 0x40 ^ lfsr, find ^ lfsr);
}
return 0;
}
int CmdAnalyseLCR(const char *Cmd) {
int CmdAnalyseLCR(const char *Cmd)
{
uint8_t data[50];
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0|| cmdp == 'h') return usage_analyse_lcr();
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_analyse_lcr();
int len = 0;
switch (param_gethex_to_eol(Cmd, 0, data, sizeof(data), &len)) {
@ -260,28 +283,29 @@ int CmdAnalyseLCR(const char *Cmd) {
return 1;
}
uint8_t finalXor = calculateLRC(data, len);
PrintAndLogEx(NORMAL, "Target [%02X] requires final LRC XOR byte value: 0x%02X",data[len-1] ,finalXor);
PrintAndLogEx(NORMAL, "Target [%02X] requires final LRC XOR byte value: 0x%02X", data[len - 1], finalXor);
return 0;
}
int CmdAnalyseCRC(const char *Cmd) {
int CmdAnalyseCRC(const char *Cmd)
{
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_analyse_crc();
int len = strlen(Cmd);
if ( len & 1 ) return usage_analyse_crc();
if (len & 1) return usage_analyse_crc();
// add 1 for null terminator.
uint8_t *data = calloc(len+1, sizeof(uint8_t));
if ( !data ) return 1;
uint8_t *data = calloc(len + 1, sizeof(uint8_t));
if (!data) return 1;
if ( param_gethex(Cmd, 0, data, len)) {
if (param_gethex(Cmd, 0, data, len)) {
free(data);
return usage_analyse_crc();
}
len >>= 1;
PrintAndLogEx(NORMAL, "\nTests with (%d) | %s",len, sprint_hex(data, len));
PrintAndLogEx(NORMAL, "\nTests with (%d) | %s", len, sprint_hex(data, len));
// 51 f5 7a d6
uint8_t uid[] = {0x51, 0xf5, 0x7a, 0xd6}; //12 34 56
@ -292,7 +316,7 @@ int CmdAnalyseCRC(const char *Cmd) {
PrintAndLogEx(NORMAL, "FeliCa | %X ", crc16_xmodem(data, len));
PrintAndLogEx(NORMAL, "\nTests of reflection. Current methods in source code");
PrintAndLogEx(NORMAL, " reflect(0x3e23L,3) is %04X == 0x3e26", reflect(0x3e23L,3) );
PrintAndLogEx(NORMAL, " reflect(0x3e23L,3) is %04X == 0x3e26", reflect(0x3e23L, 3));
PrintAndLogEx(NORMAL, " reflect8(0x80) is %02X == 0x01", reflect8(0x80));
PrintAndLogEx(NORMAL, " reflect16(0x8000) is %04X == 0x0001", reflect16(0xc6c6));
@ -301,14 +325,14 @@ int CmdAnalyseCRC(const char *Cmd) {
compute_crc(CRC_14443_B, data, len, &b1, &b2);
uint16_t crcBB_1 = b1 << 8 | b2;
uint16_t bbb = crc(CRC_14443_B, data, len);
PrintAndLogEx(NORMAL, "ISO14443 crc B | %04x == %04x \n", crcBB_1, bbb );
PrintAndLogEx(NORMAL, "ISO14443 crc B | %04x == %04x \n", crcBB_1, bbb);
// Test of CRC16, '123456789' string.
//
PrintAndLogEx(NORMAL, "\n\nStandard test with 31 32 33 34 35 36 37 38 39 '123456789'\n\n");
uint8_t dataStr[] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39 };
uint8_t dataStr[] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 };
legic8 = CRC8Legic(dataStr, sizeof(dataStr));
//these below has been tested OK.
@ -323,33 +347,33 @@ int CmdAnalyseCRC(const char *Cmd) {
// input from commandline
PrintAndLogEx(NORMAL, "CCITT | %X (29B1 expected)", crc(CRC_CCITT, dataStr, sizeof(dataStr)));
uint8_t poll[] = {0xb2,0x4d,0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80, 0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f};
PrintAndLogEx(NORMAL, "FeliCa | %04X (B37F expected)", crc(CRC_FELICA, poll+2, sizeof(poll)-4));
PrintAndLogEx(NORMAL, "FeliCa | %04X (0000 expected)", crc(CRC_FELICA, poll+2, sizeof(poll)-2));
uint8_t poll[] = {0xb2, 0x4d, 0x12, 0x01, 0x01, 0x2e, 0x3d, 0x17, 0x26, 0x47, 0x80, 0x95, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0xb3, 0x7f};
PrintAndLogEx(NORMAL, "FeliCa | %04X (B37F expected)", crc(CRC_FELICA, poll + 2, sizeof(poll) - 4));
PrintAndLogEx(NORMAL, "FeliCa | %04X (0000 expected)", crc(CRC_FELICA, poll + 2, sizeof(poll) - 2));
uint8_t sel_corr[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x43, 0x01};
PrintAndLogEx(NORMAL, "iCLASS | %04x (0143 expected)", crc(CRC_ICLASS, sel_corr, sizeof(sel_corr)-2));
PrintAndLogEx(NORMAL, "iCLASS | %04x (0143 expected)", crc(CRC_ICLASS, sel_corr, sizeof(sel_corr) - 2));
PrintAndLogEx(NORMAL, "---------------------------------------------------------------\n\n\n");
// ISO14443 crc A
compute_crc(CRC_14443_A, dataStr, sizeof(dataStr), &b1, &b2);
uint16_t crcAA = b1 << 8 | b2;
PrintAndLogEx(NORMAL, "ISO14443 crc A | %04x or %04x (BF05 expected)\n", crcAA, crc(CRC_14443_A, dataStr, sizeof(dataStr)) );
PrintAndLogEx(NORMAL, "ISO14443 crc A | %04x or %04x (BF05 expected)\n", crcAA, crc(CRC_14443_A, dataStr, sizeof(dataStr)));
// ISO14443 crc B
compute_crc(CRC_14443_B, dataStr, sizeof(dataStr), &b1, &b2);
uint16_t crcBB = b1 << 8 | b2;
PrintAndLogEx(NORMAL, "ISO14443 crc B | %04x or %04x (906E expected)\n", crcBB, crc(CRC_14443_B, dataStr, sizeof(dataStr)) );
PrintAndLogEx(NORMAL, "ISO14443 crc B | %04x or %04x (906E expected)\n", crcBB, crc(CRC_14443_B, dataStr, sizeof(dataStr)));
// ISO15693 crc (x.25)
compute_crc(CRC_15693, dataStr, sizeof(dataStr), &b1, &b2);
uint16_t crcCC = b1 << 8 | b2;
PrintAndLogEx(NORMAL, "ISO15693 crc X25| %04x or %04x (906E expected)\n", crcCC, crc(CRC_15693, dataStr, sizeof(dataStr)) );
PrintAndLogEx(NORMAL, "ISO15693 crc X25| %04x or %04x (906E expected)\n", crcCC, crc(CRC_15693, dataStr, sizeof(dataStr)));
// ICLASS
compute_crc(CRC_ICLASS, dataStr, sizeof(dataStr), &b1, &b2);
uint16_t crcDD = b1 << 8 | b2;
PrintAndLogEx(NORMAL, "ICLASS crc | %04x or %04x\n", crcDD, crc(CRC_ICLASS, dataStr, sizeof(dataStr)) );
PrintAndLogEx(NORMAL, "ICLASS crc | %04x or %04x\n", crcDD, crc(CRC_ICLASS, dataStr, sizeof(dataStr)));
// FeliCa
compute_crc(CRC_FELICA, dataStr, sizeof(dataStr), &b1, &b2);
@ -359,7 +383,8 @@ int CmdAnalyseCRC(const char *Cmd) {
free(data);
return 0;
}
int CmdAnalyseCHKSUM(const char *Cmd){
int CmdAnalyseCHKSUM(const char *Cmd)
{
uint8_t data[50];
uint8_t cmdp = 0;
@ -369,18 +394,18 @@ int CmdAnalyseCHKSUM(const char *Cmd){
int len = 0;
memset(data, 0x0, sizeof(data));
while(param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch(param_getchar(Cmd, cmdp)) {
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (param_getchar(Cmd, cmdp)) {
case 'b':
case 'B':
param_gethex_ex(Cmd, cmdp+1, data, &len);
if ( len%2 ) errors = true;
param_gethex_ex(Cmd, cmdp + 1, data, &len);
if (len % 2) errors = true;
len >>= 1;
cmdp += 2;
break;
case 'm':
case 'M':
mask = param_get32ex(Cmd, cmdp+1, 0, 16);
mask = param_get32ex(Cmd, cmdp + 1, 0, 16);
cmdp += 2;
break;
case 'v':
@ -398,7 +423,7 @@ int CmdAnalyseCHKSUM(const char *Cmd){
}
}
//Validations
if (errors || cmdp == 0 ) return usage_analyse_checksum();
if (errors || cmdp == 0) return usage_analyse_checksum();
if (useHeader) {
PrintAndLogEx(NORMAL, " add | sub | add 1's compl | sub 1's compl | xor");
@ -425,33 +450,35 @@ int CmdAnalyseCHKSUM(const char *Cmd){
return 0;
}
int CmdAnalyseDates(const char *Cmd){
int CmdAnalyseDates(const char *Cmd)
{
// look for datestamps in a given array of bytes
PrintAndLogEx(NORMAL, "To be implemented. Feel free to contribute!");
return 0;
}
int CmdAnalyseTEASelfTest(const char *Cmd){
int CmdAnalyseTEASelfTest(const char *Cmd)
{
uint8_t v[8], v_le[8];
memset(v, 0x00, sizeof(v));
memset(v_le, 0x00, sizeof(v_le));
uint8_t* v_ptr = v_le;
uint8_t *v_ptr = v_le;
uint8_t cmdlen = strlen(Cmd);
cmdlen = ( sizeof(v)<<2 < cmdlen ) ? sizeof(v)<<2 : cmdlen;
cmdlen = (sizeof(v) << 2 < cmdlen) ? sizeof(v) << 2 : cmdlen;
if ( param_gethex(Cmd, 0, v, cmdlen) > 0 ){
if (param_gethex(Cmd, 0, v, cmdlen) > 0) {
PrintAndLogEx(WARNING, "Can't read hex chars, uneven? :: %u", cmdlen);
return 1;
}
SwapEndian64ex(v , 8, 4, v_ptr);
SwapEndian64ex(v, 8, 4, v_ptr);
// ENCRYPTION KEY:
uint8_t key[16] = {0x55,0xFE,0xF6,0x30,0x62,0xBF,0x0B,0xC1,0xC9,0xB3,0x7C,0x34,0x97,0x3E,0x29,0xFB };
uint8_t key[16] = {0x55, 0xFE, 0xF6, 0x30, 0x62, 0xBF, 0x0B, 0xC1, 0xC9, 0xB3, 0x7C, 0x34, 0x97, 0x3E, 0x29, 0xFB };
uint8_t keyle[16];
uint8_t* key_ptr = keyle;
SwapEndian64ex(key , sizeof(key), 4, key_ptr);
uint8_t *key_ptr = keyle;
SwapEndian64ex(key, sizeof(key), 4, key_ptr);
PrintAndLogEx(NORMAL, "TEST LE enc| %s", sprint_hex(v_ptr, 8));
@ -465,7 +492,8 @@ int CmdAnalyseTEASelfTest(const char *Cmd){
return 0;
}
char* pb(uint32_t b) {
char *pb(uint32_t b)
{
static char buf1[33] = {0};
static char buf2[33] = {0};
static char *s;
@ -478,14 +506,15 @@ char* pb(uint32_t b) {
memset(s, 0, sizeof(buf1));
uint32_t mask = 0x80000000;
for (uint8_t i=0; i<32;i++) {
s[i] = (mask & b)?'1':'0';
for (uint8_t i = 0; i < 32; i++) {
s[i] = (mask & b) ? '1' : '0';
mask >>= 1;
}
return s;
}
int CmdAnalyseA(const char *Cmd){
int CmdAnalyseA(const char *Cmd)
{
int hexlen = 0;
uint8_t cmdp = 0;
@ -495,10 +524,10 @@ int CmdAnalyseA(const char *Cmd){
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'd':
param_gethex_ex(Cmd, cmdp+1, data, &hexlen);
param_gethex_ex(Cmd, cmdp + 1, data, &hexlen);
hexlen >>= 1;
if ( hexlen != sizeof(data) ) {
PrintAndLogEx(WARNING, "Read %d bytes of %u", hexlen, sizeof(data) );
if (hexlen != sizeof(data)) {
PrintAndLogEx(WARNING, "Read %d bytes of %u", hexlen, sizeof(data));
}
cmdp += 2;
break;
@ -511,7 +540,7 @@ int CmdAnalyseA(const char *Cmd){
}
}
//Validations
if (errors || cmdp == 0 ) return usage_analyse_a();
if (errors || cmdp == 0) return usage_analyse_a();
UsbCommand c = {CMD_FPC_SEND, {0, 0, 0}};
@ -536,7 +565,7 @@ int CmdAnalyseA(const char *Cmd){
// Sequence X followed by Sequence Y followed by Sequence Z (111100x1 11111111 00x11111)
// we therefore look for a ...xx1111 11111111 00x11111xxxxxx... pattern
// (12 '1's followed by 2 '0's, eventually followed by another '0', followed by 5 '1's)
# define SYNC_16BIT 0xB24D
# define SYNC_16BIT 0xB24D
uint32_t shiftReg = param_get32ex(Cmd, 0, 0xb24d, 16);
uint8_t bt = param_get8ex(Cmd, 1, 0xBB, 16);
uint8_t byte_offset = 99;
@ -550,47 +579,47 @@ int CmdAnalyseA(const char *Cmd){
uint8_t n0 = 0, n1 = 0;
n0 = (rev & (uint8_t)(~(0xFF >> (8-4)))) >> 4;
n0 = (rev & (uint8_t)(~(0xFF >> (8 - 4)))) >> 4;
n1 = (n1 << 4) | (rev & (uint8_t)(~(0xFF << 4)));
PrintAndLogEx(NORMAL, "rev %02X | %02X %s | %02X %s |\n", rev, n0, pb(n0), n1, pb(n1) );
PrintAndLogEx(NORMAL, "rev %02X | %02X %s | %02X %s |\n", rev, n0, pb(n0), n1, pb(n1));
/*
hex(0xb24d shr 0) 0xB24D 0b1011001001001101
hex(0xb24d shr 1) 0x5926
hex(0xb24d shr 2) 0x2C93
*/
/*
hex(0xb24d shr 0) 0xB24D 0b1011001001001101
hex(0xb24d shr 1) 0x5926
hex(0xb24d shr 2) 0x2C93
*/
for ( int i =0; i< 16; i++) {
PrintAndLogEx(NORMAL, " (shiftReg >> %d) & 0xFFFF == %08x ---", i, (( shiftReg >> i) & 0xFFFF ));
for (int i = 0; i < 16; i++) {
PrintAndLogEx(NORMAL, " (shiftReg >> %d) & 0xFFFF == %08x ---", i, ((shiftReg >> i) & 0xFFFF));
// kolla om SYNC_PATTERN finns.
if ((( shiftReg >> 7) & 0xFFFF ) == SYNC_16BIT) byte_offset = 7;
else if ((( shiftReg >> 6) & 0xFFFF ) == SYNC_16BIT) byte_offset = 6;
else if ((( shiftReg >> 5) & 0xFFFF ) == SYNC_16BIT) byte_offset = 5;
else if ((( shiftReg >> 4) & 0xFFFF ) == SYNC_16BIT) byte_offset = 4;
else if ((( shiftReg >> 3) & 0xFFFF ) == SYNC_16BIT) byte_offset = 3;
else if ((( shiftReg >> 2) & 0xFFFF ) == SYNC_16BIT) byte_offset = 2;
else if ((( shiftReg >> 1) & 0xFFFF ) == SYNC_16BIT) byte_offset = 1;
else if ((( shiftReg >> 0) & 0xFFFF ) == SYNC_16BIT) byte_offset = 0;
if (((shiftReg >> 7) & 0xFFFF) == SYNC_16BIT) byte_offset = 7;
else if (((shiftReg >> 6) & 0xFFFF) == SYNC_16BIT) byte_offset = 6;
else if (((shiftReg >> 5) & 0xFFFF) == SYNC_16BIT) byte_offset = 5;
else if (((shiftReg >> 4) & 0xFFFF) == SYNC_16BIT) byte_offset = 4;
else if (((shiftReg >> 3) & 0xFFFF) == SYNC_16BIT) byte_offset = 3;
else if (((shiftReg >> 2) & 0xFFFF) == SYNC_16BIT) byte_offset = 2;
else if (((shiftReg >> 1) & 0xFFFF) == SYNC_16BIT) byte_offset = 1;
else if (((shiftReg >> 0) & 0xFFFF) == SYNC_16BIT) byte_offset = 0;
PrintAndLogEx(NORMAL, "Offset %u \n", byte_offset);
if ( byte_offset != 99 )
if (byte_offset != 99)
break;
shiftReg >>=1;
}
shiftReg >>= 1;
}
uint8_t p1 = (rev & (uint8_t)(~(0xFF << byte_offset)));
PrintAndLogEx(NORMAL, "Offset %u | leftovers %02x %s \n", byte_offset, p1, pb(p1) );
PrintAndLogEx(NORMAL, "Offset %u | leftovers %02x %s \n", byte_offset, p1, pb(p1));
/*
pm3 --> da hex2bin 4db2 0100110110110010
*/
pm3 --> da hex2bin 4db2 0100110110110010
*/
return 0;
/*
/*
// split byte into two parts.
uint8_t offset = 3, n0 = 0, n1 = 0;
rev = 0xB2;
@ -605,7 +634,7 @@ pm3 --> da hex2bin 4db2 0100110110110010
//PrintAndLogEx(NORMAL, "~(0xFF >> (8-offset)) == %s |\n", pb( (uint8_t)(~(0xFF >> (8-offset))) ) );
//PrintAndLogEx(NORMAL, " rev & xxx == %s\n\n", pb( (rev & (uint8_t)(~(0xFF << offset))) ));
}
return 0;
return 0;
// from A -- x bits into B and the rest into C.
for ( uint8_t i=0; i<8; i++){
@ -620,30 +649,30 @@ return 0;
// 14443-A
uint8_t u14_c[] = {0x09, 0x78, 0x00, 0x92, 0x02, 0x54, 0x13, 0x02, 0x04, 0x2d, 0xe8 }; // atqs w crc
uint8_t u14_w[] = {0x09, 0x78, 0x00, 0x92, 0x02, 0x54, 0x13, 0x02, 0x04, 0x2d, 0xe7 }; // atqs w crc
PrintAndLogEx(FAILED, "14a check wrong crc | %s\n", (check_crc(CRC_14443_A, u14_w, sizeof(u14_w))) ? "YES": "NO" );
PrintAndLogEx(SUCCESS, "14a check correct crc | %s\n", (check_crc(CRC_14443_A, u14_c, sizeof(u14_c))) ? "YES": "NO" );
PrintAndLogEx(FAILED, "14a check wrong crc | %s\n", (check_crc(CRC_14443_A, u14_w, sizeof(u14_w))) ? "YES" : "NO");
PrintAndLogEx(SUCCESS, "14a check correct crc | %s\n", (check_crc(CRC_14443_A, u14_c, sizeof(u14_c))) ? "YES" : "NO");
// 14443-B
uint8_t u14b[] = {0x05,0x00,0x08,0x39,0x73};
PrintAndLogEx(NORMAL, "14b check crc | %s\n", (check_crc(CRC_14443_B, u14b, sizeof(u14b))) ? "YES": "NO");
uint8_t u14b[] = {0x05, 0x00, 0x08, 0x39, 0x73};
PrintAndLogEx(NORMAL, "14b check crc | %s\n", (check_crc(CRC_14443_B, u14b, sizeof(u14b))) ? "YES" : "NO");
// 15693 test
uint8_t u15_c[] = {0x05,0x00,0x08,0x39,0x73}; // correct
uint8_t u15_w[] = {0x05,0x00,0x08,0x39,0x72}; // wrong
PrintAndLogEx(FAILED, "15 check wrong crc | %s\n", (check_crc(CRC_15693, u15_w, sizeof(u15_w))) ? "YES": "NO");
PrintAndLogEx(SUCCESS, "15 check correct crc | %s\n", (check_crc(CRC_15693, u15_c, sizeof(u15_c))) ? "YES": "NO");
uint8_t u15_c[] = {0x05, 0x00, 0x08, 0x39, 0x73}; // correct
uint8_t u15_w[] = {0x05, 0x00, 0x08, 0x39, 0x72}; // wrong
PrintAndLogEx(FAILED, "15 check wrong crc | %s\n", (check_crc(CRC_15693, u15_w, sizeof(u15_w))) ? "YES" : "NO");
PrintAndLogEx(SUCCESS, "15 check correct crc | %s\n", (check_crc(CRC_15693, u15_c, sizeof(u15_c))) ? "YES" : "NO");
// iCLASS test - wrong crc , swapped bytes.
uint8_t iclass_w[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x01, 0x43};
uint8_t iclass_c[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x43, 0x01};
PrintAndLogEx(FAILED, "iCLASS check wrong crc | %s\n", (check_crc(CRC_ICLASS, iclass_w, sizeof(iclass_w))) ? "YES": "NO");
PrintAndLogEx(SUCCESS, "iCLASS check correct crc | %s\n", (check_crc(CRC_ICLASS, iclass_c, sizeof(iclass_c))) ? "YES": "NO");
PrintAndLogEx(FAILED, "iCLASS check wrong crc | %s\n", (check_crc(CRC_ICLASS, iclass_w, sizeof(iclass_w))) ? "YES" : "NO");
PrintAndLogEx(SUCCESS, "iCLASS check correct crc | %s\n", (check_crc(CRC_ICLASS, iclass_c, sizeof(iclass_c))) ? "YES" : "NO");
// FeliCa test
uint8_t felica_w[] = {0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80, 0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7e};
uint8_t felica_c[] = {0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80, 0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f};
PrintAndLogEx(FAILED, "FeliCa check wrong crc | %s\n", (check_crc(CRC_FELICA, felica_w, sizeof(felica_w))) ? "YES": "NO");
PrintAndLogEx(SUCCESS, "FeliCa check correct crc | %s\n", (check_crc(CRC_FELICA, felica_c, sizeof(felica_c))) ? "YES": "NO");
uint8_t felica_w[] = {0x12, 0x01, 0x01, 0x2e, 0x3d, 0x17, 0x26, 0x47, 0x80, 0x95, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0xb3, 0x7e};
uint8_t felica_c[] = {0x12, 0x01, 0x01, 0x2e, 0x3d, 0x17, 0x26, 0x47, 0x80, 0x95, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0xb3, 0x7f};
PrintAndLogEx(FAILED, "FeliCa check wrong crc | %s\n", (check_crc(CRC_FELICA, felica_w, sizeof(felica_w))) ? "YES" : "NO");
PrintAndLogEx(SUCCESS, "FeliCa check correct crc | %s\n", (check_crc(CRC_FELICA, felica_c, sizeof(felica_c))) ? "YES" : "NO");
PrintAndLogEx(NORMAL, "\n\n");
@ -687,27 +716,35 @@ return 0;
//uint64_t d1[] = {0x6e442129, 0x8f699195, 0x0000001, 0x090d0b0305020f02};
//uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0x00040f0f0305030e};
/*
uid(3e172b29) nt(039b7bd2) ks(0c0e0f0505080800) nr(00000001)
uid(3e172b29) nt(039b7bd2) ks(0e06090d03000b0f) nr(00000002)
*/
/*
uid(3e172b29) nt(039b7bd2) ks(0c0e0f0505080800) nr(00000001)
uid(3e172b29) nt(039b7bd2) ks(0e06090d03000b0f) nr(00000002)
*/
uint64_t *keylistA = NULL, *keylistB = NULL;
uint32_t keycountA = 0, keycountB = 0;
// uint64_t d1[] = {0x3e172b29, 0x039b7bd2, 0x0000001, 0, 0x0c0e0f0505080800};
// uint64_t d2[] = {0x3e172b29, 0x039b7bd2, 0x0000002, 0, 0x0e06090d03000b0f};
uint64_t d1[] = {0x6e442129, 0x8f699195, 0x0000001, 0, 0x090d0b0305020f02};
uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e};
uint64_t d1[] = {0x6e442129, 0x8f699195, 0x0000001, 0, 0x090d0b0305020f02};
uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e};
keycountA = nonce2key(d1[0], d1[1], d1[2], 0, d1[3], d1[4] ,&keylistA);
keycountA = nonce2key(d1[0], d1[1], d1[2], 0, d1[3], d1[4], &keylistA);
keycountB = nonce2key(d2[0], d2[1], d2[2], 0, d2[3], d2[4], &keylistB);
switch (keycountA) {
case 0: PrintAndLogEx(FAILED, "Key test A failed\n"); break;
case 1: PrintAndLogEx(SUCCESS, "KEY A | %012" PRIX64 " ", keylistA[0]); break;
case 0:
PrintAndLogEx(FAILED, "Key test A failed\n");
break;
case 1:
PrintAndLogEx(SUCCESS, "KEY A | %012" PRIX64 " ", keylistA[0]);
break;
}
switch (keycountB) {
case 0: PrintAndLogEx(FAILED, "Key test B failed\n"); break;
case 1: PrintAndLogEx(SUCCESS, "KEY B | %012" PRIX64 " ", keylistB[0]); break;
case 0:
PrintAndLogEx(FAILED, "Key test B failed\n");
break;
case 1:
PrintAndLogEx(SUCCESS, "KEY B | %012" PRIX64 " ", keylistB[0]);
break;
}
free(keylistA);
@ -843,7 +880,8 @@ uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e};
return 0;
}
void generate4bNUID(uint8_t *uid, uint8_t *nuid){
void generate4bNUID(uint8_t *uid, uint8_t *nuid)
{
uint16_t crc;
uint8_t b1, b2;
@ -857,12 +895,13 @@ void generate4bNUID(uint8_t *uid, uint8_t *nuid){
nuid[3] = crc & 0xFF;
}
int CmdAnalyseNuid(const char *Cmd){
int CmdAnalyseNuid(const char *Cmd)
{
uint8_t nuid[4] = {0};
uint8_t uid[7] = {0};
int len = 0;
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0|| cmdp == 'h') return usage_analyse_nuid();
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_analyse_nuid();
/* src: https://www.nxp.com/docs/en/application-note/AN10927.pdf */
/* selftest1 UID 040D681AB52281 -> NUID 8F430FEF */
@ -872,7 +911,7 @@ int CmdAnalyseNuid(const char *Cmd){
generate4bNUID(uid, nuid);
bool test1 = (0 == memcmp(nuid, "\x8f\x43\x0f\xef", 4));
PrintAndLogEx(SUCCESS, "Selftest1 %s\n", test1 ? _GREEN_(OK): _RED_(Fail));
PrintAndLogEx(SUCCESS, "Selftest1 %s\n", test1 ? _GREEN_(OK) : _RED_(Fail));
memcpy(uid, "\x04\x18\x3f\x09\x32\x1b\x85", 7);
generate4bNUID(uid, nuid);
@ -882,7 +921,7 @@ int CmdAnalyseNuid(const char *Cmd){
}
param_gethex_ex(Cmd, 0, uid, &len);
if ( len%2 || len != 14) return usage_analyse_nuid();
if (len % 2 || len != 14) return usage_analyse_nuid();
generate4bNUID(uid, nuid);
@ -903,13 +942,15 @@ static command_t CommandTable[] = {
{NULL, NULL, 0, NULL}
};
int CmdAnalyse(const char *Cmd) {
int CmdAnalyse(const char *Cmd)
{
clearCommandBuffer();
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd) {
int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable);
return 0;
}

View file

@ -11,17 +11,18 @@
#define MAX_ARGS 20
int split(char *str, char *arr[MAX_ARGS]){
int split(char *str, char *arr[MAX_ARGS])
{
int beginIndex = 0;
int endIndex;
int maxWords = MAX_ARGS;
int wordCnt = 0;
while(1){
while(isspace(str[beginIndex])) {
while (1) {
while (isspace(str[beginIndex])) {
++beginIndex;
}
if(str[beginIndex] == '\0') {
if (str[beginIndex] == '\0') {
break;
}
endIndex = beginIndex;
@ -39,7 +40,8 @@ int split(char *str, char *arr[MAX_ARGS]){
return wordCnt;
}
int CmdCrc(const char *Cmd) {
int CmdCrc(const char *Cmd)
{
char name[] = {"reveng "};
char Cmd2[100 + 7];
memcpy(Cmd2, name, 7);
@ -52,7 +54,7 @@ int CmdCrc(const char *Cmd) {
} else {
reveng_main(argc, argv);
}
for(int i = 0; i < argc; ++i) {
for (int i = 0; i < argc; ++i) {
free(argv[i]);
}
return 0;
@ -60,7 +62,8 @@ int CmdCrc(const char *Cmd) {
//returns array of model names and the count of models returning
// as well as a width array for the width of each model
int GetModels(char *Models[], int *count, uint8_t *width){
int GetModels(char *Models[], int *count, uint8_t *width)
{
/* default values */
static model_t model = MZERO;
@ -70,9 +73,9 @@ int GetModels(char *Models[], int *count, uint8_t *width){
model_t pset = model, *candmods, *mptr;
/* stdin must be binary */
#ifdef _WIN32
#ifdef _WIN32
_setmode(STDIN_FILENO, _O_BINARY);
#endif /* _WIN32 */
#endif /* _WIN32 */
SETBMP();
@ -80,7 +83,7 @@ int GetModels(char *Models[], int *count, uint8_t *width){
int Cnt = 0;
if (width[0] == 0) { //reveng -D
*count = mcount();
if (!*count){
if (!*count) {
PrintAndLogEx(WARNING, "no preset models available");
return 0;
}
@ -88,8 +91,8 @@ int GetModels(char *Models[], int *count, uint8_t *width){
mbynum(&model, mode);
mcanon(&model);
size_t size = (model.name && *model.name) ? strlen(model.name) : 7;
char *tmp = calloc(size+1, sizeof(char));
if (tmp==NULL){
char *tmp = calloc(size + 1, sizeof(char));
if (tmp == NULL) {
PrintAndLogEx(WARNING, "out of memory?");
return 0;
}
@ -100,7 +103,7 @@ int GetModels(char *Models[], int *count, uint8_t *width){
mfree(&model);
} else { //reveng -s
if (~model.flags & P_MULXN){
if (~model.flags & P_MULXN) {
PrintAndLogEx(WARNING, "cannot search for non-Williams compliant models");
return 0;
}
@ -133,7 +136,7 @@ int GetModels(char *Models[], int *count, uint8_t *width){
mbynum(&pset, --psets);
/* skip if different width, or refin or refout don't match */
if( plen(pset.spoly) != width[0] || (model.flags ^ pset.flags) & (P_REFIN | P_REFOUT))
if (plen(pset.spoly) != width[0] || (model.flags ^ pset.flags) & (P_REFIN | P_REFOUT))
continue;
/* skip if the preset doesn't match specified parameters */
if (rflags & R_HAVEP && pcmp(&model.spoly, &pset.spoly))
@ -167,8 +170,8 @@ int GetModels(char *Models[], int *count, uint8_t *width){
size_t size = (pset.name && *pset.name) ? strlen(pset.name) : 7;
//PrintAndLogEx(NORMAL, "Size: %d, %s, count: %d",size,pset.name, Cnt);
char *tmp = calloc(size+1, sizeof(char));
if (tmp == NULL){
char *tmp = calloc(size + 1, sizeof(char));
if (tmp == NULL) {
PrintAndLogEx(WARNING, "out of memory?");
return 0;
}
@ -197,12 +200,12 @@ int GetModels(char *Models[], int *count, uint8_t *width){
pfree(qptr);
}
}
if(uflags & C_NOBFS && ~rflags & R_HAVEP) {
if (uflags & C_NOBFS && ~rflags & R_HAVEP) {
PrintAndLogEx(WARNING, "no models found");
return 0;
}
if (!(model.flags & P_REFIN) != !(model.flags & P_REFOUT)){
if (!(model.flags & P_REFIN) != !(model.flags & P_REFOUT)) {
PrintAndLogEx(WARNING, "cannot search for crossed-endian models");
return 0;
}
@ -230,7 +233,7 @@ int GetModels(char *Models[], int *count, uint8_t *width){
free(apolys);
mfree(&model);
if (~uflags & C_RESULT){
if (~uflags & C_RESULT) {
PrintAndLogEx(WARNING, "no models found");
return 0;
}
@ -245,7 +248,8 @@ int GetModels(char *Models[], int *count, uint8_t *width){
//endian = {0 = calc default endian input and output, b = big endian input and output, B = big endian output, r = right justified
// l = little endian input and output, L = little endian output only, t = left justified}
//result = calculated crc hex string
int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *result){
int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *result)
{
/* default values */
static model_t model = MZERO;
@ -257,9 +261,9 @@ int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *res
char *string;
// stdin must be binary
#ifdef _WIN32
#ifdef _WIN32
_setmode(STDIN_FILENO, _O_BINARY);
#endif /* _WIN32 */
#endif /* _WIN32 */
SETBMP();
//set model
@ -268,7 +272,7 @@ int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *res
PrintAndLogEx(WARNING, "error: preset model '%s' not found. Use reveng -D to list presets. [%d]", inModel, c);
return 0;
}
if (c < 0){
if (c < 0) {
PrintAndLogEx(WARNING, "no preset models available");
return 0;
}
@ -353,9 +357,9 @@ int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *res
prev(&crc);
string = ptostr(crc, model.flags, obperhx);
for (int i = 0; i < 50; i++){
for (int i = 0; i < 50; i++) {
result[i] = string[i];
if (result[i]==0) break;
if (result[i] == 0) break;
}
free(string);
pfree(&crc);
@ -364,7 +368,8 @@ int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *res
}
//test call to RunModel
int CmdrevengTestC(const char *Cmd){
int CmdrevengTestC(const char *Cmd)
{
int cmdp = 0;
char inModel[30] = {0x00};
char inHexStr[30] = {0x00};
@ -382,24 +387,26 @@ int CmdrevengTestC(const char *Cmd){
int ans = RunModel(inModel, inHexStr, reverse, endian, result);
if (!ans) return 0;
PrintAndLogEx(SUCCESS, "result: %s",result);
PrintAndLogEx(SUCCESS, "result: %s", result);
return 1;
}
//returns a calloced string (needs to be freed)
char *SwapEndianStr(const char *inStr, const size_t len, const uint8_t blockSize){
char *tmp = calloc(len+1, sizeof(char));
for (uint8_t block=0; block < (uint8_t)(len/blockSize); block++){
for (size_t i = 0; i < blockSize; i+=2){
tmp[i+(blockSize*block)] = inStr[(blockSize-1-i-1)+(blockSize*block)];
tmp[i+(blockSize*block)+1] = inStr[(blockSize-1-i)+(blockSize*block)];
char *SwapEndianStr(const char *inStr, const size_t len, const uint8_t blockSize)
{
char *tmp = calloc(len + 1, sizeof(char));
for (uint8_t block = 0; block < (uint8_t)(len / blockSize); block++) {
for (size_t i = 0; i < blockSize; i += 2) {
tmp[i + (blockSize * block)] = inStr[(blockSize - 1 - i - 1) + (blockSize * block)];
tmp[i + (blockSize * block) + 1] = inStr[(blockSize - 1 - i) + (blockSize * block)];
}
}
return tmp;
}
// takes hex string in and searches for a matching result (hex string must include checksum)
int CmdrevengSearch(const char *Cmd){
int CmdrevengSearch(const char *Cmd)
{
#define NMODELS 105
@ -420,35 +427,35 @@ int CmdrevengSearch(const char *Cmd){
if (!ans) return 0;
// try each model and get result
for (int i = 0; i < count; i++){
for (int i = 0; i < count; i++) {
/*if (found) {
free(Models[i]);
continue;
}*/
// round up to # of characters in this model's crc
crcChars = ((width[i]+7)/8)*2;
crcChars = ((width[i] + 7) / 8) * 2;
// can't test a model that has more crc digits than our data
if (crcChars >= dataLen)
continue;
memset(result, 0, 30);
char *inCRC = calloc(crcChars+1, sizeof(char));
memcpy(inCRC, inHexStr+(dataLen-crcChars), crcChars);
char *inCRC = calloc(crcChars + 1, sizeof(char));
memcpy(inCRC, inHexStr + (dataLen - crcChars), crcChars);
char *outHex = calloc(dataLen-crcChars+1, sizeof(char));
memcpy(outHex, inHexStr, dataLen-crcChars);
char *outHex = calloc(dataLen - crcChars + 1, sizeof(char));
memcpy(outHex, inHexStr, dataLen - crcChars);
PrintAndLogEx(DEBUG, "DEBUG: dataLen: %d, crcChars: %d, Model: %s, CRC: %s, width: %d, outHex: %s",dataLen, crcChars, Models[i], inCRC, width[i], outHex);
PrintAndLogEx(DEBUG, "DEBUG: dataLen: %d, crcChars: %d, Model: %s, CRC: %s, width: %d, outHex: %s", dataLen, crcChars, Models[i], inCRC, width[i], outHex);
ans = RunModel(Models[i], outHex, false, 0, result);
if (ans) {
// test for match
if (memcmp(result, inCRC, crcChars) == 0){
if (memcmp(result, inCRC, crcChars) == 0) {
PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel: %s | value: %s\n", Models[i], result);
//optional - stop searching if found...
found = true;
} else {
if (crcChars > 2){
if (crcChars > 2) {
char *swapEndian = SwapEndianStr(result, crcChars, crcChars);
if (memcmp(swapEndian, inCRC, crcChars) == 0){
if (memcmp(swapEndian, inCRC, crcChars) == 0) {
PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel: %s | value endian swapped: %s\n", Models[i], swapEndian);
// optional - stop searching if found...
found = true;
@ -460,14 +467,14 @@ int CmdrevengSearch(const char *Cmd){
ans = RunModel(Models[i], outHex, true, 0, revResult);
if (ans) {
// test for match
if (memcmp(revResult, inCRC, crcChars) == 0){
if (memcmp(revResult, inCRC, crcChars) == 0) {
PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel reversed: %s | value: %s\n", Models[i], revResult);
// optional - stop searching if found...
found = true;
} else {
if (crcChars > 2){
if (crcChars > 2) {
char *swapEndian = SwapEndianStr(revResult, crcChars, crcChars);
if (memcmp(swapEndian, inCRC, crcChars) == 0){
if (memcmp(swapEndian, inCRC, crcChars) == 0) {
PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel reversed: %s | value endian swapped: %s\n", Models[i], swapEndian);
// optional - stop searching if found...
found = true;

File diff suppressed because it is too large Load diff

View file

@ -32,7 +32,7 @@
#include "loclass/cipherutils.h" // for decimating samples in getsamples
#include "cmdlfem4x.h" // askem410xdecode
command_t * CmdDataCommands();
command_t *CmdDataCommands();
int CmdData(const char *Cmd);
void printDemodBuff(void);
@ -83,7 +83,7 @@ int PSKDemod(const char *Cmd, bool verbose);
int NRZrawDemod(const char *Cmd, bool verbose);
int getSamples(int n, bool silent);
void setClockGrid(int clk, int offset);
int directionalThreshold(const int* in, int *out, size_t len, int8_t up, int8_t down);
int directionalThreshold(const int *in, int *out, size_t len, int8_t up, int8_t down);
extern int AskEdgeDetect(const int *in, int *out, int len, int threshold);
int CmdDataIIR(const char *Cmd);

View file

@ -26,7 +26,8 @@
static int CmdHelp(const char *Cmd);
int usage_flashmem_spibaud(void){
int usage_flashmem_spibaud(void)
{
PrintAndLogEx(NORMAL, "Usage: mem spibaud [h] <baudrate>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help");
@ -40,7 +41,8 @@ int usage_flashmem_spibaud(void){
return 0;
}
int usage_flashmem_read(void){
int usage_flashmem_read(void)
{
PrintAndLogEx(NORMAL, "Read flash memory on device");
PrintAndLogEx(NORMAL, "Usage: mem read o <offset> l <len>");
PrintAndLogEx(NORMAL, " o <offset> : offset in memory");
@ -51,7 +53,8 @@ int usage_flashmem_read(void){
PrintAndLogEx(NORMAL, " mem read o 1024 l 10"); // read 10 bytes starting at offset 1024
return 0;
}
int usage_flashmem_load(void){
int usage_flashmem_load(void)
{
PrintAndLogEx(NORMAL, "Loads binary file into flash memory on device");
PrintAndLogEx(NORMAL, "Usage: mem load o <offset> f <file name> m t i");
PrintAndLogEx(NORMAL, " o <offset> : offset in memory");
@ -68,7 +71,8 @@ int usage_flashmem_load(void){
PrintAndLogEx(NORMAL, " mem load f default_iclass_keys i");
return 0;
}
int usage_flashmem_save(void){
int usage_flashmem_save(void)
{
PrintAndLogEx(NORMAL, "Saves flash memory on device into the file");
PrintAndLogEx(NORMAL, " Usage: mem save o <offset> l <length> f <file name>");
PrintAndLogEx(NORMAL, " o <offset> : offset in memory");
@ -81,7 +85,8 @@ int usage_flashmem_save(void){
PrintAndLogEx(NORMAL, " mem save f myfile o 1024 l 4096"); // downlowd 4096 bytes from offset 1024 to file myfile
return 0;
}
int usage_flashmem_wipe(void){
int usage_flashmem_wipe(void)
{
PrintAndLogEx(WARNING, "[OBS] use with caution.");
PrintAndLogEx(NORMAL, "Wipe flash memory on device, which fills memory with 0xFF\n");
@ -95,7 +100,8 @@ int usage_flashmem_wipe(void){
PrintAndLogEx(NORMAL, " mem wipe p 0"); // wipes first page.
return 0;
}
int usage_flashmem_info(void){
int usage_flashmem_info(void)
{
PrintAndLogEx(NORMAL, "Collect signature and verify it from flash memory\n");
PrintAndLogEx(NORMAL, " Usage: mem info [h|s|w]");
PrintAndLogEx(NORMAL, " s : create a signature");
@ -107,7 +113,8 @@ int usage_flashmem_info(void){
return 0;
}
int CmdFlashMemRead(const char *Cmd) {
int CmdFlashMemRead(const char *Cmd)
{
uint8_t cmdp = 0;
bool errors = false;
@ -116,11 +123,11 @@ int CmdFlashMemRead(const char *Cmd) {
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'o':
start_index = param_get32ex(Cmd, cmdp+1, 0, 10);
start_index = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
break;
case 'l':
len = param_get32ex(Cmd, cmdp+1, 0, 10);
len = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
break;
case 'h':
@ -133,7 +140,7 @@ int CmdFlashMemRead(const char *Cmd) {
}
//Validations
if (errors || cmdp == 0 ) return usage_flashmem_read();
if (errors || cmdp == 0) return usage_flashmem_read();
if (start_index + len > FLASH_MEM_MAX_SIZE) {
PrintAndLogDevice(WARNING, "error, start_index + length is larger than available memory");
@ -146,19 +153,21 @@ int CmdFlashMemRead(const char *Cmd) {
return 0;
}
int CmdFlashmemSpiBaudrate(const char *Cmd) {
int CmdFlashmemSpiBaudrate(const char *Cmd)
{
char ctmp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) < 1 || ctmp == 'h') return usage_flashmem_spibaud();
uint32_t baudrate = param_get32ex(Cmd, 0, 0, 10);
baudrate = baudrate * 1000000;
if (baudrate != FLASH_BAUD && baudrate != FLASH_MINBAUD ) return usage_flashmem_spibaud();
if (baudrate != FLASH_BAUD && baudrate != FLASH_MINBAUD) return usage_flashmem_spibaud();
UsbCommand c = {CMD_FLASHMEM_SET_SPIBAUDRATE, {baudrate, 0, 0}};
SendCommand(&c);
return 0;
}
int CmdFlashMemLoad(const char *Cmd){
int CmdFlashMemLoad(const char *Cmd)
{
uint32_t start_index = 0;
char filename[FILE_PATH_SIZE] = {0};
@ -171,7 +180,7 @@ int CmdFlashMemLoad(const char *Cmd){
case 'h':
return usage_flashmem_load();
case 'f':
if ( param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE ) {
if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) {
PrintAndLogEx(FAILED, "Filename too long");
errors = true;
break;
@ -179,7 +188,7 @@ int CmdFlashMemLoad(const char *Cmd){
cmdp += 2;
break;
case 'o':
start_index = param_get32ex(Cmd, cmdp+1, 0, 10);
start_index = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
break;
case 'm':
@ -202,7 +211,7 @@ int CmdFlashMemLoad(const char *Cmd){
}
//Validations
if (errors || cmdp == 0 ) return usage_flashmem_load();
if (errors || cmdp == 0) return usage_flashmem_load();
size_t datalen = 0;
uint16_t keycount = 0;
@ -212,8 +221,8 @@ int CmdFlashMemLoad(const char *Cmd){
switch (d) {
case DICTIONARY_MIFARE:
start_index = DEFAULT_MF_KEYS_OFFSET;
res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 6, &keycount );
if ( res || !keycount) {
res = loadFileDICTIONARY(filename, "dic", data + 2, &datalen, 6, &keycount);
if (res || !keycount) {
free(data);
return 1;
}
@ -223,8 +232,8 @@ int CmdFlashMemLoad(const char *Cmd){
break;
case DICTIONARY_T55XX:
start_index = DEFAULT_T55XX_KEYS_OFFSET;
res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 4, &keycount );
if ( res || !keycount) {
res = loadFileDICTIONARY(filename, "dic", data + 2, &datalen, 4, &keycount);
if (res || !keycount) {
free(data);
return 1;
}
@ -234,8 +243,8 @@ int CmdFlashMemLoad(const char *Cmd){
break;
case DICTIONARY_ICLASS:
start_index = DEFAULT_ICLASS_KEYS_OFFSET;
res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 8, &keycount );
if ( res || !keycount) {
res = loadFileDICTIONARY(filename, "dic", data + 2, &datalen, 8, &keycount);
if (res || !keycount) {
free(data);
return 1;
}
@ -247,7 +256,7 @@ int CmdFlashMemLoad(const char *Cmd){
res = loadFile(filename, "bin", data, &datalen);
//int res = loadFileEML( filename, "eml", data, &datalen);
if ( res ) {
if (res) {
free(data);
return 1;
}
@ -266,7 +275,7 @@ int CmdFlashMemLoad(const char *Cmd){
uint32_t bytes_sent = 0;
uint32_t bytes_remaining = datalen;
while (bytes_remaining > 0){
while (bytes_remaining > 0) {
uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining);
UsbCommand c = {CMD_FLASHMEM_WRITE, {start_index + bytes_sent, bytes_in_packet, 0}};
@ -279,7 +288,7 @@ int CmdFlashMemLoad(const char *Cmd){
bytes_sent += bytes_in_packet;
UsbCommand resp;
if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) {
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
free(data);
return 1;
@ -295,7 +304,8 @@ int CmdFlashMemLoad(const char *Cmd){
PrintAndLogEx(SUCCESS, "Wrote %u bytes to offset %u", datalen, start_index);
return 0;
}
int CmdFlashMemSave(const char *Cmd){
int CmdFlashMemSave(const char *Cmd)
{
char filename[FILE_PATH_SIZE] = {0};
uint8_t cmdp = 0;
@ -304,18 +314,19 @@ int CmdFlashMemSave(const char *Cmd){
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h': return usage_flashmem_save();
case 'h':
return usage_flashmem_save();
case 'l':
len = param_get32ex(Cmd, cmdp+1, FLASH_MEM_MAX_SIZE, 10);
len = param_get32ex(Cmd, cmdp + 1, FLASH_MEM_MAX_SIZE, 10);
cmdp += 2;
break;
case 'o':
start_index = param_get32ex(Cmd, cmdp+1, 0, 10);
start_index = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
break;
case 'f':
//File handling
if ( param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE ) {
if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) {
PrintAndLogEx(FAILED, "Filename too long");
errors = true;
break;
@ -330,16 +341,16 @@ int CmdFlashMemSave(const char *Cmd){
}
//Validations
if (errors || cmdp == 0 ) return usage_flashmem_save();
if (errors || cmdp == 0) return usage_flashmem_save();
uint8_t* dump = calloc(len, sizeof(uint8_t));
uint8_t *dump = calloc(len, sizeof(uint8_t));
if (!dump) {
PrintAndLogDevice(WARNING, "error, cannot allocate memory ");
return 1;
}
PrintAndLogEx(NORMAL, "downloading %u bytes from flashmem", len);
if ( !GetFromDevice(FLASH_MEM, dump, len, start_index, NULL, -1, true) ) {
if (!GetFromDevice(FLASH_MEM, dump, len, start_index, NULL, -1, true)) {
PrintAndLogEx(FAILED, "ERROR; downloading flashmem");
free(dump);
return 1;
@ -350,7 +361,8 @@ int CmdFlashMemSave(const char *Cmd){
free(dump);
return 0;
}
int CmdFlashMemWipe(const char *Cmd){
int CmdFlashMemWipe(const char *Cmd)
{
uint8_t cmdp = 0;
bool errors = false;
@ -358,10 +370,11 @@ int CmdFlashMemWipe(const char *Cmd){
uint8_t page = 0;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h': return usage_flashmem_wipe();
case 'h':
return usage_flashmem_wipe();
case 'p':
page = param_get8ex(Cmd, cmdp+1, 0, 10);
if ( page > 2 ) {
page = param_get8ex(Cmd, cmdp + 1, 0, 10);
if (page > 2) {
PrintAndLogEx(WARNING, "page must be 0, 1 or 2");
errors = true;
break;
@ -380,13 +393,13 @@ int CmdFlashMemWipe(const char *Cmd){
}
//Validations
if (errors || cmdp == 0 ) return usage_flashmem_wipe();
if (errors || cmdp == 0) return usage_flashmem_wipe();
UsbCommand c = {CMD_FLASHMEM_WIPE, {page, initalwipe, 0}};
clearCommandBuffer();
SendCommand(&c);
UsbCommand resp;
if ( !WaitForResponseTimeout(CMD_ACK, &resp, 8000) ) {
if (!WaitForResponseTimeout(CMD_ACK, &resp, 8000)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return 1;
}
@ -398,7 +411,8 @@ int CmdFlashMemWipe(const char *Cmd){
return 0;
}
int CmdFlashMemInfo(const char *Cmd){
int CmdFlashMemInfo(const char *Cmd)
{
uint8_t sha_hash[20] = {0};
mbedtls_rsa_context rsa;
@ -407,7 +421,8 @@ int CmdFlashMemInfo(const char *Cmd){
bool errors = false, shall_write = false, shall_sign = false;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h': return usage_flashmem_info();
case 'h':
return usage_flashmem_info();
case 's': {
shall_sign = true;
cmdp++;
@ -425,13 +440,13 @@ int CmdFlashMemInfo(const char *Cmd){
}
//Validations
if (errors ) return usage_flashmem_info();
if (errors) return usage_flashmem_info();
UsbCommand c = {CMD_FLASHMEM_INFO, {0, 0, 0}};
clearCommandBuffer();
SendCommand(&c);
UsbCommand resp;
if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) {
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return 1;
}
@ -447,15 +462,15 @@ int CmdFlashMemInfo(const char *Cmd){
memcpy(&mem, (rdv40_validation_t *)resp.d.asBytes, sizeof(rdv40_validation_t));
// Flash ID hash (sha1)
mbedtls_sha1( mem.flashid, sizeof(mem.flashid), sha_hash );
mbedtls_sha1(mem.flashid, sizeof(mem.flashid), sha_hash);
// print header
PrintAndLogEx(INFO, "\n--- Flash memory Information ---------");
PrintAndLogEx(INFO, "-------------------------------------------------------------");
PrintAndLogEx(INFO, "ID | %s", sprint_hex(mem.flashid, sizeof(mem.flashid) ));
PrintAndLogEx(INFO, "ID | %s", sprint_hex(mem.flashid, sizeof(mem.flashid)));
PrintAndLogEx(INFO, "SHA1 | %s", sprint_hex(sha_hash, sizeof(sha_hash)));
PrintAndLogEx(INFO, "RSA SIGNATURE |");
print_hex_break( mem.signature, sizeof(mem.signature), 32);
print_hex_break(mem.signature, sizeof(mem.signature), 32);
//-------------------------------------------------------------------------------
// Example RSA-1024 keypair, for test purposes (from common/polarssl/rsa.c)
@ -518,18 +533,18 @@ int CmdFlashMemInfo(const char *Cmd){
rsa.len = KEY_LEN;
mbedtls_mpi_read_string( &rsa.N , 16, RSA_N );
mbedtls_mpi_read_string( &rsa.E , 16, RSA_E );
mbedtls_mpi_read_string( &rsa.D , 16, RSA_D );
mbedtls_mpi_read_string( &rsa.P , 16, RSA_P );
mbedtls_mpi_read_string( &rsa.Q , 16, RSA_Q );
mbedtls_mpi_read_string( &rsa.DP, 16, RSA_DP );
mbedtls_mpi_read_string( &rsa.DQ, 16, RSA_DQ );
mbedtls_mpi_read_string( &rsa.QP, 16, RSA_QP );
mbedtls_mpi_read_string(&rsa.N, 16, RSA_N);
mbedtls_mpi_read_string(&rsa.E, 16, RSA_E);
mbedtls_mpi_read_string(&rsa.D, 16, RSA_D);
mbedtls_mpi_read_string(&rsa.P, 16, RSA_P);
mbedtls_mpi_read_string(&rsa.Q, 16, RSA_Q);
mbedtls_mpi_read_string(&rsa.DP, 16, RSA_DP);
mbedtls_mpi_read_string(&rsa.DQ, 16, RSA_DQ);
mbedtls_mpi_read_string(&rsa.QP, 16, RSA_QP);
PrintAndLogEx(INFO, "KEY length | %d", KEY_LEN);
bool is_keyok = ( mbedtls_rsa_check_pubkey( &rsa ) == 0 || mbedtls_rsa_check_privkey( &rsa ) == 0 );
bool is_keyok = (mbedtls_rsa_check_pubkey(&rsa) == 0 || mbedtls_rsa_check_privkey(&rsa) == 0);
if (is_keyok)
PrintAndLogEx(SUCCESS, "RSA key validation ok");
else
@ -548,7 +563,7 @@ int CmdFlashMemInfo(const char *Cmd){
// Signing (private key)
if (shall_sign) {
int is_signed = mbedtls_rsa_pkcs1_sign( &rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, sign );
int is_signed = mbedtls_rsa_pkcs1_sign(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, sign);
if (is_signed == 0)
PrintAndLogEx(SUCCESS, "RSA Signing ok");
else
@ -556,11 +571,11 @@ int CmdFlashMemInfo(const char *Cmd){
if (shall_write) {
// save to mem
c = (UsbCommand){CMD_FLASHMEM_WRITE, {FLASH_MEM_SIGNATURE_OFFSET, FLASH_MEM_SIGNATURE_LEN, 0}};
c = (UsbCommand) {CMD_FLASHMEM_WRITE, {FLASH_MEM_SIGNATURE_OFFSET, FLASH_MEM_SIGNATURE_LEN, 0}};
memcpy(c.d.asBytes, sign, sizeof(sign));
clearCommandBuffer();
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) {
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
} else {
@ -572,11 +587,11 @@ int CmdFlashMemInfo(const char *Cmd){
}
}
PrintAndLogEx(INFO, "Signed | ");
print_hex_break( sign, sizeof(sign), 32);
print_hex_break(sign, sizeof(sign), 32);
}
// Verify (public key)
int is_verified = mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device );
int is_verified = mbedtls_rsa_pkcs1_verify(&rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device);
if (is_verified == 0)
PrintAndLogEx(SUCCESS, "RSA Verification ok");
else
@ -597,13 +612,15 @@ static command_t CommandTable[] = {
{NULL, NULL, 0, NULL}
};
int CmdFlashMem(const char *Cmd) {
int CmdFlashMem(const char *Cmd)
{
clearCommandBuffer();
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd) {
int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable);
return 0;
}

View file

@ -35,9 +35,9 @@ typedef enum {
extern int CmdFlashMem(const char *Cmd);
extern int CmdFlashMemRead(const char* cmd);
extern int CmdFlashMemLoad(const char* cmd);
extern int CmdFlashMemSave(const char* cmd);
extern int CmdFlashMemRead(const char *cmd);
extern int CmdFlashMemLoad(const char *cmd);
extern int CmdFlashMemSave(const char *cmd);
extern int CmdFlashMemWipe(const char *Cmd);
extern int CmdFlashMemInfo(const char *Cmd);
#endif

View file

@ -12,7 +12,8 @@
static int CmdHelp(const char *Cmd);
int usage_hf_search(){
int usage_hf_search()
{
PrintAndLogEx(NORMAL, "Usage: hf search");
PrintAndLogEx(NORMAL, "Will try to find a HF read out of the unknown tag. Stops when found.");
PrintAndLogEx(NORMAL, "Options:");
@ -20,7 +21,8 @@ int usage_hf_search(){
PrintAndLogEx(NORMAL, "");
return 0;
}
int usage_hf_snoop(){
int usage_hf_snoop()
{
PrintAndLogEx(NORMAL, "Usage: hf snoop <skip pairs> <skip triggers>");
PrintAndLogEx(NORMAL, "The high frequence snoop will assign all available memory on device for snooped data");
PrintAndLogEx(NORMAL, "User the 'data samples' command to download from device, and 'data plot' to look at it");
@ -36,7 +38,8 @@ int usage_hf_snoop(){
return 0;
}
int CmdHFSearch(const char *Cmd){
int CmdHFSearch(const char *Cmd)
{
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_hf_search();
@ -52,7 +55,7 @@ int CmdHFSearch(const char *Cmd){
return ans;
}
ans = HFLegicReader("", false);
if ( ans == 0) {
if (ans == 0) {
PrintAndLogEx(SUCCESS, "\nValid LEGIC Tag Found\n");
return 1;
}
@ -85,7 +88,8 @@ int CmdHFSearch(const char *Cmd){
return 0;
}
int CmdHFTune(const char *Cmd) {
int CmdHFTune(const char *Cmd)
{
PrintAndLogEx(SUCCESS, "Measuring HF antenna, press button to exit");
UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING_HF};
clearCommandBuffer();
@ -93,7 +97,8 @@ int CmdHFTune(const char *Cmd) {
return 0;
}
int CmdHFSnoop(const char *Cmd) {
int CmdHFSnoop(const char *Cmd)
{
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_hf_snoop();
@ -128,13 +133,15 @@ static command_t CommandTable[] = {
{NULL, NULL, 0, NULL}
};
int CmdHF(const char *Cmd) {
int CmdHF(const char *Cmd)
{
clearCommandBuffer();
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd) {
int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable);
return 0;
}

View file

@ -136,24 +136,26 @@ static const manufactureName manufactureMapping[] = {
// get a product description based on the UID
// uid[8] tag uid
// returns description of the best match
char* getTagInfo(uint8_t uid) {
char *getTagInfo(uint8_t uid)
{
int i;
int len = sizeof(manufactureMapping) / sizeof(manufactureName);
for ( i = 0; i < len; ++i )
if ( uid == manufactureMapping[i].uid)
for (i = 0; i < len; ++i)
if (uid == manufactureMapping[i].uid)
return manufactureMapping[i].desc;
//No match, return default
return manufactureMapping[len-1].desc;
return manufactureMapping[len - 1].desc;
}
// iso14a apdu input frame length
static uint16_t frameLength = 0;
uint16_t atsFSC[] = {16, 24, 32, 40, 48, 64, 96, 128, 256};
int usage_hf_14a_sim(void) {
int usage_hf_14a_sim(void)
{
// PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n");
PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 byte UID\n");
PrintAndLogEx(NORMAL, "Usage: hf 14a sim [h] t <type> u <uid> [x] [e] [v]");
@ -180,7 +182,8 @@ int usage_hf_14a_sim(void) {
// PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223445566778899AA\n");
return 0;
}
int usage_hf_14a_sniff(void) {
int usage_hf_14a_sniff(void)
{
PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer.");
PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list 14a'");
PrintAndLogEx(NORMAL, "Usage: hf 14a sniff [c][r]");
@ -190,7 +193,8 @@ int usage_hf_14a_sniff(void) {
PrintAndLogEx(NORMAL, " hf 14a sniff c r");
return 0;
}
int usage_hf_14a_raw(void) {
int usage_hf_14a_raw(void)
{
PrintAndLogEx(NORMAL, "Usage: hf 14a raw [-h] [-r] [-c] [-p] [-a] [-T] [-t] <milliseconds> [-b] <number of bits> <0A 0B 0C ... hex>");
PrintAndLogEx(NORMAL, " -h this help");
PrintAndLogEx(NORMAL, " -r do not read response");
@ -204,7 +208,8 @@ int usage_hf_14a_raw(void) {
PrintAndLogEx(NORMAL, " -3 ISO14443-3 select only (skip RATS)");
return 0;
}
int usage_hf_14a_reader(void) {
int usage_hf_14a_reader(void)
{
PrintAndLogEx(NORMAL, "Usage: hf 14a reader [k|s|x] [3]");
PrintAndLogEx(NORMAL, " k keep the field active after command executed");
PrintAndLogEx(NORMAL, " s silent (no messages)");
@ -212,7 +217,8 @@ int usage_hf_14a_reader(void) {
PrintAndLogEx(NORMAL, " 3 ISO14443-3 select only (skip RATS)");
return 0;
}
int usage_hf_14a_info(void){
int usage_hf_14a_info(void)
{
PrintAndLogEx(NORMAL, "This command makes more extensive tests against a ISO14443a tag in order to collect information");
PrintAndLogEx(NORMAL, "Usage: hf 14a info [h|s]");
PrintAndLogEx(NORMAL, " s silent (no messages)");
@ -220,34 +226,36 @@ int usage_hf_14a_info(void){
return 0;
}
int CmdHF14AList(const char *Cmd) {
int CmdHF14AList(const char *Cmd)
{
//PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list 14a' instead");
CmdTraceList("14a");
return 0;
}
int Hf14443_4aGetCardData(iso14a_card_select_t * card) {
int Hf14443_4aGetCardData(iso14a_card_select_t *card)
{
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}};
SendCommand(&c);
UsbCommand resp;
WaitForResponse(CMD_ACK,&resp);
WaitForResponse(CMD_ACK, &resp);
memcpy(card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
if(select_status == 0) {
if (select_status == 0) {
PrintAndLog("E->iso14443a card select failed");
return 1;
}
if(select_status == 2) {
if (select_status == 2) {
PrintAndLog("E->Card doesn't support iso14443-4 mode");
return 1;
}
if(select_status == 3) {
if (select_status == 3) {
PrintAndLog("E->Card doesn't support standard iso14443-3 anticollision");
PrintAndLog("\tATQA : %02x %02x", card->atqa[1], card->atqa[0]);
return 1;
@ -256,7 +264,7 @@ int Hf14443_4aGetCardData(iso14a_card_select_t * card) {
PrintAndLog(" UID: %s", sprint_hex(card->uid, card->uidlen));
PrintAndLog("ATQA: %02x %02x", card->atqa[1], card->atqa[0]);
PrintAndLog(" SAK: %02x [%" PRIu64 "]", card->sak, resp.arg[0]);
if(card->ats_len < 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
if (card->ats_len < 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
PrintAndLog("E-> Error ATS length(%d) : %s", card->ats_len, sprint_hex(card->ats, card->ats_len));
return 1;
}
@ -265,7 +273,8 @@ int Hf14443_4aGetCardData(iso14a_card_select_t * card) {
return 0;
}
int CmdHF14AReader(const char *Cmd) {
int CmdHF14AReader(const char *Cmd)
{
uint32_t cm = ISO14A_CONNECT;
bool disconnectAfter = true, silent = false;
@ -337,7 +346,7 @@ int CmdHF14AReader(const char *Cmd) {
PrintAndLogEx(NORMAL, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]);
PrintAndLogEx(NORMAL, " SAK : %02x [%" PRIu64 "]", card.sak, resp.arg[0]);
if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
if (card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
PrintAndLogEx(NORMAL, " ATS : %s", sprint_hex(card.ats, card.ats_len));
}
@ -353,7 +362,8 @@ int CmdHF14AReader(const char *Cmd) {
return 0;
}
int CmdHF14AInfo(const char *Cmd) {
int CmdHF14AInfo(const char *Cmd)
{
if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_hf_14a_info();
@ -425,30 +435,62 @@ int CmdHF14AInfo(const char *Cmd) {
select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS
if(select_status == 0) {
if (select_status == 0) {
DropField();
return 0;
}
break;
case 0x01: PrintAndLogEx(NORMAL, "TYPE : NXP TNP3xxx Activision Game Appliance"); break;
case 0x04: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); isMifareClassic = false; break;
case 0x08: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE CLASSIC 1k | Plus 2k SL1 | 1k Ev1"); break;
case 0x09: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Mini 0.3k"); break;
case 0x0A: PrintAndLogEx(NORMAL, "TYPE : FM11RF005SH (Shanghai Metro)"); break;
case 0x10: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Plus 2k SL2"); break;
case 0x11: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Plus 4k SL2"); break;
case 0x18: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Classic 4k | Plus 4k SL1 | 4k Ev1"); break;
case 0x20: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k SL3 | JCOP 31/41"); isMifareClassic = false; break;
case 0x24: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE DESFire | DESFire EV1"); isMifareClassic = false; break;
case 0x28: PrintAndLogEx(NORMAL, "TYPE : JCOP31 or JCOP41 v2.3.1"); break;
case 0x38: PrintAndLogEx(NORMAL, "TYPE : Nokia 6212 or 6131 MIFARE CLASSIC 4K"); break;
case 0x88: PrintAndLogEx(NORMAL, "TYPE : Infineon MIFARE CLASSIC 1K"); break;
case 0x98: PrintAndLogEx(NORMAL, "TYPE : Gemplus MPCOS"); break;
default: ;
case 0x01:
PrintAndLogEx(NORMAL, "TYPE : NXP TNP3xxx Activision Game Appliance");
break;
case 0x04:
PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE (various !DESFire !DESFire EV1)");
isMifareClassic = false;
break;
case 0x08:
PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE CLASSIC 1k | Plus 2k SL1 | 1k Ev1");
break;
case 0x09:
PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Mini 0.3k");
break;
case 0x0A:
PrintAndLogEx(NORMAL, "TYPE : FM11RF005SH (Shanghai Metro)");
break;
case 0x10:
PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Plus 2k SL2");
break;
case 0x11:
PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Plus 4k SL2");
break;
case 0x18:
PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Classic 4k | Plus 4k SL1 | 4k Ev1");
break;
case 0x20:
PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k SL3 | JCOP 31/41");
isMifareClassic = false;
break;
case 0x24:
PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE DESFire | DESFire EV1");
isMifareClassic = false;
break;
case 0x28:
PrintAndLogEx(NORMAL, "TYPE : JCOP31 or JCOP41 v2.3.1");
break;
case 0x38:
PrintAndLogEx(NORMAL, "TYPE : Nokia 6212 or 6131 MIFARE CLASSIC 4K");
break;
case 0x88:
PrintAndLogEx(NORMAL, "TYPE : Infineon MIFARE CLASSIC 1K");
break;
case 0x98:
PrintAndLogEx(NORMAL, "TYPE : Gemplus MPCOS");
break;
default:
;
}
// Double & triple sized UID, can be mapped to a manufacturer.
if ( card.uidlen > 4 ) {
if (card.uidlen > 4) {
PrintAndLogEx(NORMAL, "MANUFACTURER : %s", getTagInfo(card.uid[0]));
}
@ -461,13 +503,13 @@ int CmdHF14AInfo(const char *Cmd) {
memcpy(c.d.asBytes, rats, 2);
clearCommandBuffer();
SendCommand(&c);
WaitForResponse(CMD_ACK,&resp);
WaitForResponse(CMD_ACK, &resp);
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
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;
@ -530,7 +572,7 @@ int CmdHF14AInfo(const char *Cmd) {
(card.ats[pos] & 0x02) ? "" : " NOT");
pos++;
}
if (card.ats[0] > pos && card.ats[0] < card.ats_len - 2 ) {
if (card.ats[0] > pos && card.ats[0] < card.ats_len - 2) {
char *tip = "";
if (card.ats[0] - pos >= 7) {
if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
@ -544,29 +586,59 @@ int CmdHF14AInfo(const char *Cmd) {
PrintAndLogEx(NORMAL, " c1 -> Mifare or (multiple) virtual cards of various type");
PrintAndLogEx(NORMAL, " %02x -> Length is %d bytes", card.ats[pos + 1], card.ats[pos + 1]);
switch (card.ats[pos + 2] & 0xf0) {
case 0x10: PrintAndLogEx(NORMAL, " 1x -> MIFARE DESFire"); break;
case 0x20: PrintAndLogEx(NORMAL, " 2x -> MIFARE Plus"); break;
case 0x10:
PrintAndLogEx(NORMAL, " 1x -> MIFARE DESFire");
break;
case 0x20:
PrintAndLogEx(NORMAL, " 2x -> MIFARE Plus");
break;
}
switch (card.ats[pos + 2] & 0x0f) {
case 0x00: PrintAndLogEx(NORMAL, " x0 -> <1 kByte"); break;
case 0x01: PrintAndLogEx(NORMAL, " x1 -> 1 kByte"); break;
case 0x02: PrintAndLogEx(NORMAL, " x2 -> 2 kByte"); break;
case 0x03: PrintAndLogEx(NORMAL, " x3 -> 4 kByte"); break;
case 0x04: PrintAndLogEx(NORMAL, " x4 -> 8 kByte"); break;
case 0x00:
PrintAndLogEx(NORMAL, " x0 -> <1 kByte");
break;
case 0x01:
PrintAndLogEx(NORMAL, " x1 -> 1 kByte");
break;
case 0x02:
PrintAndLogEx(NORMAL, " x2 -> 2 kByte");
break;
case 0x03:
PrintAndLogEx(NORMAL, " x3 -> 4 kByte");
break;
case 0x04:
PrintAndLogEx(NORMAL, " x4 -> 8 kByte");
break;
}
switch (card.ats[pos + 3] & 0xf0) {
case 0x00: PrintAndLogEx(NORMAL, " 0x -> Engineering sample"); break;
case 0x20: PrintAndLogEx(NORMAL, " 2x -> Released"); break;
case 0x00:
PrintAndLogEx(NORMAL, " 0x -> Engineering sample");
break;
case 0x20:
PrintAndLogEx(NORMAL, " 2x -> Released");
break;
}
switch (card.ats[pos + 3] & 0x0f) {
case 0x00: PrintAndLogEx(NORMAL, " x0 -> Generation 1"); break;
case 0x01: PrintAndLogEx(NORMAL, " x1 -> Generation 2"); break;
case 0x02: PrintAndLogEx(NORMAL, " x2 -> Generation 3"); break;
case 0x00:
PrintAndLogEx(NORMAL, " x0 -> Generation 1");
break;
case 0x01:
PrintAndLogEx(NORMAL, " x1 -> Generation 2");
break;
case 0x02:
PrintAndLogEx(NORMAL, " x2 -> Generation 3");
break;
}
switch (card.ats[pos + 4] & 0x0f) {
case 0x00: PrintAndLogEx(NORMAL, " x0 -> Only VCSL supported"); break;
case 0x01: PrintAndLogEx(NORMAL, " x1 -> VCS, VCSL, and SVC supported"); break;
case 0x0E: PrintAndLogEx(NORMAL, " xE -> no VCS command supported"); break;
case 0x00:
PrintAndLogEx(NORMAL, " x0 -> Only VCSL supported");
break;
case 0x01:
PrintAndLogEx(NORMAL, " x1 -> VCS, VCSL, and SVC supported");
break;
case 0x0E:
PrintAndLogEx(NORMAL, " xE -> no VCS command supported");
break;
}
}
}
@ -578,14 +650,14 @@ int CmdHF14AInfo(const char *Cmd) {
if (isMifareClassic) {
int res = detect_classic_prng();
if ( res == 1 )
if (res == 1)
PrintAndLogEx(SUCCESS, "Prng detection: " _GREEN_(WEAK));
else if (res == 0 )
else if (res == 0)
PrintAndLogEx(SUCCESS, "Prng detection: " _YELLOW_(HARD));
else
PrintAndLogEx(FAILED, "prng detection: " _RED_(failed));
if ( do_nack_test )
if (do_nack_test)
detect_classic_nackbug(silent);
}
@ -593,7 +665,8 @@ int CmdHF14AInfo(const char *Cmd) {
}
// Collect ISO14443 Type A UIDs
int CmdHF14ACUIDs(const char *Cmd) {
int CmdHF14ACUIDs(const char *Cmd)
{
// requested number of UIDs
int n = atoi(Cmd);
// collect at least 1 (e.g. if no parameter was given)
@ -606,7 +679,8 @@ int CmdHF14ACUIDs(const char *Cmd) {
for (int i = 0; i < n; i++) {
if (ukbhit()) {
int gc = getchar(); (void)gc;
int gc = getchar();
(void)gc;
PrintAndLogEx(WARNING, "\n[!] aborted via keyboard!\n");
break;
}
@ -616,7 +690,7 @@ int CmdHF14ACUIDs(const char *Cmd) {
SendCommand(&c);
UsbCommand resp;
WaitForResponse(CMD_ACK,&resp);
WaitForResponse(CMD_ACK, &resp);
iso14a_card_select_t *card = (iso14a_card_select_t *) resp.d.asBytes;
@ -626,37 +700,38 @@ int CmdHF14ACUIDs(const char *Cmd) {
} else {
char uid_string[20];
for (uint16_t i = 0; i < card->uidlen; i++) {
sprintf(&uid_string[2*i], "%02X", card->uid[i]);
sprintf(&uid_string[2 * i], "%02X", card->uid[i]);
}
PrintAndLogEx(NORMAL, "%s", uid_string);
}
}
PrintAndLogEx(SUCCESS, "end: %" PRIu64 " seconds", (msclock()-t1)/1000);
PrintAndLogEx(SUCCESS, "end: %" PRIu64 " seconds", (msclock() - t1) / 1000);
return 1;
}
// ## simulate iso14443a tag
int CmdHF14ASim(const char *Cmd) {
int CmdHF14ASim(const char *Cmd)
{
bool errors = false;
uint8_t flags = 0;
uint8_t tagtype = 1;
uint8_t cmdp = 0;
uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0};
uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int uidlen = 0;
bool useUIDfromEML = true;
bool setEmulatorMem = false;
bool verbose = false;
nonces_t data[1];
while(param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch(param_getchar(Cmd, cmdp)) {
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (param_getchar(Cmd, cmdp)) {
case 'h':
case 'H':
return usage_hf_14a_sim();
case 't':
case 'T':
// Retrieve the tag type
tagtype = param_get8ex(Cmd, cmdp+1, 0, 10);
tagtype = param_get8ex(Cmd, cmdp + 1, 0, 10);
if (tagtype == 0)
errors = true;
cmdp += 2;
@ -664,15 +739,21 @@ int CmdHF14ASim(const char *Cmd) {
case 'u':
case 'U':
// Retrieve the full 4,7,10 byte long uid
param_gethex_ex(Cmd, cmdp+1, uid, &uidlen);
switch(uidlen) {
param_gethex_ex(Cmd, cmdp + 1, uid, &uidlen);
switch (uidlen) {
//case 20: flags |= FLAG_10B_UID_IN_DATA; break;
case 14: flags |= FLAG_7B_UID_IN_DATA; break;
case 8: flags |= FLAG_4B_UID_IN_DATA; break;
default: errors = true; break;
case 14:
flags |= FLAG_7B_UID_IN_DATA;
break;
case 8:
flags |= FLAG_4B_UID_IN_DATA;
break;
default:
errors = true;
break;
}
if (!errors) {
PrintAndLogEx(SUCCESS, "Emulating ISO/IEC 14443 type A tag with %d byte UID (%s)", uidlen>>1, sprint_hex(uid, uidlen>>1));
PrintAndLogEx(SUCCESS, "Emulating ISO/IEC 14443 type A tag with %d byte UID (%s)", uidlen >> 1, sprint_hex(uid, uidlen >> 1));
useUIDfromEML = false;
}
cmdp += 2;
@ -702,30 +783,31 @@ int CmdHF14ASim(const char *Cmd) {
//Validations
if (errors || cmdp == 0) return usage_hf_14a_sim();
if ( useUIDfromEML )
if (useUIDfromEML)
flags |= FLAG_UID_IN_EMUL;
UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,{ tagtype, flags, 0 }};
memcpy(c.d.asBytes, uid, uidlen>>1);
UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a, { tagtype, flags, 0 }};
memcpy(c.d.asBytes, uid, uidlen >> 1);
clearCommandBuffer();
SendCommand(&c);
UsbCommand resp;
PrintAndLogEx(SUCCESS, "press pm3-button to abort simulation");
while( !ukbhit() ){
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue;
if ( !(flags & FLAG_NR_AR_ATTACK) ) break;
if ( (resp.arg[0] & 0xffff) != CMD_SIMULATE_MIFARE_CARD ) break;
while (!ukbhit()) {
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) continue;
if (!(flags & FLAG_NR_AR_ATTACK)) break;
if ((resp.arg[0] & 0xffff) != CMD_SIMULATE_MIFARE_CARD) break;
memcpy(data, resp.d.asBytes, sizeof(data) );
memcpy(data, resp.d.asBytes, sizeof(data));
readerAttack(data[0], setEmulatorMem, verbose);
}
showSectorTable();
return 0;
}
int CmdHF14ASniff(const char *Cmd) {
int CmdHF14ASniff(const char *Cmd)
{
int param = 0;
uint8_t ctmp;
for (int i = 0; i < 2; i++) {
@ -740,7 +822,8 @@ int CmdHF14ASniff(const char *Cmd) {
return 0;
}
int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) {
int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen)
{
static bool responseNum = false;
uint16_t cmdc = 0;
*dataoutlen = 0;
@ -803,7 +886,7 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav
recv = resp.d.asBytes;
int iLen = resp.arg[0];
if(!iLen) {
if (!iLen) {
PrintAndLogEx(ERR, "No card response.");
return 1;
}
@ -839,7 +922,8 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav
return 0;
}
int SelectCard14443_4(bool disconnect, iso14a_card_select_t *card) {
int SelectCard14443_4(bool disconnect, iso14a_card_select_t *card)
{
UsbCommand resp;
frameLength = 0;
@ -909,7 +993,8 @@ int SelectCard14443_4(bool disconnect, iso14a_card_select_t *card) {
return 0;
}
int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool activateField, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool *chainingout) {
int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool activateField, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool *chainingout)
{
*chainingout = false;
if (activateField) {
@ -956,7 +1041,7 @@ int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool activa
return 0;
}
if(!iLen) {
if (!iLen) {
PrintAndLogEx(ERR, "APDU: No APDU response.");
return 1;
}
@ -993,14 +1078,15 @@ int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool activa
return 0;
}
int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) {
int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen)
{
*dataoutlen = 0;
bool chaining = false;
int res;
// 3 byte here - 1b framing header, 2b crc16
if (APDUInFramingEnable &&
( (frameLength && (datainlen > frameLength - 3)) || (datainlen > USB_CMD_DATA_SIZE - 3)) ) {
((frameLength && (datainlen > frameLength - 3)) || (datainlen > USB_CMD_DATA_SIZE - 3))) {
int clen = 0;
bool vActivateField = activateField;
@ -1063,7 +1149,8 @@ int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool lea
}
// ISO14443-4. 7. Half-duplex block transmission protocol
int CmdHF14AAPDU(const char *cmd) {
int CmdHF14AAPDU(const char *cmd)
{
uint8_t data[USB_CMD_DATA_SIZE];
int datalen = 0;
bool activateField = false;
@ -1074,7 +1161,7 @@ int CmdHF14AAPDU(const char *cmd) {
"Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL)",
"Sample:\n\thf 14a apdu -st 00A404000E325041592E5359532E444446303100\n");
void* argtable[] = {
void *argtable[] = {
arg_param_begin,
arg_lit0("sS", "select", "activate field and select card"),
arg_lit0("kK", "keep", "leave the signal field ON after receive response"),
@ -1090,8 +1177,8 @@ int CmdHF14AAPDU(const char *cmd) {
// len = data + PCB(1b) + CRC(2b)
CLIGetHexBLessWithReturn(4, data, &datalen, 1 + 2);
CLIParserFree();
PrintAndLogEx(NORMAL, ">>>>[%s%s%s] %s", activateField ? "sel ": "", leaveSignalON ? "keep ": "", decodeTLV ? "TLV": "", sprint_hex(data, datalen));
CLIParserFree();
PrintAndLogEx(NORMAL, ">>>>[%s%s%s] %s", activateField ? "sel " : "", leaveSignalON ? "keep " : "", decodeTLV ? "TLV" : "", sprint_hex(data, datalen));
int res = ExchangeAPDU14a(data, datalen, activateField, leaveSignalON, data, USB_CMD_DATA_SIZE, &datalen);
@ -1110,7 +1197,8 @@ CLIParserFree();
return 0;
}
int CmdHF14ACmdRaw(const char *cmd) {
int CmdHF14ACmdRaw(const char *cmd)
{
UsbCommand c = {CMD_READER_ISO_14443a, {0, 0, 0}};
bool reply = 1;
bool crc = false;
@ -1122,7 +1210,7 @@ int CmdHF14ACmdRaw(const char *cmd) {
bool bTimeout = false;
uint32_t timeout = 0;
bool topazmode = false;
char buf[5]="";
char buf[5] = "";
int i = 0;
uint8_t data[USB_CMD_DATA_SIZE];
uint16_t datalen = 0;
@ -1131,12 +1219,12 @@ int CmdHF14ACmdRaw(const char *cmd) {
if (strlen(cmd) < 2) return usage_hf_14a_raw();
// strip
while (*cmd==' ' || *cmd=='\t') cmd++;
while (*cmd == ' ' || *cmd == '\t') cmd++;
while (cmd[i]!='\0') {
if (cmd[i]==' ' || cmd[i]=='\t') { i++; continue; }
if (cmd[i]=='-') {
switch (cmd[i+1]) {
while (cmd[i] != '\0') {
if (cmd[i] == ' ' || cmd[i] == '\t') { i++; continue; }
if (cmd[i] == '-') {
switch (cmd[i + 1]) {
case 'H':
case 'h':
return usage_hf_14a_raw();
@ -1156,19 +1244,19 @@ int CmdHF14ACmdRaw(const char *cmd) {
active_select = true;
break;
case 'b':
sscanf(cmd+i+2, "%d", &temp);
sscanf(cmd + i + 2, "%d", &temp);
numbits = temp & 0xFFFF;
i+=3;
while(cmd[i]!=' ' && cmd[i]!='\0') { i++; }
i-=2;
i += 3;
while (cmd[i] != ' ' && cmd[i] != '\0') { i++; }
i -= 2;
break;
case 't':
bTimeout = true;
sscanf(cmd+i+2, "%d", &temp);
sscanf(cmd + i + 2, "%d", &temp);
timeout = temp;
i+=3;
while(cmd[i]!=' ' && cmd[i]!='\0') { i++; }
i-=2;
i += 3;
while (cmd[i] != ' ' && cmd[i] != '\0') { i++; }
i -= 2;
break;
case 'T':
topazmode = true;
@ -1182,10 +1270,10 @@ int CmdHF14ACmdRaw(const char *cmd) {
i += 2;
continue;
}
if ((cmd[i]>='0' && cmd[i]<='9') ||
(cmd[i]>='a' && cmd[i]<='f') ||
(cmd[i]>='A' && cmd[i]<='F') ) {
buf[strlen(buf)+1] = 0;
if ((cmd[i] >= '0' && cmd[i] <= '9') ||
(cmd[i] >= 'a' && cmd[i] <= 'f') ||
(cmd[i] >= 'A' && cmd[i] <= 'F')) {
buf[strlen(buf) + 1] = 0;
buf[strlen(buf)] = cmd[i];
i++;
@ -1193,7 +1281,7 @@ int CmdHF14ACmdRaw(const char *cmd) {
sscanf(buf, "%x", &temp);
data[datalen] = (uint8_t)(temp & 0xff);
*buf = 0;
if (++datalen >= sizeof(data)){
if (++datalen >= sizeof(data)) {
if (crc)
PrintAndLogEx(NORMAL, "Buffer is full, we can't add CRC to your data");
break;
@ -1205,7 +1293,7 @@ int CmdHF14ACmdRaw(const char *cmd) {
return 0;
}
if (crc && datalen > 0 && datalen < sizeof(data)-2) {
if (crc && datalen > 0 && datalen < sizeof(data) - 2) {
uint8_t first, second;
if (topazmode) {
compute_crc(CRC_14443_B, data, datalen, &first, &second);
@ -1222,14 +1310,14 @@ int CmdHF14ACmdRaw(const char *cmd) {
c.arg[0] |= ISO14A_NO_SELECT;
}
if (bTimeout){
#define MAX_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s
if (bTimeout) {
#define MAX_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s
c.arg[0] |= ISO14A_SET_TIMEOUT;
if(timeout > MAX_TIMEOUT) {
if (timeout > MAX_TIMEOUT) {
timeout = MAX_TIMEOUT;
PrintAndLogEx(NORMAL, "Set timeout to 40542 seconds (11.26 hours). The max we can wait for response");
}
c.arg[2] = 13560000 / 1000 / (8*16) * timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
c.arg[2] = 13560000 / 1000 / (8 * 16) * timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
}
if (power) {
@ -1266,15 +1354,16 @@ int CmdHF14ACmdRaw(const char *cmd) {
return 0;
}
static int waitCmd(uint8_t iSelect) {
static int waitCmd(uint8_t iSelect)
{
UsbCommand resp;
uint16_t len = 0;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
len = (resp.arg[0] & 0xFFFF);
if (iSelect){
if (iSelect) {
len = (resp.arg[1] & 0xFFFF);
if (len){
if (len) {
PrintAndLogEx(NORMAL, "Card selected. UID[%i]:", len);
} else {
PrintAndLogEx(WARNING, "Can't select card.");
@ -1286,7 +1375,7 @@ static int waitCmd(uint8_t iSelect) {
if (!len)
return 1;
PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.d.asBytes, len) );
PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.d.asBytes, len));
} else {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return 3;
@ -1294,14 +1383,15 @@ static int waitCmd(uint8_t iSelect) {
return 0;
}
int CmdHF14AAntiFuzz(const char *cmd) {
int CmdHF14AAntiFuzz(const char *cmd)
{
CLIParserInit("hf 14a antifuzz",
"Tries to fuzz the ISO14443a anticollision phase",
"Usage:\n"
"\thf 14a antifuzz -4\n");
void* argtable[] = {
void *argtable[] = {
arg_param_begin,
arg_lit0("4", NULL, "4 byte uid"),
arg_lit0("7", NULL, "7 byte uid"),
@ -1323,7 +1413,8 @@ int CmdHF14AAntiFuzz(const char *cmd) {
return 0;
}
int CmdHF14AChaining(const char *cmd) {
int CmdHF14AChaining(const char *cmd)
{
CLIParserInit("hf 14a chaining",
"Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS.",
@ -1331,7 +1422,7 @@ int CmdHF14AChaining(const char *cmd) {
"\thf 14a chaining disable -> disable chaining\n"
"\thf 14a chaining -> show chaining enable/disable state\n");
void* argtable[] = {
void *argtable[] = {
arg_param_begin,
arg_str0(NULL, NULL, "<enable/disable or 0/1>", NULL),
arg_param_end
@ -1369,13 +1460,15 @@ static command_t CommandTable[] = {
{NULL, NULL, 0, NULL}
};
int CmdHF14A(const char *Cmd) {
int CmdHF14A(const char *Cmd)
{
clearCommandBuffer();
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd) {
int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable);
return 0;
}

View file

@ -36,7 +36,7 @@
// structure and database for uid -> tagtype lookups
typedef struct {
uint8_t uid;
char* desc;
char *desc;
} manufactureName;
extern int CmdHF14A(const char *Cmd);
@ -49,8 +49,8 @@ extern int CmdHF14ACmdRaw(const char *Cmd);
extern int CmdHF14ACUIDs(const char *Cmd);
extern int CmdHF14AAntiFuzz(const char *cmd);
extern char* getTagInfo(uint8_t uid);
extern int Hf14443_4aGetCardData(iso14a_card_select_t * card);
extern char *getTagInfo(uint8_t uid);
extern int Hf14443_4aGetCardData(iso14a_card_select_t *card);
extern int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen);
extern int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen);

View file

@ -14,7 +14,8 @@
#define TIMEOUT 2000
static int CmdHelp(const char *Cmd);
int usage_hf_14b_info(void){
int usage_hf_14b_info(void)
{
PrintAndLogEx(NORMAL, "Usage: hf 14b info [h] [s]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help");
@ -23,7 +24,8 @@ int usage_hf_14b_info(void){
PrintAndLogEx(NORMAL, " hf 14b info");
return 0;
}
int usage_hf_14b_reader(void){
int usage_hf_14b_reader(void)
{
PrintAndLogEx(NORMAL, "Usage: hf 14b reader [h] [s]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help");
@ -32,7 +34,8 @@ int usage_hf_14b_reader(void){
PrintAndLogEx(NORMAL, " hf 14b reader");
return 0;
}
int usage_hf_14b_raw(void){
int usage_hf_14b_raw(void)
{
PrintAndLogEx(NORMAL, "Usage: hf 14b raw [-h] [-r] [-c] [-p] [-s || -ss] <0A 0B 0C ... hex>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " -h this help");
@ -45,7 +48,8 @@ int usage_hf_14b_raw(void){
PrintAndLogEx(NORMAL, " hf 14b raw -s -c -p 0200a40400");
return 0;
}
int usage_hf_14b_sniff(void){
int usage_hf_14b_sniff(void)
{
PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer.");
PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list 14b'");
PrintAndLogEx(NORMAL, "Usage: hf 14b sniff [h]");
@ -55,7 +59,8 @@ int usage_hf_14b_sniff(void){
PrintAndLogEx(NORMAL, " hf 14b sniff");
return 0;
}
int usage_hf_14b_sim(void){
int usage_hf_14b_sim(void)
{
PrintAndLogEx(NORMAL, "Emulating ISO/IEC 14443 type B tag with 4 UID / PUPI");
PrintAndLogEx(NORMAL, "Usage: hf 14b sim [h] u <uid>");
PrintAndLogEx(NORMAL, "Options:");
@ -66,7 +71,8 @@ int usage_hf_14b_sim(void){
PrintAndLogEx(NORMAL, " hf 14b sim u 11223344");
return 0;
}
int usage_hf_14b_read_srx(void){
int usage_hf_14b_read_srx(void)
{
PrintAndLogEx(NORMAL, "Usage: hf 14b sriread [h] <1|2>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help");
@ -76,7 +82,8 @@ int usage_hf_14b_read_srx(void){
PrintAndLogEx(NORMAL, " hf 14b sriread 2");
return 0;
}
int usage_hf_14b_write_srx(void){
int usage_hf_14b_write_srx(void)
{
PrintAndLogEx(NORMAL, "Usage: hf 14b [h] sriwrite <1|2> <BLOCK> <DATA>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help");
@ -90,7 +97,8 @@ int usage_hf_14b_write_srx(void){
PrintAndLogEx(NORMAL, " hf 14b sriwrite 2 FF 11223344");
return 0;
}
int usage_hf_14b_dump(void){
int usage_hf_14b_dump(void)
{
PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-14443-B tag and save it to file\n"
"\n"
"Usage: hf 14b dump [h] [card memory] <f filname> \n"
@ -113,19 +121,22 @@ static void switch_on_field_14b(void) {
}
*/
static int switch_off_field_14b(void) {
static int switch_off_field_14b(void)
{
UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_DISCONNECT, 0, 0}};
clearCommandBuffer();
SendCommand(&c);
return 0;
}
int CmdHF14BList(const char *Cmd) {
int CmdHF14BList(const char *Cmd)
{
CmdTraceList("14b");
return 0;
}
int CmdHF14BSim(const char *Cmd) {
int CmdHF14BSim(const char *Cmd)
{
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_hf_14b_sim();
@ -140,7 +151,8 @@ int CmdHF14BSim(const char *Cmd) {
return 0;
}
int CmdHF14BSniff(const char *Cmd) {
int CmdHF14BSniff(const char *Cmd)
{
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_hf_14b_sniff();
@ -151,7 +163,8 @@ int CmdHF14BSniff(const char *Cmd) {
return 0;
}
int CmdHF14BCmdRaw (const char *Cmd) {
int CmdHF14BCmdRaw(const char *Cmd)
{
bool reply = true, power = false, select = false;
char buf[5] = "";
int i = 0;
@ -160,15 +173,15 @@ int CmdHF14BCmdRaw (const char *Cmd) {
uint32_t flags = ISO14B_CONNECT;
uint32_t temp = 0;
if ( strlen(Cmd) < 3 ) return usage_hf_14b_raw();
if (strlen(Cmd) < 3) return usage_hf_14b_raw();
// strip
while (*Cmd==' ' || *Cmd=='\t') ++Cmd;
while (*Cmd == ' ' || *Cmd == '\t') ++Cmd;
while (Cmd[i]!='\0') {
if (Cmd[i]==' ' || Cmd[i]=='\t') { ++i; continue; }
if (Cmd[i]=='-') {
switch (tolower(Cmd[i+1])) {
while (Cmd[i] != '\0') {
if (Cmd[i] == ' ' || Cmd[i] == '\t') { ++i; continue; }
if (Cmd[i] == '-') {
switch (tolower(Cmd[i + 1])) {
case 'h':
return usage_hf_14b_raw();
case 'r':
@ -182,7 +195,7 @@ int CmdHF14BCmdRaw (const char *Cmd) {
break;
case 's':
select = true;
if (tolower(Cmd[i+2]) == 's') {
if (tolower(Cmd[i + 2]) == 's') {
flags |= ISO14B_SELECT_SR;
++i;
} else {
@ -192,20 +205,20 @@ int CmdHF14BCmdRaw (const char *Cmd) {
default:
return usage_hf_14b_raw();
}
i+=2;
i += 2;
continue;
}
if ((Cmd[i]>='0' && Cmd[i]<='9') ||
(Cmd[i]>='a' && Cmd[i]<='f') ||
(Cmd[i]>='A' && Cmd[i]<='F') ) {
buf[strlen(buf)+1]=0;
buf[strlen(buf)]=Cmd[i];
if ((Cmd[i] >= '0' && Cmd[i] <= '9') ||
(Cmd[i] >= 'a' && Cmd[i] <= 'f') ||
(Cmd[i] >= 'A' && Cmd[i] <= 'F')) {
buf[strlen(buf) + 1] = 0;
buf[strlen(buf)] = Cmd[i];
i++;
if (strlen(buf)>=2) {
sscanf(buf,"%x",&temp);
if (strlen(buf) >= 2) {
sscanf(buf, "%x", &temp);
data[datalen++] = (uint8_t)(temp & 0xff);
*buf=0;
*buf = 0;
memset(buf, 0x00, sizeof(buf));
}
continue;
@ -236,12 +249,13 @@ int CmdHF14BCmdRaw (const char *Cmd) {
success = waitCmd14b(false);
// get back response from the raw bytes you sent.
if (success && datalen>0) waitCmd14b(true);
if (success && datalen > 0) waitCmd14b(true);
return 1;
}
static bool get_14b_UID(iso14b_card_select_t *card) {
static bool get_14b_UID(iso14b_card_select_t *card)
{
if (!card)
return false;
@ -258,7 +272,7 @@ static bool get_14b_UID(iso14b_card_select_t *card) {
if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
uint8_t status = resp.arg[0];
if ( status == 0) {
if (status == 0) {
memcpy(card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t));
return true;
}
@ -276,14 +290,14 @@ static bool get_14b_UID(iso14b_card_select_t *card) {
if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
uint8_t status = resp.arg[0];
if ( status == 0) {
if (status == 0) {
memcpy(card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t));
return true;
}
}
} // retry
if ( retry <= 0 )
if (retry <= 0)
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return false;
@ -295,10 +309,11 @@ static bool get_14b_UID(iso14b_card_select_t *card) {
// 4 = bit rate capacity
// 5 = max frame size / -4 info
// 6 = FWI / Coding options
static void print_atqb_resp(uint8_t *data, uint8_t cid){
static void print_atqb_resp(uint8_t *data, uint8_t cid)
{
//PrintAndLogEx(NORMAL, " UID: %s", sprint_hex(data+1,4));
PrintAndLogEx(NORMAL, " App Data: %s", sprint_hex(data,4));
PrintAndLogEx(NORMAL, " Protocol: %s", sprint_hex(data+4,3));
PrintAndLogEx(NORMAL, " App Data: %s", sprint_hex(data, 4));
PrintAndLogEx(NORMAL, " Protocol: %s", sprint_hex(data + 4, 3));
uint8_t BitRate = data[4];
if (!BitRate) PrintAndLogEx(NORMAL, " Bit Rate: 106 kbit/s only PICC <-> PCD");
if (BitRate & 0x10) PrintAndLogEx(NORMAL, " Bit Rate: 212 kbit/s PICC -> PCD supported");
@ -320,10 +335,10 @@ static void print_atqb_resp(uint8_t *data, uint8_t cid){
PrintAndLogEx(NORMAL, "Max Frame Size: %u%s bytes", maxFrame, (maxFrame == 257) ? "+ RFU" : "");
uint8_t protocolT = data[5] & 0xF;
PrintAndLogEx(NORMAL, " Protocol Type: Protocol is %scompliant with ISO/IEC 14443-4",(protocolT) ? "" : "not " );
PrintAndLogEx(NORMAL, " Protocol Type: Protocol is %scompliant with ISO/IEC 14443-4", (protocolT) ? "" : "not ");
uint8_t fwt = data[6]>>4;
if ( fwt < 16 ){
uint8_t fwt = data[6] >> 4;
if (fwt < 16) {
uint32_t etus = (32 << fwt);
uint32_t fwt_time = (302 << fwt);
PrintAndLogEx(NORMAL, "Frame Wait Integer: %u - %u ETUs | %u us", fwt, etus, fwt_time);
@ -331,36 +346,54 @@ static void print_atqb_resp(uint8_t *data, uint8_t cid){
PrintAndLogEx(NORMAL, "Frame Wait Integer: %u - RFU", fwt);
}
PrintAndLogEx(NORMAL, " App Data Code: Application is %s",(data[6]&4) ? "Standard" : "Proprietary");
PrintAndLogEx(NORMAL, " Frame Options: NAD is %ssupported",(data[6]&2) ? "" : "not ");
PrintAndLogEx(NORMAL, " Frame Options: CID is %ssupported",(data[6]&1) ? "" : "not ");
PrintAndLogEx(NORMAL, " App Data Code: Application is %s", (data[6] & 4) ? "Standard" : "Proprietary");
PrintAndLogEx(NORMAL, " Frame Options: NAD is %ssupported", (data[6] & 2) ? "" : "not ");
PrintAndLogEx(NORMAL, " Frame Options: CID is %ssupported", (data[6] & 1) ? "" : "not ");
PrintAndLogEx(NORMAL, "Tag :");
PrintAndLogEx(NORMAL, " Max Buf Length: %u (MBLI) %s", cid>>4, (cid & 0xF0) ? "" : "chained frames not supported");
PrintAndLogEx(NORMAL, " Max Buf Length: %u (MBLI) %s", cid >> 4, (cid & 0xF0) ? "" : "chained frames not supported");
PrintAndLogEx(NORMAL, " CID : %u", cid & 0x0f);
return;
}
// get SRx chip model (from UID) // from ST Microelectronics
char *get_ST_Chip_Model(uint8_t data){
char *get_ST_Chip_Model(uint8_t data)
{
static char model[20];
char *retStr = model;
memset(model,0, sizeof(model));
memset(model, 0, sizeof(model));
switch (data) {
case 0x0: sprintf(retStr, "SRIX4K (Special)"); break;
case 0x2: sprintf(retStr, "SR176"); break;
case 0x3: sprintf(retStr, "SRIX4K"); break;
case 0x4: sprintf(retStr, "SRIX512"); break;
case 0x6: sprintf(retStr, "SRI512"); break;
case 0x7: sprintf(retStr, "SRI4K"); break;
case 0xC: sprintf(retStr, "SRT512"); break;
default : sprintf(retStr, "Unknown"); break;
case 0x0:
sprintf(retStr, "SRIX4K (Special)");
break;
case 0x2:
sprintf(retStr, "SR176");
break;
case 0x3:
sprintf(retStr, "SRIX4K");
break;
case 0x4:
sprintf(retStr, "SRIX512");
break;
case 0x6:
sprintf(retStr, "SRI512");
break;
case 0x7:
sprintf(retStr, "SRI4K");
break;
case 0xC:
sprintf(retStr, "SRT512");
break;
default :
sprintf(retStr, "Unknown");
break;
}
return retStr;
}
// REMAKE:
int print_ST_Lock_info(uint8_t model){
int print_ST_Lock_info(uint8_t model)
{
// PrintAndLogEx(NORMAL, "Chip Write Protection Bits:");
// // now interpret the data
@ -406,11 +439,12 @@ int print_ST_Lock_info(uint8_t model){
}
// print UID info from SRx chips (ST Microelectronics)
static void print_st_general_info(uint8_t *data, uint8_t len){
static void print_st_general_info(uint8_t *data, uint8_t len)
{
//uid = first 8 bytes in data
PrintAndLogEx(NORMAL, " UID: %s", sprint_hex(SwapEndian64(data,8,8), len));
PrintAndLogEx(NORMAL, " UID: %s", sprint_hex(SwapEndian64(data, 8, 8), len));
PrintAndLogEx(NORMAL, " MFG: %02X, %s", data[6], getTagInfo(data[6]));
PrintAndLogEx(NORMAL, "Chip: %02X, %s", data[5]>>2, get_ST_Chip_Model(data[5]>>2));
PrintAndLogEx(NORMAL, "Chip: %02X, %s", data[5] >> 2, get_ST_Chip_Model(data[5] >> 2));
return;
}
@ -433,7 +467,8 @@ static void print_st_general_info(uint8_t *data, uint8_t len){
//a2 = ? (resp 02 [6a d3])
// 14b get and print Full Info (as much as we know)
bool HF14B_Std_Info(bool verbose){
bool HF14B_Std_Info(bool verbose)
{
bool isSuccess = false;
@ -454,7 +489,7 @@ bool HF14B_Std_Info(bool verbose){
uint64_t status = resp.arg[0];
switch( status ){
switch (status) {
case 0:
PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen));
PrintAndLogEx(NORMAL, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb)));
@ -477,7 +512,8 @@ bool HF14B_Std_Info(bool verbose){
}
// SRx get and print full info (needs more info...)
bool HF14B_ST_Info(bool verbose){
bool HF14B_ST_Info(bool verbose)
{
UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0}};
clearCommandBuffer();
@ -493,7 +529,7 @@ bool HF14B_ST_Info(bool verbose){
memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t));
uint64_t status = resp.arg[0];
if ( status > 0 )
if (status > 0)
return false;
print_st_general_info(card.uid, card.uidlen);
@ -523,7 +559,8 @@ bool HF14B_ST_Info(bool verbose){
}
// get and print all info known about any known 14b tag
bool HF14BInfo(bool verbose){
bool HF14BInfo(bool verbose)
{
// try std 14b (atqb)
if (HF14B_Std_Info(verbose)) return true;
@ -538,7 +575,8 @@ bool HF14BInfo(bool verbose){
}
// menu command to get and print all info known about any known 14b tag
int CmdHF14Binfo(const char *Cmd){
int CmdHF14Binfo(const char *Cmd)
{
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_hf_14b_info();
@ -546,7 +584,8 @@ int CmdHF14Binfo(const char *Cmd){
return HF14BInfo(verbose);
}
bool HF14B_ST_Reader(bool verbose){
bool HF14B_ST_Reader(bool verbose)
{
bool isSuccess = false;
@ -565,7 +604,7 @@ bool HF14B_ST_Reader(bool verbose){
uint64_t status = resp.arg[0];
switch( status ){
switch (status) {
case 0:
print_st_general_info(card.uid, card.uidlen);
isSuccess = true;
@ -586,7 +625,8 @@ bool HF14B_ST_Reader(bool verbose){
return isSuccess;
}
bool HF14B_Std_Reader(bool verbose){
bool HF14B_Std_Reader(bool verbose)
{
bool isSuccess = false;
@ -606,7 +646,7 @@ bool HF14B_Std_Reader(bool verbose){
uint64_t status = resp.arg[0];
switch( status ){
switch (status) {
case 0:
PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen));
PrintAndLogEx(NORMAL, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb)));
@ -628,7 +668,8 @@ bool HF14B_Std_Reader(bool verbose){
}
// test for other 14b type tags (mimic another reader - don't have tags to identify)
bool HF14B_Other_Reader(){
bool HF14B_Other_Reader()
{
// uint8_t data[] = {0x00, 0x0b, 0x3f, 0x80};
// uint8_t datalen = 4;
@ -687,7 +728,8 @@ bool HF14B_Other_Reader(){
}
// get and print general info about all known 14b chips
bool HF14BReader(bool verbose){
bool HF14BReader(bool verbose)
{
// try std 14b (atqb)
if (HF14B_Std_Reader(verbose)) return true;
@ -704,7 +746,8 @@ bool HF14BReader(bool verbose){
}
// menu command to get and print general info about all known 14b chips
int CmdHF14BReader(const char *Cmd){
int CmdHF14BReader(const char *Cmd)
{
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_hf_14b_reader();
@ -716,7 +759,8 @@ int CmdHF14BReader(const char *Cmd){
* SRI* tags are ISO14443-B modulated memory tags,
* this command just dumps the contents of the memory/
*/
int CmdHF14BReadSri(const char *Cmd){
int CmdHF14BReadSri(const char *Cmd)
{
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) < 1 || cmdp == 'h') return usage_hf_14b_read_srx();
@ -729,8 +773,9 @@ int CmdHF14BReadSri(const char *Cmd){
return 0;
}
// New command to write a SRI512/SRIX4K tag.
int CmdHF14BWriteSri(const char *Cmd){
/*
int CmdHF14BWriteSri(const char *Cmd)
{
/*
* For SRIX4K blocks 00 - 7F
* hf 14b raw -c -p 09 $srix4kwblock $srix4kwdata
*
@ -749,23 +794,23 @@ int CmdHF14BWriteSri(const char *Cmd){
if (strlen(Cmd) < 1 || cmdp == 'h') return usage_hf_14b_write_srx();
if ( cmdp == '2' )
if (cmdp == '2')
isSrix4k = false;
//blockno = param_get8(Cmd, 1);
if ( param_gethex(Cmd, 1, &blockno, 2) ) {
if (param_gethex(Cmd, 1, &blockno, 2)) {
PrintAndLogEx(WARNING, "block number must include 2 HEX symbols");
return 0;
}
if ( isSrix4k ){
if ( blockno > 0x7f && blockno != 0xff ){
if (isSrix4k) {
if (blockno > 0x7f && blockno != 0xff) {
PrintAndLogEx(FAILED, "block number out of range");
return 0;
}
} else {
if ( blockno > 0x0f && blockno != 0xff ){
if (blockno > 0x0f && blockno != 0xff) {
PrintAndLogEx(FAILED, "block number out of range");
return 0;
}
@ -776,17 +821,17 @@ int CmdHF14BWriteSri(const char *Cmd){
return 0;
}
if ( blockno == 0xff) {
if (blockno == 0xff) {
PrintAndLogEx(SUCCESS, "[%s] Write special block %02X [ %s ]",
(isSrix4k) ? "SRIX4K":"SRI512",
(isSrix4k) ? "SRIX4K" : "SRI512",
blockno,
sprint_hex(data,4)
sprint_hex(data, 4)
);
} else {
PrintAndLogEx(SUCCESS, "[%s] Write block %02X [ %s ]",
(isSrix4k) ? "SRIX4K":"SRI512",
(isSrix4k) ? "SRIX4K" : "SRI512",
blockno,
sprint_hex(data,4)
sprint_hex(data, 4)
);
}
@ -796,11 +841,12 @@ int CmdHF14BWriteSri(const char *Cmd){
}
// need to write to file
int CmdHF14BDump(const char*Cmd) {
int CmdHF14BDump(const char *Cmd)
{
uint8_t fileNameLen = 0;
char filename[FILE_PATH_SIZE] = {0};
char * fptr = filename;
char *fptr = filename;
bool errors = false;
uint8_t cmdp = 0, cardtype = 1;
uint16_t cardsize = 0;
@ -812,7 +858,7 @@ int CmdHF14BDump(const char*Cmd) {
case 'h':
return usage_hf_14b_dump();
case 'f':
fileNameLen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE);
fileNameLen = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE);
cmdp += 2;
break;
default:
@ -830,14 +876,14 @@ int CmdHF14BDump(const char*Cmd) {
//Validations
if (errors) return usage_hf_14b_dump();
switch (cardtype){
switch (cardtype) {
case 2:
cardsize = (512/8) + 4;
cardsize = (512 / 8) + 4;
blocks = 0x0F;
break;
case 1:
default:
cardsize = (4096/8) + 4;
cardsize = (4096 / 8) + 4;
blocks = 0x7F;
break;
}
@ -891,21 +937,21 @@ int CmdHF14BDump(const char*Cmd) {
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
uint8_t status = resp.arg[0] & 0xFF;
if ( status > 0 ) {
if (status > 0) {
continue;
}
uint16_t len = (resp.arg[1] & 0xFFFF);
recv = resp.d.asBytes;
if ( !check_crc(CRC_14443_B, recv, len) ) {
if (!check_crc(CRC_14443_B, recv, len)) {
PrintAndLogEx(FAILED, "crc fail, retrying one more time");
continue;
}
memcpy(data + (blocknum * 4), resp.d.asBytes, 4);
if ( blocknum == 0xFF) {
if (blocknum == 0xFF) {
//last read.
break;
}
@ -913,16 +959,17 @@ int CmdHF14BDump(const char*Cmd) {
retry = 0;
blocknum++;
if ( blocknum > blocks ) {
if (blocknum > blocks) {
// read config block
blocknum = 0xFF;
}
printf("."); fflush(stdout);
printf(".");
fflush(stdout);
}
}
if ( blocknum != 0xFF) {
if (blocknum != 0xFF) {
PrintAndLogEx(NORMAL, "\n Dump failed");
goto out;
}
@ -936,92 +983,99 @@ int CmdHF14BDump(const char*Cmd) {
"%3d/0x%02X | %s | %s",
i,
i,
sprint_hex(data + (i*4), 4 ),
sprint_ascii(data + (i*4), 4)
sprint_hex(data + (i * 4), 4),
sprint_ascii(data + (i * 4), 4)
);
}
PrintAndLogEx(NORMAL, "\n");
size_t datalen = (blocks+1) * 4;
size_t datalen = (blocks + 1) * 4;
saveFileEML(filename, "eml", data, datalen, 4);
saveFile(filename, "bin", data, datalen);
out:
return switch_off_field_14b();
}
uint32_t srix4kEncode(uint32_t value) {
/*
// vv = value
// pp = position
// vv vv vv pp
4 bytes : 00 1A 20 01
*/
uint32_t srix4kEncode(uint32_t value)
{
/*
// vv = value
// pp = position
// vv vv vv pp
4 bytes : 00 1A 20 01
*/
// only the lower crumbs.
uint8_t block = (value & 0xFF);
uint8_t i = 0;
uint8_t valuebytes[] = {0,0,0};
uint8_t valuebytes[] = {0, 0, 0};
num_to_bytes(value, 3, valuebytes);
// Scrambled part
// Crumb swapping of value.
uint8_t temp[] = {0,0};
temp[0] = (CRUMB(value, 22) << 4 | CRUMB(value, 14 ) << 2 | CRUMB(value, 6)) << 4;
temp[0] |= CRUMB(value, 20) << 4 | CRUMB(value, 12 ) << 2 | CRUMB(value, 4);
temp[1] = (CRUMB(value, 18) << 4 | CRUMB(value, 10 ) << 2 | CRUMB(value, 2)) << 4;
temp[1] |= CRUMB(value, 16) << 4 | CRUMB(value, 8 ) << 2 | CRUMB(value, 0);
uint8_t temp[] = {0, 0};
temp[0] = (CRUMB(value, 22) << 4 | CRUMB(value, 14) << 2 | CRUMB(value, 6)) << 4;
temp[0] |= CRUMB(value, 20) << 4 | CRUMB(value, 12) << 2 | CRUMB(value, 4);
temp[1] = (CRUMB(value, 18) << 4 | CRUMB(value, 10) << 2 | CRUMB(value, 2)) << 4;
temp[1] |= CRUMB(value, 16) << 4 | CRUMB(value, 8) << 2 | CRUMB(value, 0);
// chksum part
uint32_t chksum = 0xFF - block;
// chksum is reduced by each nibbles of value.
for (i = 0; i < 3; ++i){
for (i = 0; i < 3; ++i) {
chksum -= NIBBLE_HIGH(valuebytes[i]);
chksum -= NIBBLE_LOW(valuebytes[i]);
}
// base4 conversion and left shift twice
i = 3;
uint8_t base4[] = {0,0,0,0};
while( chksum !=0 ){
uint8_t base4[] = {0, 0, 0, 0};
while (chksum != 0) {
base4[i--] = (chksum % 4 << 2);
chksum /= 4;
}
// merge scambled and chksum parts
uint32_t encvalue =
( NIBBLE_LOW ( base4[0]) << 28 ) |
( NIBBLE_HIGH( temp[0]) << 24 ) |
(NIBBLE_LOW(base4[0]) << 28) |
(NIBBLE_HIGH(temp[0]) << 24) |
( NIBBLE_LOW ( base4[1]) << 20 ) |
( NIBBLE_LOW ( temp[0]) << 16 ) |
(NIBBLE_LOW(base4[1]) << 20) |
(NIBBLE_LOW(temp[0]) << 16) |
( NIBBLE_LOW ( base4[2]) << 12 ) |
( NIBBLE_HIGH( temp[1]) << 8 ) |
(NIBBLE_LOW(base4[2]) << 12) |
(NIBBLE_HIGH(temp[1]) << 8) |
( NIBBLE_LOW ( base4[3]) << 4 ) |
NIBBLE_LOW ( temp[1] );
(NIBBLE_LOW(base4[3]) << 4) |
NIBBLE_LOW(temp[1]);
PrintAndLogEx(NORMAL, "ICE encoded | %08X -> %08X", value, encvalue);
return encvalue;
}
uint32_t srix4kDecode(uint32_t value) {
switch(value) {
case 0xC04F42C5: return 0x003139;
case 0xC1484807: return 0x002943;
case 0xC0C60848: return 0x001A20;
uint32_t srix4kDecode(uint32_t value)
{
switch (value) {
case 0xC04F42C5:
return 0x003139;
case 0xC1484807:
return 0x002943;
case 0xC0C60848:
return 0x001A20;
}
return 0;
}
uint32_t srix4kDecodeCounter(uint32_t num) {
uint32_t srix4kDecodeCounter(uint32_t num)
{
uint32_t value = ~num;
++value;
return value;
}
uint32_t srix4kGetMagicbytes( uint64_t uid, uint32_t block6, uint32_t block18, uint32_t block19 ){
uint32_t srix4kGetMagicbytes(uint64_t uid, uint32_t block6, uint32_t block18, uint32_t block19)
{
#define MASK 0xFFFFFFFF;
uint32_t uid32 = uid & MASK;
uint32_t counter = srix4kDecodeCounter(block6);
@ -1033,7 +1087,8 @@ uint32_t srix4kGetMagicbytes( uint64_t uid, uint32_t block6, uint32_t block18, u
PrintAndLogEx(SUCCESS, "Magic bytes | %08X", result);
return result;
}
int srix4kValid(const char *Cmd){
int srix4kValid(const char *Cmd)
{
uint64_t uid = 0xD00202501A4532F9;
uint32_t block6 = 0xFFFFFFFF;
@ -1044,14 +1099,15 @@ int srix4kValid(const char *Cmd){
uint32_t test_b18 = 0x00313918;
uint32_t test_b18_enc = srix4kEncode(test_b18);
//uint32_t test_b18_dec = srix4kDecode(test_b18_enc);
PrintAndLogEx(SUCCESS, "ENCODE & CHECKSUM | %08X -> %08X (%s)", test_b18, test_b18_enc , "");
PrintAndLogEx(SUCCESS, "ENCODE & CHECKSUM | %08X -> %08X (%s)", test_b18, test_b18_enc, "");
uint32_t magic = srix4kGetMagicbytes(uid, block6, block18, block19);
PrintAndLogEx(SUCCESS, "BLOCK 21 | %08X -> %08X (no XOR)", block21, magic ^ block21);
return 0;
}
bool waitCmd14b(bool verbose) {
bool waitCmd14b(bool verbose)
{
bool crc = false;
uint8_t data[USB_CMD_DATA_SIZE] = {0x00};
@ -1062,25 +1118,25 @@ bool waitCmd14b(bool verbose) {
if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
status = (resp.arg[0] & 0xFF);
if ( status > 0 ) return false;
if (status > 0) return false;
len = (resp.arg[1] & 0xFFFF);
memcpy(data, resp.d.asBytes, len);
if (verbose) {
if ( len >= 3 ) {
if (len >= 3) {
crc = check_crc(CRC_14443_B, data, len);
PrintAndLogEx(NORMAL, "[LEN %u] %s[%02X %02X] %s",
len,
sprint_hex(data, len-2),
data[len-2],
data[len-1],
sprint_hex(data, len - 2),
data[len - 2],
data[len - 1],
(crc) ? "OK" : "FAIL"
);
} else {
PrintAndLogEx(NORMAL, "[LEN %u] %s", len, sprint_hex(data, len) );
PrintAndLogEx(NORMAL, "[LEN %u] %s", len, sprint_hex(data, len));
}
}
return true;
@ -1105,13 +1161,15 @@ static command_t CommandTable[] = {
{NULL, NULL, 0, NULL}
};
int CmdHF14B(const char *Cmd) {
int CmdHF14B(const char *Cmd)
{
clearCommandBuffer();
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd) {
int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable);
return 0;
}

View file

@ -42,14 +42,14 @@ extern int CmdHF14BList(const char *Cmd);
extern int CmdHF14BInfo(const char *Cmd);
extern int CmdHF14BSim(const char *Cmd);
extern int CmdHF14BSniff(const char *Cmd);
extern int CmdHF14BWrite( const char *cmd);
extern int CmdHF14BWrite(const char *cmd);
extern int CmdHF14BReader(const char *Cmd);
extern int CmdHF14BDump(const char *Cmd);
extern bool HF14BInfo(bool verbose);
extern bool HF14BReader(bool verbose);
extern int CmdHF14BCmdRaw (const char *Cmd);
extern int CmdHF14BCmdRaw(const char *Cmd);
// SRi ST Microelectronics read/write
extern int CmdHF14BReadSri(const char *Cmd);

View file

@ -39,7 +39,7 @@
typedef struct {
uint64_t uid;
int mask; // how many MSB bits used
char* desc;
char *desc;
} productName;
const productName uidmapping[] = {
@ -183,13 +183,14 @@ const productName uidmapping[] = {
{ 0xE042000000000000LL, 16, "3Alogics Inc Korea" },
{ 0xE043000000000000LL, 16, "Top TroniQ Asia Limited Hong Kong" },
{ 0xE044000000000000LL, 16, "Gentag Inc (USA) USA" },
{ 0,0,"no tag-info available" } // must be the last entry
{ 0, 0, "no tag-info available" } // must be the last entry
};
// fast method to just read the UID of a tag (collission detection not supported)
// *buf should be large enough to fit the 64bit uid
// returns 1 if suceeded
int getUID(uint8_t *buf) {
int getUID(uint8_t *buf)
{
UsbCommand resp;
UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
@ -219,7 +220,7 @@ int getUID(uint8_t *buf) {
}
} // retry
if ( retry >= 3 )
if (retry >= 3)
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return 0;
@ -228,18 +229,19 @@ int getUID(uint8_t *buf) {
// get a product description based on the UID
// uid[8] tag uid
// returns description of the best match
static char* getTagInfo_15(uint8_t *uid) {
static char *getTagInfo_15(uint8_t *uid)
{
uint64_t myuid, mask;
int i = 0, best = -1;
memcpy(&myuid, uid, sizeof(uint64_t));
while (uidmapping[i].mask > 0) {
mask = (~0LL) << (64-uidmapping[i].mask);
mask = (~0LL) << (64 - uidmapping[i].mask);
if ((myuid & mask) == uidmapping[i].uid) {
if (best == -1) {
best = i;
} else {
if (uidmapping[i].mask > uidmapping[best].mask) {
best=i;
best = i;
}
}
}
@ -252,32 +254,46 @@ static char* getTagInfo_15(uint8_t *uid) {
}
// return a clear-text message to an errorcode
static char* TagErrorStr(uint8_t error) {
static char *TagErrorStr(uint8_t error)
{
switch (error) {
case 0x01: return "The command is not supported";
case 0x02: return "The command is not recognised";
case 0x03: return "The option is not supported.";
case 0x0f: return "Unknown error.";
case 0x10: return "The specified block is not available (doesn't exist).";
case 0x11: return "The specified block is already -locked and thus cannot be locked again";
case 0x12: return "The specified block is locked and its content cannot be changed.";
case 0x13: return "The specified block was not successfully programmed.";
case 0x14: return "The specified block was not successfully locked.";
default: return "Reserved for Future Use or Custom command error.";
case 0x01:
return "The command is not supported";
case 0x02:
return "The command is not recognised";
case 0x03:
return "The option is not supported.";
case 0x0f:
return "Unknown error.";
case 0x10:
return "The specified block is not available (doesn't exist).";
case 0x11:
return "The specified block is already -locked and thus cannot be locked again";
case 0x12:
return "The specified block is locked and its content cannot be changed.";
case 0x13:
return "The specified block was not successfully programmed.";
case 0x14:
return "The specified block was not successfully locked.";
default:
return "Reserved for Future Use or Custom command error.";
}
}
int usage_15_demod(void){
int usage_15_demod(void)
{
PrintAndLogEx(NORMAL, "Tries to demodulate / decode ISO15693, from downloaded samples.\n"
"Gather samples with 'hf 15 read' / 'hf 15 record'");
return 0;
}
int usage_15_samples(void){
int usage_15_samples(void)
{
PrintAndLogEx(NORMAL, "Acquire samples as Reader (enables carrier, send inquiry\n"
"and download it to graphbuffer. Try 'hf 15 demod' to try to demodulate/decode signal");
return 0;
}
int usage_15_info(void){
int usage_15_info(void)
{
PrintAndLogEx(NORMAL, "Uses the optional command 'get_systeminfo' 0x2B to try and extract information\n"
"command may fail, depending on tag.\n"
"defaults to '1 out of 4' mode\n"
@ -293,11 +309,13 @@ int usage_15_info(void){
"\thf 15 info u");
return 0;
}
int usage_15_record(void){
int usage_15_record(void)
{
PrintAndLogEx(NORMAL, "Record activity without enableing carrier");
return 0;
}
int usage_15_reader(void){
int usage_15_reader(void)
{
PrintAndLogEx(NORMAL, "This command identifies a ISO 15693 tag\n"
"\n"
"Usage: hf 15 reader [h]\n"
@ -308,18 +326,21 @@ int usage_15_reader(void){
"\thf 15 reader");
return 0;
}
int usage_15_sim(void){
int usage_15_sim(void)
{
PrintAndLogEx(NORMAL, "Usage: hf 15 sim <UID>\n"
"\n"
"Example:\n"
"\thf 15 sim E016240000000000");
return 0;
}
int usage_15_findafi(void){
int usage_15_findafi(void)
{
PrintAndLogEx(NORMAL, "'hf 15 finafi' This command needs a helptext. Feel free to add one!");
return 0;
}
int usage_15_dump(void){
int usage_15_dump(void)
{
PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-15693 tag and save it to file\n"
"\n"
"Usage: hf 15 dump [h] <f filname> \n"
@ -332,8 +353,9 @@ int usage_15_dump(void){
"\thf 15 dump f mydump");
return 0;
}
int usage_15_restore(void){
char *options[][2]={
int usage_15_restore(void)
{
char *options[][2] = {
{"h", "this help"},
{"-2", "use slower '1 out of 256' mode"},
{"-o", "set OPTION Flag (needed for TI)"},
@ -346,8 +368,9 @@ int usage_15_restore(void){
PrintAndLogOptions(options, 7, 3);
return 0;
}
int usage_15_raw(void){
char *options[][2]={
int usage_15_raw(void)
{
char *options[][2] = {
{"-r", "do not read response" },
{"-2", "use slower '1 out of 256' mode" },
{"-c", "calculate and append CRC" },
@ -357,7 +380,8 @@ int usage_15_raw(void){
PrintAndLogOptions(options, 4, 3);
return 0;
}
int usage_15_read(void){
int usage_15_read(void)
{
PrintAndLogEx(NORMAL, "Usage: hf 15 read [options] <uid|s|u|*> <page#>\n"
"Options:\n"
"\t-2 use slower '1 out of 256' mode\n"
@ -368,7 +392,8 @@ int usage_15_read(void){
"\tpage#: page number 0-255");
return 0;
}
int usage_15_write(void){
int usage_15_write(void)
{
PrintAndLogEx(NORMAL, "Usage: hf 15 write [options] <uid|s|u|*> <page#> <hexdata>\n"
"Options:\n"
"\t-2 use slower '1 out of 256' mode\n"
@ -381,7 +406,8 @@ int usage_15_write(void){
"\thexdata: data to be written eg AA BB CC DD");
return 0;
}
int usage_15_readmulti(void){
int usage_15_readmulti(void)
{
PrintAndLogEx(NORMAL, "Usage: hf 15 readmulti [options] <uid|s|u|*> <start#> <count#>\n"
"Options:\n"
"\t-2 use slower '1 out of 256' mode\n"
@ -395,7 +421,8 @@ int usage_15_readmulti(void){
}
// Mode 3
//helptext
int CmdHF15Demod(const char *Cmd) {
int CmdHF15Demod(const char *Cmd)
{
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_15_demod();
@ -475,11 +502,12 @@ int CmdHF15Demod(const char *Cmd) {
// * Acquire Samples as Reader (enables carrier, sends inquiry)
//helptext
int CmdHF15Samples(const char *Cmd) {
int CmdHF15Samples(const char *Cmd)
{
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_15_samples();
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693, {0,0,0}};
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693, {0, 0, 0}};
clearCommandBuffer();
SendCommand(&c);
@ -491,10 +519,11 @@ int CmdHF15Samples(const char *Cmd) {
* Commandline handling: HF15 CMD SYSINFO
* get system information from tag/VICC
*/
int CmdHF15Info(const char *Cmd) {
int CmdHF15Info(const char *Cmd)
{
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd)<1 || cmdp == 'h' || cmdp == 'H') return usage_15_info();
if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') return usage_15_info();
UsbCommand resp;
uint8_t *recv;
@ -506,7 +535,7 @@ int CmdHF15Info(const char *Cmd) {
strncpy(cmd, Cmd, 99);
if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_SYSINFO) )
if (!prepareHF15Cmd(&cmd, &c, ISO15_CMD_SYSINFO))
return 0;
AddCrc(req, c.arg[0]);
@ -517,28 +546,28 @@ int CmdHF15Info(const char *Cmd) {
clearCommandBuffer();
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) {
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
PrintAndLogEx(WARNING, "iso15693 card select failed");
return 1;
}
uint32_t status = resp.arg[0];
if ( status < 2 ) {
if (status < 2) {
PrintAndLogEx(WARNING, "iso15693 card doesn't answer to systeminfo command");
return 1;
}
recv = resp.d.asBytes;
if ( recv[0] & ISO15_RES_ERROR ) {
if (recv[0] & ISO15_RES_ERROR) {
PrintAndLogEx(WARNING, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0]));
return 3;
}
PrintAndLogEx(NORMAL, " UID : %s", sprintUID(NULL, recv+2));
PrintAndLogEx(NORMAL, " TYPE : %s", getTagInfo_15(recv+2));
PrintAndLogEx(NORMAL, " SYSINFO : %s", sprint_hex(recv, status-2));
PrintAndLogEx(NORMAL, " UID : %s", sprintUID(NULL, recv + 2));
PrintAndLogEx(NORMAL, " TYPE : %s", getTagInfo_15(recv + 2));
PrintAndLogEx(NORMAL, " SYSINFO : %s", sprint_hex(recv, status - 2));
// DSFID
if (recv[1] & 0x01)
@ -561,9 +590,9 @@ int CmdHF15Info(const char *Cmd) {
// memory
if (recv[1] & 0x04) {
PrintAndLogEx(NORMAL, " - Tag provides info on memory layout (vendor dependent)");
uint8_t blocks = recv[12]+1;
uint8_t blocks = recv[12] + 1;
uint8_t size = (recv[13] & 0x1F);
PrintAndLogEx(NORMAL, " %u (or %u) bytes/blocks x %u blocks", size+1, size, blocks );
PrintAndLogEx(NORMAL, " %u (or %u) bytes/blocks x %u blocks", size + 1, size, blocks);
} else {
PrintAndLogEx(NORMAL, " - Tag does not provide information on memory layout");
}
@ -573,19 +602,21 @@ int CmdHF15Info(const char *Cmd) {
// Record Activity without enabeling carrier
//helptext
int CmdHF15Record(const char *Cmd) {
int CmdHF15Record(const char *Cmd)
{
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_15_record();
UsbCommand c = {CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693, {0,0,0}};
UsbCommand c = {CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693, {0, 0, 0}};
clearCommandBuffer();
SendCommand(&c);
return 0;
}
// used with 'hf search'
int HF15Reader(const char *Cmd, bool verbose) {
uint8_t uid[8] = {0,0,0,0,0,0,0,0};
int HF15Reader(const char *Cmd, bool verbose)
{
uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0};
if (!getUID(uid)) {
if (verbose) PrintAndLogEx(WARNING, "No tag found.");
return 0;
@ -596,7 +627,8 @@ int HF15Reader(const char *Cmd, bool verbose) {
return 1;
}
int CmdHF15Reader(const char *Cmd) {
int CmdHF15Reader(const char *Cmd)
{
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_15_reader();
@ -606,17 +638,18 @@ int CmdHF15Reader(const char *Cmd) {
// Simulation is still not working very good
// helptext
int CmdHF15Sim(const char *Cmd) {
char cmdp =tolower(param_getchar(Cmd, 0));
int CmdHF15Sim(const char *Cmd)
{
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) < 1 || cmdp == 'h') return usage_15_sim();
uint8_t uid[8] = {0,0,0,0,0,0,0,0};
uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0};
if (param_gethex(Cmd, 0, uid, 16)) {
PrintAndLogEx(WARNING, "UID must include 16 HEX symbols");
return 0;
}
PrintAndLogEx(SUCCESS, "Starting simulating UID %s", sprint_hex(uid, sizeof(uid)) );
PrintAndLogEx(SUCCESS, "Starting simulating UID %s", sprint_hex(uid, sizeof(uid)));
UsbCommand c = {CMD_SIMTAG_ISO_15693, {0, 0, 0}};
memcpy(c.d.asBytes, uid, 8);
@ -628,7 +661,8 @@ int CmdHF15Sim(const char *Cmd) {
// finds the AFI (Application Family Idendifier) of a card, by trying all values
// (There is no standard way of reading the AFI, allthough some tags support this)
// helptext
int CmdHF15Afi(const char *Cmd) {
int CmdHF15Afi(const char *Cmd)
{
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_15_findafi();
@ -647,21 +681,22 @@ typedef struct {
// Reads all memory pages
// need to write to file
int CmdHF15Dump(const char*Cmd) {
int CmdHF15Dump(const char *Cmd)
{
uint8_t fileNameLen = 0;
char filename[FILE_PATH_SIZE] = {0};
char * fptr = filename;
char *fptr = filename;
bool errors = false;
uint8_t cmdp = 0;
uint8_t uid[8] = {0,0,0,0,0,0,0,0};
uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0};
while(param_getchar(Cmd, cmdp) != 0x00 && !errors) {
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_15_dump();
case 'f':
fileNameLen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE);
fileNameLen = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE);
cmdp += 2;
break;
default:
@ -684,11 +719,11 @@ int CmdHF15Dump(const char*Cmd) {
}
fptr += sprintf(fptr, "hf-15-");
FillFileNameByUID(fptr,uid,"-dump",sizeof(uid));
FillFileNameByUID(fptr, uid, "-dump", sizeof(uid));
}
// detect blocksize from card :)
PrintAndLogEx(NORMAL, "Reading memory from tag UID " _YELLOW_(%s), sprintUID(NULL, uid));
PrintAndLogEx(NORMAL, "Reading memory from tag UID " _YELLOW_( % s), sprintUID(NULL, uid));
int blocknum = 0;
uint8_t *recv = NULL;
@ -696,7 +731,7 @@ int CmdHF15Dump(const char*Cmd) {
// memory.
t15memory mem[256];
uint8_t data[256*4] = {0};
uint8_t data[256 * 4] = {0};
memset(data, 0, sizeof(data));
UsbCommand resp;
@ -706,7 +741,7 @@ int CmdHF15Dump(const char*Cmd) {
req[1] = ISO15_CMD_READ;
// copy uid to read command
memcpy(req+2, uid, sizeof(uid));
memcpy(req + 2, uid, sizeof(uid));
for (int retry = 0; retry < 5; retry++) {
@ -720,20 +755,20 @@ int CmdHF15Dump(const char*Cmd) {
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
uint8_t len = resp.arg[0];
if ( len < 2 ) {
if (len < 2) {
PrintAndLogEx(FAILED, "iso15693 card select failed");
continue;
}
recv = resp.d.asBytes;
if ( !CheckCrc(recv, len) ) {
if (!CheckCrc(recv, len)) {
PrintAndLogEx(FAILED, "crc fail");
continue;
}
if (recv[0] & ISO15_RES_ERROR) {
PrintAndLogEx(FAILED, "Tag returned Error %i: %s", recv[1], TagErrorStr(recv[1]) );
PrintAndLogEx(FAILED, "Tag returned Error %i: %s", recv[1], TagErrorStr(recv[1]));
break;
}
@ -744,7 +779,8 @@ int CmdHF15Dump(const char*Cmd) {
retry = 0;
blocknum++;
printf("."); fflush(stdout);
printf(".");
fflush(stdout);
}
}
PrintAndLogEx(NORMAL, "\n");
@ -752,7 +788,7 @@ int CmdHF15Dump(const char*Cmd) {
PrintAndLogEx(NORMAL, "block# | data |lck| ascii");
PrintAndLogEx(NORMAL, "---------+--------------+---+----------");
for (int i = 0; i < blocknum; i++) {
PrintAndLogEx(NORMAL, "%3d/0x%02X | %s | %d | %s", i, i, sprint_hex(mem[i].block, 4 ), mem[i].lock, sprint_ascii(mem[i].block, 4) );
PrintAndLogEx(NORMAL, "%3d/0x%02X | %s | %d | %s", i, i, sprint_hex(mem[i].block, 4), mem[i].lock, sprint_ascii(mem[i].block, 4));
}
PrintAndLogEx(NORMAL, "\n");
@ -762,31 +798,31 @@ int CmdHF15Dump(const char*Cmd) {
return 0;
}
int CmdHF15Restore(const char*Cmd) {
int CmdHF15Restore(const char *Cmd)
{
FILE *f;
uint8_t uid[8]={0x00};
uint8_t uid[8] = {0x00};
char filename[FILE_PATH_SIZE] = {0x00};
char buff[255] = {0x00};
size_t blocksize=4;
size_t blocksize = 4;
uint8_t cmdp = 0;
char newCmdPrefix[255] = {0x00}, tmpCmd[255] = {0x00};
char param[FILE_PATH_SIZE]="";
char hex[255]="";
char param[FILE_PATH_SIZE] = "";
char hex[255] = "";
uint8_t retries = 3, tried = 0, i = 0;
int retval=0;
int retval = 0;
size_t bytes_read;
while(param_getchar(Cmd, cmdp) != 0x00) {
switch(tolower(param_getchar(Cmd, cmdp))) {
while (param_getchar(Cmd, cmdp) != 0x00) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case '-':
param_getstr(Cmd, cmdp, param, sizeof(param));
switch(param[1])
{
switch (param[1]) {
case '2':
case 'o':
strncpy(newCmdPrefix, " ", sizeof(newCmdPrefix)-1);
strncat(newCmdPrefix, param, sizeof(newCmdPrefix)-1);
strncpy(newCmdPrefix, " ", sizeof(newCmdPrefix) - 1);
strncat(newCmdPrefix, param, sizeof(newCmdPrefix) - 1);
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%s'", param);
@ -794,21 +830,21 @@ int CmdHF15Restore(const char*Cmd) {
}
break;
case 'f':
param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE);
param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE);
cmdp++;
break;
case 'r':
retries=param_get8ex(Cmd, cmdp+1, 3, 10);
retries = param_get8ex(Cmd, cmdp + 1, 3, 10);
cmdp++;
break;
case 'b':
blocksize=param_get8ex(Cmd, cmdp+1, 4, 10);
blocksize = param_get8ex(Cmd, cmdp + 1, 4, 10);
cmdp++;
break;
case 'u':
param_getstr(Cmd, cmdp+1, buff, FILE_PATH_SIZE);
param_getstr(Cmd, cmdp + 1, buff, FILE_PATH_SIZE);
cmdp++;
snprintf(filename,sizeof(filename),"hf-15-dump-%s-bin",buff);
snprintf(filename, sizeof(filename), "hf-15-dump-%s-bin", buff);
break;
case 'h':
return usage_15_restore();
@ -819,10 +855,10 @@ int CmdHF15Restore(const char*Cmd) {
cmdp++;
}
PrintAndLogEx(INFO,"Blocksize: %u",blocksize);
PrintAndLogEx(INFO, "Blocksize: %u", blocksize);
if ( !strlen(filename)) {
PrintAndLogEx(WARNING,"Please provide a filename");
if (!strlen(filename)) {
PrintAndLogEx(WARNING, "Please provide a filename");
return usage_15_restore();
}
@ -842,32 +878,32 @@ int CmdHF15Restore(const char*Cmd) {
hex[0] = 0x00;
tmpCmd[0] = 0x00;
bytes_read = fread( buff, 1, blocksize, f );
if ( bytes_read == 0) {
bytes_read = fread(buff, 1, blocksize, f);
if (bytes_read == 0) {
PrintAndLogEx(SUCCESS, "File reading done `%s`", filename);
fclose(f);
return 0;
} else if ( bytes_read != blocksize) {
} else if (bytes_read != blocksize) {
PrintAndLogEx(WARNING, "File reading error (%s), %u bytes read instead of %u bytes.", filename, bytes_read, blocksize);
fclose(f);
return 2;
}
for(int j=0; j < blocksize; j++)
snprintf(hex+j*2, 3, "%02X", buff[j]);
for (int j = 0; j < blocksize; j++)
snprintf(hex + j * 2, 3, "%02X", buff[j]);
for(int j=0; j < sizeof(uid)/sizeof(uid[0]); j++)
snprintf(buff+j*2,3,"%02X", uid[j]);
for (int j = 0; j < sizeof(uid) / sizeof(uid[0]); j++)
snprintf(buff + j * 2, 3, "%02X", uid[j]);
//TODO: Addressed mode currently not work
//snprintf(tmpCmd, sizeof(tmpCmd), "%s %s %d %s", newCmdPrefix, buff, i, hex);
snprintf(tmpCmd, sizeof(tmpCmd), "%s u %u %s", newCmdPrefix, i, hex);
PrintAndLogEx(DEBUG, "Command to be sent| %s", tmpCmd);
for(tried=0; tried < retries; tried++)
if(!(retval = CmdHF15Write(tmpCmd)))
for (tried = 0; tried < retries; tried++)
if (!(retval = CmdHF15Write(tmpCmd)))
break;
if(tried >= retries)
if (tried >= retries)
return retval;
i++;
@ -875,16 +911,18 @@ int CmdHF15Restore(const char*Cmd) {
fclose(f);
}
int CmdHF15List(const char *Cmd) {
int CmdHF15List(const char *Cmd)
{
//PrintAndLogEx(WARNING, "Deprecated command, use 'hf list 15' instead");
CmdTraceList("15");
return 0;
}
int CmdHF15Raw(const char *Cmd) {
int CmdHF15Raw(const char *Cmd)
{
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_raw();
if (strlen(Cmd) < 3 || cmdp == 'h' || cmdp == 'H') return usage_15_raw();
UsbCommand resp;
UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
@ -895,12 +933,12 @@ int CmdHF15Raw(const char *Cmd) {
uint32_t datalen = 0, temp;
// strip
while (*Cmd==' ' || *Cmd=='\t') Cmd++;
while (*Cmd == ' ' || *Cmd == '\t') Cmd++;
while (Cmd[i]!='\0') {
if (Cmd[i]==' ' || Cmd[i]=='\t') { i++; continue; }
if (Cmd[i]=='-') {
switch (Cmd[i+1]) {
while (Cmd[i] != '\0') {
if (Cmd[i] == ' ' || Cmd[i] == '\t') { i++; continue; }
if (Cmd[i] == '-') {
switch (Cmd[i + 1]) {
case 'r':
case 'R':
reply = 0;
@ -916,13 +954,13 @@ int CmdHF15Raw(const char *Cmd) {
PrintAndLogEx(WARNING, "Invalid option");
return 0;
}
i+=2;
i += 2;
continue;
}
if ((Cmd[i]>='0' && Cmd[i]<='9') ||
(Cmd[i]>='a' && Cmd[i]<='f') ||
(Cmd[i]>='A' && Cmd[i]<='F') ) {
buf[strlen(buf)+1] = 0;
if ((Cmd[i] >= '0' && Cmd[i] <= '9') ||
(Cmd[i] >= 'a' && Cmd[i] <= 'f') ||
(Cmd[i] >= 'A' && Cmd[i] <= 'F')) {
buf[strlen(buf) + 1] = 0;
buf[strlen(buf)] = Cmd[i];
i++;
@ -955,7 +993,7 @@ int CmdHF15Raw(const char *Cmd) {
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
uint8_t len = resp.arg[0];
PrintAndLogEx(NORMAL, "received %i octets", len);
PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.d.asBytes, len) );
PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.d.asBytes, len));
} else {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
}
@ -968,14 +1006,15 @@ int CmdHF15Raw(const char *Cmd) {
* Parameters:
* **cmd command line
*/
int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd) {
int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd)
{
int temp;
uint8_t *req = c->d.asBytes;
uint8_t uid[8] = {0x00};
uint32_t reqlen = 0;
// strip
while (**cmd==' ' || **cmd=='\t') (*cmd)++;
while (**cmd == ' ' || **cmd == '\t')(*cmd)++;
if (strstr(*cmd, "-2") == *cmd) {
c->arg[1] = 0; // use 1of256
@ -983,7 +1022,7 @@ int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd) {
}
// strip
while (**cmd==' ' || **cmd=='\t') (*cmd)++;
while (**cmd == ' ' || **cmd == '\t')(*cmd)++;
if (strstr(*cmd, "-o") == *cmd) {
req[reqlen] = ISO15_REQ_OPTION;
@ -991,7 +1030,7 @@ int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd) {
}
// strip
while (**cmd == ' ' || **cmd == '\t') (*cmd)++;
while (**cmd == ' ' || **cmd == '\t')(*cmd)++;
switch (**cmd) {
case 0:
@ -1022,9 +1061,9 @@ int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd) {
req[reqlen++] = iso15cmd;
// parse UID
for (int i=0; i<8 && (*cmd)[i*2] && (*cmd)[i*2+1]; i++) {
sscanf((char[]){(*cmd)[i*2], (*cmd)[i*2+1],0}, "%X", &temp);
uid[7-i] = temp & 0xff;
for (int i = 0; i < 8 && (*cmd)[i * 2] && (*cmd)[i * 2 + 1]; i++) {
sscanf((char[]) {(*cmd)[i * 2], (*cmd)[i * 2 + 1], 0}, "%X", &temp);
uid[7 - i] = temp & 0xff;
}
PrintAndLogEx(NORMAL, "Using UID %s", sprintUID(NULL, uid));
@ -1033,9 +1072,9 @@ int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd) {
break;
}
// skip to next space
while (**cmd!=' ' && **cmd!='\t') (*cmd)++;
while (**cmd != ' ' && **cmd != '\t')(*cmd)++;
// skip over the space
while (**cmd==' ' || **cmd=='\t') (*cmd)++;
while (**cmd == ' ' || **cmd == '\t')(*cmd)++;
c->arg[0] = reqlen;
return 1;
@ -1045,10 +1084,11 @@ int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd) {
* Commandline handling: HF15 CMD READMULTI
* Read multiple blocks at once (not all tags support this)
*/
int CmdHF15Readmulti(const char *Cmd) {
int CmdHF15Readmulti(const char *Cmd)
{
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_readmulti();
if (strlen(Cmd) < 3 || cmdp == 'h' || cmdp == 'H') return usage_15_readmulti();
UsbCommand resp;
uint8_t *recv;
@ -1060,7 +1100,7 @@ int CmdHF15Readmulti(const char *Cmd) {
char *cmd = cmdbuf;
strncpy(cmd, Cmd, 99);
if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_READMULTI) )
if (!prepareHF15Cmd(&cmd, &c, ISO15_CMD_READMULTI))
return 0;
// add OPTION flag, in order to get lock-info
@ -1081,18 +1121,18 @@ int CmdHF15Readmulti(const char *Cmd) {
req[reqlen++] = pagenum;
req[reqlen++] = pagecount;
AddCrc(req, reqlen);
c.arg[0] = reqlen+2;
c.arg[0] = reqlen + 2;
clearCommandBuffer();
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) {
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
PrintAndLogEx(FAILED, "iso15693 card select failed");
return 1;
}
uint32_t status = resp.arg[0];
if ( status < 2 ) {
if (status < 2) {
PrintAndLogEx(FAILED, "iso15693 card select failed");
return 1;
}
@ -1104,20 +1144,20 @@ int CmdHF15Readmulti(const char *Cmd) {
return 2;
}
if ( recv[0] & ISO15_RES_ERROR ) {
if (recv[0] & ISO15_RES_ERROR) {
PrintAndLogEx(FAILED, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0]));
return 3;
}
int start = 1; // skip status byte
int stop = (pagecount+1) * 5;
int stop = (pagecount + 1) * 5;
int currblock = pagenum;
// print response
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "block# | data |lck| ascii");
PrintAndLogEx(NORMAL, "---------+--------------+---+----------");
for (int i = start; i < stop; i += 5) {
PrintAndLogEx(NORMAL, "%3d/0x%02X | %s | %d | %s", currblock, currblock, sprint_hex(recv+i+1, 4 ), recv[i], sprint_ascii(recv+i+1, 4) );
PrintAndLogEx(NORMAL, "%3d/0x%02X | %s | %d | %s", currblock, currblock, sprint_hex(recv + i + 1, 4), recv[i], sprint_ascii(recv + i + 1, 4));
currblock++;
}
@ -1128,10 +1168,11 @@ int CmdHF15Readmulti(const char *Cmd) {
* Commandline handling: HF15 CMD READ
* Reads a single Block
*/
int CmdHF15Read(const char *Cmd) {
int CmdHF15Read(const char *Cmd)
{
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_read();
if (strlen(Cmd) < 3 || cmdp == 'h' || cmdp == 'H') return usage_15_read();
UsbCommand resp;
uint8_t *recv;
@ -1147,7 +1188,7 @@ int CmdHF15Read(const char *Cmd) {
char *cmd = cmdbuf;
strncpy(cmd, Cmd, 99);
if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_READ) )
if (!prepareHF15Cmd(&cmd, &c, ISO15_CMD_READ))
return 0;
// add OPTION flag, in order to get lock-info
@ -1161,39 +1202,39 @@ int CmdHF15Read(const char *Cmd) {
AddCrc(req, reqlen);
c.arg[0] = reqlen+2;
c.arg[0] = reqlen + 2;
clearCommandBuffer();
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) {
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
PrintAndLogEx(NORMAL, "iso15693 card select failed");
return 1;
}
uint32_t status = resp.arg[0];
if ( status < 2 ) {
if (status < 2) {
PrintAndLogEx(NORMAL, "iso15693 card select failed");
return 1;
}
recv = resp.d.asBytes;
if ( !CheckCrc(recv, status) ) {
if (!CheckCrc(recv, status)) {
PrintAndLogEx(NORMAL, "CRC failed");
return 2;
}
if ( recv[0] & ISO15_RES_ERROR ) {
if (recv[0] & ISO15_RES_ERROR) {
PrintAndLogEx(WARNING, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0]));
return 3;
}
// print response
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "block #%3d |lck| ascii", blocknum );
PrintAndLogEx(NORMAL, "------------+---+------" );
PrintAndLogEx(NORMAL, "%s| %d | %s", sprint_hex(recv+2, status-4), recv[1], sprint_ascii(recv+2, status-4) );
PrintAndLogEx(NORMAL, "block #%3d |lck| ascii", blocknum);
PrintAndLogEx(NORMAL, "------------+---+------");
PrintAndLogEx(NORMAL, "%s| %d | %s", sprint_hex(recv + 2, status - 4), recv[1], sprint_ascii(recv + 2, status - 4));
PrintAndLogEx(NORMAL, "");
return 0;
}
@ -1202,10 +1243,11 @@ int CmdHF15Read(const char *Cmd) {
* Commandline handling: HF15 CMD WRITE
* Writes a single Block - might run into timeout, even when successful
*/
int CmdHF15Write(const char *Cmd) {
int CmdHF15Write(const char *Cmd)
{
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_write();
if (strlen(Cmd) < 3 || cmdp == 'h' || cmdp == 'H') return usage_15_write();
UsbCommand resp;
uint8_t *recv;
@ -1218,14 +1260,14 @@ int CmdHF15Write(const char *Cmd) {
strncpy(cmd, Cmd, 99);
if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_WRITE) )
if (!prepareHF15Cmd(&cmd, &c, ISO15_CMD_WRITE))
return 0;
reqlen = c.arg[0];
// *cmd -> page num ; *cmd2 -> data
cmd2=cmd;
while (*cmd2!=' ' && *cmd2!='\t' && *cmd2) cmd2++;
cmd2 = cmd;
while (*cmd2 != ' ' && *cmd2 != '\t' && *cmd2) cmd2++;
*cmd2 = 0;
cmd2++;
@ -1234,41 +1276,41 @@ int CmdHF15Write(const char *Cmd) {
req[reqlen++] = (uint8_t)pagenum;
while (cmd2[0] && cmd2[1]) { // hexdata, read by 2 hexchars
if (*cmd2==' ') {
if (*cmd2 == ' ') {
cmd2++;
continue;
}
sscanf((char[]){cmd2[0],cmd2[1],0},"%X",&temp);
req[reqlen++]=temp & 0xff;
cmd2+=2;
sscanf((char[]) {cmd2[0], cmd2[1], 0}, "%X", &temp);
req[reqlen++] = temp & 0xff;
cmd2 += 2;
}
AddCrc(req, reqlen);
c.arg[0] = reqlen+2;
c.arg[0] = reqlen + 2;
PrintAndLogEx(NORMAL, "iso15693 writing to page %02d (0x%02X) | data ", pagenum, pagenum);
clearCommandBuffer();
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) {
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
PrintAndLogEx(FAILED, "iso15693 card timeout, data may be written anyway");
return 1;
}
uint32_t status = resp.arg[0];
if ( status < 2 ) {
if (status < 2) {
PrintAndLogEx(FAILED, "iso15693 card select failed");
return 1;
}
recv = resp.d.asBytes;
if ( !CheckCrc(recv, status) ) {
if (!CheckCrc(recv, status)) {
PrintAndLogEx(FAILED, "CRC failed");
return 2;
}
if ( recv[0] & ISO15_RES_ERROR ) {
if (recv[0] & ISO15_RES_ERROR) {
PrintAndLogEx(NORMAL, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0]));
return 3;
}
@ -1296,13 +1338,15 @@ static command_t CommandTable15[] = {
{NULL, NULL, 0, NULL}
};
int CmdHF15(const char *Cmd) {
int CmdHF15(const char *Cmd)
{
clearCommandBuffer();
CmdsParse(CommandTable15, Cmd);
return 0;
}
int CmdHF15Help(const char *Cmd) {
int CmdHF15Help(const char *Cmd)
{
CmdsHelp(CommandTable15);
return 0;
}

View file

@ -37,13 +37,13 @@ extern int CmdHF15Record(const char *Cmd);
extern int CmdHF15Reader(const char *Cmd);
extern int CmdHF15Sim(const char *Cmd);
extern int CmdHF15Afi(const char *Cmd);
extern int CmdHF15Dump(const char*Cmd);
extern int CmdHF15Dump(const char *Cmd);
extern int CmdHF15Raw(const char *cmd);
extern int CmdHF15Readmulti(const char *Cmd);
extern int CmdHF15Read(const char *Cmd);
extern int CmdHF15Write(const char *Cmd);
extern int CmdHF15Help(const char*Cmd);
extern int CmdHF15Help(const char *Cmd);
// usages
extern int usage_15_demod(void);

View file

@ -28,7 +28,7 @@ int CmdHFEPACollectPACENonces(const char *Cmd)
n = n > 0 ? n : 1;
PrintAndLogEx(NORMAL, "Collecting %u %u byte nonces", n, m);
PrintAndLogEx(NORMAL, "Start: %" PRIu64, msclock()/1000);
PrintAndLogEx(NORMAL, "Start: %" PRIu64, msclock() / 1000);
// repeat n times
for (uint32_t i = 0; i < n; i++) {
// execute PACE
@ -36,15 +36,15 @@ int CmdHFEPACollectPACENonces(const char *Cmd)
clearCommandBuffer();
SendCommand(&c);
UsbCommand resp;
WaitForResponse(CMD_ACK,&resp);
WaitForResponse(CMD_ACK, &resp);
// check if command failed
if (resp.arg[0] != 0) {
PrintAndLogEx(FAILED, "Error in step %d, Return code: %d",resp.arg[0],(int)resp.arg[1]);
PrintAndLogEx(FAILED, "Error in step %d, Return code: %d", resp.arg[0], (int)resp.arg[1]);
} else {
size_t nonce_length = resp.arg[1];
char *nonce = (char *) calloc(2 * nonce_length + 1, sizeof(uint8_t));
for(int j = 0; j < nonce_length; j++) {
for (int j = 0; j < nonce_length; j++) {
sprintf(nonce + (2 * j), "%02X", resp.d.asBytes[j]);
}
// print nonce
@ -55,7 +55,7 @@ int CmdHFEPACollectPACENonces(const char *Cmd)
sleep(d);
}
}
PrintAndLogEx(NORMAL, "End: %" PRIu64, msclock()/1000);
PrintAndLogEx(NORMAL, "End: %" PRIu64, msclock() / 1000);
return 1;
}
@ -83,7 +83,7 @@ int CmdHFEPAPACEReplay(const char *Cmd)
while (Cmd[skip] != ' ' && Cmd[skip] != '\0') {
// convert
scan_return = sscanf(Cmd + skip, "%2X%n",
(unsigned int *) (apdus[i] + apdu_lengths[i]),
(unsigned int *)(apdus[i] + apdu_lengths[i]),
&skip_add);
if (scan_return < 1) {
PrintAndLogEx(NORMAL, (char *)usage_msg);
@ -169,12 +169,14 @@ static command_t CommandTable[] = {
{NULL, NULL, 0, NULL}
};
int CmdHelp(const char *Cmd) {
int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable);
return 0;
}
int CmdHFEPA(const char *Cmd) {
int CmdHFEPA(const char *Cmd)
{
clearCommandBuffer();
CmdsParse(CommandTable, Cmd);
return 0;

View file

@ -11,7 +11,8 @@
static int CmdHelp(const char *Cmd);
int usage_hf_felica_sim(void) {
int usage_hf_felica_sim(void)
{
PrintAndLogEx(NORMAL, "\n Emulating ISO/18092 FeliCa tag \n");
PrintAndLogEx(NORMAL, "Usage: hf felica sim [h] t <type> [v]");
PrintAndLogEx(NORMAL, "Options:");
@ -23,7 +24,8 @@ int usage_hf_felica_sim(void) {
PrintAndLogEx(NORMAL, " hf felica sim t 1 ");
return 0;
}
int usage_hf_felica_sniff(void){
int usage_hf_felica_sniff(void)
{
PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer.");
PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list felica'");
PrintAndLogEx(NORMAL, "Usage: hf felica sniff <s > <t>");
@ -33,7 +35,8 @@ int usage_hf_felica_sniff(void){
PrintAndLogEx(NORMAL, " hf felica sniff s 1000");
return 0;
}
int usage_hf_felica_simlite(void) {
int usage_hf_felica_simlite(void)
{
PrintAndLogEx(NORMAL, "\n Emulating ISO/18092 FeliCa Lite tag \n");
PrintAndLogEx(NORMAL, "Usage: hf felica litesim [h] u <uid>");
PrintAndLogEx(NORMAL, "Options:");
@ -43,7 +46,8 @@ int usage_hf_felica_simlite(void) {
PrintAndLogEx(NORMAL, " hf felica litesim 11223344556677");
return 0;
}
int usage_hf_felica_dumplite(void) {
int usage_hf_felica_dumplite(void)
{
PrintAndLogEx(NORMAL, "\n Dump ISO/18092 FeliCa Lite tag \n");
PrintAndLogEx(NORMAL, "press button to abort run, otherwise it will loop for 200sec.");
PrintAndLogEx(NORMAL, "Usage: hf felica litedump [h]");
@ -53,7 +57,8 @@ int usage_hf_felica_dumplite(void) {
PrintAndLogEx(NORMAL, " hf felica litedump");
return 0;
}
int usage_hf_felica_raw(void){
int usage_hf_felica_raw(void)
{
PrintAndLogEx(NORMAL, "Usage: hf felica raw [-h] [-r] [-c] [-p] [-a] <0A 0B 0C ... hex>");
PrintAndLogEx(NORMAL, " -h this help");
PrintAndLogEx(NORMAL, " -r do not read response");
@ -64,13 +69,15 @@ int usage_hf_felica_raw(void){
return 0;
}
int CmdHFFelicaList(const char *Cmd) {
int CmdHFFelicaList(const char *Cmd)
{
//PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list felica' instead");
CmdTraceList("felica");
return 0;
}
int CmdHFFelicaReader(const char *Cmd) {
int CmdHFFelicaReader(const char *Cmd)
{
bool silent = (Cmd[0] == 's' || Cmd[0] == 'S');
//UsbCommand cDisconnect = {CMD_FELICA_COMMAND, {0,0,0}};
UsbCommand c = {CMD_FELICA_COMMAND, {FELICA_CONNECT, 0, 0}};
@ -87,7 +94,7 @@ int CmdHFFelicaReader(const char *Cmd) {
memcpy(&card, (felica_card_select_t *)resp.d.asBytes, sizeof(felica_card_select_t));
uint64_t status = resp.arg[0];
switch(status) {
switch (status) {
case 1: {
if (!silent)
PrintAndLogEx(WARNING, "card timeout");
@ -122,12 +129,13 @@ int CmdHFFelicaReader(const char *Cmd) {
}
// simulate iso18092 / FeliCa tag
int CmdHFFelicaSim(const char *Cmd) {
int CmdHFFelicaSim(const char *Cmd)
{
bool errors = false;
uint8_t flags = 0;
uint8_t tagtype = 1;
uint8_t cmdp = 0;
uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0};
uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int uidlen = 0;
bool verbose = false;
@ -139,7 +147,7 @@ int CmdHFFelicaSim(const char *Cmd) {
case 't':
case 'T':
// Retrieve the tag type
tagtype = param_get8ex(Cmd, cmdp+1, 0, 10);
tagtype = param_get8ex(Cmd, cmdp + 1, 0, 10);
if (tagtype == 0)
errors = true;
cmdp += 2;
@ -147,9 +155,9 @@ int CmdHFFelicaSim(const char *Cmd) {
case 'u':
case 'U':
// Retrieve the full 4,7,10 byte long uid
param_gethex_ex(Cmd, cmdp+1, uid, &uidlen);
param_gethex_ex(Cmd, cmdp + 1, uid, &uidlen);
if (!errors) {
PrintAndLogEx(NORMAL, "Emulating ISO18092/FeliCa tag with %d byte UID (%s)", uidlen>>1, sprint_hex(uid, uidlen>>1));
PrintAndLogEx(NORMAL, "Emulating ISO18092/FeliCa tag with %d byte UID (%s)", uidlen >> 1, sprint_hex(uid, uidlen >> 1));
}
cmdp += 2;
break;
@ -172,41 +180,42 @@ int CmdHFFelicaSim(const char *Cmd) {
//Validations
if (errors || cmdp == 0) return usage_hf_felica_sim();
UsbCommand c = {CMD_FELICA_SIMULATE_TAG,{ tagtype, flags, 0 }};
memcpy(c.d.asBytes, uid, uidlen>>1);
UsbCommand c = {CMD_FELICA_SIMULATE_TAG, { tagtype, flags, 0 }};
memcpy(c.d.asBytes, uid, uidlen >> 1);
clearCommandBuffer();
SendCommand(&c);
UsbCommand resp;
if ( verbose )
if (verbose)
PrintAndLogEx(NORMAL, "Press pm3-button to abort simulation");
while( !ukbhit() ){
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue;
while (!ukbhit()) {
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) continue;
}
return 0;
}
int CmdHFFelicaSniff(const char *Cmd) {
int CmdHFFelicaSniff(const char *Cmd)
{
uint8_t cmdp = 0;
uint64_t samples2skip = 0;
uint64_t triggers2skip = 0;
bool errors = false;
while(param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch(param_getchar(Cmd, cmdp)) {
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (param_getchar(Cmd, cmdp)) {
case 'h':
case 'H':
return usage_hf_felica_sniff();
case 's':
case 'S':
samples2skip = param_get32ex(Cmd, cmdp+1, 0, 10);
samples2skip = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
break;
case 't':
case 'T':
triggers2skip = param_get32ex(Cmd, cmdp+1, 0, 10);
triggers2skip = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
break;
default:
@ -225,7 +234,8 @@ int CmdHFFelicaSniff(const char *Cmd) {
}
// uid hex
int CmdHFFelicaSimLite(const char *Cmd) {
int CmdHFFelicaSimLite(const char *Cmd)
{
uint64_t uid = param_get64ex(Cmd, 0, 0, 16);
@ -238,12 +248,14 @@ int CmdHFFelicaSimLite(const char *Cmd) {
return 0;
}
static void printSep() {
static void printSep()
{
PrintAndLogEx(NORMAL, "------------------------------------------------------------------------------------");
}
uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t tracelen) {
if (tracepos+19 >= tracelen)
uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t tracelen)
{
if (tracepos + 19 >= tracelen)
return tracelen;
trace += tracepos;
@ -253,45 +265,77 @@ uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t tracelen) {
char line[110] = {0};
for (int j = 0; j < 16; j++) {
snprintf(line + (j * 4), sizeof(line) - 1 - (j*4) , "%02x ", trace[j+3]);
snprintf(line + (j * 4), sizeof(line) - 1 - (j * 4), "%02x ", trace[j + 3]);
}
PrintAndLogEx(NORMAL, "block number %02x, status: %02x %02x",blocknum,status1, status2);
PrintAndLogEx(NORMAL, "block number %02x, status: %02x %02x", blocknum, status1, status2);
switch (blocknum) {
case 0x00: PrintAndLogEx(NORMAL, "S_PAD0: %s",line);break;
case 0x01: PrintAndLogEx(NORMAL, "S_PAD1: %s",line);break;
case 0x02: PrintAndLogEx(NORMAL, "S_PAD2: %s",line);break;
case 0x03: PrintAndLogEx(NORMAL, "S_PAD3: %s",line);break;
case 0x04: PrintAndLogEx(NORMAL, "S_PAD4: %s",line);break;
case 0x05: PrintAndLogEx(NORMAL, "S_PAD5: %s",line);break;
case 0x06: PrintAndLogEx(NORMAL, "S_PAD6: %s",line);break;
case 0x07: PrintAndLogEx(NORMAL, "S_PAD7: %s",line);break;
case 0x08: PrintAndLogEx(NORMAL, "S_PAD8: %s",line);break;
case 0x09: PrintAndLogEx(NORMAL, "S_PAD9: %s",line);break;
case 0x0a: PrintAndLogEx(NORMAL, "S_PAD10: %s",line);break;
case 0x0b: PrintAndLogEx(NORMAL, "S_PAD11: %s",line);break;
case 0x0c: PrintAndLogEx(NORMAL, "S_PAD12: %s",line);break;
case 0x0d: PrintAndLogEx(NORMAL, "S_PAD13: %s",line);break;
case 0x00:
PrintAndLogEx(NORMAL, "S_PAD0: %s", line);
break;
case 0x01:
PrintAndLogEx(NORMAL, "S_PAD1: %s", line);
break;
case 0x02:
PrintAndLogEx(NORMAL, "S_PAD2: %s", line);
break;
case 0x03:
PrintAndLogEx(NORMAL, "S_PAD3: %s", line);
break;
case 0x04:
PrintAndLogEx(NORMAL, "S_PAD4: %s", line);
break;
case 0x05:
PrintAndLogEx(NORMAL, "S_PAD5: %s", line);
break;
case 0x06:
PrintAndLogEx(NORMAL, "S_PAD6: %s", line);
break;
case 0x07:
PrintAndLogEx(NORMAL, "S_PAD7: %s", line);
break;
case 0x08:
PrintAndLogEx(NORMAL, "S_PAD8: %s", line);
break;
case 0x09:
PrintAndLogEx(NORMAL, "S_PAD9: %s", line);
break;
case 0x0a:
PrintAndLogEx(NORMAL, "S_PAD10: %s", line);
break;
case 0x0b:
PrintAndLogEx(NORMAL, "S_PAD11: %s", line);
break;
case 0x0c:
PrintAndLogEx(NORMAL, "S_PAD12: %s", line);
break;
case 0x0d:
PrintAndLogEx(NORMAL, "S_PAD13: %s", line);
break;
case 0x0E: {
uint32_t regA = trace[3] | trace[4] << 8 | trace[5] << 16 | trace[ 6] << 24;
uint32_t regB = trace[7] | trace[8] << 8 | trace[9] << 16 | trace[10] << 24;
line[0] = 0;
for (int j = 0; j < 8; j++)
snprintf(line + (j*2), sizeof(line)-1-(j*2), "%02x", trace[j+11]);
snprintf(line + (j * 2), sizeof(line) - 1 - (j * 2), "%02x", trace[j + 11]);
PrintAndLogEx(NORMAL, "REG: regA: %d regB: %d regC: %s ", regA, regB, line);
}
break;
case 0x80: PrintAndLogEx(NORMAL, "Random Challenge, WO: %s ", line); break;
case 0x81: PrintAndLogEx(NORMAL, "MAC, only set on dual read: %s ", line); break;
case 0x80:
PrintAndLogEx(NORMAL, "Random Challenge, WO: %s ", line);
break;
case 0x81:
PrintAndLogEx(NORMAL, "MAC, only set on dual read: %s ", line);
break;
case 0x82: {
char idd[20];
char idm[20];
for (int j = 0; j < 8; j++)
snprintf(idd + (j*2), sizeof(idd)-1-(j*2), "%02x", trace[j+3]);
snprintf(idd + (j * 2), sizeof(idd) - 1 - (j * 2), "%02x", trace[j + 3]);
for (int j = 0; j < 6; j++)
snprintf(idm + (j*2), sizeof(idm)-1-(j*2), "%02x", trace[j+13]);
snprintf(idm + (j * 2), sizeof(idm) - 1 - (j * 2), "%02x", trace[j + 13]);
PrintAndLogEx(NORMAL, "ID Block, IDd: 0x%s DFC: 0x%02x%02x Arb: %s ", idd, trace[11], trace [12], idm);
}
@ -300,30 +344,38 @@ uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t tracelen) {
char idm[20];
char pmm[20];
for (int j = 0; j < 8; j++)
snprintf(idm + (j*2), sizeof(idm)-1-(j*2), "%02x", trace[j+3]);
snprintf(idm + (j * 2), sizeof(idm) - 1 - (j * 2), "%02x", trace[j + 3]);
for (int j = 0; j < 8; j++)
snprintf(pmm + (j*2), sizeof(pmm)-1-(j*2), "%02x", trace[j+11]);
snprintf(pmm + (j * 2), sizeof(pmm) - 1 - (j * 2), "%02x", trace[j + 11]);
PrintAndLogEx(NORMAL, "DeviceId: IDm: 0x%s PMm: 0x%s ", idm, pmm);
}
break;
case 0x84: PrintAndLogEx(NORMAL, "SER_C: 0x%02x%02x ", trace[3], trace[4]); break;
case 0x85: PrintAndLogEx(NORMAL, "SYS_Cl 0x%02x%02x ", trace[3], trace[4]); break;
case 0x86: PrintAndLogEx(NORMAL, "CKV (key version): 0x%02x%02x ", trace[3], trace[4]); break;
case 0x87: PrintAndLogEx(NORMAL, "CK (card key), WO: %s ", line); break;
case 0x84:
PrintAndLogEx(NORMAL, "SER_C: 0x%02x%02x ", trace[3], trace[4]);
break;
case 0x85:
PrintAndLogEx(NORMAL, "SYS_Cl 0x%02x%02x ", trace[3], trace[4]);
break;
case 0x86:
PrintAndLogEx(NORMAL, "CKV (key version): 0x%02x%02x ", trace[3], trace[4]);
break;
case 0x87:
PrintAndLogEx(NORMAL, "CK (card key), WO: %s ", line);
break;
case 0x88: {
PrintAndLogEx(NORMAL, "Memory Configuration (MC):");
PrintAndLogEx(NORMAL, "MAC needed to write state: %s", trace[3+12]? "on" : "off");
PrintAndLogEx(NORMAL, "MAC needed to write state: %s", trace[3 + 12] ? "on" : "off");
//order might be off here...
PrintAndLogEx(NORMAL, "Write with MAC for S_PAD : %s ", sprint_bin(trace+3+10, 2) );
PrintAndLogEx(NORMAL, "Write with AUTH for S_PAD : %s ", sprint_bin(trace+3+8, 2) );
PrintAndLogEx(NORMAL, "Read after AUTH for S_PAD : %s ", sprint_bin(trace+3+6, 2) );
PrintAndLogEx(NORMAL, "MAC needed to write CK and CKV: %s", trace[3+5] ? "on" : "off");
PrintAndLogEx(NORMAL, "RF parameter: %02x", (trace[3+4] & 0x7) );
PrintAndLogEx(NORMAL, "Compatible with NDEF: %s", trace[3+3] ? "yes" : "no");
PrintAndLogEx(NORMAL, "Memory config writable : %s", (trace[3+2] == 0xff) ? "yes" : "no");
PrintAndLogEx(NORMAL, "RW access for S_PAD : %s ", sprint_bin(trace+3, 2) );
PrintAndLogEx(NORMAL, "Write with MAC for S_PAD : %s ", sprint_bin(trace + 3 + 10, 2));
PrintAndLogEx(NORMAL, "Write with AUTH for S_PAD : %s ", sprint_bin(trace + 3 + 8, 2));
PrintAndLogEx(NORMAL, "Read after AUTH for S_PAD : %s ", sprint_bin(trace + 3 + 6, 2));
PrintAndLogEx(NORMAL, "MAC needed to write CK and CKV: %s", trace[3 + 5] ? "on" : "off");
PrintAndLogEx(NORMAL, "RF parameter: %02x", (trace[3 + 4] & 0x7));
PrintAndLogEx(NORMAL, "Compatible with NDEF: %s", trace[3 + 3] ? "yes" : "no");
PrintAndLogEx(NORMAL, "Memory config writable : %s", (trace[3 + 2] == 0xff) ? "yes" : "no");
PrintAndLogEx(NORMAL, "RW access for S_PAD : %s ", sprint_bin(trace + 3, 2));
}
break;
case 0x90: {
@ -336,37 +388,40 @@ uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t tracelen) {
break;
case 0x92:
PrintAndLogEx(NORMAL, "State:");
PrintAndLogEx(NORMAL, "Polling disabled: %s", trace[3+8] ? "yes" : "no");
PrintAndLogEx(NORMAL, "Polling disabled: %s", trace[3 + 8] ? "yes" : "no");
PrintAndLogEx(NORMAL, "Authenticated: %s", trace[3] ? "yes" : "no");
break;
case 0xa0:
PrintAndLogEx(NORMAL, "CRC of all bloacks match : %s", (trace[3+2]==0xff) ? "no" : "yes");
PrintAndLogEx(NORMAL, "CRC of all bloacks match : %s", (trace[3 + 2] == 0xff) ? "no" : "yes");
break;
default:
PrintAndLogEx(WARNING, "INVALID %d: %s", blocknum, line);
break;
}
return tracepos+19;
return tracepos + 19;
}
int CmdHFFelicaDumpLite(const char *Cmd) {
int CmdHFFelicaDumpLite(const char *Cmd)
{
char ctmp = tolower(param_getchar(Cmd, 0));
if ( ctmp == 'h') return usage_hf_felica_dumplite();
if (ctmp == 'h') return usage_hf_felica_dumplite();
PrintAndLogEx(SUCCESS, "FeliCa lite - dump started");
PrintAndLogEx(SUCCESS, "press pm3-button to cancel");
UsbCommand c = {CMD_FELICA_LITE_DUMP, {0,0,0}};
UsbCommand c = {CMD_FELICA_LITE_DUMP, {0, 0, 0}};
clearCommandBuffer();
SendCommand(&c);
UsbCommand resp;
uint8_t timeout = 0;
while ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) {
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
timeout++;
printf("."); fflush(stdout);
printf(".");
fflush(stdout);
if (ukbhit()) {
int gc = getchar(); (void)gc;
int gc = getchar();
(void)gc;
PrintAndLogEx(WARNING, "\n[!] aborted via keyboard!\n");
DropField();
return 1;
@ -384,15 +439,15 @@ int CmdHFFelicaDumpLite(const char *Cmd) {
uint64_t tracelen = resp.arg[1];
uint8_t *trace = calloc(tracelen, sizeof(uint8_t));
if ( trace == NULL ) {
if (trace == NULL) {
PrintAndLogEx(WARNING, "Cannot allocate memory for trace");
return 1;
}
// only download data if there is any.
if ( tracelen > 0 ) {
if (tracelen > 0) {
if ( !GetFromDevice(BIG_BUF, trace, tracelen, 0, NULL, 2500, false) ){
if (!GetFromDevice(BIG_BUF, trace, tracelen, 0, NULL, 2500, false)) {
PrintAndLogEx(WARNING, "command execution time out");
free(trace);
return 0;
@ -414,7 +469,8 @@ int CmdHFFelicaDumpLite(const char *Cmd) {
return 0;
}
int CmdHFFelicaCmdRaw(const char *cmd) {
int CmdHFFelicaCmdRaw(const char *cmd)
{
UsbCommand c = {CMD_FELICA_COMMAND, {0, 0, 0}};
bool reply = 1;
bool crc = false;
@ -422,7 +478,7 @@ int CmdHFFelicaCmdRaw(const char *cmd) {
bool active = false;
bool active_select = false;
uint16_t numbits = 0;
char buf[5]="";
char buf[5] = "";
int i = 0;
uint8_t data[USB_CMD_DATA_SIZE];
uint16_t datalen = 0;
@ -431,12 +487,12 @@ int CmdHFFelicaCmdRaw(const char *cmd) {
if (strlen(cmd) < 2) return usage_hf_felica_raw();
// strip
while (*cmd==' ' || *cmd=='\t') cmd++;
while (*cmd == ' ' || *cmd == '\t') cmd++;
while (cmd[i]!='\0') {
if (cmd[i]==' ' || cmd[i]=='\t') { i++; continue; }
if (cmd[i]=='-') {
switch (cmd[i+1]) {
while (cmd[i] != '\0') {
if (cmd[i] == ' ' || cmd[i] == '\t') { i++; continue; }
if (cmd[i] == '-') {
switch (cmd[i + 1]) {
case 'H':
case 'h':
return usage_hf_felica_raw();
@ -456,11 +512,11 @@ int CmdHFFelicaCmdRaw(const char *cmd) {
active_select = true;
break;
case 'b':
sscanf(cmd+i+2, "%d", &temp);
sscanf(cmd + i + 2, "%d", &temp);
numbits = temp & 0xFFFF;
i+=3;
while(cmd[i]!=' ' && cmd[i]!='\0') { i++; }
i-=2;
i += 3;
while (cmd[i] != ' ' && cmd[i] != '\0') { i++; }
i -= 2;
break;
default:
return usage_hf_felica_raw();
@ -468,18 +524,18 @@ int CmdHFFelicaCmdRaw(const char *cmd) {
i += 2;
continue;
}
if ((cmd[i]>='0' && cmd[i]<='9') ||
(cmd[i]>='a' && cmd[i]<='f') ||
(cmd[i]>='A' && cmd[i]<='F') ) {
buf[strlen(buf)+1]=0;
buf[strlen(buf)]=cmd[i];
if ((cmd[i] >= '0' && cmd[i] <= '9') ||
(cmd[i] >= 'a' && cmd[i] <= 'f') ||
(cmd[i] >= 'A' && cmd[i] <= 'F')) {
buf[strlen(buf) + 1] = 0;
buf[strlen(buf)] = cmd[i];
i++;
if (strlen(buf)>=2) {
sscanf(buf,"%x",&temp);
data[datalen]=(uint8_t)(temp & 0xff);
*buf=0;
if (++datalen >= sizeof(data)){
if (strlen(buf) >= 2) {
sscanf(buf, "%x", &temp);
data[datalen] = (uint8_t)(temp & 0xff);
*buf = 0;
if (++datalen >= sizeof(data)) {
if (crc)
PrintAndLogEx(NORMAL, "Buffer is full, we can't add CRC to your data");
break;
@ -491,7 +547,7 @@ int CmdHFFelicaCmdRaw(const char *cmd) {
return 0;
}
if (crc && datalen>0 && datalen < sizeof(data)-2) {
if (crc && datalen > 0 && datalen < sizeof(data) - 2) {
uint8_t b1, b2;
compute_crc(CRC_FELICA, data, datalen, &b1, &b2);
data[datalen++] = b1;
@ -500,7 +556,7 @@ int CmdHFFelicaCmdRaw(const char *cmd) {
if (active || active_select) {
c.arg[0] |= FELICA_CONNECT;
if(active)
if (active)
c.arg[0] |= FELICA_NO_SELECT;
}
@ -530,16 +586,17 @@ int CmdHFFelicaCmdRaw(const char *cmd) {
return 0;
}
void waitCmdFelica(uint8_t iSelect) {
void waitCmdFelica(uint8_t iSelect)
{
UsbCommand resp;
uint16_t len = 0;
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
len = iSelect ? (resp.arg[1] & 0xffff) : (resp.arg[0] & 0xffff);
PrintAndLogEx(NORMAL, "received %i octets", len);
if(!len)
if (!len)
return;
PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.d.asBytes, len) );
PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.d.asBytes, len));
} else {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
}
@ -558,13 +615,15 @@ static command_t CommandTable[] = {
{NULL, NULL, 0, NULL}
};
int CmdHFFelica(const char *Cmd) {
int CmdHFFelica(const char *Cmd)
{
clearCommandBuffer();
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd) {
int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable);
return 0;
}

View file

@ -49,7 +49,8 @@
static int CmdHelp(const char *Cmd);
int CmdHFFidoInfo(const char *cmd) {
int CmdHFFidoInfo(const char *cmd)
{
if (cmd && strlen(cmd) > 0)
PrintAndLog("WARNING: command don't have any parameters.\n");
@ -104,7 +105,7 @@ int CmdHFFidoInfo(const char *cmd) {
return 0;
}
if(buf[0]) {
if (buf[0]) {
PrintAndLog("FIDO2 ger version error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0]));
return 0;
}
@ -124,12 +125,13 @@ int CmdHFFidoInfo(const char *cmd) {
return 0;
}
json_t *OpenJson(int paramnum, char *fname, void* argtable[], bool *err) {
json_t *OpenJson(int paramnum, char *fname, void *argtable[], bool *err)
{
json_t *root = NULL;
json_error_t error;
*err = false;
uint8_t jsonname[250] ={0};
uint8_t jsonname[250] = {0};
char *cjsonname = (char *)jsonname;
int jsonnamelen = 0;
@ -168,7 +170,8 @@ json_t *OpenJson(int paramnum, char *fname, void* argtable[], bool *err) {
return root;
}
int CmdHFFidoRegister(const char *cmd) {
int CmdHFFidoRegister(const char *cmd)
{
uint8_t data[64] = {0};
int chlen = 0;
uint8_t cdata[250] = {0};
@ -182,7 +185,7 @@ int CmdHFFidoRegister(const char *cmd) {
"\thf fido reg 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters"
"\thf fido reg -p s0 s1 -> execute command with plain parameters");
void* argtable[] = {
void *argtable[] = {
arg_param_begin,
arg_lit0("aA", "apdu", "show APDU reqests and responses"),
arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"),
@ -204,7 +207,7 @@ int CmdHFFidoRegister(const char *cmd) {
char fname[250] = {0};
bool err;
root = OpenJson(5, fname, argtable, &err);
if(err)
if (err)
return 1;
if (root) {
size_t jlen;
@ -357,7 +360,7 @@ int CmdHFFidoRegister(const char *cmd) {
if (res == -0x4e00) {
PrintAndLog("Signature is NOT VALID.");
} else {
PrintAndLog("Other signature check error: %x %s", (res<0)?-res:res, ecdsa_get_error(res));
PrintAndLog("Other signature check error: %x %s", (res < 0) ? -res : res, ecdsa_get_error(res));
}
} else {
PrintAndLog("Signature is OK.");
@ -368,11 +371,11 @@ int CmdHFFidoRegister(const char *cmd) {
}
PrintAndLog("\nauth command: ");
printf("hf fido auth %s%s", paramsPlain?"-p ":"", sprint_hex_inrow(&buf[67], keyHandleLen));
if(chlen || applen)
printf(" %s", paramsPlain?(char *)cdata:sprint_hex_inrow(cdata, 32));
if(applen)
printf(" %s", paramsPlain?(char *)adata:sprint_hex_inrow(adata, 32));
printf("hf fido auth %s%s", paramsPlain ? "-p " : "", sprint_hex_inrow(&buf[67], keyHandleLen));
if (chlen || applen)
printf(" %s", paramsPlain ? (char *)cdata : sprint_hex_inrow(cdata, 32));
if (applen)
printf(" %s", paramsPlain ? (char *)adata : sprint_hex_inrow(adata, 32));
printf("\n");
if (root) {
@ -397,7 +400,8 @@ int CmdHFFidoRegister(const char *cmd) {
return 0;
};
int CmdHFFidoAuthenticate(const char *cmd) {
int CmdHFFidoAuthenticate(const char *cmd)
{
uint8_t data[512] = {0};
uint8_t hdata[250] = {0};
bool public_key_loaded = false;
@ -412,7 +416,7 @@ int CmdHFFidoAuthenticate(const char *cmd) {
"\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f "
"000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters");
void* argtable[] = {
void *argtable[] = {
arg_param_begin,
arg_lit0("aA", "apdu", "show APDU reqests and responses"),
arg_lit0("vV", "verbose", "show technical data"),
@ -441,7 +445,7 @@ int CmdHFFidoAuthenticate(const char *cmd) {
char fname[250] = {0};
bool err;
root = OpenJson(7, fname, argtable, &err);
if(err)
if (err)
return 1;
if (root) {
size_t jlen;
@ -554,7 +558,7 @@ int CmdHFFidoAuthenticate(const char *cmd) {
}
PrintAndLog("---------------------------------------------------------------");
PrintAndLog("User presence: %s", (buf[0]?"verified":"not verified"));
PrintAndLog("User presence: %s", (buf[0] ? "verified" : "not verified"));
uint32_t cntr = (uint32_t)bytes_to_num(&buf[1], 4);
PrintAndLog("Counter: %d", cntr);
PrintAndLog("Hash[%d]: %s", len - 5, sprint_hex(&buf[5], len - 5));
@ -583,7 +587,7 @@ int CmdHFFidoAuthenticate(const char *cmd) {
if (res == -0x4e00) {
PrintAndLog("Signature is NOT VALID.");
} else {
PrintAndLog("Other signature check error: %x %s", (res<0)?-res:res, ecdsa_get_error(res));
PrintAndLog("Other signature check error: %x %s", (res < 0) ? -res : res, ecdsa_get_error(res));
}
} else {
PrintAndLog("Signature is OK.");
@ -615,13 +619,15 @@ int CmdHFFidoAuthenticate(const char *cmd) {
return 0;
};
void CheckSlash(char *fileName) {
void CheckSlash(char *fileName)
{
if ((fileName[strlen(fileName) - 1] != '/') &&
(fileName[strlen(fileName) - 1] != '\\'))
strcat(fileName, "/");
}
int GetExistsFileNameJson(char *prefixDir, char *reqestedFileName, char *fileName) {
int GetExistsFileNameJson(char *prefixDir, char *reqestedFileName, char *fileName)
{
fileName[0] = 0x00;
strcpy(fileName, get_my_executable_directory());
CheckSlash(fileName);
@ -648,7 +654,8 @@ int GetExistsFileNameJson(char *prefixDir, char *reqestedFileName, char *fileNam
return 0;
}
int CmdHFFido2MakeCredential(const char *cmd) {
int CmdHFFido2MakeCredential(const char *cmd)
{
json_error_t error;
json_t *root = NULL;
char fname[300] = {0};
@ -658,7 +665,7 @@ int CmdHFFido2MakeCredential(const char *cmd) {
"Usage:\n\thf fido make -> execute command default parameters file `fido2.json`\n"
"\thf fido make test.json -> execute command with parameters file `text.json`");
void* argtable[] = {
void *argtable[] = {
arg_param_begin,
arg_lit0("aA", "apdu", "show APDU reqests and responses"),
arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"),
@ -675,7 +682,7 @@ int CmdHFFido2MakeCredential(const char *cmd) {
bool showDERTLV = arg_get_lit(3);
bool showCBOR = arg_get_lit(4);
uint8_t jsonname[250] ={0};
uint8_t jsonname[250] = {0};
char *cjsonname = (char *)jsonname;
int jsonnamelen = 0;
CLIGetStrWithReturn(5, jsonname, &jsonnamelen);
@ -690,7 +697,7 @@ int CmdHFFido2MakeCredential(const char *cmd) {
SetAPDULogging(APDULogging);
int res = GetExistsFileNameJson("fido", cjsonname, fname);
if(res) {
if (res) {
PrintAndLog("ERROR: Can't found the json file.");
return res;
}
@ -745,7 +752,7 @@ int CmdHFFido2MakeCredential(const char *cmd) {
return 3;
}
if(buf[0]) {
if (buf[0]) {
PrintAndLog("FIDO2 make credential error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0]));
return 0;
}
@ -775,7 +782,8 @@ int CmdHFFido2MakeCredential(const char *cmd) {
return 0;
};
int CmdHFFido2GetAssertion(const char *cmd) {
int CmdHFFido2GetAssertion(const char *cmd)
{
json_error_t error;
json_t *root = NULL;
char fname[300] = {0};
@ -785,7 +793,7 @@ int CmdHFFido2GetAssertion(const char *cmd) {
"Usage:\n\thf fido assert -> execute command default parameters file `fido2.json`\n"
"\thf fido assert test.json -l -> execute command with parameters file `text.json` and add to request CredentialId");
void* argtable[] = {
void *argtable[] = {
arg_param_begin,
arg_lit0("aA", "apdu", "show APDU reqests and responses"),
arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"),
@ -802,7 +810,7 @@ int CmdHFFido2GetAssertion(const char *cmd) {
bool showCBOR = arg_get_lit(3);
bool createAllowList = arg_get_lit(4);
uint8_t jsonname[250] ={0};
uint8_t jsonname[250] = {0};
char *cjsonname = (char *)jsonname;
int jsonnamelen = 0;
CLIGetStrWithReturn(5, jsonname, &jsonnamelen);
@ -817,7 +825,7 @@ int CmdHFFido2GetAssertion(const char *cmd) {
SetAPDULogging(APDULogging);
int res = GetExistsFileNameJson("fido", "fido2", fname);
if(res) {
if (res) {
PrintAndLog("ERROR: Can't found the json file.");
return res;
}
@ -872,7 +880,7 @@ int CmdHFFido2GetAssertion(const char *cmd) {
return 3;
}
if(buf[0]) {
if (buf[0]) {
PrintAndLog("FIDO2 get assertion error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0]));
return 0;
}
@ -902,8 +910,7 @@ int CmdHFFido2GetAssertion(const char *cmd) {
return 0;
};
static command_t CommandTable[] =
{
static command_t CommandTable[] = {
{"help", CmdHelp, 1, "This help."},
{"info", CmdHFFidoInfo, 0, "Info about FIDO tag."},
{"reg", CmdHFFidoRegister, 0, "FIDO U2F Registration Message."},
@ -913,13 +920,15 @@ static command_t CommandTable[] =
{NULL, NULL, 0, NULL}
};
int CmdHFFido(const char *Cmd) {
int CmdHFFido(const char *Cmd)
{
(void)WaitForResponseTimeout(CMD_ACK, NULL, 100);
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd) {
int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable);
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -79,9 +79,9 @@ extern int CmdHFiClassPermuteKey(const char *Cmd);
void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize);
void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite);
int LoadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt);
int GenerateMacFromKeyFile( uint8_t* CSN, uint8_t* CCNR, bool use_raw, bool use_elite, uint8_t* keys, int keycnt, iclass_premac_t* list );
int GenerateFromKeyFile( uint8_t* CSN, uint8_t* CCNR, bool use_raw, bool use_elite, uint8_t* keys, int keycnt, iclass_prekey_t* list );
void PrintPreCalcMac(uint8_t* keys, int keycnt, iclass_premac_t* pre_list);
void PrintPreCalc(iclass_prekey_t* list, int itemcnt);
int LoadDictionaryKeyFile(char *filename, uint8_t **keys, int *keycnt);
int GenerateMacFromKeyFile(uint8_t *CSN, uint8_t *CCNR, bool use_raw, bool use_elite, uint8_t *keys, int keycnt, iclass_premac_t *list);
int GenerateFromKeyFile(uint8_t *CSN, uint8_t *CCNR, bool use_raw, bool use_elite, uint8_t *keys, int keycnt, iclass_prekey_t *list);
void PrintPreCalcMac(uint8_t *keys, int keycnt, iclass_premac_t *pre_list);
void PrintPreCalc(iclass_prekey_t *list, int itemcnt);
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -53,24 +53,24 @@ typedef struct {
} TAuthData;
extern void ClearAuthData();
extern uint8_t iso14443A_CRC_check(bool isResponse, uint8_t* data, uint8_t len);
extern uint8_t iso14443B_CRC_check(uint8_t* d, uint8_t n);
extern uint8_t mifare_CRC_check(bool isResponse, uint8_t* data, uint8_t len);
extern uint8_t iso15693_CRC_check(uint8_t* d, uint8_t n);
extern uint8_t iclass_CRC_check(bool isResponse, uint8_t* d, uint8_t n);
extern uint8_t iso14443A_CRC_check(bool isResponse, uint8_t *data, uint8_t len);
extern uint8_t iso14443B_CRC_check(uint8_t *d, uint8_t n);
extern uint8_t mifare_CRC_check(bool isResponse, uint8_t *data, uint8_t len);
extern uint8_t iso15693_CRC_check(uint8_t *d, uint8_t n);
extern uint8_t iclass_CRC_check(bool isResponse, uint8_t *d, uint8_t n);
int applyIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize);
int applyIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
extern void annotateIclass(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize);
extern void annotateIso15693(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize);
extern void annotateTopaz(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize);
extern void annotateLegic(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize);
extern void annotateFelica(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize);
extern void annotateIso7816(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize);
extern void annotateIso14443b(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize);
extern void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize);
extern void annotateMfDesfire(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize);
extern void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8_t* parity, uint8_t paritysize, bool isResponse);
extern void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
extern void annotateIso15693(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
extern void annotateTopaz(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
extern void annotateLegic(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
extern void annotateFelica(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
extern void annotateIso7816(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
extern void annotateIso14443b(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
extern void annotateIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
extern void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
extern void annotateMifare(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, uint8_t paritysize, bool isResponse);
extern bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isResponse, uint8_t *mfData, size_t *mfDataLen);
extern bool NTParityChk(TAuthData *ad, uint32_t ntx);

File diff suppressed because it is too large Load diff

View file

@ -36,41 +36,41 @@
extern int CmdHFMF(const char *Cmd);
extern int CmdHF14AMfList(const char *Cmd);
extern int CmdHF14AMfDbg(const char* cmd);
extern int CmdHF14AMfRdBl(const char* cmd);
extern int CmdHF14AMfURdBl(const char* cmd);
extern int CmdHF14AMfRdSc(const char* cmd);
extern int CmdHF14SMfURdCard(const char* cmd);
extern int CmdHF14AMfDump(const char* cmd);
extern int CmdHF14AMfRestore(const char* cmd);
extern int CmdHF14AMfWrBl(const char* cmd);
extern int CmdHF14AMfUWrBl(const char* cmd);
extern int CmdHF14AMfChk(const char* cmd);
extern int CmdHF14AMfDarkside(const char* cmd);
extern int CmdHF14AMfNested(const char* cmd);
extern int CmdHF14AMfDbg(const char *cmd);
extern int CmdHF14AMfRdBl(const char *cmd);
extern int CmdHF14AMfURdBl(const char *cmd);
extern int CmdHF14AMfRdSc(const char *cmd);
extern int CmdHF14SMfURdCard(const char *cmd);
extern int CmdHF14AMfDump(const char *cmd);
extern int CmdHF14AMfRestore(const char *cmd);
extern int CmdHF14AMfWrBl(const char *cmd);
extern int CmdHF14AMfUWrBl(const char *cmd);
extern int CmdHF14AMfChk(const char *cmd);
extern int CmdHF14AMfDarkside(const char *cmd);
extern int CmdHF14AMfNested(const char *cmd);
extern int CmdHF14AMfNestedHard(const char *Cmd);
//extern int CmdHF14AMfSniff(const char* cmd);
extern int CmdHF14AMf1kSim(const char* cmd);
extern int CmdHF14AMf1kSim(const char *cmd);
extern int CmdHF14AMfKeyBrute(const char *Cmd);
extern int CmdHF14AMfEClear(const char* cmd);
extern int CmdHF14AMfEGet(const char* cmd);
extern int CmdHF14AMfESet(const char* cmd);
extern int CmdHF14AMfELoad(const char* cmd);
extern int CmdHF14AMfESave(const char* cmd);
extern int CmdHF14AMfECFill(const char* cmd);
extern int CmdHF14AMfEKeyPrn(const char* cmd);
extern int CmdHF14AMfCSetUID(const char* cmd);
extern int CmdHF14AMfCSetBlk(const char* cmd);
extern int CmdHF14AMfCGetBlk(const char* cmd);
extern int CmdHF14AMfCGetSc(const char* cmd);
extern int CmdHF14AMfCLoad(const char* cmd);
extern int CmdHF14AMfCSave(const char* cmd);
extern int CmdHF14AMfEClear(const char *cmd);
extern int CmdHF14AMfEGet(const char *cmd);
extern int CmdHF14AMfESet(const char *cmd);
extern int CmdHF14AMfELoad(const char *cmd);
extern int CmdHF14AMfESave(const char *cmd);
extern int CmdHF14AMfECFill(const char *cmd);
extern int CmdHF14AMfEKeyPrn(const char *cmd);
extern int CmdHF14AMfCSetUID(const char *cmd);
extern int CmdHF14AMfCSetBlk(const char *cmd);
extern int CmdHF14AMfCGetBlk(const char *cmd);
extern int CmdHF14AMfCGetSc(const char *cmd);
extern int CmdHF14AMfCLoad(const char *cmd);
extern int CmdHF14AMfCSave(const char *cmd);
extern int CmdHf14MfDecryptBytes(const char *Cmd);
extern int CmdHf14AMfSetMod(const char *Cmd);
extern int CmdHf14AMfNack(const char *Cmd);
void showSectorTable(void);
void readerAttack(nonces_t data, bool setEmulatorMem, bool verbose);
void printKeyTable( uint8_t sectorscnt, sector_t *e_sector );
void printKeyTable_fast( uint8_t sectorscnt, icesector_t *e_sector, uint64_t bar, uint64_t foo );
void printKeyTable(uint8_t sectorscnt, sector_t *e_sector);
void printKeyTable_fast(uint8_t sectorscnt, icesector_t *e_sector, uint64_t bar, uint64_t foo);
#endif

View file

@ -30,14 +30,14 @@ uint8_t LENPOS = 1;
uint8_t key_zero_data[16] = { 0x00 };
uint8_t key_ones_data[16] = { 0x01 };
uint8_t key_defa_data[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
uint8_t key_picc_data[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f };
uint8_t key_defa_data[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
uint8_t key_picc_data[16] = { 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f };
static int CmdHelp(const char *Cmd);
int CmdHF14ADesWb(const char *Cmd)
{
/* uint8_t blockNo = 0;
/* uint8_t blockNo = 0;
uint8_t keyType = 0;
uint8_t key[6] = {0, 0, 0, 0, 0, 0};
uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
@ -132,49 +132,53 @@ int CmdHF14ADesRb(const char *Cmd)
return 0;
}
int CmdHF14ADesInfo(const char *Cmd){
int CmdHF14ADesInfo(const char *Cmd)
{
UsbCommand c = {CMD_MIFARE_DESFIRE_INFO};
SendCommand(&c);
UsbCommand resp;
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
PrintAndLogEx(WARNING, "Command execute timeout");
return 0;
}
uint8_t isOK = resp.arg[0] & 0xff;
if ( !isOK ){
switch ( resp.arg[1] ) {
if (!isOK) {
switch (resp.arg[1]) {
case 1:
PrintAndLogEx(WARNING, "Can't select card"); break;
PrintAndLogEx(WARNING, "Can't select card");
break;
case 2:
PrintAndLogEx(WARNING, "Card is most likely not Desfire. Its UID has wrong size"); break;
PrintAndLogEx(WARNING, "Card is most likely not Desfire. Its UID has wrong size");
break;
case 3:
default:
PrintAndLogEx(WARNING, "Command unsuccessful"); break;
PrintAndLogEx(WARNING, "Command unsuccessful");
break;
}
return 0;
}
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "-- Desfire Information --------------------------------------");
PrintAndLogEx(NORMAL, "-------------------------------------------------------------");
PrintAndLogEx(NORMAL, " UID : %s",sprint_hex(resp.d.asBytes, 7));
PrintAndLogEx(NORMAL, " Batch number : %s",sprint_hex(resp.d.asBytes+28,5));
PrintAndLogEx(NORMAL, " Production date : week %02x, 20%02x",resp.d.asBytes[33], resp.d.asBytes[34]);
PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(resp.d.asBytes, 7));
PrintAndLogEx(NORMAL, " Batch number : %s", sprint_hex(resp.d.asBytes + 28, 5));
PrintAndLogEx(NORMAL, " Production date : week %02x, 20%02x", resp.d.asBytes[33], resp.d.asBytes[34]);
PrintAndLogEx(NORMAL, " -----------------------------------------------------------");
PrintAndLogEx(NORMAL, " Hardware Information");
PrintAndLogEx(NORMAL, " Vendor Id : %s", getTagInfo(resp.d.asBytes[7]));
PrintAndLogEx(NORMAL, " Type : 0x%02X",resp.d.asBytes[8]);
PrintAndLogEx(NORMAL, " Subtype : 0x%02X",resp.d.asBytes[9]);
PrintAndLogEx(NORMAL, " Version : %s",GetVersionStr(resp.d.asBytes[10], resp.d.asBytes[11]) );
PrintAndLogEx(NORMAL, " Storage size : %s",GetCardSizeStr(resp.d.asBytes[12]));
PrintAndLogEx(NORMAL, " Protocol : %s",GetProtocolStr(resp.d.asBytes[13]));
PrintAndLogEx(NORMAL, " Type : 0x%02X", resp.d.asBytes[8]);
PrintAndLogEx(NORMAL, " Subtype : 0x%02X", resp.d.asBytes[9]);
PrintAndLogEx(NORMAL, " Version : %s", GetVersionStr(resp.d.asBytes[10], resp.d.asBytes[11]));
PrintAndLogEx(NORMAL, " Storage size : %s", GetCardSizeStr(resp.d.asBytes[12]));
PrintAndLogEx(NORMAL, " Protocol : %s", GetProtocolStr(resp.d.asBytes[13]));
PrintAndLogEx(NORMAL, " -----------------------------------------------------------");
PrintAndLogEx(NORMAL, " Software Information");
PrintAndLogEx(NORMAL, " Vendor Id : %s", getTagInfo(resp.d.asBytes[14]));
PrintAndLogEx(NORMAL, " Type : 0x%02X",resp.d.asBytes[15]);
PrintAndLogEx(NORMAL, " Subtype : 0x%02X",resp.d.asBytes[16]);
PrintAndLogEx(NORMAL, " Version : %d.%d",resp.d.asBytes[17], resp.d.asBytes[18]);
PrintAndLogEx(NORMAL, " Type : 0x%02X", resp.d.asBytes[15]);
PrintAndLogEx(NORMAL, " Subtype : 0x%02X", resp.d.asBytes[16]);
PrintAndLogEx(NORMAL, " Version : %d.%d", resp.d.asBytes[17], resp.d.asBytes[18]);
PrintAndLogEx(NORMAL, " storage size : %s", GetCardSizeStr(resp.d.asBytes[19]));
PrintAndLogEx(NORMAL, " Protocol : %s", GetProtocolStr(resp.d.asBytes[20]));
PrintAndLogEx(NORMAL, "-------------------------------------------------------------");
@ -188,13 +192,13 @@ int CmdHF14ADesInfo(const char *Cmd){
c.arg[1] = 0x01;
c.d.asBytes[0] = GET_FREE_MEMORY;
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500))
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500))
return 0;
uint8_t tmp[3];
memcpy(tmp, resp.d.asBytes+3,3);
memcpy(tmp, resp.d.asBytes + 3, 3);
PrintAndLogEx(NORMAL, " Available free memory on card : %d bytes", le24toh( tmp ));
PrintAndLogEx(NORMAL, " Available free memory on card : %d bytes", le24toh(tmp));
PrintAndLogEx(NORMAL, "-------------------------------------------------------------");
/*
@ -221,51 +225,55 @@ int CmdHF14ADesInfo(const char *Cmd){
and set to '1' if the storage size is between 2^n and 2^(n+1).
For this version of DESFire the 7 MSBits are set to 0x0C (2^12 = 4096) and the LSBit is '0'.
*/
char * GetCardSizeStr( uint8_t fsize ){
char *GetCardSizeStr(uint8_t fsize)
{
static char buf[30] = {0x00};
char *retStr = buf;
uint16_t usize = 1 << ((fsize >>1) + 1);
uint16_t lsize = 1 << (fsize >>1);
uint16_t usize = 1 << ((fsize >> 1) + 1);
uint16_t lsize = 1 << (fsize >> 1);
// is LSB set?
if ( fsize & 1 )
sprintf(retStr, "0x%02X (%d - %d bytes)",fsize, usize, lsize);
if (fsize & 1)
sprintf(retStr, "0x%02X (%d - %d bytes)", fsize, usize, lsize);
else
sprintf(retStr, "0x%02X (%d bytes)", fsize, lsize);
return buf;
}
char * GetProtocolStr(uint8_t id){
char *GetProtocolStr(uint8_t id)
{
static char buf[30] = {0x00};
char *retStr = buf;
if ( id == 0x05)
sprintf(retStr,"0x%02X (ISO 14443-3, 14443-4)", id);
if (id == 0x05)
sprintf(retStr, "0x%02X (ISO 14443-3, 14443-4)", id);
else
sprintf(retStr,"0x%02X (Unknown)", id);
sprintf(retStr, "0x%02X (Unknown)", id);
return buf;
}
char * GetVersionStr(uint8_t major, uint8_t minor){
char *GetVersionStr(uint8_t major, uint8_t minor)
{
static char buf[30] = {0x00};
char *retStr = buf;
if ( major == 0x00)
sprintf(retStr,"%d.%d (Desfire MF3ICD40)", major, minor);
else if ( major == 0x01 && minor == 0x00)
sprintf(retStr,"%d.%d (Desfire EV1)", major, minor);
else if ( major == 0x12 && minor == 0x00)
sprintf(retStr,"%d.%d (Desfire EV2)", major, minor);
if (major == 0x00)
sprintf(retStr, "%d.%d (Desfire MF3ICD40)", major, minor);
else if (major == 0x01 && minor == 0x00)
sprintf(retStr, "%d.%d (Desfire EV1)", major, minor);
else if (major == 0x12 && minor == 0x00)
sprintf(retStr, "%d.%d (Desfire EV2)", major, minor);
else
sprintf(retStr,"%d.%d (Unknown)", major, minor);
sprintf(retStr, "%d.%d (Unknown)", major, minor);
return buf;
}
void GetKeySettings( uint8_t *aid){
void GetKeySettings(uint8_t *aid)
{
char messStr[512] = {0x00};
char *str = messStr;
@ -276,36 +284,36 @@ void GetKeySettings( uint8_t *aid){
//memset(messStr, 0x00, 512);
if ( aid == NULL ){
if (aid == NULL) {
PrintAndLogEx(NORMAL, " CMK - PICC, Card Master Key settings ");
PrintAndLogEx(NORMAL, "");
c.arg[CMDPOS] = (INIT | DISCONNECT);
c.arg[LENPOS] = 0x01;
c.d.asBytes[0] = GET_KEY_SETTINGS; // 0x45
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;}
isOK = resp.arg[0] & 0xff;
if ( !isOK ){
if (!isOK) {
PrintAndLogEx(WARNING, " Can't select master application");
return;
}
str = (resp.d.asBytes[3] & (1 << 3 )) ? "YES":"NO";
str = (resp.d.asBytes[3] & (1 << 3)) ? "YES" : "NO";
PrintAndLogEx(NORMAL, " [0x08] Configuration changeable : %s", str);
str = (resp.d.asBytes[3] & (1 << 2 )) ? "NO":"YES";
PrintAndLogEx(NORMAL, " [0x04] CMK required for create/delete : %s",str);
str = (resp.d.asBytes[3] & (1 << 1 )) ? "NO":"YES";
PrintAndLogEx(NORMAL, " [0x02] Directory list access with CMK : %s",str);
str = (resp.d.asBytes[3] & (1 << 0 )) ? "YES" : "NO";
str = (resp.d.asBytes[3] & (1 << 2)) ? "NO" : "YES";
PrintAndLogEx(NORMAL, " [0x04] CMK required for create/delete : %s", str);
str = (resp.d.asBytes[3] & (1 << 1)) ? "NO" : "YES";
PrintAndLogEx(NORMAL, " [0x02] Directory list access with CMK : %s", str);
str = (resp.d.asBytes[3] & (1 << 0)) ? "YES" : "NO";
PrintAndLogEx(NORMAL, " [0x01] CMK is changeable : %s", str);
c.arg[LENPOS] = 0x02; //LEN
c.d.asBytes[0] = GET_KEY_VERSION; //0x64
c.d.asBytes[1] = 0x00;
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) { return; }
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) { return; }
isOK = resp.arg[0] & 0xff;
if ( !isOK ){
if (!isOK) {
PrintAndLogEx(WARNING, " Can't read key-version");
return;
}
@ -318,21 +326,21 @@ void GetKeySettings( uint8_t *aid){
c.d.asBytes[0] = AUTHENTICATE; //0x0A
c.d.asBytes[1] = 0x00; // KEY 0
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;}
isOK = resp.d.asBytes[2] & 0xff;
PrintAndLogEx(NORMAL, " [0x0A] Authenticate : %s", ( isOK==0xAE ) ? "NO":"YES");
PrintAndLogEx(NORMAL, " [0x0A] Authenticate : %s", (isOK == 0xAE) ? "NO" : "YES");
c.d.asBytes[0] = AUTHENTICATE_ISO; //0x1A
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;}
isOK = resp.d.asBytes[2] & 0xff;
PrintAndLogEx(NORMAL, " [0x1A] Authenticate ISO : %s", ( isOK==0xAE ) ? "NO":"YES");
PrintAndLogEx(NORMAL, " [0x1A] Authenticate ISO : %s", (isOK == 0xAE) ? "NO" : "YES");
c.d.asBytes[0] = AUTHENTICATE_AES; //0xAA
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;}
isOK = resp.d.asBytes[2] & 0xff;
PrintAndLogEx(NORMAL, " [0xAA] Authenticate AES : %s", ( isOK==0xAE ) ? "NO":"YES");
PrintAndLogEx(NORMAL, " [0xAA] Authenticate AES : %s", (isOK == 0xAE) ? "NO" : "YES");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, " ----------------------------------------------------------");
@ -343,16 +351,16 @@ void GetKeySettings( uint8_t *aid){
c.arg[0] = (INIT | CLEARTRACE);
c.arg[LENPOS] = 0x04;
c.d.asBytes[0] = SELECT_APPLICATION; // 0x5a
memcpy(c.d.asBytes+1, aid, 3);
memcpy(c.d.asBytes + 1, aid, 3);
SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
PrintAndLogEx(WARNING, " Timed-out");
return;
}
isOK = resp.arg[0] & 0xff;
if ( !isOK ){
PrintAndLogEx(WARNING, " Can't select AID: %s",sprint_hex(aid,3));
if (!isOK) {
PrintAndLogEx(WARNING, " Can't select AID: %s", sprint_hex(aid, 3));
return;
}
@ -362,16 +370,16 @@ void GetKeySettings( uint8_t *aid){
c.arg[LENPOS] = 0x01;
c.d.asBytes[0] = GET_KEY_SETTINGS; // 0x45
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
return;
}
isOK = resp.arg[0] & 0xff;
if ( !isOK ){
if (!isOK) {
PrintAndLogEx(WARNING, " Can't read Application Master key settings");
} else {
// Access rights.
uint8_t rights = (resp.d.asBytes[3] >> 4 & 0xff);
switch (rights){
switch (rights) {
case 0x00:
str = "AMK authentication is necessary to change any key (default)";
break;
@ -386,16 +394,16 @@ void GetKeySettings( uint8_t *aid){
break;
}
PrintAndLogEx(NORMAL, "Changekey Access rights");
PrintAndLogEx(NORMAL, "-- %s",str);
PrintAndLogEx(NORMAL, "-- %s", str);
PrintAndLogEx(NORMAL, "");
// same as CMK
str = (resp.d.asBytes[3] & (1 << 3 )) ? "YES":"NO";
str = (resp.d.asBytes[3] & (1 << 3)) ? "YES" : "NO";
PrintAndLogEx(NORMAL, " 0x08 Configuration changeable : %s", str);
str = (resp.d.asBytes[3] & (1 << 2 )) ? "NO":"YES";
PrintAndLogEx(NORMAL, " 0x04 AMK required for create/delete : %s",str);
str = (resp.d.asBytes[3] & (1 << 1 )) ? "NO":"YES";
PrintAndLogEx(NORMAL, " 0x02 Directory list access with AMK : %s",str);
str = (resp.d.asBytes[3] & (1 << 0 )) ? "YES" : "NO";
str = (resp.d.asBytes[3] & (1 << 2)) ? "NO" : "YES";
PrintAndLogEx(NORMAL, " 0x04 AMK required for create/delete : %s", str);
str = (resp.d.asBytes[3] & (1 << 1)) ? "NO" : "YES";
PrintAndLogEx(NORMAL, " 0x02 Directory list access with AMK : %s", str);
str = (resp.d.asBytes[3] & (1 << 0)) ? "YES" : "NO";
PrintAndLogEx(NORMAL, " 0x01 AMK is changeable : %s", str);
}
@ -405,7 +413,7 @@ void GetKeySettings( uint8_t *aid){
c.d.asBytes[0] = GET_KEY_VERSION; //0x64
c.d.asBytes[1] = 0x00;
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
PrintAndLogEx(WARNING, " Timed-out");
return;
}
@ -413,21 +421,20 @@ void GetKeySettings( uint8_t *aid){
int numOfKeys;
isOK = resp.arg[0] & 0xff;
if ( !isOK ){
if (!isOK) {
PrintAndLogEx(WARNING, " Can't read Application Master key version. Trying all keys");
numOfKeys = MAX_NUM_KEYS;
}
else{
} else {
numOfKeys = resp.d.asBytes[4];
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, " Max number of keys : %d", numOfKeys );
PrintAndLogEx(NORMAL, " Max number of keys : %d", numOfKeys);
PrintAndLogEx(NORMAL, " Application Master key Version : %d (0x%02x)", resp.d.asBytes[3], resp.d.asBytes[3]);
PrintAndLogEx(NORMAL, "-------------------------------------------------------------");
}
// LOOP over numOfKeys that we got before.
// From 0x01 to numOfKeys. We already got 0x00. (AMK)
for(int i=0x01; i<=0x0f; ++i){
for (int i = 0x01; i <= 0x0f; ++i) {
}
@ -435,23 +442,24 @@ void GetKeySettings( uint8_t *aid){
}
}
int CmdHF14ADesEnumApplications(const char *Cmd){
int CmdHF14ADesEnumApplications(const char *Cmd)
{
uint8_t isOK = 0x00;
uint8_t aid[3];
uint32_t options = (INIT | DISCONNECT);
UsbCommand c = {CMD_MIFARE_DESFIRE, {options , 0x01 }};
UsbCommand c = {CMD_MIFARE_DESFIRE, {options, 0x01 }};
c.d.asBytes[0] = GET_APPLICATION_IDS; //0x6a
SendCommand(&c);
UsbCommand resp;
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
return 0;
}
isOK = resp.arg[0] & 0xff;
if ( !isOK ){
if (!isOK) {
PrintAndLogEx(NORMAL, "Command unsuccessful");
return 0;
}
@ -463,15 +471,15 @@ int CmdHF14ADesEnumApplications(const char *Cmd){
UsbCommand respFiles;
uint8_t num = 0;
int max = resp.arg[1] -3 -2;
int max = resp.arg[1] - 3 - 2;
for(int i=3; i<=max; i+=3){
PrintAndLogEx(NORMAL, " Aid %d : %02X %02X %02X ",num ,resp.d.asBytes[i],resp.d.asBytes[i+1],resp.d.asBytes[i+2]);
for (int i = 3; i <= max; i += 3) {
PrintAndLogEx(NORMAL, " Aid %d : %02X %02X %02X ", num, resp.d.asBytes[i], resp.d.asBytes[i + 1], resp.d.asBytes[i + 2]);
num++;
aid[0] = resp.d.asBytes[i];
aid[1] = resp.d.asBytes[i+1];
aid[2] = resp.d.asBytes[i+2];
aid[1] = resp.d.asBytes[i + 1];
aid[2] = resp.d.asBytes[i + 2];
GetKeySettings(aid);
// Select Application
@ -479,17 +487,17 @@ int CmdHF14ADesEnumApplications(const char *Cmd){
c.arg[LENPOS] = 0x04;
c.d.asBytes[0] = SELECT_APPLICATION; // 0x5a
c.d.asBytes[1] = resp.d.asBytes[i];
c.d.asBytes[2] = resp.d.asBytes[i+1];
c.d.asBytes[3] = resp.d.asBytes[i+2];
c.d.asBytes[2] = resp.d.asBytes[i + 1];
c.d.asBytes[3] = resp.d.asBytes[i + 2];
SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK,&respAid,1500) ) {
if (!WaitForResponseTimeout(CMD_ACK, &respAid, 1500)) {
PrintAndLogEx(WARNING, " Timed-out");
continue;
}
isOK = respAid.d.asBytes[2] & 0xff;
if ( isOK != 0x00 ){
PrintAndLogEx(WARNING, " Can't select AID: %s",sprint_hex(resp.d.asBytes+i,3));
if (isOK != 0x00) {
PrintAndLogEx(WARNING, " Can't select AID: %s", sprint_hex(resp.d.asBytes + i, 3));
continue;
}
@ -499,17 +507,17 @@ int CmdHF14ADesEnumApplications(const char *Cmd){
c.d.asBytes[0] = GET_FILE_IDS; // 0x6f
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&respFiles,1500) ) {
if (!WaitForResponseTimeout(CMD_ACK, &respFiles, 1500)) {
PrintAndLogEx(WARNING, " Timed-out");
continue;
} else {
isOK = respFiles.d.asBytes[2] & 0xff;
if ( !isOK ){
if (!isOK) {
PrintAndLogEx(WARNING, " Can't get file ids ");
} else {
int respfileLen = resp.arg[1]-3-2;
for (int j=0; j< respfileLen; ++j){
PrintAndLogEx(NORMAL, " Fileid %d :", resp.d.asBytes[j+3]);
int respfileLen = resp.arg[1] - 3 - 2;
for (int j = 0; j < respfileLen; ++j) {
PrintAndLogEx(NORMAL, " Fileid %d :", resp.d.asBytes[j + 3]);
}
}
}
@ -520,17 +528,17 @@ int CmdHF14ADesEnumApplications(const char *Cmd){
c.d.asBytes[0] = GET_ISOFILE_IDS; // 0x61
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&respFiles,1500) ) {
if (!WaitForResponseTimeout(CMD_ACK, &respFiles, 1500)) {
PrintAndLogEx(WARNING, " Timed-out");
continue;
} else {
isOK = respFiles.d.asBytes[2] & 0xff;
if ( !isOK ){
if (!isOK) {
PrintAndLogEx(WARNING, " Can't get ISO file ids ");
} else {
int respfileLen = resp.arg[1]-3-2;
for (int j=0; j< respfileLen; ++j){
PrintAndLogEx(NORMAL, " ISO Fileid %d :", resp.d.asBytes[j+3]);
int respfileLen = resp.arg[1] - 3 - 2;
for (int j = 0; j < respfileLen; ++j) {
PrintAndLogEx(NORMAL, " ISO Fileid %d :", resp.d.asBytes[j + 3]);
}
}
}
@ -546,7 +554,8 @@ int CmdHF14ADesEnumApplications(const char *Cmd){
// MIAFRE DesFire Authentication
//
#define BUFSIZE 256
int CmdHF14ADesAuth(const char *Cmd){
int CmdHF14ADesAuth(const char *Cmd)
{
// NR DESC KEYLENGHT
// ------------------------
@ -558,7 +567,7 @@ int CmdHF14ADesAuth(const char *Cmd){
uint8_t keylength = 8;
unsigned char key[24];
if (strlen(Cmd)<3) {
if (strlen(Cmd) < 3) {
PrintAndLogEx(NORMAL, "Usage: hf mfdes auth <1|2|3> <1|2|3|4> <keyno> <key> ");
PrintAndLogEx(NORMAL, " Auth modes");
PrintAndLogEx(NORMAL, " 1 = normal, 2 = iso, 3 = aes");
@ -570,26 +579,25 @@ int CmdHF14ADesAuth(const char *Cmd){
PrintAndLogEx(NORMAL, " hf mfdes auth 3 4 0 404142434445464748494a4b4c4d4e4f");
return 0;
}
uint8_t cmdAuthMode = param_get8(Cmd,0);
uint8_t cmdAuthAlgo = param_get8(Cmd,1);
uint8_t cmdKeyNo = param_get8(Cmd,2);
uint8_t cmdAuthMode = param_get8(Cmd, 0);
uint8_t cmdAuthAlgo = param_get8(Cmd, 1);
uint8_t cmdKeyNo = param_get8(Cmd, 2);
switch (cmdAuthMode)
{
switch (cmdAuthMode) {
case 1:
if ( cmdAuthAlgo != 1 && cmdAuthAlgo != 2) {
if (cmdAuthAlgo != 1 && cmdAuthAlgo != 2) {
PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth mode");
return 1;
}
break;
case 2:
if ( cmdAuthAlgo != 1 && cmdAuthAlgo != 2 && cmdAuthAlgo != 3) {
if (cmdAuthAlgo != 1 && cmdAuthAlgo != 2 && cmdAuthAlgo != 3) {
PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth mode");
return 1;
}
break;
case 3:
if ( cmdAuthAlgo != 4) {
if (cmdAuthAlgo != 4) {
PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth mode");
return 1;
}
@ -600,7 +608,7 @@ int CmdHF14ADesAuth(const char *Cmd){
break;
}
switch (cmdAuthAlgo){
switch (cmdAuthAlgo) {
case 2:
keylength = 16;
PrintAndLogEx(NORMAL, "3DES selected");
@ -621,7 +629,7 @@ int CmdHF14ADesAuth(const char *Cmd){
}
// key
if (param_gethex(Cmd, 3, key, keylength*2)) {
if (param_gethex(Cmd, 3, key, keylength * 2)) {
PrintAndLogEx(WARNING, "Key must include %d HEX symbols", keylength);
return 1;
}
@ -629,25 +637,25 @@ int CmdHF14ADesAuth(const char *Cmd){
UsbCommand c = {CMD_MIFARE_DESFIRE_AUTH1, { cmdAuthMode, cmdAuthAlgo, cmdKeyNo }};
c.d.asBytes[0] = keylength;
memcpy(c.d.asBytes+1, key, keylength);
memcpy(c.d.asBytes + 1, key, keylength);
clearCommandBuffer();
SendCommand(&c);
UsbCommand resp;
if (!WaitForResponseTimeout(CMD_ACK,&resp,3000)) {
if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) {
PrintAndLogEx(WARNING, "Client command execute timeout");
return 0;
}
uint8_t isOK = resp.arg[0] & 0xff;
if ( isOK) {
uint8_t * data= resp.d.asBytes;
if (isOK) {
uint8_t *data = resp.d.asBytes;
PrintAndLogEx(NORMAL, " Key :%s",sprint_hex(key, keylength));
PrintAndLogEx(NORMAL, " SESSION :%s",sprint_hex(data, keylength));
PrintAndLogEx(NORMAL, " Key :%s", sprint_hex(key, keylength));
PrintAndLogEx(NORMAL, " SESSION :%s", sprint_hex(data, keylength));
PrintAndLogEx(NORMAL, "-------------------------------------------------------------");
//PrintAndLogEx(NORMAL, " Expected :B5 21 9E E8 1A A7 49 9D 21 96 68 7E 13 97 38 56");
} else{
} else {
PrintAndLogEx(NORMAL, "Client command failed.");
}
PrintAndLogEx(NORMAL, "-------------------------------------------------------------");
@ -658,21 +666,23 @@ int CmdHF14ADesAuth(const char *Cmd){
static command_t CommandTable[] = {
{"help", CmdHelp, 1, "This help"},
{"info", CmdHF14ADesInfo, 0, "Tag information"},
{"enum", CmdHF14ADesEnumApplications,0, "Tries enumerate all applications"},
{"enum", CmdHF14ADesEnumApplications, 0, "Tries enumerate all applications"},
{"auth", CmdHF14ADesAuth, 0, "Tries a MIFARE DesFire Authentication"},
{"rdbl", CmdHF14ADesRb, 0, "Read MIFARE DesFire block"},
{"wrbl", CmdHF14ADesWb, 0, "write MIFARE DesFire block"},
{NULL, NULL, 0, NULL}
};
int CmdHFMFDes(const char *Cmd) {
int CmdHFMFDes(const char *Cmd)
{
// flush
clearCommandBuffer();
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd) {
int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable);
return 0;
}

View file

@ -11,16 +11,16 @@
#define __MFDESFIRE_H
int CmdHFMFDes(const char *Cmd);
int CmdHF14ADesAuth(const char* cmd);
int CmdHF14ADesRb(const char* cmd);
int CmdHF14ADesWb(const char* cmd);
int CmdHF14ADesAuth(const char *cmd);
int CmdHF14ADesRb(const char *cmd);
int CmdHF14ADesWb(const char *cmd);
int CmdHF14ADesInfo(const char *Cmd);
int CmdHF14ADesEnumApplications(const char *Cmd);
char * GetCardSizeStr( uint8_t fsize );
char * GetProtocolStr( uint8_t id );
char * GetVersionStr( uint8_t major, uint8_t minor );
void GetKeySettings( uint8_t * aid );
char *GetCardSizeStr(uint8_t fsize);
char *GetProtocolStr(uint8_t id);
char *GetVersionStr(uint8_t major, uint8_t minor);
void GetKeySettings(uint8_t *aid);
// Command options for Desfire behavior.
enum {
@ -80,51 +80,51 @@ enum {
// status- and error codes |
#define OPERATION_OK 0x00 // Successful operation
#define NO_CHANGES 0x0C // No changes done to backup files
// ,CommitTransaction/
// AbortTransaction not necessary
// ,CommitTransaction/
// AbortTransaction not necessary
#define OUT_OF_EEPROM_ERROR 0x0E // Insufficient NV-Memory to
// complete command
// complete command
#define ILLEGAL_COMMAND_CODE 0x1C // Command code not supported
#define INTEGRITY_ERROR 0x1E // CRC or MAC does not match data
// Padding bytes not valid
// Padding bytes not valid
#define NO_SUCH_KEY 0x40 // Invalid key number specified
#define LENGTH_ERROR 0x7E // Length of command string invalid
#define PERMISSION_DENIED 0x9D // Current configuration status
// does not allow the requested
// command
// does not allow the requested
// command
#define PARAMETER_ERROR 0x9E // Value of the parameter(s) inval.
#define APPLICATION_NOT_FOUND 0xA0 // Requested AID not present on PIC
#define APPL_INTEGRITY_ERROR 0xA1 // [1] // Unrecoverable error within app-
// lication, app will be disabled
// lication, app will be disabled
#define AUTHENTICATION_ERROR 0xAE // Current authentication status
// does not allow the requested
// command
// does not allow the requested
// command
#define ADDITIONAL_FRAME 0xAF // Additional data frame is
// expected to be sent
// expected to be sent
#define BOUNDARY_ERROR 0xBE // Attempt to read/write data from/
// to beyond the file's/record's
// limits. Attempt to exceed the
// limits of a value file.
// to beyond the file's/record's
// limits. Attempt to exceed the
// limits of a value file.
#define PICC_INTEGRITY_ERROR 0xC1 // [1] // Unrecoverable error within PICC
// ,PICC will be disabled
// ,PICC will be disabled
#define COMMAND_ABORTED 0xCA // Previous Command was not fully
// completed Not all Frames were
// requested or provided by PCD
// completed Not all Frames were
// requested or provided by PCD
#define PICC_DISABLED_ERROR 0xCD // [1] // PICC was disabled by an unrecoverable error
#define COUNT_ERROR 0xCE // Number of Applications limited
// to 28, no additional
// CreateApplication possible
// to 28, no additional
// CreateApplication possible
#define DUPLICATE_ERROR 0xDE // Creation of file/application
// failed because file/application
// with same number already exists
// failed because file/application
// with same number already exists
#define EEPROM_ERROR 0xEE // [1] // Could not complete NV-write
// operation due to loss of power,
// internal backup/rollback
// mechanism activated
// operation due to loss of power,
// internal backup/rollback
// mechanism activated
#define FILE_NOT_FOUND_ERROR 0xF0 // Specified file number does not
// exist
// exist
#define FILE_INTEGRITY_ERROR 0xF1 // [1] // Unrecoverable error within file,
// file will be disabled
// file will be disabled
//
// [1] These errors are not expected to appear during normal operation

View file

@ -29,24 +29,25 @@ static int CmdHelp(const char *Cmd);
//n'r=rol(r5)
//verify n'r=nr
int CmdHF14AMfDESAuth(const char *Cmd){
int CmdHF14AMfDESAuth(const char *Cmd)
{
uint8_t blockNo = 0;
//keyNo=0;
uint32_t cuid = 0;
uint8_t reply[16] = {0x00};
//DES_cblock r1_b1;
uint8_t b1[8]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t b2[8]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t b1[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t b2[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
DES_cblock nr, b0, r1, r0;
uint8_t key[8]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t key[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
//DES_cblock iv={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
DES_key_schedule ks1;
DES_cblock key1;
if (strlen(Cmd)<1) {
if (strlen(Cmd) < 1) {
PrintAndLogEx(NORMAL, "Usage: hf desfire des-auth k <key number>");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " hf desfire des-auth k 0");
@ -55,23 +56,23 @@ int CmdHF14AMfDESAuth(const char *Cmd){
//Change key to user defined one
memcpy(key1,key,8);
memcpy(key1, key, 8);
//memcpy(key2,key+8,8);
DES_set_key((DES_cblock *)key1,&ks1);
DES_set_key((DES_cblock *)key1, &ks1);
//DES_set_key((DES_cblock *)key2,&ks2);
//Auth1
UsbCommand c = {CMD_MIFARE_DES_AUTH1, {blockNo}};
SendCommand(&c);
UsbCommand resp;
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
uint8_t isOK = resp.arg[0] & 0xff;
cuid = resp.arg[1];
uint8_t * data= resp.d.asBytes;
uint8_t *data = resp.d.asBytes;
if (isOK){
PrintAndLogEx(NORMAL, "enc(nc)/b0:%s", sprint_hex(data+2,8));
memcpy(b0,data+2,8);
if (isOK) {
PrintAndLogEx(NORMAL, "enc(nc)/b0:%s", sprint_hex(data + 2, 8));
memcpy(b0, data + 2, 8);
}
} else {
PrintAndLogEx(WARNING, "Command execute timeout");
@ -81,35 +82,35 @@ int CmdHF14AMfDESAuth(const char *Cmd){
DES_random_key(&nr);
//b1=dec(nr)
//r0=dec(b0)
DES_ecb_encrypt(&nr,&b1,&ks1,0);
DES_ecb_encrypt(&b0,&r0,&ks1,0);
DES_ecb_encrypt(&nr, &b1, &ks1, 0);
DES_ecb_encrypt(&b0, &r0, &ks1, 0);
//PrintAndLogEx(NORMAL, "b1:%s",sprint_hex(b1, 8));
PrintAndLogEx(NORMAL, "r0:%s",sprint_hex(r0, 8));
PrintAndLogEx(NORMAL, "r0:%s", sprint_hex(r0, 8));
//r1=rol(r0)
memcpy(r1,r0,8);
rol(r1,8);
PrintAndLogEx(NORMAL, "r1:%s",sprint_hex(r1, 8));
for(int i=0;i<8;i++){
b2[i]=(r1[i] ^ b1[i]);
memcpy(r1, r0, 8);
rol(r1, 8);
PrintAndLogEx(NORMAL, "r1:%s", sprint_hex(r1, 8));
for (int i = 0; i < 8; i++) {
b2[i] = (r1[i] ^ b1[i]);
}
DES_ecb_encrypt(&b2,&b2,&ks1,0);
DES_ecb_encrypt(&b2, &b2, &ks1, 0);
//PrintAndLogEx(NORMAL, "b1:%s",sprint_hex(b1, 8));
PrintAndLogEx(NORMAL, "b2:%s",sprint_hex(b2, 8));
PrintAndLogEx(NORMAL, "b2:%s", sprint_hex(b2, 8));
//Auth2
UsbCommand d = {CMD_MIFARE_DES_AUTH2, {cuid}};
memcpy(reply,b1,8);
memcpy(reply+8,b2,8);
memcpy(d.d.asBytes,reply, 16);
memcpy(reply, b1, 8);
memcpy(reply + 8, b2, 8);
memcpy(d.d.asBytes, reply, 16);
SendCommand(&d);
UsbCommand respb;
if (WaitForResponseTimeout(CMD_ACK,&respb,1500)) {
if (WaitForResponseTimeout(CMD_ACK, &respb, 1500)) {
uint8_t isOK = respb.arg[0] & 0xff;
uint8_t * data2= respb.d.asBytes;
uint8_t *data2 = respb.d.asBytes;
if (isOK)
PrintAndLogEx(NORMAL, "b3:%s", sprint_hex(data2+2, 8));
PrintAndLogEx(NORMAL, "b3:%s", sprint_hex(data2 + 2, 8));
} else {
PrintAndLogEx(WARNING, "Command execute timeout");
@ -122,7 +123,8 @@ int CmdHF14AMfDESAuth(const char *Cmd){
// Card 2 Reader : 02AF, 16 Bytes(b0), CRC1 CRC2
// Reader 2 Card : 03AF, 16 Bytes(b1),16Bytes(b2) CRC1 CRC2
// Card 2 Reader : 0300, 16 bytes(b3), CRC1 CRC2 ; success
int CmdHF14AMfAESAuth(const char *Cmd){
int CmdHF14AMfAESAuth(const char *Cmd)
{
uint8_t blockNo = 0;
//keyNo=0;
@ -131,19 +133,19 @@ int CmdHF14AMfAESAuth(const char *Cmd){
//DES_cblock r1_b1;
//unsigned char * b1, b2, nr, b0, r0, r1;
uint8_t b1[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t b2[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t nr[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t b0[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t r0[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t r1[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t b1[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t b2[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t nr[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t b0[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t r0[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t r1[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
//
uint8_t key[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t iv[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t key[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t iv[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
AES_KEY key_e;
AES_KEY key_d;
if (strlen(Cmd)<1) {
if (strlen(Cmd) < 1) {
PrintAndLogEx(NORMAL, "Usage: hf desfire aes-auth k <key number>");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " hf desfire aes-auth k 0");
@ -157,8 +159,8 @@ int CmdHF14AMfAESAuth(const char *Cmd){
//
//memcpy(key1,key,16);
//memcpy(key2,key+8,8);
AES_set_encrypt_key(key,128,&key_e);
AES_set_decrypt_key(key,128,&key_d);
AES_set_encrypt_key(key, 128, &key_e);
AES_set_decrypt_key(key, 128, &key_d);
//Auth1
UsbCommand c = {CMD_MIFARE_DES_AUTH1, {blockNo}};
@ -167,11 +169,11 @@ int CmdHF14AMfAESAuth(const char *Cmd){
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
uint8_t isOK = resp.arg[0] & 0xff;
cuid = resp.arg[1];
uint8_t * data= resp.d.asBytes;
uint8_t *data = resp.d.asBytes;
if (isOK){
PrintAndLogEx(NORMAL, "enc(nc)/b0:%s", sprint_hex(data+2,16));
memcpy(b0,data+2,16);
if (isOK) {
PrintAndLogEx(NORMAL, "enc(nc)/b0:%s", sprint_hex(data + 2, 16));
memcpy(b0, data + 2, 16);
}
} else {
PrintAndLogEx(WARNING, "Command execute timeout");
@ -186,37 +188,37 @@ int CmdHF14AMfAESAuth(const char *Cmd){
//b1=dec(nr)
//r0=dec(b0)
//AES_cbc_encrypt(&nr,&b1,16,&key,0);
AES_cbc_encrypt(&b0,&r0,16,&key_d,iv,0);
AES_cbc_encrypt(&b0, &r0, 16, &key_d, iv, 0);
//PrintAndLogEx(NORMAL, "b1:%s",sprint_hex(b1, 8));
PrintAndLogEx(NORMAL, "r0:%s",sprint_hex(r0, 16));
PrintAndLogEx(NORMAL, "r0:%s", sprint_hex(r0, 16));
//r1=rol(r0)
memcpy(r1,r0,16);
rol(r1,8);
PrintAndLogEx(NORMAL, "r1:%s",sprint_hex(r1, 16));
for(int i=0;i<16;i++){
b1[i]=(nr[i] ^ b0[i]);
b2[i]=(r1[i] ^ b1[i]);
memcpy(r1, r0, 16);
rol(r1, 8);
PrintAndLogEx(NORMAL, "r1:%s", sprint_hex(r1, 16));
for (int i = 0; i < 16; i++) {
b1[i] = (nr[i] ^ b0[i]);
b2[i] = (r1[i] ^ b1[i]);
}
PrintAndLogEx(NORMAL, "nr:%s",sprint_hex(nr, 16));
AES_cbc_encrypt(&b1,&b1,16,&key_e,iv,1);
AES_cbc_encrypt(&b2,&b2,16,&key_e,iv,1);
PrintAndLogEx(NORMAL, "b1:%s",sprint_hex(b1, 16));
PrintAndLogEx(NORMAL, "b2:%s",sprint_hex(b2, 16));
PrintAndLogEx(NORMAL, "nr:%s", sprint_hex(nr, 16));
AES_cbc_encrypt(&b1, &b1, 16, &key_e, iv, 1);
AES_cbc_encrypt(&b2, &b2, 16, &key_e, iv, 1);
PrintAndLogEx(NORMAL, "b1:%s", sprint_hex(b1, 16));
PrintAndLogEx(NORMAL, "b2:%s", sprint_hex(b2, 16));
//Auth2
UsbCommand d = {CMD_MIFARE_DES_AUTH2, {cuid}};
memcpy(reply,b1,16);
memcpy(reply+16,b2,16);
memcpy(d.d.asBytes,reply, 32);
memcpy(reply, b1, 16);
memcpy(reply + 16, b2, 16);
memcpy(d.d.asBytes, reply, 32);
SendCommand(&d);
UsbCommand respb;
if (WaitForResponseTimeout(CMD_ACK, &respb, 1500)) {
uint8_t isOK = respb.arg[0] & 0xff;
uint8_t * data2= respb.d.asBytes;
uint8_t *data2 = respb.d.asBytes;
if (isOK)
PrintAndLogEx(NORMAL, "b3:%s", sprint_hex(data2+2, 16));
PrintAndLogEx(NORMAL, "b3:%s", sprint_hex(data2 + 2, 16));
} else {
PrintAndLogEx(WARNING, "Command execute timeout");
@ -228,23 +230,24 @@ int CmdHF14AMfAESAuth(const char *Cmd){
//------------------------------------
// Menu Stuff
//------------------------------------
static command_t CommandTable[] =
{
{"help", CmdHelp, 1,"This help"},
{"dbg", CmdHF14AMfDbg, 0,"Set default debug mode"},
{"des-auth",CmdHF14AMfDESAuth, 0,"Desfire Authentication"},
{"ev1-auth",CmdHF14AMfAESAuth, 0,"EV1 Authentication"},
static command_t CommandTable[] = {
{"help", CmdHelp, 1, "This help"},
{"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},
{"des-auth", CmdHF14AMfDESAuth, 0, "Desfire Authentication"},
{"ev1-auth", CmdHF14AMfAESAuth, 0, "EV1 Authentication"},
{NULL, NULL, 0, NULL}
};
int CmdHFMFDesfire(const char *Cmd){
int CmdHFMFDesfire(const char *Cmd)
{
// flush
clearCommandBuffer();
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd){
int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable);
return 0;
}

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