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: style:
find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" \) -exec perl -pi -e 's/[ \t\r]+$$//' {} \; 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 # Dummy target to test for GNU make availability
_test: _test:

View file

@ -13,7 +13,7 @@
// BigBuf is the large multi-purpose buffer, typically used to hold A/D samples or traces. // 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. // Also used to hold various smaller buffers and the Mifare Emulator Memory.
// declare it as uint32_t to achieve alignment to 4 Byte boundary // 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: /* BigBuf memory layout:
Pointer to highest available memory: BigBuf_hi Pointer to highest available memory: BigBuf_hi
@ -34,12 +34,14 @@ static uint32_t traceLen = 0;
static bool tracing = true; //todo static? static bool tracing = true; //todo static?
// get the address of BigBuf // get the address of BigBuf
uint8_t *BigBuf_get_addr(void) { uint8_t *BigBuf_get_addr(void)
{
return (uint8_t *)BigBuf; return (uint8_t *)BigBuf;
} }
// get the address of the emulator memory. Allocate part of Bigbuf for it, if not yet done // 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 // not yet allocated
if (emulator_memory == NULL) if (emulator_memory == NULL)
emulator_memory = BigBuf_malloc(CARD_MEMORY_SIZE); emulator_memory = BigBuf_malloc(CARD_MEMORY_SIZE);
@ -48,28 +50,33 @@ uint8_t *BigBuf_get_EM_addr(void) {
} }
// clear ALL of BigBuf // clear ALL of BigBuf
void BigBuf_Clear(void) { void BigBuf_Clear(void)
{
BigBuf_Clear_ext(true); BigBuf_Clear_ext(true);
} }
// clear ALL of BigBuf // clear ALL of BigBuf
void BigBuf_Clear_ext(bool verbose) { void BigBuf_Clear_ext(bool verbose)
{
memset(BigBuf, 0, BIGBUF_SIZE); memset(BigBuf, 0, BIGBUF_SIZE);
if (verbose) if (verbose)
Dbprintf("Buffer cleared (%i bytes)", BIGBUF_SIZE); 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); 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); memset(BigBuf, 0, BigBuf_hi);
} }
// allocate a chunk of memory from BigBuf. We allocate high memory first. The unallocated memory // 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 // 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) if (BigBuf_hi - chunksize < 0)
return NULL; // no memory left 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. // 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; BigBuf_hi = BIGBUF_SIZE;
emulator_memory = NULL; emulator_memory = NULL;
// shouldn't this empty BigBuf also? // shouldn't this empty BigBuf also?
} }
// free allocated chunks EXCEPT the emulator memory // free allocated chunks EXCEPT the emulator memory
void BigBuf_free_keep_EM(void) { void BigBuf_free_keep_EM(void)
{
if (emulator_memory != NULL) if (emulator_memory != NULL)
BigBuf_hi = emulator_memory - (uint8_t *)BigBuf; BigBuf_hi = emulator_memory - (uint8_t *)BigBuf;
else else
@ -95,7 +104,8 @@ void BigBuf_free_keep_EM(void) {
// shouldn't this empty BigBuf also? // shouldn't this empty BigBuf also?
} }
void BigBuf_print_status(void) { void BigBuf_print_status(void)
{
Dbprintf("Memory"); Dbprintf("Memory");
Dbprintf(" BIGBUF_SIZE.............%d", BIGBUF_SIZE); Dbprintf(" BIGBUF_SIZE.............%d", BIGBUF_SIZE);
Dbprintf(" Available memory........%d", BigBuf_hi); 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) // 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; return BigBuf_hi;
} }
void clear_trace(void) { void clear_trace(void)
{
traceLen = 0; traceLen = 0;
} }
void set_tracelen(uint32_t value) { void set_tracelen(uint32_t value)
{
traceLen = value; traceLen = value;
} }
void set_tracing(bool enable) { void set_tracing(bool enable)
{
tracing = enable; tracing = enable;
} }
bool get_tracing(void) { bool get_tracing(void)
{
return tracing; return tracing;
} }
@ -127,7 +142,8 @@ bool get_tracing(void) {
* Get the number of bytes traced * Get the number of bytes traced
* @return * @return
*/ */
uint32_t BigBuf_get_traceLen(void) { uint32_t BigBuf_get_traceLen(void)
{
return traceLen; return traceLen;
} }
@ -137,12 +153,13 @@ uint32_t BigBuf_get_traceLen(void) {
by 'hf list raw', alternatively 'hf list <proto>' for protocol-specific by 'hf list raw', alternatively 'hf list <proto>' for protocol-specific
annotation of commands/responses. 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; if (!tracing) return false;
uint8_t *trace = BigBuf_get_addr(); 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; uint32_t duration = timestamp_end - timestamp_start;
// Return when trace is full // Return when trace is full
@ -195,7 +212,8 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_
return true; 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, 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. 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 // Emulator memory
uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length){ uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length)
uint8_t* mem = BigBuf_get_EM_addr(); {
uint8_t *mem = BigBuf_get_EM_addr();
if (offset + length < CARD_MEMORY_SIZE) { if (offset + length < CARD_MEMORY_SIZE) {
memcpy(mem+offset, data, length); memcpy(mem + offset, data, length);
return 0; return 0;
} }
Dbprintf("Error, trying to set memory outside of bounds! %d > %d", (offset + length), CARD_MEMORY_SIZE); 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 void set_tracelen(uint32_t value);
extern bool get_tracing(void); 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 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); extern uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length);
#endif /* __BIGBUF_H */ #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 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 // 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 // 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) 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) 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(PRAMWR); // Now write the pixel to the display
LCDSend(color); // Write the data in the specified Color 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 for (i = 0; i < height; i++) { // Number of horizontal lines
{ LCDSetXY(xs, ys + i); // Goto start of fill area (Top Left)
LCDSetXY(xs,ys+i); // Goto start of fill area (Top Left)
LCDSend(PRAMWR); // Write to display 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); 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 int i;
unsigned char mask=0, px, py, xme, yme, offset; unsigned char mask = 0, px, py, xme, yme, offset;
const char *data; const char *data;
data = font_style; // point to the start of the font table 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++; data++;
offset = *data; // get data bytes per font offset = *data; // get data bytes per font
do do {
{
// point to data in table to be loaded // point to data in table to be loaded
data = (font_style + offset) + (offset * (int)(*lcd_string - 32)); data = (font_style + offset) + (offset * (int)(*lcd_string - 32));
for (i=0;i < yme;i++) { for (i = 0; i < yme; i++) {
mask |=0x80; mask |= 0x80;
for (px=x; px < (x + xme); px++) { for (px = x; px < (x + xme); px++) {
py= y + i; py = y + i;
if (*data & mask) LCDSetPixel (px,py,fcolor); if (*data & mask) LCDSetPixel(px, py, fcolor);
else LCDSetPixel (px,py,bcolor); else LCDSetPixel(px, py, bcolor);
mask>>=1; mask >>= 1;
} }
data++; data++;
} }
x+=xme; x += xme;
lcd_string++; // next character in string 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) void LCDReset(void)
@ -121,29 +119,29 @@ void LCDInit(void)
LCDSend(0xDC); LCDSend(0xDC);
// clear display // clear display
LCDSetXY(0,0); LCDSetXY(0, 0);
LCDSend(PRAMWR); // Write to display LCDSend(PRAMWR); // Write to display
i=LCD_XRES*LCD_YRES; i = LCD_XRES * LCD_YRES;
while(i--) LCDSend(WHITE); while (i--) LCDSend(WHITE);
// test text on different colored backgrounds // test text on different colored backgrounds
LCDString(" The quick brown fox ", (char *)&FONT6x8,1,1+8*0,WHITE ,BLACK ); 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(" jumped over the ", (char *)&FONT6x8, 1, 1 + 8 * 1, BLACK, WHITE);
LCDString(" lazy dog. ", (char *)&FONT6x8,1,1+8*2,YELLOW ,RED ); LCDString(" lazy dog. ", (char *)&FONT6x8, 1, 1 + 8 * 2, YELLOW, RED);
LCDString(" AaBbCcDdEeFfGgHhIiJj ", (char *)&FONT6x8,1,1+8*3,RED ,GREEN ); LCDString(" AaBbCcDdEeFfGgHhIiJj ", (char *)&FONT6x8, 1, 1 + 8 * 3, RED, GREEN);
LCDString(" KkLlMmNnOoPpQqRrSsTt ", (char *)&FONT6x8,1,1+8*4,MAGENTA,BLUE ); LCDString(" KkLlMmNnOoPpQqRrSsTt ", (char *)&FONT6x8, 1, 1 + 8 * 4, MAGENTA, BLUE);
LCDString("UuVvWwXxYyZz0123456789", (char *)&FONT6x8,1,1+8*5,BLUE ,YELLOW); 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 * 6, BLACK, CYAN);
LCDString(" _+{}|:\\\"<>? ", (char *)&FONT6x8,1,1+8*7,BLUE ,MAGENTA); LCDString(" _+{}|:\\\"<>? ", (char *)&FONT6x8, 1, 1 + 8 * 7, BLUE, MAGENTA);
// color bands // color bands
LCDFill(0, 1+8* 8, 132, 8, BLACK); LCDFill(0, 1 + 8 * 8, 132, 8, BLACK);
LCDFill(0, 1+8* 9, 132, 8, WHITE); LCDFill(0, 1 + 8 * 9, 132, 8, WHITE);
LCDFill(0, 1+8*10, 132, 8, RED); LCDFill(0, 1 + 8 * 10, 132, 8, RED);
LCDFill(0, 1+8*11, 132, 8, GREEN); LCDFill(0, 1 + 8 * 11, 132, 8, GREEN);
LCDFill(0, 1+8*12, 132, 8, BLUE); LCDFill(0, 1 + 8 * 12, 132, 8, BLUE);
LCDFill(0, 1+8*13, 132, 8, YELLOW); LCDFill(0, 1 + 8 * 13, 132, 8, YELLOW);
LCDFill(0, 1+8*14, 132, 8, CYAN); LCDFill(0, 1 + 8 * 14, 132, 8, CYAN);
LCDFill(0, 1+8*15, 132, 8, MAGENTA); LCDFill(0, 1 + 8 * 15, 132, 8, MAGENTA);
} }

View file

@ -124,7 +124,7 @@ void LCDInit(void);
void LCDReset(void); void LCDReset(void);
void LCDSetXY(unsigned char x, unsigned char y); void LCDSetXY(unsigned char x, unsigned char y);
void LCDSetPixel(unsigned char x, unsigned char y, unsigned char color); 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 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 LCDFill(unsigned char xs, unsigned char ys, unsigned char width, unsigned char height, unsigned char color);
#endif #endif

View file

@ -27,13 +27,13 @@ from the client to view the stored quadlets.
// Maximum number of auth attempts per standalone session // Maximum number of auth attempts per standalone session
#define MAX_PWDS_PER_SESSION 64 #define MAX_PWDS_PER_SESSION 64
uint8_t FindOffsetInFlash() { uint8_t FindOffsetInFlash()
{
uint8_t mem[4] = { 0x00, 0x00, 0x00, 0x00 }; uint8_t mem[4] = { 0x00, 0x00, 0x00, 0x00 };
uint8_t eom[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; uint8_t eom[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
uint8_t memcnt = 0; uint8_t memcnt = 0;
while (memcnt < 0xFF) while (memcnt < 0xFF) {
{
Flash_ReadData(memcnt, mem, 4); Flash_ReadData(memcnt, mem, 4);
if (memcmp(mem, eom, 4) == 0) { if (memcmp(mem, eom, 4) == 0) {
return memcnt; return memcnt;
@ -44,14 +44,15 @@ uint8_t FindOffsetInFlash() {
return 0; // wrap-around return 0; // wrap-around
} }
void EraseMemory() { void EraseMemory()
if (!FlashInit()){ {
if (!FlashInit()) {
return; return;
} }
Flash_CheckBusy(BUSY_TIMEOUT); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable(); Flash_WriteEnable();
Flash_Erase4k(0,0); Flash_Erase4k(0, 0);
if (MF_DBGLEVEL > 1) Dbprintf("[!] Erased flash!"); if (MF_DBGLEVEL > 1) Dbprintf("[!] Erased flash!");
FlashStop(); FlashStop();
@ -59,13 +60,15 @@ void EraseMemory() {
} }
// This is actually copied from SniffIso14443a // This is actually copied from SniffIso14443a
void RAMFUNC SniffAndStore(uint8_t param) { void RAMFUNC SniffAndStore(uint8_t param)
{
iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER);
// Allocate memory from BigBuf for some buffers // Allocate memory from BigBuf for some buffers
// free all previous allocations first // free all previous allocations first
BigBuf_free(); BigBuf_Clear_ext(false); BigBuf_free();
BigBuf_Clear_ext(false);
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
@ -96,13 +99,13 @@ void RAMFUNC SniffAndStore(uint8_t param) {
UartInit(receivedCmd, receivedCmdPar); UartInit(receivedCmd, receivedCmdPar);
// Setup and start DMA. // 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"); if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting");
return; return;
} }
tUart* uart = GetUart(); tUart *uart = GetUart();
tDemod* demod = GetDemod(); tDemod *demod = GetDemod();
// We won't start recording the frames that we acquire until we trigger; // We won't start recording the frames that we acquire until we trigger;
// a good trigger condition to get started is probably when we see a // a good trigger condition to get started is probably when we see a
@ -155,7 +158,7 @@ void RAMFUNC SniffAndStore(uint8_t param) {
if (!TagIsActive) { // no need to try decoding reader data if the tag is sending if (!TagIsActive) { // no need to try decoding reader data if the tag is sending
uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4); uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4);
if (MillerDecoding(readerdata, (rsamples-1)*4)) { if (MillerDecoding(readerdata, (rsamples - 1) * 4)) {
LED_C_ON(); LED_C_ON();
// check - if there is a short 7bit request from reader // 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]); 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 // 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++; auth_attempts++;
} }
if (!LogTrace(receivedCmd, if (!LogTrace(receivedCmd,
uart->len, uart->len,
uart->startTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, uart->startTime * 16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
uart->endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, uart->endTime * 16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
uart->parity, uart->parity,
true)) break; 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 // no need to try decoding tag data if the reader is sending - and we cannot afford the time
if (!ReaderIsActive) { if (!ReaderIsActive) {
uint8_t tagdata = (previous_data << 4) | (*data & 0x0F); 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(); LED_B_ON();
if (!LogTrace(receivedResp, if (!LogTrace(receivedResp,
demod->len, demod->len,
demod->startTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, demod->startTime * 16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
demod->endTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, demod->endTime * 16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
demod->parity, demod->parity,
false)) break; false)) break;
@ -239,8 +242,7 @@ void RAMFUNC SniffAndStore(uint8_t param) {
uint8_t memoffset = FindOffsetInFlash(); uint8_t memoffset = FindOffsetInFlash();
if (MF_DBGLEVEL > 1) Dbprintf("[!] Memory offset = %u", memoffset); 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 // We opt to keep the new data only
memoffset = 0; memoffset = 0;
if (MF_DBGLEVEL > 1) Dbprintf("[!] Size of total data > 256 bytes. Discarding the old data."); 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 // Get previous data from flash mem
uint8_t *previousdata = BigBuf_malloc(memoffset); uint8_t *previousdata = BigBuf_malloc(memoffset);
if (memoffset > 0) if (memoffset > 0) {
{
uint16_t readlen = Flash_ReadData(0, previousdata, memoffset); uint16_t readlen = Flash_ReadData(0, previousdata, memoffset);
if (MF_DBGLEVEL > 1) Dbprintf("[!] Read %u bytes from flash mem", readlen); if (MF_DBGLEVEL > 1) Dbprintf("[!] Read %u bytes from flash mem", readlen);
} }
@ -271,7 +272,7 @@ void RAMFUNC SniffAndStore(uint8_t param) {
uint16_t writelen = Flash_WriteData(0, total_data, memoffset + 4 * auth_attempts); uint16_t writelen = Flash_WriteData(0, total_data, memoffset + 4 * auth_attempts);
if (MF_DBGLEVEL > 1) Dbprintf("[!] Wrote %u bytes into flash mem", writelen); if (MF_DBGLEVEL > 1) Dbprintf("[!] Wrote %u bytes into flash mem", writelen);
// If pwd saved successfully, blink led A three times // If pwd saved successfully, blink led A three times
if (writelen > 0) { if (writelen > 0) {
SpinErr(0, 200, 5); // blink led A SpinErr(0, 200, 5); // blink led A
} }
@ -283,7 +284,8 @@ void RAMFUNC SniffAndStore(uint8_t param) {
} }
} }
void RunMod() { void RunMod()
{
StandAloneMode(); StandAloneMode();

View file

@ -112,16 +112,12 @@ void ReadLastTagFromFlash()
uint32_t end_time; uint32_t end_time;
uint32_t start_time = end_time = GetTickCount(); 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); len = MIN((len - i), size);
isok = Flash_ReadDataCont(startidx + i, mem, len); isok = Flash_ReadDataCont(startidx + i, mem, len);
if (isok == len) if (isok == len) {
{
emlSetMem(mem, 0, 64); emlSetMem(mem, 0, 64);
} } else {
else
{
DbprintfEx(FLAG_NOLOG, "FlashMem reading failed | %d | %d", len, isok); DbprintfEx(FLAG_NOLOG, "FlashMem reading failed | %d | %d", len, isok);
cjSetCursLeft(); cjSetCursLeft();
FlashStop(); FlashStop();
@ -153,24 +149,23 @@ void WriteTagToFlash(uint8_t index, size_t size)
uint32_t bytes_sent = 0; uint32_t bytes_sent = 0;
uint32_t bytes_remaining = len; uint32_t bytes_remaining = len;
uint8_t data[(size * (16 * 64))/1024]; uint8_t data[(size * (16 * 64)) / 1024];
uint8_t buff[PAGESIZE]; uint8_t buff[PAGESIZE];
emlGetMem(data, 0, (size * 64)/1024); emlGetMem(data, 0, (size * 64) / 1024);
if (!FlashInit()){ if (!FlashInit()) {
return; return;
} }
Flash_CheckBusy(BUSY_TIMEOUT); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable(); Flash_WriteEnable();
Flash_Erase4k(0,0); Flash_Erase4k(0, 0);
uint32_t end_time; uint32_t end_time;
uint32_t start_time = end_time = GetTickCount(); uint32_t start_time = end_time = GetTickCount();
while (bytes_remaining > 0) while (bytes_remaining > 0) {
{
Flash_CheckBusy(BUSY_TIMEOUT); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable(); Flash_WriteEnable();
@ -184,8 +179,7 @@ void WriteTagToFlash(uint8_t index, size_t size)
isok = (res == bytes_in_packet) ? 1 : 0; isok = (res == bytes_in_packet) ? 1 : 0;
if (!isok) if (!isok) {
{
DbprintfEx(FLAG_NOLOG, "FlashMem write FAILEd [offset %u]", bytes_sent); DbprintfEx(FLAG_NOLOG, "FlashMem write FAILEd [offset %u]", bytes_sent);
cjSetCursLeft(); cjSetCursLeft();
SpinOff(100); SpinOff(100);
@ -223,40 +217,40 @@ void RunMod()
uint8_t *keyBlock = NULL; // Where the keys will be held in memory. uint8_t *keyBlock = NULL; // Where the keys will be held in memory.
/* VIGIK EXPIRED DUMP FOR STUDY /* VIGIK EXPIRED DUMP FOR STUDY
Sector 0 Sector 0
121C7F730208040001FA33F5CB2D021D 121C7F730208040001FA33F5CB2D021D
44001049164916491649000000000000 44001049164916491649000000000000
00000000000000000000000000000000 00000000000000000000000000000000
A0A1A2A3A4A579678800010203040506 A0A1A2A3A4A579678800010203040506
Sector 1 Sector 1
0F000000000000000000000000000000 0F000000000000000000000000000000
AA0700002102080000740C110600AF13 AA0700002102080000740C110600AF13
000000000000000001740C1108220000 000000000000000001740C1108220000
314B4947495679678800010203040506 314B4947495679678800010203040506
Sector 2 Sector 2
24E572B923A3D243B402D60CAB576956 24E572B923A3D243B402D60CAB576956
216D6501FC8618B6C426762511AC2DEE 216D6501FC8618B6C426762511AC2DEE
25BF4CEC3618D0BAB3A6E9210D887746 25BF4CEC3618D0BAB3A6E9210D887746
314B4947495679678800010203040506 314B4947495679678800010203040506
Sector 3 Sector 3
0FBC41A5D95398E76A1B2029E8EA9735 0FBC41A5D95398E76A1B2029E8EA9735
088BA2CE732653D0C1147596AFCF94D7 088BA2CE732653D0C1147596AFCF94D7
77B4D91F0442182273A29DEAF7A2D095 77B4D91F0442182273A29DEAF7A2D095
314B4947495679678800010203040506 314B4947495679678800010203040506
Sector 4 Sector 4
4CEE715866E508CDBC95C640EC9D1E58 4CEE715866E508CDBC95C640EC9D1E58
E800457CF8B079414E1B45DD3E6C9317 E800457CF8B079414E1B45DD3E6C9317
77B4D91F0442182273A29DEAF7A2D095 77B4D91F0442182273A29DEAF7A2D095
314B4947495679678800010203040506 314B4947495679678800010203040506
010203040506 0 010203040506 0
Sector 5-0F Sector 5-0F
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
FFFFFFFFFFFFFF078069FFFFFFFFFFFF FFFFFFFFFFFFFF078069FFFFFFFFFFFF
KEY A : 1KGIV ; KEY A : 1KGIV ;
ACCBITS : 796788[00]+VALUE ACCBITS : 796788[00]+VALUE
*/ */
//---------------------------- //----------------------------
// Set of keys to be used. // Set of keys to be used.
@ -310,8 +304,7 @@ ACCBITS : 796788[00]+VALUE
keyBlock = BigBuf_malloc(STKEYS * 6); keyBlock = BigBuf_malloc(STKEYS * 6);
int mfKeysCnt = sizeof(mfKeys) / sizeof(uint64_t); 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)); 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 ? // 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]; //= [ {0xff} ]; /* C99 abusal 6.7.8.21
uint8_t foundKey[2][40][6]; uint8_t foundKey[2][40][6];
for (uint16_t t = 0; t < 2; t++) for (uint16_t t = 0; t < 2; t++) {
{ for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) {
for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++)
{
foundKey[t][sectorNo][0] = 0xFF; foundKey[t][sectorNo][0] = 0xFF;
foundKey[t][sectorNo][1] = 0xFF; foundKey[t][sectorNo][1] = 0xFF;
foundKey[t][sectorNo][2] = 0xFF; foundKey[t][sectorNo][2] = 0xFF;
@ -363,18 +354,15 @@ failtag:
LED_A_ON(); LED_A_ON();
uint8_t ticker = 0; uint8_t ticker = 0;
//while (!BUTTON_PRESS() && !iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) //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(); WDT_HIT();
ticker++; ticker++;
if (ticker % 64 == 0) if (ticker % 64 == 0) {
{
LED_A_INV(); LED_A_INV();
} }
if (BUTTON_HELD(10) > 0) if (BUTTON_HELD(10) > 0) {
{
WDT_HIT(); WDT_HIT();
DbprintfEx(FLAG_NOLOG, "\t\t\t[ READING FLASH ]"); DbprintfEx(FLAG_NOLOG, "\t\t\t[ READING FLASH ]");
ReadLastTagFromFlash(); ReadLastTagFromFlash();
@ -393,8 +381,7 @@ failtag:
DbprintfEx(FLAG_NOLOG, "\t%sGOT TAG :%s %08x%s", _RED_, _CYAN_, cjcuid, _WHITE_); DbprintfEx(FLAG_NOLOG, "\t%sGOT TAG :%s %08x%s", _RED_, _CYAN_, cjcuid, _WHITE_);
if (cjcuid == 0) if (cjcuid == 0) {
{
cjSetCursLeft(); cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, "%s>>%s BUG: 0000_CJCUID! Retrying...", _RED_, _WHITE_); DbprintfEx(FLAG_NOLOG, "%s>>%s BUG: 0000_CJCUID! Retrying...", _RED_, _WHITE_);
SpinErr(0, 100, 8); SpinErr(0, 100, 8);
@ -441,29 +428,22 @@ failtag:
// also we could avoid first UID check for every block // also we could avoid first UID check for every block
// then lets expose this “optimal case” of “well known vigik schemes” : // then lets expose this “optimal case” of “well known vigik schemes” :
for (uint8_t type = 0; type < 2 && !err && !trapped; type++) for (uint8_t type = 0; type < 2 && !err && !trapped; type++) {
{ for (int sec = 0; sec < sectorsCnt && !err && !trapped; ++sec) {
for (int sec = 0; sec < sectorsCnt && !err && !trapped; ++sec)
{
key = cjat91_saMifareChkKeys(sec * 4, type, NULL, size, &keyBlock[0], &key64); key = cjat91_saMifareChkKeys(sec * 4, type, NULL, size, &keyBlock[0], &key64);
if (key == -1) if (key == -1) {
{
err = 1; err = 1;
allKeysFound = false; allKeysFound = false;
// used in “portable” imlementation on microcontroller: it reports back the fail and open the standalone lock // 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); // cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0);
break; break;
} } else if (key == -2) {
else if (key == -2)
{
err = 1; // Can't select card. err = 1; // Can't select card.
allKeysFound = false; allKeysFound = false;
// cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); // cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0);
break; break;
} } else {
else
{
/* BRACE YOURSELF : AS LONG AS WE TRAP A KNOWN KEY, WE STOP CHECKING AND ENFORCE KNOWN SCHEMES */ /* BRACE YOURSELF : AS LONG AS WE TRAP A KNOWN KEY, WE STOP CHECKING AND ENFORCE KNOWN SCHEMES */
// uint8_t tosendkey[13]; // uint8_t tosendkey[13];
char tosendkey[13]; char tosendkey[13];
@ -471,243 +451,236 @@ failtag:
cjSetCursRight(); cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %012" PRIx64 " ; TYP: %i", sec, key64, type); 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);*/ /*cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sec, type, tosendkey, 12);*/
switch (key64) switch (key64) {
{ /////////////////////////////////////////////////////////
///////////////////////////////////////////////////////// // COMMON SCHEME 1 : INFINITRON/HEXACT
// COMMON SCHEME 1 : INFINITRON/HEXACT case 0x484558414354:
case 0x484558414354: cjSetCursLeft();
cjSetCursLeft(); DbprintfEx(FLAG_NOLOG, "%s>>>>>>>>>>>>!*STOP*!<<<<<<<<<<<<<<%s", _RED_, _WHITE_);
DbprintfEx(FLAG_NOLOG, "%s>>>>>>>>>>>>!*STOP*!<<<<<<<<<<<<<<%s", _RED_, _WHITE_); cjSetCursLeft();
cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, " .TAG SEEMS %sDETERMINISTIC%s. ", _GREEN_, _WHITE_); DbprintfEx(FLAG_NOLOG, " .TAG SEEMS %sDETERMINISTIC%s. ", _GREEN_, _WHITE_);
cjSetCursLeft(); cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, "%sDetected: %s INFI_HEXACT_VIGIK_TAG%s", _ORANGE_, _CYAN_, _WHITE_); DbprintfEx(FLAG_NOLOG, "%sDetected: %s INFI_HEXACT_VIGIK_TAG%s", _ORANGE_, _CYAN_, _WHITE_);
cjSetCursLeft(); cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, "...%s[%sKey_derivation_schemeTest%s]%s...", _YELLOW_, _GREEN_, _YELLOW_, _GREEN_); DbprintfEx(FLAG_NOLOG, "...%s[%sKey_derivation_schemeTest%s]%s...", _YELLOW_, _GREEN_, _YELLOW_, _GREEN_);
cjSetCursLeft(); cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, "%s>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%s", _GREEN_, _WHITE_); DbprintfEx(FLAG_NOLOG, "%s>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%s", _GREEN_, _WHITE_);
; ;
// Type 0 / A first // Type 0 / A first
uint16_t t = 0; 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
}
t = 1;
uint16_t sectorNo = 0;
num_to_bytes(0xa22ae129c013, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 1;
num_to_bytes(0x49fae4e3849f, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 2;
num_to_bytes(0x38fcf33072e0, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 3;
num_to_bytes(0x8ad5517b4b18, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 4;
num_to_bytes(0x509359f131b1, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 5;
num_to_bytes(0x6c78928e1317, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 6;
num_to_bytes(0xaa0720018738, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 7;
num_to_bytes(0xa6cac2886412, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 8;
num_to_bytes(0x62d0c424ed8e, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 9;
num_to_bytes(0xe64a986a5d94, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 10;
num_to_bytes(0x8fa1d601d0a2, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 11;
num_to_bytes(0x89347350bd36, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 12;
num_to_bytes(0x66d2b7dc39ef, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 13;
num_to_bytes(0x6bc1e1ae547d, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 14;
num_to_bytes(0x22729a9bd40f, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 15;
num_to_bytes(0x484558414354, 6, foundKey[t][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], 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]); foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
cjSetCursRight(); cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
} trapped = 1;
t = 1; break;
uint16_t sectorNo = 0; ////////////////END OF SCHEME 1//////////////////////////////
num_to_bytes(0xa22ae129c013, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); ///////////////////////////////////////
sectorNo = 1; // COMMON SCHEME 2 : URMET CAPTIVE / COGELEC!/?
num_to_bytes(0x49fae4e3849f, 6, foundKey[t][sectorNo]); case 0x8829da9daf76:
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], cjSetCursLeft();
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); DbprintfEx(FLAG_NOLOG, "%s>>>>>>>>>>>>!*STOP*!<<<<<<<<<<<<<<%s", _RED_, _WHITE_);
sectorNo = 2; cjSetCursLeft();
num_to_bytes(0x38fcf33072e0, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); DbprintfEx(FLAG_NOLOG, " .TAG SEEMS %sDETERMINISTIC%s. ", _GREEN_, _WHITE_);
sectorNo = 3; cjSetCursLeft();
num_to_bytes(0x8ad5517b4b18, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); DbprintfEx(FLAG_NOLOG, "%sDetected :%sURMET_CAPTIVE_VIGIK_TAG%s", _ORANGE_, _CYAN_, _WHITE_);
sectorNo = 4; cjSetCursLeft();
num_to_bytes(0x509359f131b1, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); DbprintfEx(FLAG_NOLOG, "...%s[%sKey_derivation_schemeTest%s]%s...", _YELLOW_, _GREEN_, _YELLOW_, _GREEN_);
sectorNo = 5; cjSetCursLeft();
num_to_bytes(0x6c78928e1317, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); DbprintfEx(FLAG_NOLOG, "%s>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%s", _GREEN_, _WHITE_);
sectorNo = 6; cjSetCursLeft();
num_to_bytes(0xaa0720018738, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); // emlClearMem();
sectorNo = 7; // A very weak one...
num_to_bytes(0xa6cac2886412, 6, foundKey[t][sectorNo]); for (uint16_t t = 0; t < 2; t++) {
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) {
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); num_to_bytes(key64, 6, foundKey[t][sectorNo]);
cjSetCursRight(); 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 8; }
num_to_bytes(0x62d0c424ed8e, 6, foundKey[t][sectorNo]); }
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], trapped = 1;
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); break;
cjSetCursRight(); ////////////////END OF SCHEME 2//////////////////////////////
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); ///////////////////////////////////////
sectorNo = 9; // COMMON SCHEME 3 : NORALSY "A-LARON & B-LARON . . . NORAL-B & NORAL-A"
num_to_bytes(0xe64a986a5d94, 6, foundKey[t][sectorNo]); case 0x414c41524f4e: // Thumbs up to the guy who had the idea of such a "mnemotechnical" key pair
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], case 0x424c41524f4e:
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); cjSetCursLeft();
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); DbprintfEx(FLAG_NOLOG, "%s>>>>>>>>>>>>!*STOP*!<<<<<<<<<<<<<<%s", _RED_, _WHITE_);
sectorNo = 10; cjSetCursLeft();
num_to_bytes(0x8fa1d601d0a2, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); DbprintfEx(FLAG_NOLOG, " .TAG SEEMS %sDETERMINISTIC%s. ", _GREEN_, _WHITE_);
sectorNo = 11; cjSetCursLeft();
num_to_bytes(0x89347350bd36, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); DbprintfEx(FLAG_NOLOG, "%s Detected :%sNORALSY_VIGIK_TAG %s", _ORANGE_, _CYAN_, _WHITE_);
sectorNo = 12; cjSetCursLeft();
num_to_bytes(0x66d2b7dc39ef, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); DbprintfEx(FLAG_NOLOG, "...%s[%sKey_derivation_schemeTest%s]%s...", _YELLOW_, _GREEN_, _YELLOW_, _GREEN_);
sectorNo = 13; cjSetCursLeft();
num_to_bytes(0x6bc1e1ae547d, 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); DbprintfEx(FLAG_NOLOG, "%s>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%s", _GREEN_, _WHITE_);
sectorNo = 14; ;
num_to_bytes(0x22729a9bd40f, 6, foundKey[t][sectorNo]); t = 0;
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) {
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); num_to_bytes(0x414c41524f4e, 6, foundKey[t][sectorNo]);
cjSetCursRight(); 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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 15; ;
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], t = 1;
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) {
cjSetCursRight(); num_to_bytes(0x424c41524f4e, 6, foundKey[t][sectorNo]);
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
trapped = 1;
break;
////////////////END OF SCHEME 1//////////////////////////////
///////////////////////////////////////
// COMMON SCHEME 2 : URMET CAPTIVE / COGELEC!/?
case 0x8829da9daf76:
cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, "%s>>>>>>>>>>>>!*STOP*!<<<<<<<<<<<<<<%s", _RED_, _WHITE_);
cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, " .TAG SEEMS %sDETERMINISTIC%s. ", _GREEN_, _WHITE_);
cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, "%sDetected :%sURMET_CAPTIVE_VIGIK_TAG%s", _ORANGE_, _CYAN_, _WHITE_);
cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, "...%s[%sKey_derivation_schemeTest%s]%s...", _YELLOW_, _GREEN_, _YELLOW_, _GREEN_);
cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, "%s>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%s", _GREEN_, _WHITE_);
cjSetCursLeft();
// emlClearMem();
// A very weak one...
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], 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]); foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
cjSetCursRight(); cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
} }
} trapped = 1;
trapped = 1; break;
break; ////////////////END OF SCHEME 3//////////////////////////////
////////////////END OF SCHEME 2//////////////////////////////
///////////////////////////////////////
// COMMON SCHEME 3 : NORALSY "A-LARON & B-LARON . . . NORAL-B & NORAL-A"
case 0x414c41524f4e: // Thumbs up to the guy who had the idea of such a "mnemotechnical" key pair
case 0x424c41524f4e:
cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, "%s>>>>>>>>>>>>!*STOP*!<<<<<<<<<<<<<<%s", _RED_, _WHITE_);
cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, " .TAG SEEMS %sDETERMINISTIC%s. ", _GREEN_, _WHITE_);
cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, "%s Detected :%sNORALSY_VIGIK_TAG %s", _ORANGE_, _CYAN_, _WHITE_);
cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, "...%s[%sKey_derivation_schemeTest%s]%s...", _YELLOW_, _GREEN_, _YELLOW_, _GREEN_);
cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, "%s>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%s", _GREEN_, _WHITE_);
;
t = 0;
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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
;
}
t = 1;
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]);
cjSetCursRight();
DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
}
trapped = 1;
break;
////////////////END OF SCHEME 3//////////////////////////////
} }
/* etc etc for testing schemes quick schemes */ /* etc etc for testing schemes quick schemes */
} }
} }
} }
if (!allKeysFound) if (!allKeysFound) {
{
cjSetCursLeft(); cjSetCursLeft();
cjTabulize(); cjTabulize();
DbprintfEx(FLAG_NOLOG, "%s[ FAIL ]%s\r\n->did not found all the keys :'(", _RED_, _WHITE_); 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 */ /* Settings keys to emulator */
emlClearMem(); emlClearMem();
uint8_t mblock[16]; 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); 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); memcpy(mblock + t * 10, foundKey[t][sectorNo], 6);
} }
emlSetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); 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_); DbprintfEx(FLAG_NOLOG, "%s>>%s Filling Emulator <- from A keys...", _YELLOW_, _WHITE_);
e_MifareECardLoad(sectorsCnt, 0, 0, &filled); e_MifareECardLoad(sectorsCnt, 0, 0, &filled);
if (filled != 1) if (filled != 1) {
{
cjSetCursLeft(); cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, "%s>>%s W_FAILURE ! %sTrying fallback B keys....", _RED_, _ORANGE_, _WHITE_); DbprintfEx(FLAG_NOLOG, "%s>>%s W_FAILURE ! %sTrying fallback B keys....", _RED_, _ORANGE_, _WHITE_);
/* no trace, no dbg */ /* no trace, no dbg */
e_MifareECardLoad(sectorsCnt, 1, 0, &filled); e_MifareECardLoad(sectorsCnt, 1, 0, &filled);
if (filled != 1) if (filled != 1) {
{
cjSetCursLeft(); cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, "FATAL:EML_FALLBACKFILL_B"); 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; 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; isOK = false;
if (MF_DBGLEVEL >= 1) if (MF_DBGLEVEL >= 1)
DbprintfEx(FLAG_RAWPRINT, "Can't select card"); 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); ui64Key = emlGetKey(sectorNo, keyType);
if (sectorNo == 0) if (sectorNo == 0) {
{ if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) {
if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST))
{
isOK = false; isOK = false;
if (MF_DBGLEVEL >= 1) if (MF_DBGLEVEL >= 1)
DbprintfEx(FLAG_NOLOG, "Sector[%2d]. Auth error", sectorNo); DbprintfEx(FLAG_NOLOG, "Sector[%2d]. Auth error", sectorNo);
break; break;
} }
} } else {
else if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) {
{
if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED))
{
isOK = false; isOK = false;
if (MF_DBGLEVEL >= 1) if (MF_DBGLEVEL >= 1)
DbprintfEx(FLAG_NOLOG, "Sector[%2d]. Auth nested error", sectorNo); 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++) for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
{ if (isOK && mifare_classic_readblock(pcs, cjcuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) {
if (isOK && mifare_classic_readblock(pcs, cjcuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf))
{
isOK = false; isOK = false;
if (MF_DBGLEVEL >= 1) if (MF_DBGLEVEL >= 1)
DbprintfEx(FLAG_NOLOG, "Error reading sector %2d block %2d", sectorNo, blockNo); DbprintfEx(FLAG_NOLOG, "Error reading sector %2d block %2d", sectorNo, blockNo);
break; break;
}; };
if (isOK) if (isOK) {
{
*datain = 1; *datain = 1;
if (blockNo < NumBlocksPerSector(sectorNo) - 1) if (blockNo < NumBlocksPerSector(sectorNo) - 1) {
{
emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1); emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1);
} } else {
else // sector trailer, keep the keys, set only the AC
{ // sector trailer, keep the keys, set only the AC
emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1);
memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4); memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4);
emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1);
} }
} } else {
else
{
*datain = 0; *datain = 0;
} }
} }
} }
if (mifare_classic_halt(pcs, cjcuid)) if (mifare_classic_halt(pcs, cjcuid)) {
{
if (MF_DBGLEVEL >= 1) if (MF_DBGLEVEL >= 1)
DbprintfEx(FLAG_NOLOG, "Halt error"); DbprintfEx(FLAG_NOLOG, "Halt error");
}; };
@ -944,21 +898,18 @@ int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, ui
struct Crypto1State *pcs; struct Crypto1State *pcs;
pcs = &mpcs; 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 */ /* no need for anticollision. just verify tag is still here */
// if (!iso14443a_fast_select_card(cjuid, 0)) { // 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(); cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, "%sFATAL%s : E_MF_LOSTTAG", _RED_, _WHITE_); DbprintfEx(FLAG_NOLOG, "%sFATAL%s : E_MF_LOSTTAG", _RED_, _WHITE_);
return -1; return -1;
} }
uint64_t ui64Key = bytes_to_num(datain + i * 6, 6); 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; uint8_t dummy_answer = 0;
ReaderTransmit(&dummy_answer, 1, NULL); ReaderTransmit(&dummy_answer, 1, NULL);
// wait for the card to become ready again // wait for the card to become ready again
@ -990,8 +941,7 @@ void saMifareMakeTag(void)
DbprintfEx(FLAG_NOLOG, ">> Write to Special:"); DbprintfEx(FLAG_NOLOG, ">> Write to Special:");
int flags = 0; int flags = 0;
for (int blockNum = 0; blockNum < 16 * 4; blockNum++) for (int blockNum = 0; blockNum < 16 * 4; blockNum++) {
{
uint8_t mblock[16]; uint8_t mblock[16];
// cnt = 0; // cnt = 0;
emlGetMem(mblock, blockNum, 1); emlGetMem(mblock, blockNum, 1);
@ -1007,12 +957,11 @@ void saMifareMakeTag(void)
if (blockNum == 16 * 4 - 1) if (blockNum == 16 * 4 - 1)
flags = 0x04 + 0x10; flags = 0x04 + 0x10;
if (saMifareCSetBlock(0, flags & 0xFE, blockNum, mblock)) if (saMifareCSetBlock(0, flags & 0xFE, blockNum, mblock)) {
{ //&& cnt <= retry) { //&& cnt <= retry) {
// cnt++; // cnt++;
cjSetCursFRight(); cjSetCursFRight();
if (currfline > 53) if (currfline > 53) {
{
currfline = 54; currfline = 54;
} }
DbprintfEx(FLAG_NOLOG, "Block :%02x %sOK%s", blockNum, _GREEN_, _WHITE_); DbprintfEx(FLAG_NOLOG, "Block :%02x %sOK%s", blockNum, _GREEN_, _WHITE_);
@ -1020,9 +969,7 @@ void saMifareMakeTag(void)
// cfail=1; // cfail=1;
// return; // return;
continue; continue;
} } else {
else
{
cjSetCursLeft(); cjSetCursLeft();
cjSetCursLeft(); cjSetCursLeft();
@ -1041,8 +988,7 @@ void saMifareMakeTag(void)
break; break;
} */ } */
} }
if (cfail == 0) if (cfail == 0) {
{
SpinUp(50); SpinUp(50);
SpinUp(50); 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]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
// reset FPGA and LED // reset FPGA and LED
if (workFlags & 0x08) if (workFlags & 0x08) {
{
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
// clear_trace(); // clear_trace();
set_tracing(FALSE); set_tracing(FALSE);
} }
while (true) while (true) {
{
cjSetCursLeft(); cjSetCursLeft();
// get UID from chip // get UID from chip
if (workFlags & 0x01) if (workFlags & 0x01) {
{ if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) {
if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true))
{
DbprintfEx(FLAG_NOLOG, "Can't select card"); DbprintfEx(FLAG_NOLOG, "Can't select card");
break; break;
}; };
if (mifare_classic_halt(NULL, cjcuid)) if (mifare_classic_halt(NULL, cjcuid)) {
{
DbprintfEx(FLAG_NOLOG, "Halt error"); DbprintfEx(FLAG_NOLOG, "Halt error");
break; break;
}; };
}; };
// reset chip // reset chip
if (needWipe) if (needWipe) {
{
ReaderTransmitBitsPar(wupC1, 7, 0, NULL); ReaderTransmitBitsPar(wupC1, 7, 0, NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
{
DbprintfEx(FLAG_NOLOG, "wupC1 error"); DbprintfEx(FLAG_NOLOG, "wupC1 error");
break; break;
}; };
ReaderTransmit(wipeC, sizeof(wipeC), NULL); ReaderTransmit(wipeC, sizeof(wipeC), NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
{
DbprintfEx(FLAG_NOLOG, "wipeC error"); DbprintfEx(FLAG_NOLOG, "wipeC error");
break; break;
}; };
if (mifare_classic_halt(NULL, cjcuid)) if (mifare_classic_halt(NULL, cjcuid)) {
{
DbprintfEx(FLAG_NOLOG, "Halt error"); DbprintfEx(FLAG_NOLOG, "Halt error");
break; break;
}; };
@ -1131,25 +1068,21 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
// chaud // chaud
// write block // write block
if (workFlags & 0x02) if (workFlags & 0x02) {
{
ReaderTransmitBitsPar(wupC1, 7, 0, NULL); ReaderTransmitBitsPar(wupC1, 7, 0, NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
{
DbprintfEx(FLAG_NOLOG, "wupC1 error"); DbprintfEx(FLAG_NOLOG, "wupC1 error");
break; break;
}; };
ReaderTransmit(wupC2, sizeof(wupC2), NULL); ReaderTransmit(wupC2, sizeof(wupC2), NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
{
DbprintfEx(FLAG_NOLOG, "wupC2 errorv"); DbprintfEx(FLAG_NOLOG, "wupC2 errorv");
break; 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"); DbprintfEx(FLAG_NOLOG, "write block send command error");
break; break;
}; };
@ -1157,16 +1090,13 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
memcpy(d_block, datain, 16); memcpy(d_block, datain, 16);
AddCrc14A(d_block, 16); AddCrc14A(d_block, 16);
ReaderTransmit(d_block, sizeof(d_block), NULL); 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"); DbprintfEx(FLAG_NOLOG, "write block send data error");
break; break;
}; };
if (workFlags & 0x04) if (workFlags & 0x04) {
{ if (mifare_classic_halt(NULL, cjcuid)) {
if (mifare_classic_halt(NULL, cjcuid))
{
cjSetCursFRight(); cjSetCursFRight();
DbprintfEx(FLAG_NOLOG, "Halt error"); DbprintfEx(FLAG_NOLOG, "Halt error");
@ -1178,8 +1108,7 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
break; break;
} }
if ((workFlags & 0x10) || (!isOK)) if ((workFlags & 0x10) || (!isOK)) {
{
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); 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]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
// reset FPGA and LED // reset FPGA and LED
if (workFlags & 0x08) if (workFlags & 0x08) {
{
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
set_tracing(false); set_tracing(false);
} }
while (true) while (true) {
{
// get UID from chip // get UID from chip
if (workFlags & 0x01) if (workFlags & 0x01) {
{ if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true))
{
DbprintfEx(FLAG_NOLOG, "Can't select card"); DbprintfEx(FLAG_NOLOG, "Can't select card");
break; break;
}; };
if (mifare_classic_halt(NULL, cuid)) if (mifare_classic_halt(NULL, cuid)) {
{
DbprintfEx(FLAG_NOLOG, "Halt error"); DbprintfEx(FLAG_NOLOG, "Halt error");
break; break;
}; };
}; };
// reset chip // reset chip
if (needWipe) if (needWipe) {
{
ReaderTransmitBitsPar(wupC1, 7, 0, NULL); ReaderTransmitBitsPar(wupC1, 7, 0, NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
{
DbprintfEx(FLAG_NOLOG, "wupC1 error"); DbprintfEx(FLAG_NOLOG, "wupC1 error");
break; break;
}; };
ReaderTransmit(wipeC, sizeof(wipeC), NULL); ReaderTransmit(wipeC, sizeof(wipeC), NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
{
DbprintfEx(FLAG_NOLOG, "wipeC error"); DbprintfEx(FLAG_NOLOG, "wipeC error");
break; break;
}; };
if (mifare_classic_halt(NULL, cuid)) if (mifare_classic_halt(NULL, cuid)) {
{
DbprintfEx(FLAG_NOLOG, "Halt error"); DbprintfEx(FLAG_NOLOG, "Halt error");
break; break;
}; };
@ -117,25 +108,21 @@ static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_
// chaud // chaud
// write block // write block
if (workFlags & 0x02) if (workFlags & 0x02) {
{
ReaderTransmitBitsPar(wupC1, 7, 0, NULL); ReaderTransmitBitsPar(wupC1, 7, 0, NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
{
DbprintfEx(FLAG_NOLOG, "wupC1 error"); DbprintfEx(FLAG_NOLOG, "wupC1 error");
break; break;
}; };
ReaderTransmit(wupC2, sizeof(wupC2), NULL); ReaderTransmit(wupC2, sizeof(wupC2), NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
{
DbprintfEx(FLAG_NOLOG, "wupC2 errorv"); DbprintfEx(FLAG_NOLOG, "wupC2 errorv");
break; 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"); DbprintfEx(FLAG_NOLOG, "write block send command error");
break; break;
}; };
@ -143,16 +130,13 @@ static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_
memcpy(d_block, datain, 16); memcpy(d_block, datain, 16);
AddCrc14A(d_block, 16); AddCrc14A(d_block, 16);
ReaderTransmit(d_block, sizeof(d_block), NULL); 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"); DbprintfEx(FLAG_NOLOG, "write block send data error");
break; break;
}; };
if (workFlags & 0x04) if (workFlags & 0x04) {
{ if (mifare_classic_halt(NULL, cuid)) {
if (mifare_classic_halt(NULL, cuid))
{
DbprintfEx(FLAG_NOLOG, "Halt error"); DbprintfEx(FLAG_NOLOG, "Halt error");
break; break;
}; };
@ -162,8 +146,7 @@ static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_
break; break;
} }
if ((workFlags & 0x10) || (!isOK)) if ((workFlags & 0x10) || (!isOK)) {
{
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
} }
@ -182,20 +165,17 @@ static int saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, ui
struct Crypto1State *pcs; struct Crypto1State *pcs;
pcs = &mpcs; 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 */ /* no need for anticollision. just verify tag is still here */
// if (!iso14443a_fast_select_card(cjuid, 0)) { // 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"); DbprintfEx(FLAG_NOLOG, "FATAL : E_MF_LOSTTAG");
return -1; return -1;
} }
uint64_t ui64Key = bytes_to_num(datain + i * 6, 6); 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; uint8_t dummy_answer = 0;
ReaderTransmit(&dummy_answer, 1, NULL); ReaderTransmit(&dummy_answer, 1, NULL);
// wait for the card to become ready again // 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(); StandAloneMode();
Dbprintf(">> Matty mifare chk/dump/sim a.k.a MattyRun Started <<"); Dbprintf(">> Matty mifare chk/dump/sim a.k.a MattyRun Started <<");
FpgaDownloadAndGo(FPGA_BITSTREAM_HF); FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
@ -249,7 +230,7 @@ void RunMod() {
uint16_t mifare_size = 1024; // Mifare 1k (only 1k supported for now) 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 sectorSize = 64; // 1k's sector size is 64 bytes.
uint8_t blockNo = 3; // Security block is number 3 for each sector. 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 uint8_t keyType = 2; // Keytype buffer
uint64_t key64; // Defines current key uint64_t key64; // Defines current key
uint8_t *keyBlock = NULL; // Where the keys will be held in memory. 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); 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)); num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t *)(keyBlock + mfKeyCounter * 6));
} }
/* /*
@ -294,8 +275,8 @@ void RunMod() {
Dbprintf("[+] Printing mf keys"); Dbprintf("[+] Printing mf keys");
for (uint8_t keycnt = 0; keycnt < mfKeysCnt; keycnt++) for (uint8_t keycnt = 0; keycnt < mfKeysCnt; keycnt++)
Dbprintf("[-] chk mf key[%2d] %02x%02x%02x%02x%02x%02x", 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)[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)[3], (keyBlock + 6 * keycnt)[4], (keyBlock + 6 * keycnt)[5], 6);
DbpString("--------------------------------------------------------"); DbpString("--------------------------------------------------------");
} }
@ -327,7 +308,7 @@ void RunMod() {
for (int type = !keyType; type < 2 && !err; keyType == 2 ? (type++) : (type = 2)) { for (int type = !keyType; type < 2 && !err; keyType == 2 ? (type++) : (type = 2)) {
block = blockNo; block = blockNo;
for (int sec = 0; sec < sectorsCnt && !err; ++sec) { 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); key = saMifareChkKeys(block, type, true, size, &keyBlock[0], &key64);
if (key == -1) { if (key == -1) {
LED(LED_RED, 50); //red LED(LED_RED, 50); //red
@ -342,9 +323,9 @@ void RunMod() {
validKey[type][sec] = true; validKey[type][sec] = true;
keyFound = true; keyFound = true;
Dbprintf("\t✓ Found valid key: [%02x%02x%02x%02x%02x%02x]\n", 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)[0], (keyBlock + 6 * key)[1], (keyBlock + 6 * key)[2],
(keyBlock + 6*key)[3], (keyBlock + 6*key)[4], (keyBlock + 6*key)[5] (keyBlock + 6 * key)[3], (keyBlock + 6 * key)[4], (keyBlock + 6 * key)[5]
); );
} }
block < 127 ? (block += 4) : (block += 16); block < 127 ? (block += 4) : (block += 16);
@ -378,14 +359,14 @@ void RunMod() {
for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) {
if (validKey[0][sectorNo] || validKey[1][sectorNo]) { if (validKey[0][sectorNo] || validKey[1][sectorNo]) {
emlGetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); // data, block num, blocks count (max 4) emlGetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); // data, block num, blocks count (max 4)
for (uint16_t t = 0; t < 2; t++) { for (uint16_t t = 0; t < 2; t++) {
if (validKey[t][sectorNo]) { 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);
} }
emlSetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);
} }
}
Dbprintf("\t✓ Found keys have been transferred to the emulator memory."); Dbprintf("\t✓ Found keys have been transferred to the emulator memory.");
if (ecfill) { if (ecfill) {
@ -409,7 +390,7 @@ void RunMod() {
LED_B_ON(); // green LED_B_ON(); // green
// assuming arg0==0, use hardcoded uid 0xdeadbeaf // 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(); LED_B_OFF();
/* /*

View file

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

View file

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

View file

@ -19,6 +19,6 @@
#define OPTS 3 #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 */ #endif /* __LF_HIDBRUTE_H */

View file

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

View file

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

View file

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

View file

@ -8,11 +8,11 @@
// AES context structure // AES context structure
typedef struct { typedef struct {
unsigned int Ek[60]; unsigned int Ek[60];
unsigned int Dk[60]; unsigned int Dk[60];
unsigned int Iv[4]; unsigned int Iv[4];
unsigned char Nr; unsigned char Nr;
unsigned char Mode; unsigned char Mode;
} AesCtx; } AesCtx;
// key length in bytes // key length in bytes

View file

@ -27,7 +27,7 @@
#define DEBUG 1 #define DEBUG 1
#ifdef WITH_LCD #ifdef WITH_LCD
#include "LCD.h" #include "LCD.h"
#endif #endif
#ifdef WITH_SMARTCARD #ifdef WITH_SMARTCARD
@ -54,55 +54,59 @@ int ToSendMax = -1;
static int ToSendBit; static int ToSendBit;
struct common_area common_area __attribute__((section(".commonarea"))); struct common_area common_area __attribute__((section(".commonarea")));
void ToSendReset(void) { void ToSendReset(void)
{
ToSendMax = -1; ToSendMax = -1;
ToSendBit = 8; ToSendBit = 8;
} }
void ToSendStuffBit(int b) { void ToSendStuffBit(int b)
if(ToSendBit >= 8) { {
if (ToSendBit >= 8) {
ToSendMax++; ToSendMax++;
ToSend[ToSendMax] = 0; ToSend[ToSendMax] = 0;
ToSendBit = 0; ToSendBit = 0;
} }
if(b) if (b)
ToSend[ToSendMax] |= (1 << (7 - ToSendBit)); ToSend[ToSendMax] |= (1 << (7 - ToSendBit));
ToSendBit++; ToSendBit++;
if(ToSendMax >= sizeof(ToSend)) { if (ToSendMax >= sizeof(ToSend)) {
ToSendBit = 0; ToSendBit = 0;
DbpString("ToSendStuffBit overflowed!"); DbpString("ToSendStuffBit overflowed!");
} }
} }
void PrintToSendBuffer(void) { void PrintToSendBuffer(void)
{
DbpString("Printing ToSendBuffer:"); DbpString("Printing ToSendBuffer:");
Dbhexdump(ToSendMax, ToSend, 0); 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; uint8_t *p = buf;
uint16_t tmp = len & 0xFFF0; 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", Dbprintf("[%s: %02d/%02d] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
name, name,
p-buf, p - buf,
len, 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) { if (len % 16 != 0) {
char s[46] = {0}; char s[46] = {0};
char *sp = s; char *sp = s;
for (; p-buf < len; p++ ) { for (; p - buf < len; p++) {
sprintf(sp, "%02x ", p[0] ); sprintf(sp, "%02x ", p[0]);
sp += 3; 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. // 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 #if DEBUG
uint8_t len = strlen(str); 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 #endif
} }
void DbpString(char *str) { void DbpString(char *str)
{
#if DEBUG #if DEBUG
DbpStringEx(str, 0); DbpStringEx(str, 0);
#endif #endif
} }
#if 0 #if 0
void DbpIntegers(int x1, int x2, int x3) { void DbpIntegers(int x1, int x2, int x3)
cmd_send(CMD_DEBUG_PRINT_INTEGERS,x1,x2,x3,0,0); {
cmd_send(CMD_DEBUG_PRINT_INTEGERS, x1, x2, x3, 0, 0);
} }
#endif #endif
void DbprintfEx(uint32_t cmd, const char *fmt, ...) { void DbprintfEx(uint32_t cmd, const char *fmt, ...)
{
#if DEBUG #if DEBUG
// should probably limit size here; oh well, let's just use a big buffer // should probably limit size here; oh well, let's just use a big buffer
char output_string[128] = {0x00}; char output_string[128] = {0x00};
@ -141,7 +149,8 @@ void DbprintfEx(uint32_t cmd, const char *fmt, ...) {
#endif #endif
} }
void Dbprintf(const char *fmt, ...) { void Dbprintf(const char *fmt, ...)
{
#if DEBUG #if DEBUG
// should probably limit size here; oh well, let's just use a big buffer // should probably limit size here; oh well, let's just use a big buffer
char output_string[128] = {0x00}; char output_string[128] = {0x00};
@ -156,9 +165,10 @@ void Dbprintf(const char *fmt, ...) {
} }
// prints HEX & ASCII // prints HEX & ASCII
void Dbhexdump(int len, uint8_t *d, bool bAsci) { void Dbhexdump(int len, uint8_t *d, bool bAsci)
{
#if DEBUG #if DEBUG
int l=0, i; int l = 0, i;
char ascii[9]; char ascii[9];
while (len > 0) { while (len > 0) {
@ -169,7 +179,7 @@ void Dbhexdump(int len, uint8_t *d, bool bAsci) {
ascii[l] = 0; ascii[l] = 0;
// filter safe ascii // filter safe ascii
for (i=0; i<l; i++) { for (i = 0; i < l; i++) {
if (ascii[i] < 32 || ascii[i] > 126) { if (ascii[i] < 32 || ascii[i] > 126) {
ascii[i] = '.'; 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 // in ADC units (0 to 1023). Also a routine to average 32 samples and
// return that. // 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. // 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 // AMPL_HI is are high impedance (10MOhm || 1MOhm) output, the input capacitance of the ADC is 12pF (typical). This results in a time constant
@ -204,9 +215,9 @@ static uint16_t ReadAdc(int ch) {
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST; AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST;
AT91C_BASE_ADC->ADC_MR = AT91C_BASE_ADC->ADC_MR =
ADC_MODE_PRESCALE(63) // ADC_CLK = MCK / ((63+1) * 2) = 48MHz / 128 = 375kHz ADC_MODE_PRESCALE(63) // ADC_CLK = MCK / ((63+1) * 2) = 48MHz / 128 = 375kHz
| ADC_MODE_STARTUP_TIME(1) // Startup Time = (1+1) * 8 / ADC_CLK = 16 / 375kHz = 42,7us Note: must be > 20us | ADC_MODE_STARTUP_TIME(1) // Startup Time = (1+1) * 8 / ADC_CLK = 16 / 375kHz = 42,7us Note: must be > 20us
| ADC_MODE_SAMPLE_HOLD_TIME(15); // Sample & Hold Time SHTIM = 15 / ADC_CLK = 15 / 375kHz = 40us | ADC_MODE_SAMPLE_HOLD_TIME(15); // Sample & Hold Time SHTIM = 15 / ADC_CLK = 15 / 375kHz = 40us
AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ch); AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ch);
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
@ -217,16 +228,18 @@ static uint16_t ReadAdc(int ch) {
} }
// was static - merlok // was static - merlok
uint16_t AvgAdc(int ch) { uint16_t AvgAdc(int ch)
{
uint16_t a = 0; uint16_t a = 0;
for(uint8_t i = 0; i < 32; i++) for (uint8_t i = 0; i < 32; i++)
a += ReadAdc(ch); a += ReadAdc(ch);
//division by 32 //division by 32
return (a + 15) >> 5; return (a + 15) >> 5;
} }
void MeasureAntennaTuning(void) { void MeasureAntennaTuning(void)
{
uint8_t LF_Results[256]; uint8_t LF_Results[256];
uint32_t i, adcval = 0, peak = 0, peakv = 0, peakf = 0; uint32_t i, adcval = 0, peak = 0, peakv = 0, peakf = 0;
@ -235,20 +248,20 @@ void MeasureAntennaTuning(void) {
memset(LF_Results, 0, sizeof(LF_Results)); memset(LF_Results, 0, sizeof(LF_Results));
LED_B_ON(); LED_B_ON();
/* /*
* Sweeps the useful LF range of the proxmark from * Sweeps the useful LF range of the proxmark from
* 46.8kHz (divisor=255) to 600kHz (divisor=19) and * 46.8kHz (divisor=255) to 600kHz (divisor=19) and
* read the voltage in the antenna, the result left * read the voltage in the antenna, the result left
* in the buffer is a graph which should clearly show * in the buffer is a graph which should clearly show
* the resonating frequency of your LF antenna * the resonating frequency of your LF antenna
* ( hopefully around 95 if it is tuned to 125kHz!) * ( hopefully around 95 if it is tuned to 125kHz!)
*/ */
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
SpinDelay(50); SpinDelay(50);
for (i = 255; i >= 19; i--) { for (i = 255; i >= 19; i--) {
WDT_HIT(); WDT_HIT();
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i);
SpinDelay(20); SpinDelay(20);
@ -259,7 +272,7 @@ void MeasureAntennaTuning(void) {
v_lf134 = adcval; // voltage at 134Khz v_lf134 = adcval; // voltage at 134Khz
LF_Results[i] = adcval >> 9; // scale int to fit in byte for graphing purposes 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; peakv = adcval;
peakf = i; peakf = i;
peak = LF_Results[i]; peak = LF_Results[i];
@ -274,7 +287,7 @@ void MeasureAntennaTuning(void) {
v_hf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; 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. // 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; v_hf = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10;
} }
@ -291,29 +304,31 @@ void MeasureAntennaTuning(void) {
LEDsoff(); LEDsoff();
} }
void MeasureAntennaTuningHf(void) { void MeasureAntennaTuningHf(void)
{
uint16_t volt = 0; // in mV uint16_t volt = 0; // in mV
// Let the FPGA drive the high-frequency antenna around 13.56 MHz. // Let the FPGA drive the high-frequency antenna around 13.56 MHz.
FpgaDownloadAndGo(FPGA_BITSTREAM_HF); FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
SpinDelay(50); SpinDelay(50);
volt = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; 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); SpinDelay(20);
if ( !use_high ) { if (!use_high) {
volt = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; volt = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
} else { } else {
volt = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10; 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); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
DbprintfEx(FLAG_NOOPT, "\n[+] cancelled", 1); DbprintfEx(FLAG_NOOPT, "\n[+] cancelled", 1);
} }
void ReadMem(int addr) { void ReadMem(int addr)
{
const uint8_t *data = ((uint8_t *)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]); 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; extern struct version_information version_information;
/* bootrom version information is pointed to from _bootphase1_version_pointer */ /* bootrom version information is pointed to from _bootphase1_version_pointer */
extern char *_bootphase1_version_pointer, _flash_start, _flash_end, _bootrom_start, _bootrom_end, __data_src_start__; 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 temp[USB_CMD_DATA_SIZE]; /* Limited data payload in USB packets */
char VersionString[USB_CMD_DATA_SIZE] = { '\0' }; char VersionString[USB_CMD_DATA_SIZE] = { '\0' };
@ -331,11 +347,11 @@ void SendVersion(void) {
* symbol _bootphase1_version_pointer, perform slight sanity checks on the * symbol _bootphase1_version_pointer, perform slight sanity checks on the
* pointer, then use it. * 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); 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"); strcat(VersionString, "bootrom version information appears invalid\n");
} else { } else {
FormatVersionInformation(temp, sizeof(temp), " bootrom: ", bootrom_version); 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. // 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. // 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("USB Speed");
Dbprintf(" Sending USB packets to client..."); 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(); uint8_t *test_data = BigBuf_get_addr();
uint32_t end_time; uint32_t end_time;
@ -388,7 +405,8 @@ void printUSBSpeed(void) {
/** /**
* Prints runtime information about the PM3. * Prints runtime information about the PM3.
**/ **/
void SendStatus(void) { void SendStatus(void)
{
BigBuf_print_status(); BigBuf_print_status();
Fpga_print_status(); Fpga_print_status();
#ifdef WITH_FLASH #ifdef WITH_FLASH
@ -412,7 +430,8 @@ void SendStatus(void) {
} }
// Show some leds in a pattern to identify StandAlone mod is running // 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."); DbpString("Stand-alone mode! No PC necessary.");
@ -425,7 +444,8 @@ void StandAloneMode(void) {
} }
// detection of which Standalone Modes is installed // detection of which Standalone Modes is installed
// (iceman) // (iceman)
void printStandAloneModes(void) { void printStandAloneModes(void)
{
DbpString("Installed StandAlone Mode"); DbpString("Installed StandAlone Mode");
@ -492,18 +512,19 @@ at the same place! :-)
LIGHT SCHEME USED: LIGHT SCHEME USED:
*/ */
static const char LIGHT_SCHEME[] = { static const char LIGHT_SCHEME[] = {
0x0, /* ---- | No field detected */ 0x0, /* ---- | No field detected */
0x1, /* X--- | 14% of maximum current detected */ 0x1, /* X--- | 14% of maximum current detected */
0x2, /* -X-- | 29% of maximum current detected */ 0x2, /* -X-- | 29% of maximum current detected */
0x4, /* --X- | 43% of maximum current detected */ 0x4, /* --X- | 43% of maximum current detected */
0x8, /* ---X | 57% of maximum current detected */ 0x8, /* ---X | 57% of maximum current detected */
0xC, /* --XX | 71% of maximum current detected */ 0xC, /* --XX | 71% of maximum current detected */
0xE, /* -XXX | 86% of maximum current detected */ 0xE, /* -XXX | 86% of maximum current detected */
0xF, /* XXXX | 100% 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 LF_ONLY 1
#define HF_ONLY 2 #define HF_ONLY 2
#define REPORT_CHANGE 10 // report new values only if they have changed at least by REPORT_CHANGE #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. // 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. // 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 ); bool use_high = (((MAX_ADC_HF_VOLTAGE * hf_max) >> 10) > MAX_ADC_HF_VOLTAGE - 300);
if ( use_high ) { if (use_high) {
hf_av = hf_max = AvgAdc(ADC_CHAN_HF_RDV40); hf_av = hf_max = AvgAdc(ADC_CHAN_HF_RDV40);
} }
@ -540,7 +561,7 @@ void ListenReaderField(int limit) {
hf_baseline = hf_av; hf_baseline = hf_av;
} }
for(;;) { for (;;) {
// Switch modes with button // Switch modes with button
if (BUTTON_PRESS()) { if (BUTTON_PRESS()) {
SpinDelay(500); SpinDelay(500);
@ -560,7 +581,7 @@ void ListenReaderField(int limit) {
WDT_HIT(); WDT_HIT();
if (limit != HF_ONLY) { if (limit != HF_ONLY) {
if(mode == 1) { if (mode == 1) {
if (ABS(lf_av - lf_baseline) > REPORT_CHANGE) if (ABS(lf_av - lf_baseline) > REPORT_CHANGE)
LED_D_ON(); LED_D_ON();
else else
@ -578,7 +599,7 @@ void ListenReaderField(int limit) {
} }
if (limit != LF_ONLY) { if (limit != LF_ONLY) {
if (mode == 1){ if (mode == 1) {
if (ABS(hf_av - hf_baseline) > REPORT_CHANGE) if (ABS(hf_av - hf_baseline) > REPORT_CHANGE)
LED_B_ON(); LED_B_ON();
else else
@ -588,7 +609,7 @@ void ListenReaderField(int limit) {
hf_av_new = (use_high) ? AvgAdc(ADC_CHAN_HF_RDV40) : AvgAdc(ADC_CHAN_HF); hf_av_new = (use_high) ? AvgAdc(ADC_CHAN_HF_RDV40) : AvgAdc(ADC_CHAN_HF);
// see if there's a significant change // 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); Dbprintf("HF 13.56MHz Field Change: %5dmV", (MAX_ADC_HF_VOLTAGE * hf_av_new) >> 10);
hf_av = hf_av_new; hf_av = hf_av_new;
if (hf_av > hf_max) if (hf_av > hf_max)
@ -604,7 +625,7 @@ void ListenReaderField(int limit) {
display_val = hf_av; display_val = hf_av;
display_max = hf_max; display_max = hf_max;
} else { /* Pick one at random */ } 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_val = hf_av;
display_max = hf_max; display_max = hf_max;
} else { } else {
@ -612,12 +633,16 @@ void ListenReaderField(int limit) {
display_max = lf_max; display_max = lf_max;
} }
} }
for (i=0; i<LIGHT_LEN; i++) { for (i = 0; i < LIGHT_LEN; i++) {
if (display_val >= ((display_max/LIGHT_LEN)*i) && display_val <= ((display_max/LIGHT_LEN)*(i+1))) { 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] & 0x1) LED_C_ON();
if (LIGHT_SCHEME[i] & 0x2) LED_A_ON(); else LED_A_OFF(); else LED_C_OFF();
if (LIGHT_SCHEME[i] & 0x4) LED_B_ON(); else LED_B_OFF(); if (LIGHT_SCHEME[i] & 0x2) LED_A_ON();
if (LIGHT_SCHEME[i] & 0x8) LED_D_ON(); else LED_D_OFF(); 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; 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; 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]); //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 #ifdef WITH_LF
case CMD_SET_LF_T55XX_CONFIG: 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; break;
case CMD_SET_LF_SAMPLING_CONFIG: case CMD_SET_LF_SAMPLING_CONFIG:
setSamplingConfig((sample_config *) c->d.asBytes); setSamplingConfig((sample_config *) c->d.asBytes);
@ -692,7 +718,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
ReadTItag(); ReadTItag();
break; break;
case CMD_WRITE_TI_TYPE: 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; break;
case CMD_SIMULATE_TAG_125K: case CMD_SIMULATE_TAG_125K:
LED_A_ON(); LED_A_ON();
@ -709,7 +735,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
CopyIndala224toT55x7( CopyIndala224toT55x7(
c->d.asDwords[0], c->d.asDwords[1], c->d.asDwords[2], c->d.asDwords[3], c->d.asDwords[0], c->d.asDwords[1], c->d.asDwords[2], c->d.asDwords[3],
c->d.asDwords[4], c->d.asDwords[5], c->d.asDwords[6] c->d.asDwords[4], c->d.asDwords[5], c->d.asDwords[6]
); );
break; break;
case CMD_T55XX_READ_BLOCK: { case CMD_T55XX_READ_BLOCK: {
T55xxReadBlock(c->arg[0], c->arg[1], c->arg[2]); T55xxReadBlock(c->arg[0], c->arg[1], c->arg[2]);
@ -738,7 +764,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
c->arg[0], c->arg[0],
c->arg[1], c->arg[1],
c->arg[2] c->arg[2]
); );
break; break;
case CMD_EM4X_READ_WORD: case CMD_EM4X_READ_WORD:
EM4xReadWord(c->arg[0], c->arg[1], c->arg[2]); EM4xReadWord(c->arg[0], c->arg[1], c->arg[2]);
@ -765,25 +791,25 @@ void UsbPacketReceived(uint8_t *packet, int len) {
SnoopHitag(c->arg[0]); SnoopHitag(c->arg[0]);
break; break;
case CMD_SIMULATE_HITAG: // Simulate Hitag tag, args = memory content 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; break;
case CMD_READER_HITAG: // Reader for Hitag tags, args = type and function 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; break;
case CMD_SIMULATE_HITAG_S:// Simulate Hitag s tag, args = memory content 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; break;
case CMD_TEST_HITAGS_TRACES:// Tests every challenge within the given file 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; break;
case CMD_READ_HITAG_S: //Reader for only Hitag S tags, args = key or challenge 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; break;
case CMD_WR_HITAG_S: //writer for Hitag tags args=data to write,page and key or challenge 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) { 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) { } 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; break;
#endif #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); MifareReadBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
break; break;
case CMD_MIFAREU_READBL: case CMD_MIFAREU_READBL:
MifareUReadBlock(c->arg[0],c->arg[1], c->d.asBytes); MifareUReadBlock(c->arg[0], c->arg[1], c->d.asBytes);
break; break;
case CMD_MIFAREUC_AUTH: case CMD_MIFAREUC_AUTH:
MifareUC_Auth(c->arg[0],c->d.asBytes); MifareUC_Auth(c->arg[0], c->d.asBytes);
break; break;
case CMD_MIFAREU_READCARD: case CMD_MIFAREU_READCARD:
MifareUReadCard(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); MifareUReadCard(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
@ -910,8 +936,8 @@ void UsbPacketReceived(uint8_t *packet, int len) {
MifareWriteBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); MifareWriteBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
break; break;
//case CMD_MIFAREU_WRITEBL_COMPAT: //case CMD_MIFAREU_WRITEBL_COMPAT:
//MifareUWriteBlockCompat(c->arg[0], c->d.asBytes); //MifareUWriteBlockCompat(c->arg[0], c->d.asBytes);
//break; //break;
case CMD_MIFAREU_WRITEBL: case CMD_MIFAREU_WRITEBL:
MifareUWriteBlock(c->arg[0], c->arg[1], c->d.asBytes); MifareUWriteBlock(c->arg[0], c->arg[1], c->d.asBytes);
break; break;
@ -1050,11 +1076,11 @@ void UsbPacketReceived(uint8_t *packet, int len) {
SmartCardAtr(); SmartCardAtr();
break; break;
} }
case CMD_SMART_SETBAUD:{ case CMD_SMART_SETBAUD: {
SmartCardSetBaud(c->arg[0]); SmartCardSetBaud(c->arg[0]);
break; break;
} }
case CMD_SMART_SETCLOCK:{ case CMD_SMART_SETCLOCK: {
SmartCardSetClock(c->arg[0]); SmartCardSetClock(c->arg[0]);
break; break;
} }
@ -1065,8 +1091,8 @@ void UsbPacketReceived(uint8_t *packet, int len) {
case CMD_SMART_UPLOAD: { case CMD_SMART_UPLOAD: {
// upload file from client // upload file from client
uint8_t *mem = BigBuf_get_addr(); uint8_t *mem = BigBuf_get_addr();
memcpy( mem + c->arg[0], c->d.asBytes, USB_CMD_DATA_SIZE); memcpy(mem + c->arg[0], c->d.asBytes, USB_CMD_DATA_SIZE);
cmd_send(CMD_ACK,1,0,0,0,0); cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
break; break;
} }
case CMD_SMART_UPGRADE: { case CMD_SMART_UPGRADE: {
@ -1101,14 +1127,14 @@ void UsbPacketReceived(uint8_t *packet, int len) {
char dest[USB_CMD_DATA_SIZE] = { '\0' }; 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); strncat(dest, welcome, sizeof(dest) - strlen(dest) - 1);
sprintf(dest + strlen(dest) - 1, "| bytes 0x%02x 0x%02x 0x%02x 0x%02x \n" sprintf(dest + strlen(dest) - 1, "| bytes 0x%02x 0x%02x 0x%02x 0x%02x \n"
, c->d.asBytes[0] , c->d.asBytes[0]
, c->d.asBytes[1] , c->d.asBytes[1]
, c->d.asBytes[2] , c->d.asBytes[2]
, c->d.asBytes[3] , c->d.asBytes[3]
); );
UsbCommand txcmd = { CMD_DEBUG_PRINT_STRING, { strlen(dest), 0, 0 } }; UsbCommand txcmd = { CMD_DEBUG_PRINT_STRING, { strlen(dest), 0, 0 } };
memcpy(txcmd.d.asBytes, dest, sizeof(dest)); memcpy(txcmd.d.asBytes, dest, sizeof(dest));
@ -1116,7 +1142,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
LED_A_ON(); LED_A_ON();
usart_init(); usart_init();
usart_writebuffer((uint8_t*)&txcmd, sizeof(UsbCommand)); usart_writebuffer((uint8_t *)&txcmd, sizeof(UsbCommand));
//usb //usb
cmd_send(CMD_DEBUG_PRINT_STRING, strlen(dest), 0, 0, dest, strlen(dest)); 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_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(); StopTicks();
break; break;
} }
@ -1180,11 +1206,11 @@ void UsbPacketReceived(uint8_t *packet, int len) {
// arg2 = BigBuf tracelen // arg2 = BigBuf tracelen
//Dbprintf("transfer to client parameters: %" PRIu32 " | %" PRIu32 " | %" PRIu32, startidx, numofbytes, c->arg[2]); //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) { for (size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) {
len = MIN( (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); isok = cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K, i, len, BigBuf_get_traceLen(), mem + startidx + i, len);
if (isok != 0) 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 // Trigger a finish downloading signal with an ACK frame
// iceman, when did sending samplingconfig array got attached here?!? // 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 // to be able to use this one for uploading data to device
// arg1 = 0 upload for LF usage // arg1 = 0 upload for LF usage
// 1 upload for HF usage // 1 upload for HF usage
#define FPGA_LF 1 #define FPGA_LF 1
if ( c->arg[1] == FPGA_LF ) if (c->arg[1] == FPGA_LF)
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
else else
FpgaDownloadAndGo(FPGA_BITSTREAM_HF); FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
uint8_t *mem = BigBuf_get_addr(); uint8_t *mem = BigBuf_get_addr();
memcpy( mem + c->arg[0], c->d.asBytes, USB_CMD_DATA_SIZE); memcpy(mem + c->arg[0], c->d.asBytes, USB_CMD_DATA_SIZE);
cmd_send(CMD_ACK,1,0,0,0,0); cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
break; break;
} }
case CMD_DOWNLOAD_EML_BIGBUF: { case CMD_DOWNLOAD_EML_BIGBUF: {
@ -1229,7 +1255,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); len = MIN((numofbytes - i), USB_CMD_DATA_SIZE);
isok = cmd_send(CMD_DOWNLOADED_EML_BIGBUF, i, len, 0, mem + startidx + i, len); isok = cmd_send(CMD_DOWNLOADED_EML_BIGBUF, i, len, 0, mem + startidx + i, len);
if (isok != 0) 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 // Trigger a finish downloading signal with an ACK frame
cmd_send(CMD_ACK, 1, 0, 0, 0, 0); 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); 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); len = MIN((len - i), size);
Dbprintf("FlashMem reading | %d | %d | %d |", startidx + i, i, len); Dbprintf("FlashMem reading | %d | %d | %d |", startidx + i, i, len);
isok = Flash_ReadDataCont(startidx + i, mem, len); isok = Flash_ReadDataCont(startidx + i, mem, len);
if ( isok == len ) { if (isok == len) {
print_result("Chunk: ", mem, len); print_result("Chunk: ", mem, len);
} else { } else {
Dbprintf("FlashMem reading failed | %d | %d", len, isok); Dbprintf("FlashMem reading failed | %d | %d", len, isok);
@ -1282,7 +1308,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
uint16_t res = 0; uint16_t res = 0;
uint32_t startidx = c->arg[0]; uint32_t startidx = c->arg[0];
uint16_t len = c->arg[1]; uint16_t len = c->arg[1];
uint8_t* data = c->d.asBytes; uint8_t *data = c->d.asBytes;
uint32_t tmp = startidx + len; uint32_t tmp = startidx + len;
@ -1293,9 +1319,9 @@ void UsbPacketReceived(uint8_t *packet, int len) {
Flash_CheckBusy(BUSY_TIMEOUT); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable(); Flash_WriteEnable();
if ( startidx == DEFAULT_T55XX_KEYS_OFFSET ) if (startidx == DEFAULT_T55XX_KEYS_OFFSET)
Flash_Erase4k(3, 0xC); Flash_Erase4k(3, 0xC);
else if (startidx == DEFAULT_MF_KEYS_OFFSET ) else if (startidx == DEFAULT_MF_KEYS_OFFSET)
Flash_Erase4k(3, 0xB); Flash_Erase4k(3, 0xB);
else if (startidx == DEFAULT_ICLASS_KEYS_OFFSET) else if (startidx == DEFAULT_ICLASS_KEYS_OFFSET)
Flash_Erase4k(3, 0xA); Flash_Erase4k(3, 0xA);
@ -1304,29 +1330,29 @@ void UsbPacketReceived(uint8_t *packet, int len) {
Flash_WriteEnable(); Flash_WriteEnable();
// inside 256b page? // inside 256b page?
if ( (tmp & 0xFF) != 0) { if ((tmp & 0xFF) != 0) {
// is offset+len larger than a page // is offset+len larger than a page
tmp = (startidx & 0xFF ) + len; tmp = (startidx & 0xFF) + len;
if (tmp > 0xFF ) { if (tmp > 0xFF) {
// data spread over two pages. // data spread over two pages.
// offset xxxx10, // offset xxxx10,
uint8_t first_len = (~startidx & 0xFF)+1; uint8_t first_len = (~startidx & 0xFF) + 1;
// first mem page // first mem page
res = Flash_WriteDataCont(startidx, data, first_len); res = Flash_WriteDataCont(startidx, data, first_len);
// second mem page // second mem page
res = Flash_WriteDataCont(startidx + first_len, data + first_len, len - first_len); res = Flash_WriteDataCont(startidx + first_len, data + first_len, len - first_len);
isok = (res == (len - first_len)) ? 1 : 0; isok = (res == (len - first_len)) ? 1 : 0;
} else { } else {
res = Flash_WriteDataCont(startidx, data, len); res = Flash_WriteDataCont(startidx, data, len);
isok = (res == len) ? 1 : 0; isok = (res == len) ? 1 : 0;
} }
} else { } else {
res = Flash_WriteDataCont(startidx, data, len); res = Flash_WriteDataCont(startidx, data, len);
isok = (res == len) ? 1 : 0; isok = (res == len) ? 1 : 0;
@ -1342,13 +1368,13 @@ void UsbPacketReceived(uint8_t *packet, int len) {
uint8_t page = c->arg[0]; uint8_t page = c->arg[0];
uint8_t initalwipe = c->arg[1]; uint8_t initalwipe = c->arg[1];
bool isok = false; bool isok = false;
if ( initalwipe ) { if (initalwipe) {
isok = Flash_WipeMemory(); isok = Flash_WipeMemory();
cmd_send(CMD_ACK, isok, 0, 0, 0, 0); cmd_send(CMD_ACK, isok, 0, 0, 0, 0);
LED_B_OFF(); LED_B_OFF();
break; break;
} }
if ( page < 3) if (page < 3)
isok = Flash_WipeMemoryPage(page); isok = Flash_WipeMemoryPage(page);
cmd_send(CMD_ACK, isok, 0, 0, 0, 0); cmd_send(CMD_ACK, isok, 0, 0, 0, 0);
@ -1375,14 +1401,14 @@ void UsbPacketReceived(uint8_t *packet, int len) {
len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); len = MIN((numofbytes - i), USB_CMD_DATA_SIZE);
isok = Flash_ReadDataCont(startidx + i, mem, len); isok = Flash_ReadDataCont(startidx + i, mem, len);
if (!isok ) if (!isok)
Dbprintf("reading flash memory failed :: | bytes between %d - %d", i, len); Dbprintf("reading flash memory failed :: | bytes between %d - %d", i, len);
isok = cmd_send(CMD_FLASHMEM_DOWNLOADED, i, len, 0, mem, len); isok = cmd_send(CMD_FLASHMEM_DOWNLOADED, i, len, 0, mem, len);
if (isok != 0) if (isok != 0)
Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len); Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len);
} }
FlashStop(); FlashStop();
cmd_send(CMD_ACK, 1, 0, 0, 0, 0); cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
LED_B_OFF(); LED_B_OFF();
@ -1391,12 +1417,12 @@ void UsbPacketReceived(uint8_t *packet, int len) {
case CMD_FLASHMEM_INFO: { case CMD_FLASHMEM_INFO: {
LED_B_ON(); 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); bool isok = Flash_ReadData(FLASH_MEM_SIGNATURE_OFFSET, info->signature, FLASH_MEM_SIGNATURE_LEN);
if (FlashInit()) { if (FlashInit()) {
Flash_UniqueID( info->flashid); Flash_UniqueID(info->flashid);
FlashStop(); FlashStop();
} }
cmd_send(CMD_ACK, isok, 0, 0, info, sizeof(rdv40_validation_t)); cmd_send(CMD_ACK, isok, 0, 0, info, sizeof(rdv40_validation_t));
@ -1412,14 +1438,22 @@ void UsbPacketReceived(uint8_t *packet, int len) {
break; break;
case CMD_SET_ADC_MUX: case CMD_SET_ADC_MUX:
switch(c->arg[0]) { switch (c->arg[0]) {
case 0: SetAdcMuxFor(GPIO_MUXSEL_LOPKD); break; case 0:
case 2: SetAdcMuxFor(GPIO_MUXSEL_HIPKD); break; SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
break;
case 2:
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
break;
#ifndef WITH_FPC #ifndef WITH_FPC
case 1: SetAdcMuxFor(GPIO_MUXSEL_LORAW); break; case 1:
case 3: SetAdcMuxFor(GPIO_MUXSEL_HIRAW); break; SetAdcMuxFor(GPIO_MUXSEL_LORAW);
break;
case 3:
SetAdcMuxFor(GPIO_MUXSEL_HIRAW);
break;
#endif #endif
} }
break; break;
case CMD_VERSION: case CMD_VERSION:
@ -1429,7 +1463,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
SendStatus(); SendStatus();
break; break;
case CMD_PING: case CMD_PING:
cmd_send(CMD_ACK,0,0,0,0,0); cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
break; break;
#ifdef WITH_LCD #ifdef WITH_LCD
case CMD_LCD_RESET: case CMD_LCD_RESET:
@ -1448,17 +1482,17 @@ void UsbPacketReceived(uint8_t *packet, int len) {
SpinDelay(1000); SpinDelay(1000);
AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST; AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
// We're going to reset, and the bootrom will take control. // We're going to reset, and the bootrom will take control.
for(;;) {} for (;;) {}
break; break;
case CMD_START_FLASH: 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; common_area.command = COMMON_AREA_COMMAND_ENTER_FLASH_MODE;
} }
usb_disable(); usb_disable();
AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST; AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
// We're going to flash, and the bootrom will take control. // We're going to flash, and the bootrom will take control.
for(;;) {} for (;;) {}
break; break;
case CMD_DEVICE_INFO: { case CMD_DEVICE_INFO: {
@ -1466,21 +1500,22 @@ void UsbPacketReceived(uint8_t *packet, int len) {
if (common_area.flags.bootrom_present) { if (common_area.flags.bootrom_present) {
dev_info |= DEVICE_INFO_FLAG_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; break;
} }
default: default:
Dbprintf("%s: 0x%04x","unknown command:", c->cmd); Dbprintf("%s: 0x%04x", "unknown command:", c->cmd);
break; break;
} }
} }
void __attribute__((noreturn)) AppMain(void) { void __attribute__((noreturn)) AppMain(void)
{
SpinDelay(100); SpinDelay(100);
clear_trace(); 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 */ /* Initialize common area */
memset(&common_area, 0, sizeof(common_area)); memset(&common_area, 0, sizeof(common_area));
common_area.magic = COMMON_AREA_MAGIC; common_area.magic = COMMON_AREA_MAGIC;
@ -1537,12 +1572,12 @@ void __attribute__((noreturn)) AppMain(void) {
uint8_t rx[sizeof(UsbCommand)]; uint8_t rx[sizeof(UsbCommand)];
for(;;) { for (;;) {
WDT_HIT(); WDT_HIT();
// Check if there is a usb packet available // Check if there is a usb packet available
if (usb_poll_validate_length()) { if (usb_poll_validate_length()) {
if (usb_read(rx, sizeof(rx)) ) if (usb_read(rx, sizeof(rx)))
UsbPacketReceived(rx, sizeof(rx)); UsbPacketReceived(rx, sizeof(rx));
} }
#ifdef WITH_FPC #ifdef WITH_FPC
@ -1558,11 +1593,11 @@ void __attribute__((noreturn)) AppMain(void) {
// Press button for one second to enter a possible standalone mode // Press button for one second to enter a possible standalone mode
if (BUTTON_HELD(1000) > 0) { if (BUTTON_HELD(1000) > 0) {
/* /*
* So this is the trigger to execute a standalone mod. Generic entrypoint by following the standalone/standalone.h headerfile * 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. * All standalone mod "main loop" should be the RunMod() function.
* Since the standalone is either LF or HF, the somewhat bisarr defines below exists. * 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) ) #if defined (WITH_LF) && ( defined (WITH_LF_SAMYRUN) || defined (WITH_LF_HIDBRUTE) || defined (WITH_LF_PROXBRUTE) )
RunMod(); RunMod();
#endif #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 EM4xWriteWord(uint32_t flag, uint32_t data, uint32_t pwd);
void Cotag(uint32_t arg0); void Cotag(uint32_t arg0);
void setT55xxConfig(uint8_t arg0, t55xx_config *c); void setT55xxConfig(uint8_t arg0, t55xx_config *c);
t55xx_config * getT55xxConfig(void); t55xx_config *getT55xxConfig(void);
void printT55xxConfig(void); void printT55xxConfig(void);
void loadT55xxConfig(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 GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *parity);
void iso14a_set_trigger(bool enable); void iso14a_set_trigger(bool enable);
// also used in emv // 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); int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len);
// epa.h // epa.h
void EPA_PACE_Collect_Nonce(UsbCommand * c); void EPA_PACE_Collect_Nonce(UsbCommand *c);
void EPA_PACE_Replay(UsbCommand *c); void EPA_PACE_Replay(UsbCommand *c);
// mifarecmd.h // mifarecmd.h
@ -169,35 +169,35 @@ void OnSuccessMagic();
void OnErrorMagic(uint8_t reason); void OnErrorMagic(uint8_t reason);
int32_t dist_nt(uint32_t nt1, uint32_t nt2); 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); //void RAMFUNC SniffMifare(uint8_t param);
//desfire //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); void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
// mifaredesfire.h // mifaredesfire.h
bool InitDesfireCard(); 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 MifareDesfireGetInformation();
void MifareDES_Auth1(uint8_t arg0,uint8_t arg1,uint8_t arg2, 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); void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t *datain);
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 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 OnSuccess();
void OnError(uint8_t reason); void OnError(uint8_t reason);
// desfire_crypto.h // 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_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_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_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); 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 key_block_size(const desfirekey_t key);
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);
size_t maced_data_length (const desfirekey_t key, const size_t nbytes); 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); 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_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 cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac);
// iso15693.h // iso15693.h
void RecordRawAdcSamplesIso15693(void); void RecordRawAdcSamplesIso15693(void);
@ -205,14 +205,14 @@ void AcquireRawAdcSamplesIso15693(void);
void ReaderIso15693(uint32_t parameter); // Simulate an ISO15693 reader - greg void ReaderIso15693(uint32_t parameter); // Simulate an ISO15693 reader - greg
void SimTagIso15693(uint32_t parameter, uint8_t *uid); // simulate an ISO15693 tag - 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 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); void Iso15693InitReader(void);
// iclass.h // iclass.h
void RAMFUNC SniffIClass(void); void RAMFUNC SniffIClass(void);
void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void ReaderIClass(uint8_t arg0); 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(uint8_t *MAC);
void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain); void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain);
void iClass_WriteBlock(uint8_t blockNo, uint8_t *data); void iClass_WriteBlock(uint8_t blockNo, uint8_t *data);
@ -224,22 +224,22 @@ void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType);
// hitag2.h // hitag2.h
void SnoopHitag(uint32_t type); void SnoopHitag(uint32_t type);
void SimulateHitagTag(bool tag_mem_supplied, byte_t* data); void SimulateHitagTag(bool tag_mem_supplied, byte_t *data);
void ReaderHitag(hitag_function htf, hitag_data* htd); void ReaderHitag(hitag_function htf, hitag_data *htd);
void WriterHitag(hitag_function htf, hitag_data* htd, int page); void WriterHitag(hitag_function htf, hitag_data *htd, int page);
//hitagS.h //hitagS.h
void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data); void SimulateHitagSTag(bool tag_mem_supplied, byte_t *data);
void ReadHitagS(hitag_function htf, hitag_data* htd); void ReadHitagS(hitag_function htf, hitag_data *htd);
void WritePageHitagS(hitag_function htf, hitag_data* htd,int page); void WritePageHitagS(hitag_function htf, hitag_data *htd, int page);
void check_challenges(bool file_given, byte_t* data); void check_challenges(bool file_given, byte_t *data);
// cmd.h // cmd.h
uint8_t cmd_receive(UsbCommand* cmd); 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_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len);
// util.h // util.h
void HfSnoop(int , int); void HfSnoop(int, int);
//felica.c //felica.c
extern void felica_sendraw(UsbCommand *c); extern void felica_sendraw(UsbCommand *c);

View file

@ -1,41 +1,46 @@
#include "buzzer.h" #include "buzzer.h"
void Ring_BEE_ONCE(uint16_t music_note) { void Ring_BEE_ONCE(uint16_t music_note)
{
BEE_ON(); BEE_ON();
SpinDelayUs(music_note); SpinDelayUs(music_note);
BEE_OFF(); BEE_OFF();
SpinDelayUs(music_note); SpinDelayUs(music_note);
} }
void ring_2_7khz(uint16_t count) { void ring_2_7khz(uint16_t count)
Ring_BEE_TIME(n_2_7khz,count); {
Ring_BEE_TIME(n_2_7khz, count);
} }
void Ring_BEE_TIME(uint16_t music_note,uint16_t count) { void Ring_BEE_TIME(uint16_t music_note, uint16_t count)
for(uint16_t i=0 ; i < count; i++) {
for (uint16_t i = 0 ; i < count; i++)
Ring_BEE_ONCE(music_note); Ring_BEE_ONCE(music_note);
SpinDelay(9); 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_1, count);
Ring_BEE_TIME(note_3, count); Ring_BEE_TIME(note_2, count);
Ring_BEE_TIME(note_4, count); Ring_BEE_TIME(note_3, count);
Ring_BEE_TIME(note_5, count); Ring_BEE_TIME(note_4, count);
Ring_BEE_TIME(note_6, count); Ring_BEE_TIME(note_5, count);
Ring_BEE_TIME(note_7, count); Ring_BEE_TIME(note_6, count);
SpinDelay(10); Ring_BEE_TIME(note_7, count);
SpinDelay(10);
} }
void Ring_Little_Star(uint16_t count) { void Ring_Little_Star(uint16_t count)
Ring_BEE_TIME(note_1,count); {
Ring_BEE_TIME(note_1,count); Ring_BEE_TIME(note_1, count);
Ring_BEE_TIME(note_5,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_5, count);
Ring_BEE_TIME(note_6,count); Ring_BEE_TIME(note_6, count);
Ring_BEE_TIME(note_5,2*count); Ring_BEE_TIME(note_6, count);
Ring_BEE_TIME(note_5, 2 * count);
LED_A_ON(); LED_A_ON();
/* /*
Ring_BEE_TIME(note_4,count); Ring_BEE_TIME(note_4,count);

View file

@ -21,7 +21,7 @@
#define note_8 0 #define note_8 0
extern void Ring_BEE_ONCE(uint16_t music_note); 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_2_7khz(uint16_t count);
extern void Ring_ALL(uint16_t count); extern void Ring_ALL(uint16_t count);
extern void Ring_Little_Star(uint16_t count); extern void Ring_Little_Star(uint16_t count);

View file

@ -29,53 +29,53 @@
#include "des.h" #include "des.h"
const uint8_t sbox[256] = { const uint8_t sbox[256] = {
/* S-box 1 */ /* S-box 1 */
0xE4, 0xD1, 0x2F, 0xB8, 0x3A, 0x6C, 0x59, 0x07, 0xE4, 0xD1, 0x2F, 0xB8, 0x3A, 0x6C, 0x59, 0x07,
0x0F, 0x74, 0xE2, 0xD1, 0xA6, 0xCB, 0x95, 0x38, 0x0F, 0x74, 0xE2, 0xD1, 0xA6, 0xCB, 0x95, 0x38,
0x41, 0xE8, 0xD6, 0x2B, 0xFC, 0x97, 0x3A, 0x50, 0x41, 0xE8, 0xD6, 0x2B, 0xFC, 0x97, 0x3A, 0x50,
0xFC, 0x82, 0x49, 0x17, 0x5B, 0x3E, 0xA0, 0x6D, 0xFC, 0x82, 0x49, 0x17, 0x5B, 0x3E, 0xA0, 0x6D,
/* S-box 2 */ /* S-box 2 */
0xF1, 0x8E, 0x6B, 0x34, 0x97, 0x2D, 0xC0, 0x5A, 0xF1, 0x8E, 0x6B, 0x34, 0x97, 0x2D, 0xC0, 0x5A,
0x3D, 0x47, 0xF2, 0x8E, 0xC0, 0x1A, 0x69, 0xB5, 0x3D, 0x47, 0xF2, 0x8E, 0xC0, 0x1A, 0x69, 0xB5,
0x0E, 0x7B, 0xA4, 0xD1, 0x58, 0xC6, 0x93, 0x2F, 0x0E, 0x7B, 0xA4, 0xD1, 0x58, 0xC6, 0x93, 0x2F,
0xD8, 0xA1, 0x3F, 0x42, 0xB6, 0x7C, 0x05, 0xE9, 0xD8, 0xA1, 0x3F, 0x42, 0xB6, 0x7C, 0x05, 0xE9,
/* S-box 3 */ /* S-box 3 */
0xA0, 0x9E, 0x63, 0xF5, 0x1D, 0xC7, 0xB4, 0x28, 0xA0, 0x9E, 0x63, 0xF5, 0x1D, 0xC7, 0xB4, 0x28,
0xD7, 0x09, 0x34, 0x6A, 0x28, 0x5E, 0xCB, 0xF1, 0xD7, 0x09, 0x34, 0x6A, 0x28, 0x5E, 0xCB, 0xF1,
0xD6, 0x49, 0x8F, 0x30, 0xB1, 0x2C, 0x5A, 0xE7, 0xD6, 0x49, 0x8F, 0x30, 0xB1, 0x2C, 0x5A, 0xE7,
0x1A, 0xD0, 0x69, 0x87, 0x4F, 0xE3, 0xB5, 0x2C, 0x1A, 0xD0, 0x69, 0x87, 0x4F, 0xE3, 0xB5, 0x2C,
/* S-box 4 */ /* S-box 4 */
0x7D, 0xE3, 0x06, 0x9A, 0x12, 0x85, 0xBC, 0x4F, 0x7D, 0xE3, 0x06, 0x9A, 0x12, 0x85, 0xBC, 0x4F,
0xD8, 0xB5, 0x6F, 0x03, 0x47, 0x2C, 0x1A, 0xE9, 0xD8, 0xB5, 0x6F, 0x03, 0x47, 0x2C, 0x1A, 0xE9,
0xA6, 0x90, 0xCB, 0x7D, 0xF1, 0x3E, 0x52, 0x84, 0xA6, 0x90, 0xCB, 0x7D, 0xF1, 0x3E, 0x52, 0x84,
0x3F, 0x06, 0xA1, 0xD8, 0x94, 0x5B, 0xC7, 0x2E, 0x3F, 0x06, 0xA1, 0xD8, 0x94, 0x5B, 0xC7, 0x2E,
/* S-box 5 */ /* S-box 5 */
0x2C, 0x41, 0x7A, 0xB6, 0x85, 0x3F, 0xD0, 0xE9, 0x2C, 0x41, 0x7A, 0xB6, 0x85, 0x3F, 0xD0, 0xE9,
0xEB, 0x2C, 0x47, 0xD1, 0x50, 0xFA, 0x39, 0x86, 0xEB, 0x2C, 0x47, 0xD1, 0x50, 0xFA, 0x39, 0x86,
0x42, 0x1B, 0xAD, 0x78, 0xF9, 0xC5, 0x63, 0x0E, 0x42, 0x1B, 0xAD, 0x78, 0xF9, 0xC5, 0x63, 0x0E,
0xB8, 0xC7, 0x1E, 0x2D, 0x6F, 0x09, 0xA4, 0x53, 0xB8, 0xC7, 0x1E, 0x2D, 0x6F, 0x09, 0xA4, 0x53,
/* S-box 6 */ /* S-box 6 */
0xC1, 0xAF, 0x92, 0x68, 0x0D, 0x34, 0xE7, 0x5B, 0xC1, 0xAF, 0x92, 0x68, 0x0D, 0x34, 0xE7, 0x5B,
0xAF, 0x42, 0x7C, 0x95, 0x61, 0xDE, 0x0B, 0x38, 0xAF, 0x42, 0x7C, 0x95, 0x61, 0xDE, 0x0B, 0x38,
0x9E, 0xF5, 0x28, 0xC3, 0x70, 0x4A, 0x1D, 0xB6, 0x9E, 0xF5, 0x28, 0xC3, 0x70, 0x4A, 0x1D, 0xB6,
0x43, 0x2C, 0x95, 0xFA, 0xBE, 0x17, 0x60, 0x8D, 0x43, 0x2C, 0x95, 0xFA, 0xBE, 0x17, 0x60, 0x8D,
/* S-box 7 */ /* S-box 7 */
0x4B, 0x2E, 0xF0, 0x8D, 0x3C, 0x97, 0x5A, 0x61, 0x4B, 0x2E, 0xF0, 0x8D, 0x3C, 0x97, 0x5A, 0x61,
0xD0, 0xB7, 0x49, 0x1A, 0xE3, 0x5C, 0x2F, 0x86, 0xD0, 0xB7, 0x49, 0x1A, 0xE3, 0x5C, 0x2F, 0x86,
0x14, 0xBD, 0xC3, 0x7E, 0xAF, 0x68, 0x05, 0x92, 0x14, 0xBD, 0xC3, 0x7E, 0xAF, 0x68, 0x05, 0x92,
0x6B, 0xD8, 0x14, 0xA7, 0x95, 0x0F, 0xE2, 0x3C, 0x6B, 0xD8, 0x14, 0xA7, 0x95, 0x0F, 0xE2, 0x3C,
/* S-box 8 */ /* S-box 8 */
0xD2, 0x84, 0x6F, 0xB1, 0xA9, 0x3E, 0x50, 0xC7, 0xD2, 0x84, 0x6F, 0xB1, 0xA9, 0x3E, 0x50, 0xC7,
0x1F, 0xD8, 0xA3, 0x74, 0xC5, 0x6B, 0x0E, 0x92, 0x1F, 0xD8, 0xA3, 0x74, 0xC5, 0x6B, 0x0E, 0x92,
0x7B, 0x41, 0x9C, 0xE2, 0x06, 0xAD, 0xF3, 0x58, 0x7B, 0x41, 0x9C, 0xE2, 0x06, 0xAD, 0xF3, 0x58,
0x21, 0xE7, 0x4A, 0x8D, 0xFC, 0x90, 0x35, 0x6B 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*/ 4, 6, /* 4 bytes in 6 bytes out*/
32, 1, 2, 3, 4, 5, 32, 1, 2, 3, 4, 5,
4, 5, 6, 7, 8, 9, 4, 5, 6, 7, 8, 9,
8, 9, 10, 11, 12, 13, 8, 9, 10, 11, 12, 13,
12, 13, 14, 15, 16, 17, 12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21, 16, 17, 18, 19, 20, 21,
20, 21, 22, 23, 24, 25, 20, 21, 22, 23, 24, 25,
@ -83,20 +83,20 @@ const uint8_t e_permtab[] ={
28, 29, 30, 31, 32, 1 28, 29, 30, 31, 32, 1
}; };
const uint8_t p_permtab[] ={ const uint8_t p_permtab[] = {
4, 4, /* 32 bit -> 32 bit */ 4, 4, /* 32 bit -> 32 bit */
16, 7, 20, 21, 16, 7, 20, 21,
29, 12, 28, 17, 29, 12, 28, 17,
1, 15, 23, 26, 1, 15, 23, 26,
5, 18, 31, 10, 5, 18, 31, 10,
2, 8, 24, 14, 2, 8, 24, 14,
32, 27, 3, 9, 32, 27, 3, 9,
19, 13, 30, 6, 19, 13, 30, 6,
22, 11, 4, 25 22, 11, 4, 25
}; };
const uint8_t ip_permtab[] ={ const uint8_t ip_permtab[] = {
8, 8, /* 64 bit -> 64 bit */ 8, 8, /* 64 bit -> 64 bit */
58, 50, 42, 34, 26, 18, 10, 2, 58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4, 60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6, 62, 54, 46, 38, 30, 22, 14, 6,
@ -107,8 +107,8 @@ const uint8_t ip_permtab[] ={
63, 55, 47, 39, 31, 23, 15, 7 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 */ 8, 8, /* 64 bit -> 64 bit */
40, 8, 48, 16, 56, 24, 64, 32, 40, 8, 48, 16, 56, 24, 64, 32,
39, 7, 47, 15, 55, 23, 63, 31, 39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30, 38, 6, 46, 14, 54, 22, 62, 30,
@ -119,22 +119,22 @@ const uint8_t inv_ip_permtab[] ={
33, 1, 41, 9, 49, 17, 57, 25 33, 1, 41, 9, 49, 17, 57, 25
}; };
const uint8_t pc1_permtab[] ={ const uint8_t pc1_permtab[] = {
8, 7, /* 64 bit -> 56 bit*/ 8, 7, /* 64 bit -> 56 bit*/
57, 49, 41, 33, 25, 17, 9, 57, 49, 41, 33, 25, 17, 9,
1, 58, 50, 42, 34, 26, 18, 1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27, 10, 2, 59, 51, 43, 35, 27,
19, 11, 3, 60, 52, 44, 36, 19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15, 63, 55, 47, 39, 31, 23, 15,
7, 62, 54, 46, 38, 30, 22, 7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29, 14, 6, 61, 53, 45, 37, 29,
21, 13, 5, 28, 20, 12, 4 21, 13, 5, 28, 20, 12, 4
}; };
const uint8_t pc2_permtab[] ={ const uint8_t pc2_permtab[] = {
7, 6, /* 56 bit -> 48 bit */ 7, 6, /* 56 bit -> 48 bit */
14, 17, 11, 24, 1, 5, 14, 17, 11, 24, 1, 5,
3, 28, 15, 6, 21, 10, 3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8, 23, 19, 12, 4, 26, 8,
16, 7, 27, 20, 13, 2, 16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55, 41, 52, 31, 37, 47, 55,
@ -144,7 +144,7 @@ const uint8_t pc2_permtab[] ={
}; };
const uint8_t splitin6bitword_permtab[] = { const uint8_t splitin6bitword_permtab[] = {
8, 8, /* 64 bit -> 64 bit */ 8, 8, /* 64 bit -> 64 bit */
64, 64, 1, 6, 2, 3, 4, 5, 64, 64, 1, 6, 2, 3, 4, 5,
64, 64, 7, 12, 8, 9, 10, 11, 64, 64, 7, 12, 8, 9, 10, 11,
64, 64, 13, 18, 14, 15, 16, 17, 64, 64, 13, 18, 14, 15, 16, 17,
@ -156,8 +156,8 @@ const uint8_t splitin6bitword_permtab[] = {
}; };
const uint8_t shiftkey_permtab[] = { const uint8_t shiftkey_permtab[] = {
7, 7, /* 56 bit -> 56 bit */ 7, 7, /* 56 bit -> 56 bit */
2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 1, 26, 27, 28, 1,
@ -168,9 +168,9 @@ const uint8_t shiftkey_permtab[] = {
}; };
const uint8_t shiftkeyinv_permtab[] = { const uint8_t shiftkeyinv_permtab[] = {
7, 7, 7, 7,
28, 1, 2, 3, 4, 5, 6, 7, 28, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 24, 25, 26, 27,
56, 29, 30, 31, 32, 33, 34, 35, 56, 29, 30, 31, 32, 33, 34, 35,
@ -202,27 +202,29 @@ const uint8_t shiftkeyinv_permtab[] = {
#define ROTTABLE_INV 0x3F7E #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 ob; /* in-bytes and out-bytes */
uint8_t byte, bit; /* counter for bit and byte */ uint8_t byte, bit; /* counter for bit and byte */
ob = ptable[1]; ob = ptable[1];
ptable = &(ptable[2]); ptable = &(ptable[2]);
for(byte=0; byte<ob; ++byte){ for (byte = 0; byte < ob; ++byte) {
uint8_t x,t=0; uint8_t x, t = 0;
for(bit=0; bit<8; ++bit){ for (bit = 0; bit < 8; ++bit) {
x = *ptable++ - 1; x = *ptable++ - 1;
t<<=1; t <<= 1;
if((in[x/8]) & (0x80>>(x%8)) ){ if ((in[x / 8]) & (0x80 >> (x % 8))) {
t|=0x01; t |= 0x01;
} }
} }
out[byte]=t; out[byte] = t;
} }
} }
/******************************************************************************/ /******************************************************************************/
void changeendian32(uint32_t * a){ void changeendian32(uint32_t *a)
{
*a = (*a & 0x000000FF) << 24 | *a = (*a & 0x000000FF) << 24 |
(*a & 0x0000FF00) << 8 | (*a & 0x0000FF00) << 8 |
(*a & 0x00FF0000) >> 8 | (*a & 0x00FF0000) >> 8 |
@ -231,65 +233,70 @@ void changeendian32(uint32_t * a){
/******************************************************************************/ /******************************************************************************/
static inline static inline
void shiftkey(uint8_t *key){ void shiftkey(uint8_t *key)
{
uint8_t k[7]; uint8_t k[7];
memcpy(k, key, 7); memcpy(k, key, 7);
permute((uint8_t*)shiftkey_permtab, k, key); permute((uint8_t *)shiftkey_permtab, k, key);
} }
/******************************************************************************/ /******************************************************************************/
static inline static inline
void shiftkey_inv(uint8_t *key){ void shiftkey_inv(uint8_t *key)
{
uint8_t k[7]; uint8_t k[7];
memcpy(k, key, 7); memcpy(k, key, 7);
permute((uint8_t*)shiftkeyinv_permtab, k, key); permute((uint8_t *)shiftkeyinv_permtab, k, key);
} }
/******************************************************************************/ /******************************************************************************/
static inline static inline
uint64_t splitin6bitwords(uint64_t a){ uint64_t splitin6bitwords(uint64_t a)
uint64_t ret=0; {
uint64_t ret = 0;
a &= 0x0000ffffffffffffLL; 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; return ret;
} }
/******************************************************************************/ /******************************************************************************/
static inline static inline
uint8_t substitute(uint8_t a, uint8_t * sbp){ uint8_t substitute(uint8_t a, uint8_t *sbp)
{
uint8_t x; uint8_t x;
x = sbp[a>>1]; x = sbp[a >> 1];
x = (a&1)?x&0x0F:x>>4; x = (a & 1) ? x & 0x0F : x >> 4;
return x; 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; uint8_t i;
uint32_t t=0,ret; uint32_t t = 0, ret;
uint64_t data; uint64_t data;
uint8_t *sbp; /* sboxpointer */ uint8_t *sbp; /* sboxpointer */
permute((uint8_t*)e_permtab, (uint8_t*)&r, (uint8_t*)&data); permute((uint8_t *)e_permtab, (uint8_t *)&r, (uint8_t *)&data);
for(i=0; i<6; ++i) for (i = 0; i < 6; ++i)
((uint8_t*)&data)[i] ^= kr[i]; ((uint8_t *)&data)[i] ^= kr[i];
/* Sbox substitution */ /* Sbox substitution */
data = splitin6bitwords(data); data = splitin6bitwords(data);
sbp=(uint8_t*)sbox; sbp = (uint8_t *)sbox;
for(i=0; i<8; ++i){ for (i = 0; i < 8; ++i) {
uint8_t x; uint8_t x;
x = substitute(((uint8_t*)&data)[i], sbp); x = substitute(((uint8_t *)&data)[i], sbp);
t<<=4; t <<= 4;
t |= x; t |= x;
sbp += 32; sbp += 32;
} }
changeendian32(&t); 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; return ret;
} }
@ -305,26 +312,27 @@ typedef struct {
#define R (data.d.v32[1]) #define R (data.d.v32[1])
#define L (data.d.v32[0]) #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 kr[6], k[7];
uint8_t i; uint8_t i;
data_t data; data_t data;
permute((uint8_t*)ip_permtab, (uint8_t*)in, data.d.v8); permute((uint8_t *)ip_permtab, (uint8_t *)in, data.d.v8);
permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k); permute((uint8_t *)pc1_permtab, (const uint8_t *)key, k);
for(i=0; i<8; ++i){ for (i = 0; i < 8; ++i) {
shiftkey(k); shiftkey(k);
if(ROTTABLE&((1<<((i<<1)+0))) ) if (ROTTABLE & ((1 << ((i << 1) + 0))))
shiftkey(k); shiftkey(k);
permute((uint8_t*)pc2_permtab, k, kr); permute((uint8_t *)pc2_permtab, k, kr);
L ^= des_f(R, kr); L ^= des_f(R, kr);
shiftkey(k); shiftkey(k);
if(ROTTABLE&((1<<((i<<1)+1))) ) if (ROTTABLE & ((1 << ((i << 1) + 1))))
shiftkey(k); shiftkey(k);
permute((uint8_t*)pc2_permtab, k, kr); permute((uint8_t *)pc2_permtab, k, kr);
R ^= des_f(L, kr); R ^= des_f(L, kr);
} }
@ -333,32 +341,33 @@ void des_enc(void* out, const void* in, const void* key){
L ^= R; L ^= R;
R ^= L; 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; int8_t i;
data_t data; data_t data;
permute((uint8_t*)ip_permtab, (uint8_t*)in, data.d.v8); permute((uint8_t *)ip_permtab, (uint8_t *)in, data.d.v8);
permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k); permute((uint8_t *)pc1_permtab, (const uint8_t *)key, k);
for(i=7; i>=0; --i){ 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); L ^= des_f(R, kr);
shiftkey_inv(k); shiftkey_inv(k);
if(ROTTABLE&((1<<((i<<1)+1))) ){ if (ROTTABLE & ((1 << ((i << 1) + 1)))) {
shiftkey_inv(k); shiftkey_inv(k);
} }
permute((uint8_t*)pc2_permtab, k, kr); permute((uint8_t *)pc2_permtab, k, kr);
R ^= des_f(L, kr); R ^= des_f(L, kr);
shiftkey_inv(k); shiftkey_inv(k);
if(ROTTABLE&((1<<((i<<1)+0))) ){ if (ROTTABLE & ((1 << ((i << 1) + 0)))) {
shiftkey_inv(k); shiftkey_inv(k);
} }
@ -368,77 +377,79 @@ void des_dec(void* out, const void* in, const uint8_t* key){
L ^= R; L ^= R;
R ^= L; 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){ 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, in, (uint8_t *)key + 0);
des_enc(out, out, (uint8_t*)key +16); 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){ 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, in, (uint8_t *)key + 16);
des_dec(out, out, (uint8_t*)key + 0); 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 i;
uint8_t* tin = (uint8_t*) in; uint8_t *tin = (uint8_t *) in;
uint8_t* tout = (uint8_t*) out; uint8_t *tout = (uint8_t *) out;
while( length > 0 ) while (length > 0) {
{ for (i = 0; i < 8; i++)
for( i = 0; i < 8; i++ ) tout[i] = (unsigned char)(tin[i] ^ iv[i]);
tout[i] = (unsigned char)( tin[i] ^ iv[i] );
des_enc(tout, tin, (uint8_t*)key + 0); des_enc(tout, tin, (uint8_t *)key + 0);
des_dec(tout, tout, (uint8_t*)key + 8); des_dec(tout, tout, (uint8_t *)key + 8);
des_enc(tout, tout, (uint8_t*)key + 0); des_enc(tout, tout, (uint8_t *)key + 0);
memcpy( iv, tout, 8 ); memcpy(iv, tout, 8);
tin += 8; tin += 8;
tout += 8; tout += 8;
length -= 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; uint8_t i;
unsigned char temp[8]; unsigned char temp[8];
uint8_t* tin = (uint8_t*) in; uint8_t *tin = (uint8_t *) in;
uint8_t* tout = (uint8_t*) out; uint8_t *tout = (uint8_t *) out;
while( length > 0 ) while (length > 0) {
{ memcpy(temp, tin, 8);
memcpy( temp, tin, 8 );
des_dec(tout, tin, (uint8_t*)key + 0); des_dec(tout, tin, (uint8_t *)key + 0);
des_enc(tout, tout, (uint8_t*)key + 8); des_enc(tout, tout, (uint8_t *)key + 8);
des_dec(tout, tout, (uint8_t*)key + 0); des_dec(tout, tout, (uint8_t *)key + 0);
for( i = 0; i < 8; i++ ) for (i = 0; i < 8; i++)
tout[i] = (unsigned char)( tout[i] ^ iv[i] ); tout[i] = (unsigned char)(tout[i] ^ iv[i]);
memcpy( iv, temp, 8 ); memcpy(iv, temp, 8);
tin += 8; tin += 8;
tout += 8; tout += 8;
length -= 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 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) * \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) /** \fn void des_dec(void* out, const void* in, const void* key)
* \brief decrypt a block with DES * \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) * \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 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) /** \fn void tdes_enc(void* out, const void* in, const void* key)
* \brief encrypt a block with Tripple-DES * \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) * \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, 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) /** \fn void tdes_dec(void* out, const void* in, const void* key)
* \brief decrypt a block with Tripple-DES * \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 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) * \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, const void* in, const void* key);
void tdes_dec(void* out, void* in, const uint8_t* 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_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_dec(void *out, const void *in, size_t length, const void *key, unsigned char iv[8]);
// Copied from des.h in desfire imp. // Copied from des.h in desfire imp.
typedef unsigned long DES_KS[16][2]; /* Single-key DES key schedule */ typedef unsigned long DES_KS[16][2]; /* Single-key DES key schedule */

View file

@ -27,68 +27,72 @@
*/ */
#include "desfire_crypto.h" #include "desfire_crypto.h"
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);
static size_t key_macing_length (desfirekey_t key); static size_t key_macing_length(desfirekey_t key);
// iceman, see memxor inside string.c, dest/src swapped.. // 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++) { for (size_t i = 0; i < len; i++) {
data[i] ^= ivect[i]; data[i] ^= ivect[i];
} }
} }
void cmac_generate_subkeys ( desfirekey_t key) { void cmac_generate_subkeys(desfirekey_t key)
int kbs = key_block_size (key); {
int kbs = key_block_size(key);
const uint8_t R = (kbs == 8) ? 0x1B : 0x87; const uint8_t R = (kbs == 8) ? 0x1B : 0x87;
uint8_t l[kbs]; uint8_t l[kbs];
memset (l, 0, kbs); memset(l, 0, kbs);
uint8_t ivect[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; bool xor = false;
// Used to compute CMAC on complete blocks // Used to compute CMAC on complete blocks
memcpy (key->cmac_sk1, l, kbs); memcpy(key->cmac_sk1, l, kbs);
xor = l[0] & 0x80; xor = l[0] & 0x80;
lsl (key->cmac_sk1, kbs); lsl(key->cmac_sk1, kbs);
if (xor) 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 // 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; xor = key->cmac_sk1[0] & 0x80;
lsl (key->cmac_sk2, kbs); lsl(key->cmac_sk2, kbs);
if (xor) 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) { 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)); 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)) { if ((!len) || (len % kbs)) {
buffer[len++] = 0x80; buffer[len++] = 0x80;
while (len % kbs) { while (len % kbs) {
buffer[len++] = 0x00; buffer[len++] = 0x00;
} }
xor (key->cmac_sk2, buffer + len - kbs, kbs); xor(key->cmac_sk2, buffer + len - kbs, kbs);
} else { } 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); 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; size_t block_size = 8;
switch (key->type) { switch (key->type) {
case T_DES: case T_DES:
@ -106,17 +110,18 @@ size_t key_block_size (const desfirekey_t key) {
/* /*
* Size of MACing produced with the 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; size_t mac_length = MAC_LENGTH;
switch (key->type) { switch (key->type) {
case T_DES: case T_DES:
case T_3DES: case T_3DES:
mac_length = MAC_LENGTH; mac_length = MAC_LENGTH;
break; break;
case T_3K3DES: case T_3K3DES:
case T_AES: case T_AES:
mac_length = CMAC_LENGTH; mac_length = CMAC_LENGTH;
break; break;
} }
return mac_length; return mac_length;
} }
@ -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 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)) if ((!nbytes) || (nbytes % block_size))
return ((nbytes / block_size) + 1) * block_size; return ((nbytes / block_size) + 1) * block_size;
else else
@ -134,31 +140,34 @@ size_t padded_data_length (const size_t nbytes, const size_t block_size) {
/* /*
* Buffer size required to MAC nbytes of data * Buffer size required to MAC nbytes of data
*/ */
size_t maced_data_length (const desfirekey_t key, const size_t nbytes) { size_t maced_data_length(const desfirekey_t key, const size_t nbytes)
return nbytes + key_macing_length (key); {
return nbytes + key_macing_length(key);
} }
/* /*
* Buffer size required to encipher nbytes of data and a two bytes CRC. * 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; size_t crc_length = 0;
if (!(communication_settings & NO_CRC)) { if (!(communication_settings & NO_CRC)) {
switch (DESFIRE(tag)->authentication_scheme) { switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY: case AS_LEGACY:
crc_length = 2; crc_length = 2;
break; break;
case AS_NEW: case AS_NEW:
crc_length = 4; crc_length = 4;
break; break;
} }
} }
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 *res = data;
uint8_t mac[4]; uint8_t mac[4];
size_t edl; size_t edl;
@ -169,124 +178,124 @@ void* mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes
return data; return data;
switch (communication_settings & MDCM_MASK) { switch (communication_settings & MDCM_MASK) {
case MDCM_PLAIN: case MDCM_PLAIN:
if (AS_LEGACY == DESFIRE(tag)->authentication_scheme) if (AS_LEGACY == DESFIRE(tag)->authentication_scheme)
break; break;
/* /*
* When using new authentication methods, PLAIN data transmission from * When using new authentication methods, PLAIN data transmission from
* the PICC to the PCD are CMACed, so we have to maintain the * the PICC to the PCD are CMACed, so we have to maintain the
* cryptographic initialisation vector up-to-date to check data * cryptographic initialisation vector up-to-date to check data
* integrity later. * integrity later.
* *
* The only difference with CMACed data transmission is that the CMAC * The only difference with CMACed data transmission is that the CMAC
* is not apended to the data send by the PCD to the PICC. * is not apended to the data send by the PCD to the PICC.
*/ */
append_mac = false; append_mac = false;
/* pass through */ /* pass through */
case MDCM_MACED: case MDCM_MACED:
switch (DESFIRE(tag)->authentication_scheme) { switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY: case AS_LEGACY:
if (!(communication_settings & MAC_COMMAND)) if (!(communication_settings & MAC_COMMAND))
break; break;
/* pass through */ /* 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 ... // Fill in the crypto buffer with data ...
memcpy (res, data, *nbytes); memcpy(res, data, *nbytes);
// ... and 0 padding // ... 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) // Copy again provided data (was overwritten by mifare_cypher_blocks_chained)
memcpy (res, data, *nbytes); memcpy(res, data, *nbytes);
if (!(communication_settings & MAC_COMMAND)) if (!(communication_settings & MAC_COMMAND))
break; break;
// Append MAC // 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++; bla++;
memcpy (res + *nbytes, mac, 4); memcpy(res + *nbytes, mac, 4);
*nbytes += 4; *nbytes += 4;
break; break;
case AS_NEW: case AS_NEW:
if (!(communication_settings & CMAC_COMMAND)) if (!(communication_settings & CMAC_COMMAND))
break; break;
cmac (key, DESFIRE (tag)->ivect, res, *nbytes, DESFIRE (tag)->cmac); cmac(key, DESFIRE(tag)->ivect, res, *nbytes, DESFIRE(tag)->cmac);
if (append_mac) { if (append_mac) {
size_t len = maced_data_length (key, *nbytes); size_t len = maced_data_length(key, *nbytes);
++len; ++len;
memcpy (res, data, *nbytes); memcpy(res, data, *nbytes);
memcpy (res + *nbytes, DESFIRE (tag)->cmac, CMAC_LENGTH); memcpy(res + *nbytes, DESFIRE(tag)->cmac, CMAC_LENGTH);
*nbytes += CMAC_LENGTH; *nbytes += CMAC_LENGTH;
}
break;
} }
break;
}
break; break;
case MDCM_ENCIPHERED: case MDCM_ENCIPHERED:
/* |<-------------- data -------------->| /* |<-------------- data -------------->|
* |<--- offset -->| | * |<--- offset -->| |
* +---------------+--------------------+-----+---------+ * +---------------+--------------------+-----+---------+
* | CMD + HEADERS | DATA TO BE SECURED | CRC | PADDING | * | CMD + HEADERS | DATA TO BE SECURED | CRC | PADDING |
* +---------------+--------------------+-----+---------+ ---------------- * +---------------+--------------------+-----+---------+ ----------------
* | |<~~~~v~~~~~~~~~~~~~>| ^ | | (DES / 3DES) * | |<~~~~v~~~~~~~~~~~~~>| ^ | | (DES / 3DES)
* | | `---- crc16() ----' | | * | | `---- crc16() ----' | |
* | | | ^ | | ----- *or* ----- * | | | ^ | | ----- *or* -----
* |<~~~~~~~~~~~~~~~~~~~~v~~~~~~~~~~~~~>| ^ | | (3K3DES / AES) * |<~~~~~~~~~~~~~~~~~~~~v~~~~~~~~~~~~~>| ^ | | (3K3DES / AES)
* | `---- crc32() ----' | | * | `---- crc32() ----' | |
* | | ---- *then* ---- * | | ---- *then* ----
* |<---------------------------------->| * |<---------------------------------->|
* encypher()/decypher() * encypher()/decypher()
*/ */
if (!(communication_settings & ENC_COMMAND)) if (!(communication_settings & ENC_COMMAND))
break; 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 ... // Fill in the crypto buffer with data ...
memcpy (res, data, *nbytes); memcpy(res, data, *nbytes);
if (!(communication_settings & NO_CRC)) { if (!(communication_settings & NO_CRC)) {
// ... CRC ... // ... CRC ...
switch (DESFIRE (tag)->authentication_scheme) { switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY: case AS_LEGACY:
AddCrc14A(res + offset, *nbytes - offset); AddCrc14A(res + offset, *nbytes - offset);
*nbytes += 2; *nbytes += 2;
break; break;
case AS_NEW: case AS_NEW:
crc32_append (res, *nbytes); crc32_append(res, *nbytes);
*nbytes += 4; *nbytes += 4;
break; break;
} }
} }
// ... and padding // ... and padding
memset (res + *nbytes, 0, edl - *nbytes); memset(res + *nbytes, 0, edl - *nbytes);
*nbytes = edl; *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; break;
default: default:
*nbytes = -1; *nbytes = -1;
res = NULL; res = NULL;
break; break;
} }
return res; return res;
} }
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; void *res = data;
size_t edl; size_t edl;
@ -303,300 +312,297 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
return res; return res;
switch (communication_settings & MDCM_MASK) { switch (communication_settings & MDCM_MASK) {
case MDCM_PLAIN: case MDCM_PLAIN:
if (AS_LEGACY == DESFIRE(tag)->authentication_scheme) if (AS_LEGACY == DESFIRE(tag)->authentication_scheme)
break; break;
/* pass through */ /* pass through */
case MDCM_MACED: case MDCM_MACED:
switch (DESFIRE (tag)->authentication_scheme) { switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY: case AS_LEGACY:
if (communication_settings & MAC_VERIFY) { if (communication_settings & MAC_VERIFY) {
*nbytes -= key_macing_length (key); *nbytes -= key_macing_length(key);
if (*nbytes <= 0) { if (*nbytes <= 0) {
*nbytes = -1; *nbytes = -1;
res = NULL; res = NULL;
#ifdef WITH_DEBUG #ifdef WITH_DEBUG
Dbprintf ("No room for MAC!"); Dbprintf("No room for MAC!");
#endif #endif
break;
}
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);
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)) {
#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);
#endif
DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
*nbytes = -1;
res = NULL;
}
}
break; break;
} case AS_NEW:
if (!(communication_settings & CMAC_COMMAND))
break;
if (communication_settings & CMAC_VERIFY) {
if (*nbytes < 9) {
*nbytes = -1;
res = NULL;
break;
}
first_cmac_byte = ((uint8_t *)data)[*nbytes - 9];
((uint8_t *)data)[*nbytes - 9] = ((uint8_t *)data)[*nbytes - 1];
}
edl = enciphered_data_length (tag, *nbytes - 1, communication_settings); int n = (communication_settings & CMAC_VERIFY) ? 8 : 0;
edata = malloc (edl); cmac(key, DESFIRE(tag)->ivect, ((uint8_t *)data), *nbytes - n, DESFIRE(tag)->cmac);
memcpy (edata, data, *nbytes - 1); if (communication_settings & CMAC_VERIFY) {
memset ((uint8_t *)edata + *nbytes - 1, 0, edl - *nbytes + 1); ((uint8_t *)data)[*nbytes - 9] = first_cmac_byte;
if (0 != memcmp(DESFIRE(tag)->cmac, (uint8_t *)data + *nbytes - 9, 8)) {
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)) {
#ifdef WITH_DEBUG #ifdef WITH_DEBUG
Dbprintf ("MACing not verified"); Dbprintf("CMAC NOT verified :-(");
hexdump ((uint8_t *)data + *nbytes - 1, key_macing_length (key), "Expect ", 0); hexdump((uint8_t *)data + *nbytes - 9, 8, "Expect ", 0);
hexdump ((uint8_t *)edata + edl - 8, key_macing_length (key), "Actual ", 0); hexdump(DESFIRE(tag)->cmac, 8, "Actual ", 0);
#endif #endif
DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR; DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
*nbytes = -1; *nbytes = -1;
res = NULL; res = NULL;
} } else {
*nbytes -= 8;
}
}
break;
} }
free(edata);
break; break;
case AS_NEW: case MDCM_ENCIPHERED:
if (!(communication_settings & CMAC_COMMAND)) (*nbytes)--;
break; bool verified = false;
if (communication_settings & CMAC_VERIFY) { int crc_pos = 0x00;
if (*nbytes < 9) { int end_crc_pos = 0x00;
*nbytes = -1; uint8_t x;
res = NULL;
/*
* AS_LEGACY:
* ,-----------------+-------------------------------+--------+
* \ BLOCK n-1 | BLOCK n | STATUS |
* / PAYLOAD | CRC0 | CRC1 | 0x80? | 0x000000000000 | 0x9100 |
* `-----------------+-------------------------------+--------+
*
* <------------ DATA ------------>
* FRAME = PAYLOAD + CRC(PAYLOAD) + PADDING
*
* AS_NEW:
* ,-------------------------------+-----------------------------------------------+--------+
* \ BLOCK n-1 | BLOCK n | STATUS |
* / PAYLOAD | CRC0 | CRC1 | CRC2 | CRC3 | 0x80? | 0x0000000000000000000000000000 | 0x9100 |
* `-------------------------------+-----------------------------------------------+--------+
* <----------------------------------- DATA ------------------------------------->|
*
* <----------------- DATA ---------------->
* FRAME = PAYLOAD + CRC(PAYLOAD + STATUS) + PADDING + STATUS
* `------------------'
*/
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) {
case AS_LEGACY:
crc_pos = *nbytes - 8 - 1; // The CRC can be over two blocks
if (crc_pos < 0) {
/* Single block */
crc_pos = 0;
}
break;
case AS_NEW:
/* Move status between payload and CRC */
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);
((uint8_t *)res)[crc_pos] = 0x00;
crc_pos++;
*nbytes += 1;
break; break;
}
first_cmac_byte = ((uint8_t *)data)[*nbytes - 9];
((uint8_t *)data)[*nbytes - 9] = ((uint8_t *)data)[*nbytes-1];
} }
int n = (communication_settings & CMAC_VERIFY) ? 8 : 0; do {
cmac (key, DESFIRE (tag)->ivect, ((uint8_t *)data), *nbytes - n, DESFIRE (tag)->cmac); uint16_t crc16 = 0x00;
uint32_t crc;
switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY:
AddCrc14A((uint8_t *)res, end_crc_pos);
end_crc_pos = crc_pos + 2;
//
if (communication_settings & CMAC_VERIFY) {
((uint8_t *)data)[*nbytes - 9] = first_cmac_byte; crc = crc16;
if (0 != memcmp (DESFIRE (tag)->cmac, (uint8_t *)data + *nbytes - 9, 8)) { break;
#ifdef WITH_DEBUG case AS_NEW:
Dbprintf ("CMAC NOT verified :-("); end_crc_pos = crc_pos + 4;
hexdump ((uint8_t *)data + *nbytes - 9, 8, "Expect ", 0); crc32_ex(res, end_crc_pos, (uint8_t *)&crc);
hexdump (DESFIRE (tag)->cmac, 8, "Actual ", 0); break;
#endif }
DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR; if (!crc) {
*nbytes = -1; verified = true;
res = NULL; 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))))
verified = false;
}
}
if (verified) {
*nbytes = crc_pos;
switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY:
((uint8_t *)data)[(*nbytes)++] = 0x00;
break;
case AS_NEW:
/* The status byte was already before the CRC */
break;
}
} else { } else {
*nbytes -= 8; switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY:
break;
case AS_NEW:
x = ((uint8_t *)res)[crc_pos - 1];
((uint8_t *)res)[crc_pos - 1] = ((uint8_t *)res)[crc_pos];
((uint8_t *)res)[crc_pos] = x;
break;
}
crc_pos++;
} }
} } while (!verified && (end_crc_pos < *nbytes));
break;
}
free (edata); if (!verified) {
break;
case MDCM_ENCIPHERED:
(*nbytes)--;
bool verified = false;
int crc_pos = 0x00;
int end_crc_pos = 0x00;
uint8_t x;
/*
* AS_LEGACY:
* ,-----------------+-------------------------------+--------+
* \ BLOCK n-1 | BLOCK n | STATUS |
* / PAYLOAD | CRC0 | CRC1 | 0x80? | 0x000000000000 | 0x9100 |
* `-----------------+-------------------------------+--------+
*
* <------------ DATA ------------>
* FRAME = PAYLOAD + CRC(PAYLOAD) + PADDING
*
* AS_NEW:
* ,-------------------------------+-----------------------------------------------+--------+
* \ BLOCK n-1 | BLOCK n | STATUS |
* / PAYLOAD | CRC0 | CRC1 | CRC2 | CRC3 | 0x80? | 0x0000000000000000000000000000 | 0x9100 |
* `-------------------------------+-----------------------------------------------+--------+
* <----------------------------------- DATA ------------------------------------->|
*
* <----------------- DATA ---------------->
* FRAME = PAYLOAD + CRC(PAYLOAD + STATUS) + PADDING + STATUS
* `------------------'
*/
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) {
case AS_LEGACY:
crc_pos = *nbytes - 8 - 1; // The CRC can be over two blocks
if (crc_pos < 0) {
/* Single block */
crc_pos = 0;
}
break;
case AS_NEW:
/* Move status between payload and CRC */
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);
((uint8_t *)res)[crc_pos] = 0x00;
crc_pos++;
*nbytes += 1;
break;
}
do {
uint16_t crc16 =0x00;
uint32_t crc;
switch (DESFIRE (tag)->authentication_scheme) {
case AS_LEGACY:
AddCrc14A( (uint8_t*)res, end_crc_pos);
end_crc_pos = crc_pos + 2;
//
crc = crc16;
break;
case AS_NEW:
end_crc_pos = crc_pos + 4;
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)) ))
verified = false;
}
}
if (verified) {
*nbytes = crc_pos;
switch (DESFIRE (tag)->authentication_scheme) {
case AS_LEGACY:
((uint8_t *)data)[(*nbytes)++] = 0x00;
break;
case AS_NEW:
/* The status byte was already before the CRC */
break;
}
} else {
switch (DESFIRE (tag)->authentication_scheme) {
case AS_LEGACY:
break;
case AS_NEW:
x = ((uint8_t *)res)[crc_pos - 1];
((uint8_t *)res)[crc_pos - 1] = ((uint8_t *)res)[crc_pos];
((uint8_t *)res)[crc_pos] = x;
break;
}
crc_pos++;
}
} while (!verified && (end_crc_pos < *nbytes));
if (!verified) {
#ifdef WITH_DEBUG #ifdef WITH_DEBUG
/* FIXME In some configurations, the file is transmitted PLAIN */ /* FIXME In some configurations, the file is transmitted PLAIN */
Dbprintf("CRC not verified in decyphered stream"); Dbprintf("CRC not verified in decyphered stream");
#endif #endif
DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR; DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
*nbytes = -1;
res = NULL;
}
break;
default:
Dbprintf("Unknown communication settings");
*nbytes = -1; *nbytes = -1;
res = NULL; res = NULL;
} break;
break;
default:
Dbprintf("Unknown communication settings");
*nbytes = -1;
res = NULL;
break;
} }
return res; return res;
} }
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]; uint8_t ovect[MAX_CRYPTO_BLOCK_SIZE];
if (direction == MCD_SEND) { if (direction == MCD_SEND) {
xor (ivect, data, block_size); xor(ivect, data, block_size);
} else { } else {
memcpy (ovect, data, block_size); memcpy(ovect, data, block_size);
} }
uint8_t edata[MAX_CRYPTO_BLOCK_SIZE]; uint8_t edata[MAX_CRYPTO_BLOCK_SIZE];
switch (key->type) { switch (key->type) {
case T_DES: case T_DES:
switch (operation) { switch (operation) {
case MCO_ENCYPHER: case MCO_ENCYPHER:
//DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT); //DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
des_enc(edata, data, key->data); des_enc(edata, data, key->data);
break; break;
case MCO_DECYPHER: case MCO_DECYPHER:
//DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT); //DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
des_dec(edata, data, key->data); des_dec(edata, data, key->data);
break; break;
}
break;
case T_3DES:
switch (operation) {
case MCO_ENCYPHER:
// 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);
break;
case MCO_DECYPHER:
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
tdes_dec(data, edata, key->data);
break;
}
break;
case T_3K3DES:
switch (operation) {
case MCO_ENCYPHER:
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);
break;
case MCO_DECYPHER:
tdes_dec(data, edata, key->data);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_DECRYPT);
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
break;
}
break;
case T_AES:
switch (operation)
{
case MCO_ENCYPHER:
{
AesCtx ctx;
AesCtxIni(&ctx, ivect, key->data, KEY128,CBC);
AesEncrypt(&ctx, data, edata, sizeof(edata) );
break;
} }
case MCO_DECYPHER: break;
{ case T_3DES:
AesCtx ctx; switch (operation) {
AesCtxIni(&ctx, ivect, key->data, KEY128,CBC); case MCO_ENCYPHER:
AesDecrypt(&ctx, edata, data, sizeof(edata)); // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
break; // 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);
break;
case MCO_DECYPHER:
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
tdes_dec(data, edata, key->data);
break;
} }
} break;
break; case T_3K3DES:
switch (operation) {
case MCO_ENCYPHER:
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);
break;
case MCO_DECYPHER:
tdes_dec(data, edata, key->data);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_DECRYPT);
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
break;
}
break;
case T_AES:
switch (operation) {
case MCO_ENCYPHER: {
AesCtx ctx;
AesCtxIni(&ctx, ivect, key->data, KEY128, CBC);
AesEncrypt(&ctx, data, edata, sizeof(edata));
break;
}
case MCO_DECYPHER: {
AesCtx ctx;
AesCtxIni(&ctx, ivect, key->data, KEY128, CBC);
AesDecrypt(&ctx, edata, data, sizeof(edata));
break;
}
}
break;
} }
memcpy (data, edata, block_size); memcpy(data, edata, block_size);
if (direction == MCD_SEND) { if (direction == MCD_SEND) {
memcpy (ivect, data, block_size); memcpy(ivect, data, block_size);
} else { } else {
xor (ivect, data, block_size); xor(ivect, data, block_size);
memcpy (ivect, ovect, 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 * Because the tag may contain additional data, one may need to call this
* function with tag, key and ivect defined. * 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; size_t block_size;
if (tag) { if (tag) {
if (!key) if (!key)
key = DESFIRE (tag)->session_key; key = DESFIRE(tag)->session_key;
if (!ivect) if (!ivect)
ivect = DESFIRE (tag)->ivect; ivect = DESFIRE(tag)->ivect;
switch (DESFIRE (tag)->authentication_scheme) { switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY: case AS_LEGACY:
memset (ivect, 0, MAX_CRYPTO_BLOCK_SIZE); memset(ivect, 0, MAX_CRYPTO_BLOCK_SIZE);
break; break;
case AS_NEW: case AS_NEW:
break; break;
} }
} }
block_size = key_block_size (key); block_size = key_block_size(key);
size_t offset = 0; size_t offset = 0;
while (offset < data_size) { 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; offset += block_size;
} }
} }

View file

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

View file

@ -6,15 +6,15 @@
#include "iso14443a.h" #include "iso14443a.h"
#include "desfire.h" #include "desfire.h"
//#include "mifare.h" // iso14a_card_select_t struct //#include "mifare.h" // iso14a_card_select_t struct
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);
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);
void Desfire_des_key_new_with_version (const uint8_t value[8], 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_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(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_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(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); 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); uint8_t Desfire_key_get_version(desfirekey_t key);
void Desfire_key_set_version (desfirekey_t key, uint8_t version); 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_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key);
#endif #endif

View file

@ -105,8 +105,7 @@ static char iso_type = 0;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response) int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response)
{ {
switch(iso_type) switch (iso_type) {
{
case 'a': case 'a':
return iso14_apdu(apdu, (uint16_t) length, false, response, NULL); return iso14_apdu(apdu, (uint16_t) length, false, response, NULL);
break; break;
@ -156,7 +155,7 @@ size_t EPA_Parse_CardAccess(uint8_t *data,
index += 2; index += 2;
// check for extended length // check for extended length
if ((data[index - 1] & 0x80) != 0) { if ((data[index - 1] & 0x80) != 0) {
index += (data[index-1] & 0x7F); index += (data[index - 1] & 0x7F);
} }
} }
// OID // OID
@ -166,8 +165,7 @@ size_t EPA_Parse_CardAccess(uint8_t *data,
&& memcmp(data + index + 2, && memcmp(data + index + 2,
oid_pace_start, oid_pace_start,
sizeof(oid_pace_start)) == 0 // content matches sizeof(oid_pace_start)) == 0 // content matches
&& pace_info != NULL) && pace_info != NULL) {
{
// first, clear the pace_info struct // first, clear the pace_info struct
memset(pace_info, 0, sizeof(pace_version_info_t)); memset(pace_info, 0, sizeof(pace_version_info_t));
memcpy(pace_info->oid, data + index + 2, sizeof(pace_info->oid)); 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) { if (data[index] == 02 && data[index + 1] == 01) {
pace_info->version = data[index + 2]; pace_info->version = data[index + 2];
index += 3; index += 3;
} } else {
else {
return index; return index;
} }
// after that there might(!) be the parameter ID // 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]; pace_info->parameter_id = data[index + 2];
index += 3; index += 3;
} }
} } else {
else {
// skip this OID // skip this OID
index += 2 + data[index + 1]; 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 // TODO: This needs to be extended to support long tags
else if (data[index + 1] == 0) { else if (data[index + 1] == 0) {
return index; return index;
} } else {
else {
// skip this part // skip this part
// TODO: This needs to be extended to support long tags // TODO: This needs to be extended to support long tags
// TODO: This needs to be extended to support unknown elements with // TODO: This needs to be extended to support unknown elements with
@ -225,24 +220,22 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length)
// select the file EF.CardAccess // select the file EF.CardAccess
rapdu_length = EPA_APDU((uint8_t *)apdu_select_binary_cardaccess, rapdu_length = EPA_APDU((uint8_t *)apdu_select_binary_cardaccess,
sizeof(apdu_select_binary_cardaccess), sizeof(apdu_select_binary_cardaccess),
response_apdu); response_apdu);
if (rapdu_length < 6 if (rapdu_length < 6
|| response_apdu[rapdu_length - 4] != 0x90 || response_apdu[rapdu_length - 4] != 0x90
|| response_apdu[rapdu_length - 3] != 0x00) || response_apdu[rapdu_length - 3] != 0x00) {
{
DbpString("Failed to select EF.CardAccess!"); DbpString("Failed to select EF.CardAccess!");
return -1; return -1;
} }
// read the file // read the file
rapdu_length = EPA_APDU((uint8_t *)apdu_read_binary, rapdu_length = EPA_APDU((uint8_t *)apdu_read_binary,
sizeof(apdu_read_binary), sizeof(apdu_read_binary),
response_apdu); response_apdu);
if (rapdu_length <= 6 if (rapdu_length <= 6
|| response_apdu[rapdu_length - 4] != 0x90 || response_apdu[rapdu_length - 4] != 0x90
|| response_apdu[rapdu_length - 3] != 0x00) || response_apdu[rapdu_length - 3] != 0x00) {
{
Dbprintf("Failed to read EF.CardAccess!"); Dbprintf("Failed to read EF.CardAccess!");
return -1; 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) // length of data available: apdu_length - 4 (ISO frame) - 2 (SW)
size_t to_copy = rapdu_length - 6; size_t to_copy = rapdu_length - 6;
to_copy = to_copy < max_length ? to_copy : max_length; 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; return to_copy;
} }
@ -265,7 +258,7 @@ static void EPA_PACE_Collect_Nonce_Abort(uint8_t step, int func_return)
EPA_Finish(); EPA_Finish();
// send the USB packet // send the USB packet
cmd_send(CMD_ACK,step,func_return,0,0,0); cmd_send(CMD_ACK, step, func_return, 0, 0, 0);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -324,8 +317,7 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
uint8_t requested_size = (uint8_t)c->arg[0]; uint8_t requested_size = (uint8_t)c->arg[0];
func_return = EPA_PACE_Get_Nonce(requested_size, nonce); func_return = EPA_PACE_Get_Nonce(requested_size, nonce);
// check if the command succeeded // check if the command succeeded
if (func_return < 0) if (func_return < 0) {
{
EPA_PACE_Collect_Nonce_Abort(4, func_return); EPA_PACE_Collect_Nonce_Abort(4, func_return);
return; return;
} }
@ -334,7 +326,7 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
EPA_Finish(); EPA_Finish();
// save received information // 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);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -359,26 +351,23 @@ int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce)
// send it // send it
uint8_t response_apdu[262]; uint8_t response_apdu[262];
int send_return = EPA_APDU(apdu, int send_return = EPA_APDU(apdu,
sizeof(apdu), sizeof(apdu),
response_apdu); response_apdu);
// check if the command succeeded // check if the command succeeded
if (send_return < 6 if (send_return < 6
|| response_apdu[send_return - 4] != 0x90 || response_apdu[send_return - 4] != 0x90
|| response_apdu[send_return - 3] != 0x00) || response_apdu[send_return - 3] != 0x00) {
{
return -1; return -1;
} }
// if there is no nonce in the RAPDU, return here // if there is no nonce in the RAPDU, return here
if (send_return < 10) if (send_return < 10) {
{
// no error // no error
return 0; return 0;
} }
// get the actual length of the nonce // get the actual length of the nonce
uint8_t nonce_length = response_apdu[5]; uint8_t nonce_length = response_apdu[5];
if (nonce_length > send_return - 10) if (nonce_length > send_return - 10) {
{
nonce_length = send_return - 10; nonce_length = send_return - 10;
} }
// copy the nonce // copy the nonce
@ -430,13 +419,12 @@ int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password)
// send it // send it
uint8_t response_apdu[6]; uint8_t response_apdu[6];
int send_return = EPA_APDU(apdu, int send_return = EPA_APDU(apdu,
apdu_length, apdu_length,
response_apdu); response_apdu);
// check if the command succeeded // check if the command succeeded
if (send_return != 6 if (send_return != 6
|| response_apdu[send_return - 4] != 0x90 || response_apdu[send_return - 4] != 0x90
|| response_apdu[send_return - 3] != 0x00) || response_apdu[send_return - 3] != 0x00) {
{
return 1; return 1;
} }
return 0; return 0;
@ -452,8 +440,7 @@ void EPA_PACE_Replay(UsbCommand *c)
// if an APDU has been passed, save it // if an APDU has been passed, save it
if (c->arg[0] != 0) { if (c->arg[0] != 0) {
// make sure it's not too big // 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); cmd_send(CMD_ACK, 1, 0, 0, NULL, 0);
} }
memcpy(apdus_replay[c->arg[0] - 1].data + c->arg[1], memcpy(apdus_replay[c->arg[0] - 1].data + c->arg[1],
@ -490,22 +477,21 @@ void EPA_PACE_Replay(UsbCommand *c)
for (int i = 0; i < sizeof(apdu_lengths_replay); i++) { for (int i = 0; i < sizeof(apdu_lengths_replay); i++) {
StartCountUS(); StartCountUS();
func_return = EPA_APDU(apdus_replay[i].data, func_return = EPA_APDU(apdus_replay[i].data,
apdu_lengths_replay[i], apdu_lengths_replay[i],
response_apdu); response_apdu);
timings[i] = GetCountUS(); timings[i] = GetCountUS();
// every step but the last one should succeed // every step but the last one should succeed
if (i < sizeof(apdu_lengths_replay) - 1 if (i < sizeof(apdu_lengths_replay) - 1
&& (func_return < 6 && (func_return < 6
|| response_apdu[func_return - 4] != 0x90 || response_apdu[func_return - 4] != 0x90
|| response_apdu[func_return - 3] != 0x00)) || response_apdu[func_return - 3] != 0x00)) {
{
EPA_Finish(); EPA_Finish();
cmd_send(CMD_ACK, 3 + i, func_return, 0, timings, 20); cmd_send(CMD_ACK, 3 + i, func_return, 0, timings, 20);
return; return;
} }
} }
EPA_Finish(); EPA_Finish();
cmd_send(CMD_ACK,0,0,0,timings,20); cmd_send(CMD_ACK, 0, 0, 0, timings, 20);
return; return;
} }
@ -543,7 +529,7 @@ int EPA_Setup()
// power up the field // power up the field
iso14443b_setup(); iso14443b_setup();
// select the card // select the card
return_code = iso14443b_select_card( &card_b_info ); return_code = iso14443b_select_card(&card_b_info);
if (return_code == 0) { if (return_code == 0) {
Dbprintf("ISO 14443 Type B"); Dbprintf("ISO 14443 Type B");
iso_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 void iso18092_setup(uint8_t fpga_minor_mode);
static uint8_t felica_select_card(felica_card_select_t *card); 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); bool WaitForFelicaReply(uint16_t maxbytes);
void iso18092_set_timeout(uint32_t timeout) { void iso18092_set_timeout(uint32_t timeout)
felica_timeout = timeout + (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/(16*8) + 2; {
felica_timeout = timeout + (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / (16 * 8) + 2;
} }
uint32_t iso18092_get_timeout(void) { uint32_t iso18092_get_timeout(void)
return felica_timeout - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/(16*8) - 2; {
return felica_timeout - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / (16 * 8) - 2;
} }
#ifndef FELICA_MAX_FRAME_SIZE #ifndef FELICA_MAX_FRAME_SIZE
#define FELICA_MAX_FRAME_SIZE 260 #define FELICA_MAX_FRAME_SIZE 260
#endif #endif
//structure to hold outgoing NFC frame //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 //structure to hold incoming NFC frame, used for ISO/IEC 18092-compatible frames
static struct { static struct {
@ -67,8 +69,8 @@ static struct {
uint16_t len; uint16_t len;
uint8_t byte_offset; uint8_t byte_offset;
uint8_t *framebytes; uint8_t *framebytes;
//should be enough. maxlen is 255, 254 for data, 2 for sync, 2 for 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 // 0,1 -> SYNC, 2 - len, 3-(len+1)->data, then crc
} FelicaFrame; } FelicaFrame;
//b2 4d is SYNC, 45645 in 16-bit notation, 10110010 01001101 binary. Frame will not start filling until this is shifted in //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 # define SYNC_16BIT 0xB24D
#endif #endif
static void FelicaFrameReset() { static void FelicaFrameReset()
{
FelicaFrame.state = STATE_UNSYNCD; FelicaFrame.state = STATE_UNSYNCD;
FelicaFrame.posCnt = 0; FelicaFrame.posCnt = 0;
FelicaFrame.crc_ok = false; FelicaFrame.crc_ok = false;
FelicaFrame.byte_offset = 0; FelicaFrame.byte_offset = 0;
} }
static void FelicaFrameinit(uint8_t *data) { static void FelicaFrameinit(uint8_t *data)
{
FelicaFrame.framebytes = data; FelicaFrame.framebytes = data;
FelicaFrameReset(); FelicaFrameReset();
} }
//shift byte into frame, reversing it at the same time //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; uint8_t j;
for(j=0; j < FelicaFrame.byte_offset; j++) { for (j = 0; j < FelicaFrame.byte_offset; j++) {
FelicaFrame.framebytes[FelicaFrame.posCnt] = ( FelicaFrame.framebytes[FelicaFrame.posCnt]<<1 ) + (bt & 1); FelicaFrame.framebytes[FelicaFrame.posCnt] = (FelicaFrame.framebytes[FelicaFrame.posCnt] << 1) + (bt & 1);
bt >>= 1; bt >>= 1;
} }
FelicaFrame.posCnt++; FelicaFrame.posCnt++;
FelicaFrame.rem_len--; FelicaFrame.rem_len--;
for(j = FelicaFrame.byte_offset; j<8; j++) { for (j = FelicaFrame.byte_offset; j < 8; j++) {
FelicaFrame.framebytes[FelicaFrame.posCnt] = (FelicaFrame.framebytes[FelicaFrame.posCnt]<<1 ) + (bt & 1); FelicaFrame.framebytes[FelicaFrame.posCnt] = (FelicaFrame.framebytes[FelicaFrame.posCnt] << 1) + (bt & 1);
bt >>= 1; bt >>= 1;
} }
} }
static void Process18092Byte(uint8_t bt) { static void Process18092Byte(uint8_t bt)
{
switch (FelicaFrame.state) { switch (FelicaFrame.state) {
case STATE_UNSYNCD: { 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 //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.shiftReg = bt;
FelicaFrame.state = STATE_UNSYNCD; FelicaFrame.state = STATE_UNSYNCD;
} else { } else {
for (uint8_t i=0; i<8; i++) { for (uint8_t i = 0; i < 8; i++) {
if (FelicaFrame.shiftReg == SYNC_16BIT) { if (FelicaFrame.shiftReg == SYNC_16BIT) {
//SYNC done! //SYNC done!
@ -128,13 +134,13 @@ static void Process18092Byte(uint8_t bt) {
FelicaFrame.framebytes[1] = 0x4d; FelicaFrame.framebytes[1] = 0x4d;
FelicaFrame.byte_offset = i; FelicaFrame.byte_offset = i;
//shift in remaining byte, slowly... //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); FelicaFrame.framebytes[2] = (FelicaFrame.framebytes[2] << 1) + (bt & 1);
bt >>= 1; bt >>= 1;
} }
FelicaFrame.posCnt = 2; FelicaFrame.posCnt = 2;
if (i==0) if (i == 0)
break; break;
} }
FelicaFrame.shiftReg = (FelicaFrame.shiftReg << 1) + (bt & 1); FelicaFrame.shiftReg = (FelicaFrame.shiftReg << 1) + (bt & 1);
@ -171,12 +177,12 @@ static void Process18092Byte(uint8_t bt) {
case STATE_GET_CRC: { case STATE_GET_CRC: {
shiftInByte(bt); shiftInByte(bt);
if ( FelicaFrame.rem_len <= 0 ) { if (FelicaFrame.rem_len <= 0) {
// skip sync 2bytes. IF ok, residue should be 0x0000 // 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.state = STATE_FULL;
FelicaFrame.rem_len = 0; 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; break;
} }
@ -190,7 +196,8 @@ static void Process18092Byte(uint8_t bt) {
* Currently does NOT do any collision handling. * Currently does NOT do any collision handling.
* It expects 0-1 cards in the device's range. * 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 // POLL command
// 0xB2 0x4B = sync code // 0xB2 0x4B = sync code
@ -205,7 +212,7 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
// b0 = fc/64 (212kbps) // b0 = fc/64 (212kbps)
// 0x00 = timeslot // 0x00 = timeslot
// 0x09 0x21 = crc // 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; int len = 20;
@ -225,7 +232,7 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
} while (--len); } while (--len);
// timed-out // timed-out
if ( len == 0 ) if (len == 0)
return 1; return 1;
// wrong answer // wrong answer
@ -233,7 +240,7 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
return 2; return 2;
// VALIDATE CRC residue is 0, hence if crc is a value it failed. // 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; return 3;
// copy UID // 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->code, card->IDm, 2);
memcpy(card->uid, card->IDm + 2, 6); memcpy(card->uid, card->IDm + 2, 6);
memcpy(card->iccode, card->PMm, 2); memcpy(card->iccode, card->PMm, 2);
memcpy(card->mrt, card->PMm+2, 6); memcpy(card->mrt, card->PMm + 2, 6);
} }
// more status bytes? // 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, // Felica standard has a different file system, AFAIK,
// 8-byte IDm, number of blocks, blocks numbers // 8-byte IDm, number of blocks, blocks numbers
// number of blocks limited to 4 for FelicaLite(S) // 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) if (blocknum > 4 || blocknum <= 0)
Dbprintf("Invalid number of blocks, %d != 4", blocknum); Dbprintf("Invalid number of blocks, %d != 4", blocknum);
@ -298,13 +306,13 @@ static void BuildFliteRdblk(uint8_t* idm, int blocknum, uint16_t *blocks ) {
//number of blocks //number of blocks
frameSpace[c++] = blocknum; frameSpace[c++] = blocknum;
for (i=0; i < blocknum; i++) { for (i = 0; i < blocknum; i++) {
//3-byte block //3-byte block
if (blocks[i] >= 256) { if (blocks[i] >= 256) {
frameSpace[c++] = 0x00; frameSpace[c++] = 0x00;
frameSpace[c++] = (blocks[i] >> 8); //block number, little endian.... frameSpace[c++] = (blocks[i] >> 8); //block number, little endian....
frameSpace[c++] = (blocks[i] & 0xff); frameSpace[c++] = (blocks[i] & 0xff);
} else { } else {
frameSpace[c++] = 0x80; frameSpace[c++] = 0x80;
frameSpace[c++] = blocks[i]; frameSpace[c++] = blocks[i];
@ -312,15 +320,16 @@ static void BuildFliteRdblk(uint8_t* idm, int blocknum, uint16_t *blocks ) {
} }
//set length //set length
frameSpace[2] = c-2; frameSpace[2] = c - 2;
AddCrc(frameSpace, 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; uint8_t flags = FPGA_MAJOR_MODE_ISO18092;
if ( power ) if (power)
flags |= FPGA_HF_ISO18092_FLAG_READER; flags |= FPGA_HF_ISO18092_FLAG_READER;
if (highspeed) if (highspeed)
flags |= FPGA_HF_ISO18092_FLAG_424K; 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))) {}; while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {};
AT91C_BASE_SSC->SSC_THR = 0x00; //minimum delay AT91C_BASE_SSC->SSC_THR = 0x00; //minimum delay
while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {}; while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {};
AT91C_BASE_SSC->SSC_THR = 0x00; //spin AT91C_BASE_SSC->SSC_THR = 0x00; //spin
/**/ /**/
// log // log
LogTrace( LogTrace(
frame, frame,
len, len,
(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, ((felica_lasttime_prox2air_start + felica_lasttime_prox2air_start) << 4) + DELAY_ARM2AIR_AS_READER,
NULL, NULL,
true 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 // Wait for tag reply
// stop when button is pressed // stop when button is pressed
// or return TRUE when command is captured // or return TRUE when command is captured
bool WaitForFelicaReply(uint16_t maxbytes) { bool WaitForFelicaReply(uint16_t maxbytes)
{
uint32_t c = 0; uint32_t c = 0;
@ -393,7 +403,7 @@ bool WaitForFelicaReply(uint16_t maxbytes) {
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
uint32_t timeout = iso18092_get_timeout(); uint32_t timeout = iso18092_get_timeout();
for(;;) { for (;;) {
WDT_HIT(); WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
@ -403,15 +413,15 @@ bool WaitForFelicaReply(uint16_t maxbytes) {
felica_nexttransfertime = felica_nexttransfertime =
MAX( MAX(
felica_nexttransfertime, 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( LogTrace(
FelicaFrame.framebytes, FelicaFrame.framebytes,
FelicaFrame.len, FelicaFrame.len,
((GetCountSspClk() & 0xfffffff8)<<4) - DELAY_AIR2ARM_AS_READER - timeout, ((GetCountSspClk() & 0xfffffff8) << 4) - DELAY_AIR2ARM_AS_READER - timeout,
((GetCountSspClk() & 0xfffffff8)<<4) - DELAY_AIR2ARM_AS_READER, ((GetCountSspClk() & 0xfffffff8) << 4) - DELAY_AIR2ARM_AS_READER,
NULL, NULL,
false false
); );
@ -430,13 +440,15 @@ bool WaitForFelicaReply(uint16_t maxbytes) {
// Set up FeliCa communication (similar to iso14443a_setup) // Set up FeliCa communication (similar to iso14443a_setup)
// field is setup for "Sending as Reader" // 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(); LEDsoff();
FpgaDownloadAndGo(FPGA_BITSTREAM_HF); FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// allocate command receive buffer // allocate command receive buffer
BigBuf_free(); BigBuf_Clear_ext(false); BigBuf_free();
BigBuf_Clear_ext(false);
// Initialize Demod and Uart structs // Initialize Demod and Uart structs
//DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); //DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
@ -473,7 +485,8 @@ static void iso18092_setup(uint8_t fpga_minor_mode) {
// arg0 FeliCa flags // arg0 FeliCa flags
// arg1 len of commandbytes // arg1 len of commandbytes
// d.asBytes command bytes to send // d.asBytes command bytes to send
void felica_sendraw(UsbCommand *c) { void felica_sendraw(UsbCommand *c)
{
if (MF_DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Enter"); if (MF_DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Enter");
@ -494,10 +507,10 @@ void felica_sendraw(UsbCommand *c) {
// notify client selecting status. // notify client selecting status.
// if failed selecting, turn off antenna and quite. // if failed selecting, turn off antenna and quite.
if( !(param & FELICA_NO_SELECT) ) { if (!(param & FELICA_NO_SELECT)) {
arg0 = felica_select_card(&card); arg0 = felica_select_card(&card);
cmd_send(CMD_ACK, arg0, sizeof(card.uid), 0, &card, sizeof(felica_card_select_t)); cmd_send(CMD_ACK, arg0, sizeof(card.uid), 0, &card, sizeof(felica_card_select_t));
if ( arg0 > 0 ) if (arg0 > 0)
goto OUT; goto OUT;
} }
} }
@ -505,26 +518,26 @@ void felica_sendraw(UsbCommand *c) {
if ((param & FELICA_RAW)) { if ((param & FELICA_RAW)) {
// 2 sync, 1 len, 2crc == 5 // 2 sync, 1 len, 2crc == 5
uint8_t *buf = BigBuf_malloc(len+5); uint8_t *buf = BigBuf_malloc(len + 5);
// add sync bits // add sync bits
buf[0] = 0xb2; buf[0] = 0xb2;
buf[1] = 0x4d; buf[1] = 0x4d;
buf[2] = len; buf[2] = len;
// copy command // copy command
memcpy(buf+2, cmd, len); memcpy(buf + 2, cmd, len);
if ((param & FELICA_APPEND_CRC)) { if ((param & FELICA_APPEND_CRC)) {
// Don't append crc on empty bytearray... // Don't append crc on empty bytearray...
if ( len > 0 ) { if (len > 0) {
AddCrc(buf, len); AddCrc(buf, len);
len += 2; len += 2;
} }
} }
TransmitFor18092_AsReader(buf, buf[2]+4, NULL, 1, 0); TransmitFor18092_AsReader(buf, buf[2] + 4, NULL, 1, 0);
arg0 = !WaitForFelicaReply(1024); 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)) if ((param & FELICA_NO_DISCONNECT))
@ -539,25 +552,26 @@ OUT:
if (MF_DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Exit"); 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; int remFrames = (samplesToSkip) ? samplesToSkip : 0;
Dbprintf("Snoop FelicaLiteS: Getting first %d frames, Skipping %d triggers.\n", samplesToSkip, triggersToSkip); 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. //the frame bits are slow enough.
int n = BigBuf_max_traceLen() / sizeof(uint8_t); // take all memory int n = BigBuf_max_traceLen() / sizeof(uint8_t); // take all memory
int numbts = 0; int numbts = 0;
uint8_t *dest = (uint8_t *)BigBuf_get_addr(); uint8_t *dest = (uint8_t *)BigBuf_get_addr();
uint8_t *destend = dest + n-2; uint8_t *destend = dest + n - 2;
uint32_t endframe = GetCountSspClk(); uint32_t endframe = GetCountSspClk();
while (dest <= destend) { while (dest <= destend) {
WDT_HIT(); WDT_HIT();
if( BUTTON_PRESS()) break; if (BUTTON_PRESS()) break;
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); 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 //to be sure we are in frame
if (FelicaFrame.state == STATE_GET_LENGTH) { if (FelicaFrame.state == STATE_GET_LENGTH) {
//length is after 48 (PRE)+16 (SYNC) - 64 ticks +maybe offset? not 100% //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 = distance >> 8;
dest++; dest++;
*dest = (distance & 0xff); *dest = (distance & 0xff);
@ -577,16 +591,16 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
endframe = GetCountSspClk(); endframe = GetCountSspClk();
//*dest = FelicaFrame.crc_ok; //kind of wasteful //*dest = FelicaFrame.crc_ok; //kind of wasteful
dest++; dest++;
for(int i=0; i < FelicaFrame.len; i++) { for (int i = 0; i < FelicaFrame.len; i++) {
*dest = FelicaFrame.framebytes[i]; *dest = FelicaFrame.framebytes[i];
dest++; dest++;
if (dest >= destend ) break; if (dest >= destend) break;
} }
remFrames--; remFrames--;
if (remFrames <= 0) break; if (remFrames <= 0) break;
if (dest >= destend ) break; if (dest >= destend) break;
numbts += FelicaFrame.len; numbts += FelicaFrame.len;
@ -602,7 +616,7 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
set_tracelen(numbts); set_tracelen(numbts);
Dbprintf("Felica sniffing done, tracelen: %i, use hf list felica for annotations", BigBuf_get_traceLen()); 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 #define R_POLL0_LEN 0x16
@ -610,7 +624,8 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
#define R_READBLK_LEN 0x21 #define R_READBLK_LEN 0x21
//simulate NFC Tag3 card - for now only poll response works //simulate NFC Tag3 card - for now only poll response works
// second half (4 bytes) of NDEF2 goes into nfcid2_0, first into nfcid2_1 // 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; int i, curlen = 0;
uint8_t *curresp = 0; uint8_t *curresp = 0;
@ -619,21 +634,21 @@ void felica_sim_lite(uint64_t nfcid) {
num_to_bytes(nfcid, 8, ndef); num_to_bytes(nfcid, 8, ndef);
//prepare our 3 responses... //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_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_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_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 //NFC tag 3/ ISo technically. Many overlapping standards
DbpString("Felica Lite-S sim start"); DbpString("Felica Lite-S sim start");
Dbprintf("NDEF2 UID: %02x %02x %02x %02x %02x %02x %02x %02x", Dbprintf("NDEF2 UID: %02x %02x %02x %02x %02x %02x %02x %02x",
ndef[0], ndef[1], ndef[2], ndef[3], ndef[4], ndef[5], ndef[6], ndef[7] ndef[0], ndef[1], ndef[2], ndef[3], ndef[4], ndef[5], ndef[6], ndef[7]
); );
//fill in blanks //fill in blanks
for( i=0; i<8; i++) { for (i = 0; i < 8; i++) {
resp_poll0[i+4] = ndef[i]; resp_poll0[i + 4] = ndef[i];
resp_poll1[i+4] = ndef[i]; resp_poll1[i + 4] = ndef[i];
resp_readblk[i+4] = ndef[i]; resp_readblk[i + 4] = ndef[i];
} }
//calculate and set CRC //calculate and set CRC
@ -641,12 +656,12 @@ void felica_sim_lite(uint64_t nfcid) {
AddCrc(resp_poll1, resp_poll1[2]); AddCrc(resp_poll1, resp_poll1[2]);
AddCrc(resp_readblk, resp_readblk[2]); AddCrc(resp_readblk, resp_readblk[2]);
iso18092_setup( FPGA_HF_ISO18092_FLAG_NOMOD); iso18092_setup(FPGA_HF_ISO18092_FLAG_NOMOD);
bool listenmode = true; bool listenmode = true;
//uint32_t frtm = GetCountSspClk(); //uint32_t frtm = GetCountSspClk();
for(;;) { for (;;) {
if( BUTTON_PRESS()) break; if (BUTTON_PRESS()) break;
WDT_HIT(); WDT_HIT();
if (listenmode) { if (listenmode) {
@ -716,11 +731,12 @@ void felica_sim_lite(uint64_t nfcid) {
DbpString("Felica Lite-S sim end"); DbpString("Felica Lite-S sim end");
} }
void felica_dump_lite_s() { void felica_dump_lite_s()
{
uint8_t ndef[8]; uint8_t ndef[8];
uint8_t poll[10] = { 0xb2,0x4d,0x06,FELICA_POLL_REQ,0xff,0xff,0x00,0x00,0x09,0x21}; 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}; 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. // setup device.
iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD);
@ -743,15 +759,15 @@ void felica_dump_lite_s() {
// copy 8bytes to ndef. // copy 8bytes to ndef.
memcpy(ndef, FelicaFrame.framebytes + 4, 8); memcpy(ndef, FelicaFrame.framebytes + 4, 8);
// for (c=0; c < 8; c++) // for (c=0; c < 8; c++)
// ndef[c] = FelicaFrame.framebytes[c+4]; // ndef[c] = FelicaFrame.framebytes[c+4];
for (blknum=0; blknum < sizeof(liteblks); ) { for (blknum = 0; blknum < sizeof(liteblks);) {
// block to read. // block to read.
BuildFliteRdblk(ndef, 1, &liteblks[blknum]); BuildFliteRdblk(ndef, 1, &liteblks[blknum]);
//TransmitFor18092_AsReader(frameSpace, frameSpace[2]+4, GetCountSspClk()+512, 1, 0); //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 // read block
if (WaitForFelicaReply(1024) && FelicaFrame.framebytes[3] == FELICA_RDBLK_ACK) { 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); //memcpy(dest+cnt, FelicaFrame.framebytes + 15, 16);
//cnt += 16; //cnt += 16;
for(uint8_t j=0; j < 16; j++) for (uint8_t j = 0; j < 16; j++)
dest[cnt++] = fb[15+j]; dest[cnt++] = fb[15 + j];
blknum++; blknum++;
cntfails = 0; cntfails = 0;
// // print raw log. // // print raw log.
// Dbprintf("LEN %u | Dump bytes count %u ", FelicaFrame.len, cnt); // 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 { } else {
cntfails++; cntfails++;
if (cntfails > 12) { if (cntfails > 12) {

View file

@ -13,13 +13,15 @@
uint32_t FLASHMEM_SPIBAUDRATE = FLASH_BAUD; 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); FLASHMEM_SPIBAUDRATE = baudrate;
Dbprintf("Spi Baudrate : %dMhz", FLASHMEM_SPIBAUDRATE / 1000000);
} }
// initialize // initialize
bool FlashInit() { bool FlashInit()
{
FlashSetup(FLASHMEM_SPIBAUDRATE); FlashSetup(FLASHMEM_SPIBAUDRATE);
StartTicks(); StartTicks();
@ -32,8 +34,9 @@ bool FlashInit() {
return true; return true;
} }
void FlashSetup(uint32_t baudrate){ void FlashSetup(uint32_t baudrate)
//WDT_DISABLE {
//WDT_DISABLE
AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS; AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS;
// PA10 -> SPI_NCS2 chip select (FLASHMEM) // PA10 -> SPI_NCS2 chip select (FLASHMEM)
@ -68,13 +71,13 @@ void FlashSetup(uint32_t baudrate){
// NPCS2 Mode 0 // NPCS2 Mode 0
AT91C_BASE_SPI->SPI_MR = AT91C_BASE_SPI->SPI_MR =
(0 << 24) | // Delay between chip selects = DYLBCS/MCK BUT: (0 << 24) | // Delay between chip selects = DYLBCS/MCK BUT:
// If DLYBCS is less than or equal to six, six MCK periods // If DLYBCS is less than or equal to six, six MCK periods
// will be inserted by default. // will be inserted by default.
SPI_PCS(SPI_CSR_NUM) | // Peripheral Chip Select (selects SPI_NCS2 or PA10) SPI_PCS(SPI_CSR_NUM) | // Peripheral Chip Select (selects SPI_NCS2 or PA10)
( 0 << 7) | // Disable LLB (1=MOSI2MISO test mode) (0 << 7) | // Disable LLB (1=MOSI2MISO test mode)
( 1 << 4) | // Disable ModeFault Protection (1 << 4) | // Disable ModeFault Protection
( 0 << 3) | // makes spi operate at MCK (1 is MCK/2) (0 << 3) | // makes spi operate at MCK (1 is MCK/2)
( 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_PS_FIXED | // Fixed Peripheral Select
AT91C_SPI_MSTR; // Master Mode AT91C_SPI_MSTR; // Master Mode
@ -87,17 +90,17 @@ void FlashSetup(uint32_t baudrate){
} }
AT91C_BASE_SPI->SPI_CSR[2] = AT91C_BASE_SPI->SPI_CSR[2] =
SPI_DLYBCT(dlybct,MCK)| // Delay between Consecutive Transfers (32 MCK periods) SPI_DLYBCT(dlybct, MCK) | // Delay between Consecutive Transfers (32 MCK periods)
SPI_DLYBS(0,MCK) | // Delay Beforce SPCK CLock SPI_DLYBS(0, MCK) | // Delay Beforce SPCK CLock
SPI_SCBR(baudrate,MCK)| // SPI Baudrate Selection SPI_SCBR(baudrate, MCK) | // SPI Baudrate Selection
AT91C_SPI_BITS_8 | // Bits per Transfer (8 bits) AT91C_SPI_BITS_8 | // Bits per Transfer (8 bits)
//AT91C_SPI_CSAAT | // Chip Select inactive after transfer //AT91C_SPI_CSAAT | // Chip Select inactive after transfer
// 40.4.6.2 SPI: Bad tx_ready Behavior when CSAAT = 1 and SCBR = 1 // 40.4.6.2 SPI: Bad tx_ready Behavior when CSAAT = 1 and SCBR = 1
// If the SPI is programmed with CSAAT = 1, SCBR(baudrate) = 1 and two transfers are performed consecutively on // If the SPI is programmed with CSAAT = 1, SCBR(baudrate) = 1 and two transfers are performed consecutively on
// the same slave with an IDLE state between them, the tx_ready signal does not rise after the second data has been // 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. // 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 // 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: /* Spi modes:
Mode CPOL CPHA NCPHA Mode CPOL CPHA NCPHA
0 0 0 1 clock normally low read on rising edge 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 2 1 0 0 clock normally high read on falling edge
3 1 1 1 clock normally high read on rising 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 << 1) | // 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
// read first, empty buffer // read first, empty buffer
if (AT91C_BASE_SPI->SPI_RDR == 0) {}; if (AT91C_BASE_SPI->SPI_RDR == 0) {};
} }
void FlashStop(void) { void FlashStop(void)
{
//Bof //Bof
//* Reset all the Chip Select register //* Reset all the Chip Select register
AT91C_BASE_SPI->SPI_CSR[0] = 0; AT91C_BASE_SPI->SPI_CSR[0] = 0;
@ -144,13 +148,14 @@ void FlashStop(void) {
// SPI disable // SPI disable
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS; AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS;
if ( MF_DBGLEVEL > 3 ) Dbprintf("FlashStop"); if (MF_DBGLEVEL > 3) Dbprintf("FlashStop");
StopTicks(); StopTicks();
} }
// send one byte over SPI // send one byte over SPI
uint16_t FlashSendByte(uint32_t data) { uint16_t FlashSendByte(uint32_t data)
{
// wait until SPI is ready for transfer // wait until SPI is ready for transfer
//if you are checking for incoming data returned then the TXEMPTY flag is redundant //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){}; //while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TDRE) == 0){};
// wait recive transfer is complete // 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 // reading incoming data
return ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF); return ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF);
} }
// send last byte over SPI // send last byte over SPI
uint16_t FlashSendLastByte(uint32_t data) { uint16_t FlashSendLastByte(uint32_t data)
{
return FlashSendByte(data | AT91C_SPI_LASTXFER); return FlashSendByte(data | AT91C_SPI_LASTXFER);
} }
// read state register 1 // read state register 1
uint8_t Flash_ReadStat1(void) { uint8_t Flash_ReadStat1(void)
{
FlashSendByte(READSTAT1); FlashSendByte(READSTAT1);
return FlashSendLastByte(0xFF); return FlashSendLastByte(0xFF);
} }
@ -185,18 +192,15 @@ bool Flash_CheckBusy(uint32_t timeout)
StartCountUS(); StartCountUS();
uint32_t _time = GetCountUS(); uint32_t _time = GetCountUS();
if ( MF_DBGLEVEL > 3 ) Dbprintf("Checkbusy in..."); if (MF_DBGLEVEL > 3) Dbprintf("Checkbusy in...");
do do {
{ if (!(Flash_ReadStat1() & BUSY)) {
if (!(Flash_ReadStat1() & BUSY))
{
return false; return false;
} }
} while ((GetCountUS() - _time) < timeout); } while ((GetCountUS() - _time) < timeout);
if (timeout <= (GetCountUS() - _time)) if (timeout <= (GetCountUS() - _time)) {
{
return true; return true;
} }
@ -204,7 +208,8 @@ bool Flash_CheckBusy(uint32_t timeout)
} }
// read ID out // read ID out
uint8_t Flash_ReadID(void) { uint8_t Flash_ReadID(void)
{
if (Flash_CheckBusy(BUSY_TIMEOUT)) return 0; if (Flash_CheckBusy(BUSY_TIMEOUT)) return 0;
@ -217,16 +222,17 @@ uint8_t Flash_ReadID(void) {
uint8_t man_id = FlashSendByte(0xFF); uint8_t man_id = FlashSendByte(0xFF);
uint8_t dev_id = FlashSendLastByte(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 dev_id;
return 0; return 0;
} }
// read unique id for chip. // read unique id for chip.
void Flash_UniqueID(uint8_t *uid) { void Flash_UniqueID(uint8_t *uid)
{
if (Flash_CheckBusy(BUSY_TIMEOUT)) return; if (Flash_CheckBusy(BUSY_TIMEOUT)) return;
@ -247,7 +253,8 @@ void Flash_UniqueID(uint8_t *uid) {
uid[0] = FlashSendLastByte(0xFF); 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; if (!FlashInit()) return 0;
@ -259,7 +266,7 @@ uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) {
FlashSendByte(cmd); FlashSendByte(cmd);
Flash_TransferAdresse(address); Flash_TransferAdresse(address);
if (FASTFLASH){ if (FASTFLASH) {
FlashSendByte(DUMMYBYTE); FlashSendByte(DUMMYBYTE);
} }
@ -272,14 +279,16 @@ uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) {
return len; return len;
} }
void Flash_TransferAdresse(uint32_t address){ void Flash_TransferAdresse(uint32_t address)
{
FlashSendByte((address >> 16) & 0xFF); FlashSendByte((address >> 16) & 0xFF);
FlashSendByte((address >> 8) & 0xFF); FlashSendByte((address >> 8) & 0xFF);
FlashSendByte((address >> 0) & 0xFF); FlashSendByte((address >> 0) & 0xFF);
} }
/* This ensure we can ReadData without having to cycle through initialization everytime */ /* 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 // length should never be zero
if (!len) return 0; if (!len) return 0;
@ -289,7 +298,7 @@ uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) {
FlashSendByte(cmd); FlashSendByte(cmd);
Flash_TransferAdresse(address); Flash_TransferAdresse(address);
if (FASTFLASH){ if (FASTFLASH) {
FlashSendByte(DUMMYBYTE); 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. // Write data can only program one page. A page has 256 bytes.
// if len > 256, it might wrap around and overwrite pos 0. // 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 // length should never be zero
if (!len) if (!len)
@ -313,18 +323,18 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
// Max 256 bytes write // Max 256 bytes write
if (((address & 0xFF) + len) > 256) { 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; return 0;
} }
// out-of-range // out-of-range
if ( (( address >> 16 ) & 0xFF ) > MAX_BLOCKS) { if (((address >> 16) & 0xFF) > MAX_BLOCKS) {
Dbprintf("Flash_WriteData, block out-of-range"); Dbprintf("Flash_WriteData, block out-of-range");
return 0; return 0;
} }
if (!FlashInit()) { if (!FlashInit()) {
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); if (MF_DBGLEVEL > 3) Dbprintf("Flash_WriteData init fail");
return 0; return 0;
} }
@ -351,17 +361,18 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
// length should never be zero // length should never be zero
// Max 256 bytes write // Max 256 bytes write
// out-of-range // 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) if (!len)
return 0; return 0;
if (((address & 0xFF) + len) > 256) { 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; return 0;
} }
if ( (( address >> 16 ) & 0xFF ) > MAX_BLOCKS) { if (((address >> 16) & 0xFF) > MAX_BLOCKS) {
Dbprintf("Flash_WriteDataCont, block out-of-range"); Dbprintf("Flash_WriteDataCont, block out-of-range");
return 0; 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 // 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; bool isok;
uint16_t res, bytes_sent = 0, bytes_remaining = len; 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 (!FlashInit()) {
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); if (MF_DBGLEVEL > 3) Dbprintf("Flash_WriteData init fail");
return false; return false;
} }
Flash_ReadStat1(); Flash_ReadStat1();
// Each block is 64Kb. One block erase takes 1s ( 1000ms ) // 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(); FlashStop();
return true; return true;
} }
// Wipes flash memory completely, fills with 0xFF // Wipes flash memory completely, fills with 0xFF
bool Flash_WipeMemory() { bool Flash_WipeMemory()
{
if (!FlashInit()) { if (!FlashInit()) {
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); if (MF_DBGLEVEL > 3) Dbprintf("Flash_WriteData init fail");
return false; return false;
} }
Flash_ReadStat1(); Flash_ReadStat1();
// Each block is 64Kb. Four blocks // Each block is 64Kb. Four blocks
// one block erase takes 1s ( 1000ms ) // one block erase takes 1s ( 1000ms )
Flash_WriteEnable(); Flash_Erase64k(0); Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable();
Flash_WriteEnable(); Flash_Erase64k(1); Flash_CheckBusy(BUSY_TIMEOUT); Flash_Erase64k(0);
Flash_WriteEnable(); Flash_Erase64k(2); Flash_CheckBusy(BUSY_TIMEOUT); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable(); Flash_Erase64k(3); 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(); FlashStop();
return true; return true;
} }
// enable the flash write // enable the flash write
void Flash_WriteEnable() { void Flash_WriteEnable()
{
FlashSendLastByte(WRITEENABLE); FlashSendLastByte(WRITEENABLE);
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash Write enabled"); if (MF_DBGLEVEL > 3) Dbprintf("Flash Write enabled");
} }
// erase 4K at one time // erase 4K at one time
// execution time: 0.8ms / 800us // 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; 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 // 0x01 00 00 -- 0x 01 FF FF == block 1
// 0x02 00 00 -- 0x 02 FF FF == block 2 // 0x02 00 00 -- 0x 02 FF FF == block 2
// 0x03 00 00 -- 0x 03 FF FF == block 3 // 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; if (block > MAX_BLOCKS) return false;
@ -499,13 +526,15 @@ bool Flash_Erase64k(uint8_t block) {
} }
// Erase chip // Erase chip
void Flash_EraseChip(void) { void Flash_EraseChip(void)
{
FlashSendLastByte(CHIPERASE); FlashSendLastByte(CHIPERASE);
} }
void Flashmem_print_status(void) { void Flashmem_print_status(void)
{
DbpString("Flash memory"); DbpString("Flash memory");
Dbprintf(" Baudrate................%dMHz",FLASHMEM_SPIBAUDRATE/1000000); Dbprintf(" Baudrate................%dMHz", FLASHMEM_SPIBAUDRATE / 1000000);
if (!FlashInit()) { if (!FlashInit()) {
DbpString(" Init....................FAIL"); DbpString(" Init....................FAIL");
@ -529,12 +558,12 @@ void Flashmem_print_status(void) {
break; 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); Flash_UniqueID(uid);
Dbprintf(" Unique ID...............0x%02x%02x%02x%02x%02x%02x%02x%02x", Dbprintf(" Unique ID...............0x%02x%02x%02x%02x%02x%02x%02x%02x",
uid[7], uid[6], uid[5], uid[4], uid[7], uid[6], uid[5], uid[4],
uid[3], uid[2], uid[1], uid[0] uid[3], uid[2], uid[1], uid[0]
); );
FlashStop(); FlashStop();
} }

View file

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

View file

@ -28,7 +28,8 @@ static uint32_t uncompressed_bytes_cnt;
// Used to write the FPGA config word // Used to write the FPGA config word
// May also be used to write to other SPI attached devices like an LCD // 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 //* Reset all the Chip Select register
AT91C_BASE_SPI->SPI_CSR[0] = 0; AT91C_BASE_SPI->SPI_CSR[0] = 0;
AT91C_BASE_SPI->SPI_CSR[1] = 0; AT91C_BASE_SPI->SPI_CSR[1] = 0;
@ -45,7 +46,8 @@ static void DisableSpi(void) {
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS; AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS;
} }
void SetupSpi(int mode) { void SetupSpi(int mode)
{
// PA1 -> SPI_NCS3 chip select (MEM) // PA1 -> SPI_NCS3 chip select (MEM)
// PA10 -> SPI_NCS2 chip select (LCD) // PA10 -> SPI_NCS2 chip select (LCD)
// PA11 -> SPI_NCS0 chip select (FPGA) // PA11 -> SPI_NCS0 chip select (FPGA)
@ -70,44 +72,44 @@ void SetupSpi(int mode) {
switch (mode) { switch (mode) {
case SPI_FPGA_MODE: case SPI_FPGA_MODE:
AT91C_BASE_SPI->SPI_MR = 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) (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 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_PS_FIXED | // Fixed Peripheral Select
AT91C_SPI_MSTR; // Master Mode AT91C_SPI_MSTR; // Master Mode
AT91C_BASE_SPI->SPI_CSR[0] = AT91C_BASE_SPI->SPI_CSR[0] =
( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods) (1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
( 1 << 16) | // Delay Before SPCK (1 MCK period) (1 << 16) | // Delay Before SPCK (1 MCK period)
( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud (6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud
AT91C_SPI_BITS_16 | // Bits per Transfer (16 bits) 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 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; break;
/* /*
case SPI_LCD_MODE: case SPI_LCD_MODE:
AT91C_BASE_SPI->SPI_MR = 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)
(0xB << 16) | // Peripheral Chip Select (selects LCD SPI_NCS2 or PA10) (0xB << 16) | // Peripheral Chip Select (selects LCD SPI_NCS2 or PA10)
( 0 << 7) | // Local Loopback Disabled ( 0 << 7) | // Local Loopback Disabled
( 1 << 4) | // Mode Fault Detection disabled ( 1 << 4) | // Mode Fault Detection disabled
( 0 << 2) | // Chip selects connected directly to peripheral ( 0 << 2) | // Chip selects connected directly to peripheral
( 0 << 1) | // Fixed Peripheral Select ( 0 << 1) | // Fixed Peripheral Select
( 1 << 0); // Master Mode ( 1 << 0); // Master Mode
AT91C_BASE_SPI->SPI_CSR[2] = AT91C_BASE_SPI->SPI_CSR[2] =
( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods) ( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
( 1 << 16) | // Delay Before SPCK (1 MCK period) ( 1 << 16) | // Delay Before SPCK (1 MCK period)
( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud ( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud
AT91C_SPI_BITS_9 | // Bits per Transfer (9 bits) AT91C_SPI_BITS_9 | // Bits per Transfer (9 bits)
( 0 << 3) | // Chip Select inactive after transfer ( 0 << 3) | // Chip Select inactive after transfer
( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge ( 1 << 1) | // 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; break;
*/ */
default: default:
DisableSpi(); DisableSpi();
break; break;
@ -118,7 +120,8 @@ void SetupSpi(int mode) {
// Set up the synchronous serial port, with the one set of options that we // 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. // 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. // First configure the GPIOs, and get ourselves a clock.
AT91C_BASE_PIOA->PIO_ASR = AT91C_BASE_PIOA->PIO_ASR =
GPIO_SSC_FRAME | GPIO_SSC_FRAME |
@ -127,7 +130,7 @@ void FpgaSetupSsc(void) {
GPIO_SSC_CLK; GPIO_SSC_CLK;
AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT;
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SSC); AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SSC);
// Now set up the SSC proper, starting from a known state. // Now set up the SSC proper, starting from a known state.
AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST; AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST;
@ -156,7 +159,8 @@ void FpgaSetupSsc(void) {
// ourselves, not to another buffer). The stuff to manipulate those buffers // ourselves, not to another buffer). The stuff to manipulate those buffers
// is in apps.h, because it should be inlined, for speed. // 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; if (buf == NULL) return false;
FpgaDisableSscDma(); FpgaDisableSscDma();
@ -172,7 +176,8 @@ bool FpgaSetupSscDma(uint8_t *buf, int len) {
// Uncompress (inflate) the FPGA data. Returns one decompressed byte with // Uncompress (inflate) the FPGA data. Returns one decompressed byte with
// each call. // 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 if (fpga_image_ptr == compressed_fpga_stream->next_out) { // need more data
compressed_fpga_stream->next_out = output_buffer; compressed_fpga_stream->next_out = output_buffer;
compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN; 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: // are combined into one big file:
// 288 bytes from FPGA file 1, followed by 288 bytes from FGPA file 2, etc. // 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) { 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)) { {
while ((uncompressed_bytes_cnt / FPGA_INTERLEAVE_SIZE) % fpga_bitstream_num != (bitstream_version - 1)) {
// skip undesired data belonging to other bitstream_versions // skip undesired data belonging to other bitstream_versions
get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer); 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); return get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer);
} }
static voidpf fpga_inflate_malloc(voidpf opaque, uInt items, uInt size) { static voidpf fpga_inflate_malloc(voidpf opaque, uInt items, uInt size)
return BigBuf_malloc(items*size); {
return BigBuf_malloc(items * size);
} }
// free eventually allocated BigBuf memory // free eventually allocated BigBuf memory
static void fpga_inflate_free(voidpf opaque, voidpf address) { static void fpga_inflate_free(voidpf opaque, voidpf address)
BigBuf_free(); BigBuf_Clear_ext(false); {
BigBuf_free();
BigBuf_Clear_ext(false);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Initialize decompression of the respective (HF or LF) FPGA stream // 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]; uint8_t header[FPGA_BITSTREAM_FIXED_HEADER_SIZE];
uncompressed_bytes_cnt = 0; uncompressed_bytes_cnt = 0;
@ -242,7 +252,8 @@ static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_s
return false; 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); } #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(7);
SEND_BIT(6); 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 // 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; int i = 0;
AT91C_BASE_PIOA->PIO_OER = GPIO_FPGA_ON; 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; i = 100000;
// wait for FPGA ready to accept data signal // 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--; i--;
} }
// crude error indicator, leave both red LEDs on and return // crude error indicator, leave both red LEDs on and return
if (i==0){ if (i == 0) {
LED_C_ON(); LED_C_ON();
LED_D_ON(); LED_D_ON();
return; 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 // continue to clock FPGA until ready signal goes high
i = 100000; i = 100000;
while ( (i--) && ( !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_DONE ) ) ) { while ((i--) && (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_DONE))) {
HIGH(GPIO_FPGA_CCLK); HIGH(GPIO_FPGA_CCLK);
LOW(GPIO_FPGA_CCLK); LOW(GPIO_FPGA_CCLK);
} }
// crude error indicator, leave both red LEDs on and return // crude error indicator, leave both red LEDs on and return
if (i==0){ if (i == 0) {
LED_C_ON(); LED_C_ON();
LED_D_ON(); LED_D_ON();
return; 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 * (big endian), <length> bytes content. Except for section 'e' which has 4 bytes
* length. * 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; 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; 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); char current_name = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
numbytes++; numbytes++;
uint32_t current_length = 0; uint32_t current_length = 0;
@ -351,15 +364,15 @@ static int bitparse_find_section(int bitstream_version, char section_name, uint3
} }
current_length = 0; current_length = 0;
switch (current_name) { switch (current_name) {
case 'e': case 'e':
/* Four byte length field */ /* Four byte length field */
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 24; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 24;
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 16; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 16;
numbytes += 2; numbytes += 2;
default: /* Fall through, two byte length field */ default: /* Fall through, two byte length field */
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 8; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 8;
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 0; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 0;
numbytes += 2; numbytes += 2;
} }
if (current_name != 'e' && current_length > 255) { if (current_name != 'e' && current_length > 255) {
@ -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 // Check which FPGA image is currently loaded (if any). If necessary
// decompress and load the correct (HF or LF) image to the FPGA // 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 // check whether or not the bitstream is already loaded
if (downloaded_bitstream == bitstream_version) if (downloaded_bitstream == bitstream_version)
@ -398,7 +412,8 @@ void FpgaDownloadAndGo(int bitstream_version) {
bool verbose = (MF_DBGLEVEL > 3); bool verbose = (MF_DBGLEVEL > 3);
// make sure that we have enough memory to decompress // 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)) if (!reset_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer))
return; return;
@ -415,7 +430,8 @@ void FpgaDownloadAndGo(int bitstream_version) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
// free eventually allocated BigBuf memory // 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 // 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 // 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); SetupSpi(SPI_FPGA_MODE);
while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); // wait for the transfer to complete 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 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 // vs. clone vs. etc.). This is now a special case of FpgaSendCommand() to
// avoid changing this function's occurence everywhere in the source code. // 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); 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 // closable, but should only close one at a time. Not an FPGA thing, but
// the samples from the ADC always flow through the FPGA. // 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 = AT91C_BASE_PIOA->PIO_OER =
GPIO_MUXSEL_HIPKD | GPIO_MUXSEL_HIPKD |
GPIO_MUXSEL_LOPKD | GPIO_MUXSEL_LOPKD |
@ -466,12 +485,14 @@ void SetAdcMuxFor(uint32_t whichGpio) {
HIGH(whichGpio); HIGH(whichGpio);
} }
void Fpga_print_status(void) { void Fpga_print_status(void)
{
Dbprintf("Currently loaded FPGA image"); 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; return downloaded_bitstream;
} }
@ -479,10 +500,11 @@ int FpgaGetCurrent(void) {
// log message // log message
// if HF, Disable SSC DMA // if HF, Disable SSC DMA
// turn off trace and leds off. // turn off trace and leds off.
void switch_off(void) { void switch_off(void)
{
if (MF_DBGLEVEL > 3) Dbprintf("switch_off"); if (MF_DBGLEVEL > 3) Dbprintf("switch_off");
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
if (downloaded_bitstream == FPGA_BITSTREAM_HF ) if (downloaded_bitstream == FPGA_BITSTREAM_HF)
FpgaDisableSscDma(); FpgaDisableSscDma();
set_tracing(false); set_tracing(false);
LEDsoff(); LEDsoff();

View file

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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -70,7 +70,7 @@ typedef struct {
STATE_MILLER_Z, STATE_MILLER_Z,
// DROP_NONE, // DROP_NONE,
// DROP_FIRST_HALF, // DROP_FIRST_HALF,
} state; } state;
uint16_t shiftReg; uint16_t shiftReg;
int16_t bitCount; int16_t bitCount;
uint16_t len; uint16_t len;
@ -95,10 +95,10 @@ typedef struct {
extern void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par); 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 DemodReset(void);
extern void DemodInit(uint8_t *data, uint8_t *parity); extern void DemodInit(uint8_t *data, uint8_t *parity);
extern tUart* GetUart(void); extern tUart *GetUart(void);
extern void UartReset(void); extern void UartReset(void);
extern void UartInit(uint8_t *data, uint8_t *parity); extern void UartInit(uint8_t *data, uint8_t *parity);
extern RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time); 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); //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(); void DetectNACKbug();
#ifdef __cplusplus #ifdef __cplusplus

View file

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

View file

@ -37,11 +37,11 @@ extern "C" {
extern void SendRawCommand14443B_Ex(UsbCommand *c); extern void SendRawCommand14443B_Ex(UsbCommand *c);
extern void iso14443b_setup(); extern void iso14443b_setup();
extern uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response); 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(iso14b_card_select_t *card);
extern uint8_t iso14443b_select_card_srx(iso14b_card_select_t* card); extern uint8_t iso14443b_select_card_srx(iso14b_card_select_t *card);
// testfunctions // testfunctions
extern void WaitForFpgaDelayQueueIsEmpty( uint16_t delay ); extern void WaitForFpgaDelayQueueIsEmpty(uint16_t delay);
extern void ClearFpgaShiftingRegisters(void); extern void ClearFpgaShiftingRegisters(void);
// States for 14B SIM command // 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) // resulting data rate is 26,48 kbit/s (fc/512)
// cmd ... data // cmd ... data
// n ... length of data // n ... length of data
static void CodeIso15693AsReader(uint8_t *cmd, int n) { static void CodeIso15693AsReader(uint8_t *cmd, int n)
{
int i, j; int i, j;
ToSendReset(); ToSendReset();
// Give it a bit of slack at the beginning // Give it a bit of slack at the beginning
for(i = 0; i < 24; i++) for (i = 0; i < 24; i++)
ToSendStuffBit(1); ToSendStuffBit(1);
// SOF for 1of4 // SOF for 1of4
@ -117,10 +118,10 @@ static void CodeIso15693AsReader(uint8_t *cmd, int n) {
ToSendStuffBit(0); ToSendStuffBit(0);
ToSendStuffBit(1); ToSendStuffBit(1);
ToSendStuffBit(1); ToSendStuffBit(1);
for(i = 0; i < n; i++) { for (i = 0; i < n; i++) {
for(j = 0; j < 8; j += 2) { for (j = 0; j < 8; j += 2) {
int these = (cmd[i] >> j) & 3; int these = (cmd[i] >> j) & 3;
switch(these) { switch (these) {
case 0: case 0:
ToSendStuffBit(1); ToSendStuffBit(1);
ToSendStuffBit(0); ToSendStuffBit(0);
@ -171,20 +172,21 @@ static void CodeIso15693AsReader(uint8_t *cmd, int n) {
ToSendStuffBit(1); ToSendStuffBit(1);
// And slack at the end, too. // And slack at the end, too.
for(i = 0; i < 24; i++) for (i = 0; i < 24; i++)
ToSendStuffBit(1); ToSendStuffBit(1);
} }
// encode data using "1 out of 256" sheme // encode data using "1 out of 256" sheme
// data rate is 1,66 kbit/s (fc/8192) // data rate is 1,66 kbit/s (fc/8192)
// is designed for more robust communication over longer distances // 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; int i, j;
ToSendReset(); ToSendReset();
// Give it a bit of slack at the beginning // Give it a bit of slack at the beginning
for(i = 0; i < 24; i++) for (i = 0; i < 24; i++)
ToSendStuffBit(1); ToSendStuffBit(1);
// SOF for 1of256 // SOF for 1of256
@ -197,7 +199,7 @@ static void CodeIso15693AsReader256(uint8_t *cmd, int n) {
ToSendStuffBit(1); ToSendStuffBit(1);
ToSendStuffBit(0); ToSendStuffBit(0);
for(i = 0; i < n; i++) { for (i = 0; i < n; i++) {
for (j = 0; j <= 255; j++) { for (j = 0; j <= 255; j++) {
if (cmd[i] == j) { if (cmd[i] == j) {
ToSendStuffBit(1); ToSendStuffBit(1);
@ -215,12 +217,13 @@ static void CodeIso15693AsReader256(uint8_t *cmd, int n) {
ToSendStuffBit(1); ToSendStuffBit(1);
// And slack at the end, too. // And slack at the end, too.
for(i = 0; i < 24; i++) for (i = 0; i < 24; i++)
ToSendStuffBit(1); ToSendStuffBit(1);
} }
// Transmit the command (to the tag) that was placed in ToSend[]. // 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; int c;
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX); 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; c = 0;
for(;;) { for (;;) {
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = cmd[c]; AT91C_BASE_SSC->SSC_THR = cmd[c];
if( ++c >= len) break; if (++c >= len) break;
} }
WDT_HIT(); 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[]. // 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; int c = 0;
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_424K); 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; c = 0;
for(;;) { for (;;) {
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = cmd[c]; AT91C_BASE_SSC->SSC_THR = cmd[c];
if( ++c >= len) break; if (++c >= len) break;
} }
WDT_HIT(); WDT_HIT();
} }
@ -288,7 +292,8 @@ static void TransmitTo15693Reader(const uint8_t *cmd, int len, int *samples, int
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// DEMODULATE tag answer // 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 i, j;
int max = 0, maxPos = 0, skip = 4; 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 // First, correlate for SOF
for (i = 0; i < samplecount; i++) { for (i = 0; i < samplecount; i++) {
int corr = 0; int corr = 0;
for ( j = 0; j < ARRAYLEN(FrameSOF); j += skip) { for (j = 0; j < ARRAYLEN(FrameSOF); j += skip) {
corr += FrameSOF[j] * dest[i+(j/skip)]; corr += FrameSOF[j] * dest[i + (j / skip)];
} }
if (corr > max) { if (corr > max) {
max = corr; 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)); // 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 // 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; return k;
i = maxPos + ARRAYLEN(FrameSOF) / skip; i = maxPos + ARRAYLEN(FrameSOF) / skip;
@ -316,22 +321,22 @@ static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) {
uint8_t outBuf[ISO15_MAX_FRAME]; uint8_t outBuf[ISO15_MAX_FRAME];
memset(outBuf, 0, sizeof(outBuf)); memset(outBuf, 0, sizeof(outBuf));
uint8_t mask = 0x01; uint8_t mask = 0x01;
for(;;) { for (;;) {
int corr0 = 0, corr1 = 0, corrEOF = 0; int corr0 = 0, corr1 = 0, corrEOF = 0;
for (j = 0; j < ARRAYLEN(Logic0); j += skip) { 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) { 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) { 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. // Even things out by the length of the target waveform.
corr0 *= 4; corr0 *= 4;
corr1 *= 4; corr1 *= 4;
// if (MF_DBGLEVEL >= MF_DBG_EXTENDED) // if (MF_DBGLEVEL >= MF_DBG_EXTENDED)
// Dbprintf("Corr1 %d, Corr0 %d, CorrEOF %d", corr1, corr0, corrEOF); // Dbprintf("Corr1 %d, Corr0 %d, CorrEOF %d", corr1, corr0, corrEOF);
if (corrEOF > corr1 && corrEOF > corr0) if (corrEOF > corr1 && corrEOF > corr0)
break; break;
@ -350,7 +355,7 @@ static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) {
mask = 0x01; 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); //Dbprintf("[!] ran off end! %d | %d",( i + (int)ARRAYLEN(FrameEOF)), samplecount-1);
break; 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 // 0x08 is an assumption - but works quite often
} }
for(i = 0; i < k; i++) for (i = 0; i < k; i++)
received[i] = outBuf[i]; received[i] = outBuf[i];
// return the number of bytes demodulated // return the number of bytes demodulated
@ -381,7 +386,8 @@ static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) {
// returns: // returns:
// number of decoded bytes // number of decoded bytes
// logging enabled // logging enabled
static int GetIso15693AnswerFromTag(uint8_t *received, int *elapsed) { static int GetIso15693AnswerFromTag(uint8_t *received, int *elapsed)
{
#define SIGNAL_BUFF_SIZE 15000 #define SIGNAL_BUFF_SIZE 15000
// get current clock // get current clock
@ -395,13 +401,13 @@ static int GetIso15693AnswerFromTag(uint8_t *received, int *elapsed) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
for(;;) { for (;;) {
WDT_HIT(); 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 = 0x00; //0x43; AT91C_BASE_SSC->SSC_THR = 0x00; //0x43;
// To make use of exact timing of next command from reader!! // 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)) { 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)) // iceman 2016, amplitude sqrt(abs(i) + abs(q))
if (getNext) { 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) if (counter >= SIGNAL_BUFF_SIZE)
break; break;
@ -435,7 +441,8 @@ static int GetIso15693AnswerFromTag(uint8_t *received, int *elapsed) {
// Now the GetISO15693 message from sniffing command // Now the GetISO15693 message from sniffing command
// logging enable, // 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; bool getNext = false;
int counter = 0, ci = 0, cq = 0; 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); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
for(;;) { for (;;) {
WDT_HIT(); WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
@ -461,12 +468,12 @@ static int GetIso15693AnswerFromSniff(uint8_t *received, int *samples, int *elap
// close to what we want. // close to what we want.
if (getNext) { 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; break;
} else { } else {
cq = ci; cq = ci;
} }
getNext = !getNext; getNext = !getNext;
} }
@ -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 // 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. // so that it can be downloaded to a PC and processed there.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void AcquireRawAdcSamplesIso15693(void) { void AcquireRawAdcSamplesIso15693(void)
{
int c = 0, getNext = false; int c = 0, getNext = false;
int ci = 0, cq = 0; int ci = 0, cq = 0;
@ -503,13 +511,13 @@ void AcquireRawAdcSamplesIso15693(void) {
// sending command // sending command
c = 0; c = 0;
for(;;) { for (;;) {
WDT_HIT(); 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]; AT91C_BASE_SSC->SSC_THR = ToSend[c];
c++; c++;
if(c == ToSendMax + 3) { if (c == ToSendMax + 3) {
break; break;
} }
} }
@ -521,7 +529,7 @@ void AcquireRawAdcSamplesIso15693(void) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
c = 0; c = 0;
for(;;) { for (;;) {
WDT_HIT(); WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
@ -536,7 +544,7 @@ void AcquireRawAdcSamplesIso15693(void) {
// iceman 2016, amplitude sqrt(abs(i) + abs(q)) // iceman 2016, amplitude sqrt(abs(i) + abs(q))
if (getNext) { 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; if (c >= 7000) break;
@ -549,7 +557,8 @@ void AcquireRawAdcSamplesIso15693(void) {
} }
// switch_off, initreader, no logging // switch_off, initreader, no logging
void RecordRawAdcSamplesIso15693(void) { void RecordRawAdcSamplesIso15693(void)
{
int c = 0, getNext = false; int c = 0, getNext = false;
int ci = 0, cq = 0; int ci = 0, cq = 0;
@ -558,7 +567,7 @@ void RecordRawAdcSamplesIso15693(void) {
uint8_t *buf = BigBuf_get_addr(); uint8_t *buf = BigBuf_get_addr();
for(;;) { for (;;) {
WDT_HIT(); WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
@ -571,9 +580,9 @@ void RecordRawAdcSamplesIso15693(void) {
// close to what we want. // close to what we want.
if (getNext) { 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; break;
} else { } else {
cq = ci; cq = ci;
@ -589,7 +598,8 @@ void RecordRawAdcSamplesIso15693(void) {
// Initialize the proxmark as iso15k reader // Initialize the proxmark as iso15k reader
// (this might produces glitches that confuse some tags // (this might produces glitches that confuse some tags
void Iso15693InitReader(void) { void Iso15693InitReader(void)
{
LEDsoff(); LEDsoff();
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
@ -621,7 +631,8 @@ void Iso15693InitReader(void) {
// Encode (into the ToSend buffers) an identify request, which is the first // Encode (into the ToSend buffers) an identify request, which is the first
// thing that you must send to a tag to get a response. // 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}; uint8_t cmd[CMD_ID_RESP] = {0, ISO15_CMD_INVENTORY, 0, 0, 0};
// flags // 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 // 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 // one sub-carrier, inventory, 1 slot, fast rate
// AFI is at bit 5 (1<<4) when doing an INVENTORY // 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[] // If you do not need the answer use NULL for *recv[]
// return: lenght of received data // return: lenght of received data
// logging enabled // 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; 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 // Decodes a message from a tag and displays its metadata and content
#define DBD15STATLEN 48 #define DBD15STATLEN 48
void DbdecodeIso15693Answer(int len, uint8_t *d) { void DbdecodeIso15693Answer(int len, uint8_t *d)
char status[DBD15STATLEN+1] = {0}; {
char status[DBD15STATLEN + 1] = {0};
if (len > 3) { if (len > 3) {
if (d[0] & ( 1 << 3 )) if (d[0] & (1 << 3))
strncat(status, "ProtExt ", DBD15STATLEN); strncat(status, "ProtExt ", DBD15STATLEN);
if (d[0] & 1) { if (d[0] & 1) {
// error // error
@ -774,9 +788,9 @@ void DbdecodeIso15693Answer(int len, uint8_t *d) {
default: default:
strncat(status, "unknown error", DBD15STATLEN); strncat(status, "unknown error", DBD15STATLEN);
} }
strncat(status ," " ,DBD15STATLEN); strncat(status, " ", DBD15STATLEN);
} else { } else {
strncat(status ,"No error ", DBD15STATLEN); strncat(status, "No error ", DBD15STATLEN);
} }
if (CheckCrc(d, len)) if (CheckCrc(d, len))
@ -784,7 +798,7 @@ void DbdecodeIso15693Answer(int len, uint8_t *d) {
else else
strncat(status, "[!] crc fail", DBD15STATLEN); 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 // ok
// parameter is unused !?! // parameter is unused !?!
void ReaderIso15693(uint32_t parameter) { void ReaderIso15693(uint32_t parameter)
{
int answerLen1 = 0; int answerLen1 = 0;
int tsamples = 0, wait = 0, elapsed = 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 // set up device/fpga
Iso15693InitReader(); Iso15693InitReader();
@ -819,7 +834,7 @@ void ReaderIso15693(uint32_t parameter) {
// THIS MEANS WE CAN PRE-BUILD REQUESTS TO SAVE CPU TIME // THIS MEANS WE CAN PRE-BUILD REQUESTS TO SAVE CPU TIME
uint32_t time_start = GetCountSspClk(); uint32_t time_start = GetCountSspClk();
uint8_t cmd[CMD_ID_RESP] = {0}; uint8_t cmd[CMD_ID_RESP] = {0};
BuildIdentifyRequest( cmd ); BuildIdentifyRequest(cmd);
TransmitTo15693Tag(ToSend, ToSendMax, &tsamples, &wait); TransmitTo15693Tag(ToSend, ToSendMax, &tsamples, &wait);
LogTrace(cmd, CMD_ID_RESP, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true); LogTrace(cmd, CMD_ID_RESP, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true);
@ -837,11 +852,11 @@ void ReaderIso15693(uint32_t parameter) {
uid[6] = answer1[3]; uid[6] = answer1[3];
uid[7] = answer1[2]; 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", Dbprintf("[+] UID = %02X%02X%02X%02X%02X%02X%02X%02X",
uid[0], uid[1], uid[2], uid[3], uid[0], uid[1], uid[2], uid[3],
uid[4], uid[5], uid[5], uid[6] uid[4], uid[5], uid[5], uid[6]
); );
} }
// send UID back to client. // send UID back to client.
// arg0 = 1 = OK // arg0 = 1 = OK
@ -851,7 +866,7 @@ void ReaderIso15693(uint32_t parameter) {
cmd_send(CMD_ACK, 1, sizeof(uid), 0, uid, sizeof(uid)); 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); Dbprintf("[+] %d octets read from IDENTIFY request:", answerLen1);
DbdecodeIso15693Answer(answerLen1, answer1); DbdecodeIso15693Answer(answerLen1, answer1);
Dbhexdump(answerLen1, answer1, true); 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 // Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands
// all demodulation performed in arm rather than host. - greg // 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(); LEDsoff();
FpgaDownloadAndGo(FPGA_BITSTREAM_HF); FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
@ -890,14 +906,14 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid) {
uint8_t cmd[CMD_INV_RESP] = {0}; uint8_t cmd[CMD_INV_RESP] = {0};
BuildInventoryResponse(cmd, uid); BuildInventoryResponse(cmd, uid);
while (!BUTTON_PRESS() && !usb_poll_validate_length() ) { while (!BUTTON_PRESS() && !usb_poll_validate_length()) {
WDT_HIT(); WDT_HIT();
// Listen to reader // Listen to reader
ans = GetIso15693AnswerFromSniff(buf, &samples, &elapsed) ; ans = GetIso15693AnswerFromSniff(buf, &samples, &elapsed) ;
// we should do a better check than this // we should do a better check than this
if (ans >= 1 ) { if (ans >= 1) {
time_start = GetCountSspClk(); time_start = GetCountSspClk();
TransmitTo15693Reader(ToSend, ToSendMax, &tsamples, &wait); TransmitTo15693Reader(ToSend, ToSendMax, &tsamples, &wait);
@ -905,9 +921,9 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
Dbprintf("[+] %d octets read from reader command: %x %x %x %x %x %x %x %x", ans, Dbprintf("[+] %d octets read from reader command: %x %x %x %x %x %x %x %x", ans,
buf[0], buf[1], buf[2], buf[3], buf[0], buf[1], buf[2], buf[3],
buf[4], buf[5], buf[6], buf[7] buf[4], buf[5], buf[6], buf[7]
); );
} }
} }
} }
@ -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 // 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) // (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]; uint8_t buf[ISO15_MAX_FRAME];
memset(buf, 0x00, sizeof(buf)); memset(buf, 0x00, sizeof(buf));
int datalen = 0, recvlen = 0; int datalen = 0, recvlen = 0;
@ -939,7 +956,7 @@ void BruteforceIso15693Afi(uint32_t speed) {
WDT_HIT(); WDT_HIT();
if (recvlen >= 12) { if (recvlen >= 12) {
Dbprintf("NoAFI UID = %s", sprintUID(NULL, buf + 2) ); Dbprintf("NoAFI UID = %s", sprintUID(NULL, buf + 2));
} }
// now with AFI // now with AFI
@ -955,7 +972,7 @@ void BruteforceIso15693Afi(uint32_t speed) {
recvlen = SendDataTag(data, datalen, false, speed, buf); recvlen = SendDataTag(data, datalen, false, speed, buf);
WDT_HIT(); WDT_HIT();
if (recvlen >= 12) { 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()) { if (BUTTON_PRESS()) {
@ -970,7 +987,8 @@ void BruteforceIso15693Afi(uint32_t speed) {
// Allows to directly send commands to the tag via the client // Allows to directly send commands to the tag via the client
// Has to increase dialog between device and 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; bool init = true;
int buflen = 0; int buflen = 0;
@ -997,6 +1015,6 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint
Dbhexdump(buflen, buf, true); Dbhexdump(buflen, buf, true);
} }
} else { } 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_prng.h" /* legic PRNG impl */
#include "legic.h" /* legic_card_select_t struct */ #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 legic_card_select_t card;/* metadata of currently selected card */
static crc_t legic_crc; static crc_t legic_crc;
@ -50,21 +50,22 @@ 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 WRITE_LOWERLIMIT 4 /* UID and MCC are not writable */
#define INPUT_THRESHOLD 8 /* heuristically determined, lower values */ #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) // I/O interface abstraction (FPGA -> ARM)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static inline uint8_t rx_byte_from_fpga() { static inline uint8_t rx_byte_from_fpga()
for(;;) { {
WDT_HIT(); for (;;) {
WDT_HIT();
// wait for byte be become available in rx holding register // 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)) {
return AT91C_BASE_SSC->SSC_RHR; return AT91C_BASE_SSC->SSC_RHR;
}
} }
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -83,11 +84,14 @@ static inline uint8_t rx_byte_from_fpga() {
// //
// Note: The SSC receiver is never synchronized the calculation may be performed // 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. // on a i/q pair from two subsequent correlations, but does not matter.
static inline int32_t sample_power() { 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); 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); return MAX(i, q) + (MIN(i, q) >> 1);
} }
// Returns a demedulated bit // Returns a demedulated bit
@ -97,14 +101,15 @@ static inline int32_t sample_power() {
// //
// Note: The demodulator would be drifting (18.9us * 5 != 100us), rx_frame // 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. // 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; {
int32_t power;
for (size_t i = 0; i<5; ++i) { for (size_t i = 0; i < 5; ++i) {
power = sample_power(); power = sample_power();
} }
return (power > INPUT_THRESHOLD); return (power > INPUT_THRESHOLD);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -116,16 +121,17 @@ static inline bool rx_bit() {
// be circumvented, but the adventage over bitbang would be little. // 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); // insert pause
last_frame_end += RWD_TIME_PAUSE; LOW(GPIO_SSC_DOUT);
while (GET_TICKS < last_frame_end) { }; last_frame_end += RWD_TIME_PAUSE;
HIGH(GPIO_SSC_DOUT); while (GET_TICKS < last_frame_end) { };
HIGH(GPIO_SSC_DOUT);
// return to high, wait for bit periode to end // return to high, wait for bit periode to end
last_frame_end += (bit ? RWD_TIME_1 : RWD_TIME_0) - RWD_TIME_PAUSE; last_frame_end += (bit ? RWD_TIME_1 : RWD_TIME_0) - RWD_TIME_PAUSE;
while (GET_TICKS < last_frame_end) { }; while (GET_TICKS < last_frame_end) { };
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -138,163 +144,168 @@ static inline void tx_bit(bool bit) {
// present. // 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); {
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
// wait for next tx timeslot // wait for next tx timeslot
last_frame_end += RWD_FRAME_WAIT; last_frame_end += RWD_FRAME_WAIT;
while (GET_TICKS < last_frame_end) { };
// backup ts for trace log
uint32_t last_frame_start = last_frame_end;
// transmit frame, MSB first
for (uint8_t i = 0; i < len; ++i) {
bool bit = (frame >> i) & 0x01;
tx_bit(bit ^ legic_prng_get_bit());
legic_prng_forward(1);
};
// add pause to mark end of the frame
LOW(GPIO_SSC_DOUT);
last_frame_end += RWD_TIME_PAUSE;
while (GET_TICKS < last_frame_end) { };
HIGH(GPIO_SSC_DOUT);
// log
uint8_t cmdbytes[] = {len, BYTEx(frame, 0), BYTEx(frame, 1), BYTEx(frame, 2)};
LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, true);
}
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);
// hold sampling until card is expected to respond
last_frame_end += TAG_FRAME_WAIT;
while (GET_TICKS < last_frame_end) { };
// backup ts for trace log
uint32_t last_frame_start = last_frame_end;
uint32_t frame = 0;
for (uint8_t i = 0; i < len; ++i) {
frame |= (rx_bit() ^ legic_prng_get_bit()) << i;
legic_prng_forward(1);
// rx_bit runs only 95us, resync to TAG_BIT_PERIOD
last_frame_end += TAG_BIT_PERIOD;
while (GET_TICKS < last_frame_end) { };
}
// log
uint8_t cmdbytes[] = {len, BYTEx(frame, 0), BYTEx(frame, 1)};
LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, false);
return frame;
}
static bool rx_ack() {
// change fpga into rx mode
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
| FPGA_HF_READER_RX_XCORR_848_KHZ
| FPGA_HF_READER_RX_XCORR_QUARTER);
// hold sampling until card is expected to respond
last_frame_end += TAG_FRAME_WAIT;
while (GET_TICKS < last_frame_end) { };
// backup ts for trace log
uint32_t last_frame_start = last_frame_end;
uint32_t ack = 0;
for (uint8_t i = 0; i < TAG_WRITE_TIMEOUT; ++i) {
// sample bit
ack = rx_bit();
legic_prng_forward(1);
// rx_bit runs only 95us, resync to TAG_BIT_PERIOD
last_frame_end += TAG_BIT_PERIOD;
while (GET_TICKS < last_frame_end) { }; while (GET_TICKS < last_frame_end) { };
// check if it was an ACK // backup ts for trace log
if (ack) { uint32_t last_frame_start = last_frame_end;
break;
// transmit frame, MSB first
for (uint8_t i = 0; i < len; ++i) {
bool bit = (frame >> i) & 0x01;
tx_bit(bit ^ legic_prng_get_bit());
legic_prng_forward(1);
};
// add pause to mark end of the frame
LOW(GPIO_SSC_DOUT);
last_frame_end += RWD_TIME_PAUSE;
while (GET_TICKS < last_frame_end) { };
HIGH(GPIO_SSC_DOUT);
// log
uint8_t cmdbytes[] = {len, BYTEx(frame, 0), BYTEx(frame, 1), BYTEx(frame, 2)};
LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, true);
}
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);
// hold sampling until card is expected to respond
last_frame_end += TAG_FRAME_WAIT;
while (GET_TICKS < last_frame_end) { };
// backup ts for trace log
uint32_t last_frame_start = last_frame_end;
uint32_t frame = 0;
for (uint8_t i = 0; i < len; ++i) {
frame |= (rx_bit() ^ legic_prng_get_bit()) << i;
legic_prng_forward(1);
// rx_bit runs only 95us, resync to TAG_BIT_PERIOD
last_frame_end += TAG_BIT_PERIOD;
while (GET_TICKS < last_frame_end) { };
} }
}
// log // log
uint8_t cmdbytes[] = {1, BYTEx(ack, 0)}; uint8_t cmdbytes[] = {len, BYTEx(frame, 0), BYTEx(frame, 1)};
LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, false); LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, false);
return ack; return frame;
}
static bool rx_ack()
{
// change fpga into rx mode
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
| FPGA_HF_READER_RX_XCORR_848_KHZ
| FPGA_HF_READER_RX_XCORR_QUARTER);
// hold sampling until card is expected to respond
last_frame_end += TAG_FRAME_WAIT;
while (GET_TICKS < last_frame_end) { };
// backup ts for trace log
uint32_t last_frame_start = last_frame_end;
uint32_t ack = 0;
for (uint8_t i = 0; i < TAG_WRITE_TIMEOUT; ++i) {
// sample bit
ack = rx_bit();
legic_prng_forward(1);
// rx_bit runs only 95us, resync to TAG_BIT_PERIOD
last_frame_end += TAG_BIT_PERIOD;
while (GET_TICKS < last_frame_end) { };
// check if it was an ACK
if (ack) {
break;
}
}
// log
uint8_t cmdbytes[] = {1, BYTEx(ack, 0)};
LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, false);
return ack;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Legic Reader // 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; {
p_card->tagtype = cardtype;
switch(p_card->tagtype) { switch (p_card->tagtype) {
case 0x0d: case 0x0d:
p_card->cmdsize = 6; p_card->cmdsize = 6;
p_card->addrsize = 5; p_card->addrsize = 5;
p_card->cardsize = 22; p_card->cardsize = 22;
break; break;
case 0x1d: case 0x1d:
p_card->cmdsize = 9; p_card->cmdsize = 9;
p_card->addrsize = 8; p_card->addrsize = 8;
p_card->cardsize = 256; p_card->cardsize = 256;
break; break;
case 0x3d: case 0x3d:
p_card->cmdsize = 11; p_card->cmdsize = 11;
p_card->addrsize = 10; p_card->addrsize = 10;
p_card->cardsize = 1024; p_card->cardsize = 1024;
break; break;
default: default:
p_card->cmdsize = 0; p_card->cmdsize = 0;
p_card->addrsize = 0; p_card->addrsize = 0;
p_card->cardsize = 0; p_card->cardsize = 0;
return 2; return 2;
} }
return 0; return 0;
} }
static void init_reader(bool clear_mem) { static void init_reader(bool clear_mem)
// configure FPGA {
FpgaDownloadAndGo(FPGA_BITSTREAM_HF); // configure FPGA
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
| FPGA_HF_READER_RX_XCORR_848_KHZ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
| FPGA_HF_READER_RX_XCORR_QUARTER); | FPGA_HF_READER_RX_XCORR_848_KHZ
SetAdcMuxFor(GPIO_MUXSEL_HIPKD); | FPGA_HF_READER_RX_XCORR_QUARTER);
LED_A_ON(); SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
LED_A_ON();
// configure SSC with defaults // configure SSC with defaults
FpgaSetupSsc(); FpgaSetupSsc();
// re-claim GPIO_SSC_DOUT as GPIO and enable output // re-claim GPIO_SSC_DOUT as GPIO and enable output
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
HIGH(GPIO_SSC_DOUT); HIGH(GPIO_SSC_DOUT);
// reserve a cardmem, meaning we can use the tracelog function in bigbuff easier. // reserve a cardmem, meaning we can use the tracelog function in bigbuff easier.
legic_mem = BigBuf_get_EM_addr(); legic_mem = BigBuf_get_EM_addr();
if (legic_mem) { if (legic_mem) {
memset(legic_mem, 0x00, LEGIC_CARD_MEMSIZE); memset(legic_mem, 0x00, LEGIC_CARD_MEMSIZE);
} }
// start trace // start trace
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
// init crc calculator // init crc calculator
crc_init(&legic_crc, 4, 0x19 >> 1, 0x05, 0); crc_init(&legic_crc, 4, 0x19 >> 1, 0x05, 0);
// start us timer // start us timer
StartTicks(); StartTicks();
} }
// Setup reader to card connection // Setup reader to card connection
@ -303,89 +314,93 @@ static void init_reader(bool clear_mem) {
// - Transmit initialisation vector 7 bits // - Transmit initialisation vector 7 bits
// - Receive card type 6 bits // - Receive card type 6 bits
// - Transmit Acknowledge 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; // init coordination timestamp
last_frame_end = GET_TICKS;
// Switch on carrier and let the card charge for 5ms. // Switch on carrier and let the card charge for 5ms.
last_frame_end += 7500; last_frame_end += 7500;
while (GET_TICKS < last_frame_end) { }; while (GET_TICKS < last_frame_end) { };
legic_prng_init(0); legic_prng_init(0);
tx_frame(iv, 7); tx_frame(iv, 7);
// configure prng // configure prng
legic_prng_init(iv); legic_prng_init(iv);
legic_prng_forward(2); legic_prng_forward(2);
// receive card type // receive card type
int32_t card_type = rx_frame(6); int32_t card_type = rx_frame(6);
legic_prng_forward(3); legic_prng_forward(3);
// send obsfuscated acknowledgment frame // send obsfuscated acknowledgment frame
switch (card_type) { switch (card_type) {
case 0x0D: case 0x0D:
tx_frame(0x19, 6); // MIM22 | READCMD = 0x18 | 0x01 tx_frame(0x19, 6); // MIM22 | READCMD = 0x18 | 0x01
break; break;
case 0x1D: case 0x1D:
case 0x3D: case 0x3D:
tx_frame(0x39, 6); // MIM256 | READCMD = 0x38 | 0x01 tx_frame(0x39, 6); // MIM256 | READCMD = 0x38 | 0x01
break; break;
} }
return card_type; 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); crc_clear(&legic_crc);
return crc_finish(&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; {
uint16_t cmd = (index << 1) | LEGIC_READ;
// read one byte // read one byte
LED_B_ON(); LED_B_ON();
legic_prng_forward(2); legic_prng_forward(2);
tx_frame(cmd, cmd_sz); tx_frame(cmd, cmd_sz);
legic_prng_forward(2); legic_prng_forward(2);
uint32_t frame = rx_frame(12); uint32_t frame = rx_frame(12);
LED_B_OFF(); LED_B_OFF();
// split frame into data and crc // split frame into data and crc
uint8_t byte = BYTEx(frame, 0); uint8_t byte = BYTEx(frame, 0);
uint8_t crc = BYTEx(frame, 1); uint8_t crc = BYTEx(frame, 1);
// check received against calculated crc // check received against calculated crc
uint8_t calc_crc = calc_crc4(cmd, cmd_sz, byte); uint8_t calc_crc = calc_crc4(cmd, cmd_sz, byte);
if (calc_crc != crc) { if (calc_crc != crc) {
Dbprintf("!!! crc mismatch: %x != %x !!!", calc_crc, crc); Dbprintf("!!! crc mismatch: %x != %x !!!", calc_crc, crc);
return -1; return -1;
} }
legic_prng_forward(1); legic_prng_forward(1);
return byte; return byte;
} }
// Transmit write command, wait until (3.6ms) the tag sends back an unencrypted // Transmit write command, wait until (3.6ms) the tag sends back an unencrypted
// ACK ('1' bit) and forward the prng time based. // 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 uint32_t cmd = index << 1 | LEGIC_WRITE; // prepare command
cmd |= byte << (addr_sz + 1); // append value uint8_t crc = calc_crc4(cmd, addr_sz + 1, byte); // calculate crc
cmd |= (crc & 0xF) << (addr_sz + 1 + 8); // and crc cmd |= byte << (addr_sz + 1); // append value
cmd |= (crc & 0xF) << (addr_sz + 1 + 8); // and crc
// send write command // send write command
LED_C_ON(); LED_C_ON();
legic_prng_forward(2); legic_prng_forward(2);
tx_frame(cmd, addr_sz + 1 + 8 + 4); // cmd_sz = addr_sz + cmd + data + crc tx_frame(cmd, addr_sz + 1 + 8 + 4); // cmd_sz = addr_sz + cmd + data + crc
legic_prng_forward(3); legic_prng_forward(3);
LED_C_OFF(); LED_C_OFF();
// wait for ack // wait for ack
return rx_ack(); return rx_ack();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -393,111 +408,114 @@ bool write_byte(uint16_t index, uint8_t byte, uint8_t addr_sz) {
// //
// Only this functions are public / called from appmain.c // Only this functions are public / called from appmain.c
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void LegicRfInfo(void) { void LegicRfInfo(void)
// configure ARM and FPGA {
init_reader(false); // configure ARM and FPGA
init_reader(false);
// establish shared secret and detect card type // establish shared secret and detect card type
uint8_t card_type = setup_phase(0x01); uint8_t card_type = setup_phase(0x01);
if (init_card(card_type, &card) != 0) { if (init_card(card_type, &card) != 0) {
cmd_send(CMD_ACK, 0, 0, 0, 0, 0); cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT; goto OUT;
}
// read UID
for (uint8_t i = 0; i < sizeof(card.uid); ++i) {
int16_t byte = read_byte(i, card.cmdsize);
if (byte == -1) {
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT;
} }
card.uid[i] = byte & 0xFF;
}
// read MCC and check against UID // read UID
int16_t mcc = read_byte(4, card.cmdsize); for (uint8_t i = 0; i < sizeof(card.uid); ++i) {
int16_t calc_mcc = CRC8Legic(card.uid, 4);; int16_t byte = read_byte(i, card.cmdsize);
if (mcc != calc_mcc) { if (byte == -1) {
cmd_send(CMD_ACK, 0, 0, 0, 0, 0); cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT; goto OUT;
} }
card.uid[i] = byte & 0xFF;
}
// OK // read MCC and check against UID
cmd_send(CMD_ACK, 1, 0, 0, (uint8_t*)&card, sizeof(legic_card_select_t)); int16_t mcc = read_byte(4, card.cmdsize);
int16_t calc_mcc = CRC8Legic(card.uid, 4);;
if (mcc != calc_mcc) {
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT;
}
// OK
cmd_send(CMD_ACK, 1, 0, 0, (uint8_t *)&card, sizeof(legic_card_select_t));
OUT: OUT:
switch_off(); switch_off();
StopTicks(); 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); // configure ARM and FPGA
init_reader(false);
// establish shared secret and detect card type // establish shared secret and detect card type
uint8_t card_type = setup_phase(iv); uint8_t card_type = setup_phase(iv);
if (init_card(card_type, &card) != 0) { if (init_card(card_type, &card) != 0) {
cmd_send(CMD_ACK, 0, 0, 0, 0, 0); cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT; goto OUT;
}
// do not read beyond card memory
if (len + offset > card.cardsize) {
len = card.cardsize - offset;
}
for (uint16_t i = 0; i < len; ++i) {
int16_t byte = read_byte(offset + i, card.cmdsize);
if (byte == -1) {
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT;
} }
legic_mem[i] = byte;
}
// OK // do not read beyond card memory
cmd_send(CMD_ACK, 1, len, 0, legic_mem, len); if (len + offset > card.cardsize) {
len = card.cardsize - offset;
}
for (uint16_t i = 0; i < len; ++i) {
int16_t byte = read_byte(offset + i, card.cmdsize);
if (byte == -1) {
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT;
}
legic_mem[i] = byte;
}
// OK
cmd_send(CMD_ACK, 1, len, 0, legic_mem, len);
OUT: OUT:
switch_off(); switch_off();
StopTicks(); 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); // configure ARM and FPGA
init_reader(false);
// uid is not writeable // uid is not writeable
if (offset <= WRITE_LOWERLIMIT) { if (offset <= WRITE_LOWERLIMIT) {
cmd_send(CMD_ACK, 0, 0, 0, 0, 0); cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT; goto OUT;
}
// establish shared secret and detect card type
uint8_t card_type = setup_phase(iv);
if (init_card(card_type, &card) != 0) {
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT;
}
// do not write beyond card memory
if (len + offset > card.cardsize) {
len = card.cardsize - offset;
}
// write in reverse order, only then is DCF (decremental field) writable
while (len-- > 0 && !BUTTON_PRESS()) {
if (!write_byte(len + offset, data[len], card.addrsize)) {
Dbprintf("operation failed | %02X | %02X | %02X", len + offset, len, data[len]);
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT;
} }
}
// OK // establish shared secret and detect card type
cmd_send(CMD_ACK, 1, len, 0, legic_mem, len); uint8_t card_type = setup_phase(iv);
if (init_card(card_type, &card) != 0) {
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT;
}
// do not write beyond card memory
if (len + offset > card.cardsize) {
len = card.cardsize - offset;
}
// write in reverse order, only then is DCF (decremental field) writable
while (len-- > 0 && !BUTTON_PRESS()) {
if (!write_byte(len + offset, data[len], card.addrsize)) {
Dbprintf("operation failed | %02X | %02X | %02X", len + offset, len, data[len]);
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT;
}
}
// OK
cmd_send(CMD_ACK, 1, len, 0, legic_mem, len);
OUT: OUT:
switch_off(); switch_off();
StopTicks(); StopTicks();
} }

View file

@ -16,7 +16,7 @@
#include "legic_prng.h" /* legic PRNG impl */ #include "legic_prng.h" /* legic PRNG impl */
#include "legic.h" /* legic_card_select_t struct */ #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 legic_card_select_t card;/* metadata of currently selected card */
static crc_t legic_crc; static crc_t legic_crc;
@ -58,13 +58,14 @@ 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 // 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) { while ((bool)(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_DIN) != value) {
return false; if (GetCountSspClk() > timeout) {
return false;
}
} }
} return true;
return true;
} }
// Returns a demedulated bit or -1 on code violation // Returns a demedulated bit or -1 on code violation
@ -76,30 +77,31 @@ 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 1
// - A bit length <80.2us is a 0 // - A bit length <80.2us is a 0
// - A bit length >148.6us is a code violation // - 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; // backup ts for threshold calculation
uint32_t bit_start = last_frame_end;
// wait for pause to 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; return -1;
} }
// wait for next pause // 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; return -1;
} }
// update bit and frame end // update bit and frame end
last_frame_end = GetCountSspClk(); last_frame_end = GetCountSspClk();
// check for code violation (bit to short) // check for code violation (bit to short)
if (last_frame_end - bit_start < RWD_TIME_PAUSE) { if (last_frame_end - bit_start < RWD_TIME_PAUSE) {
return -1; return -1;
} }
// apply threshold (average of RWD_TIME_0 and ) // apply threshold (average of RWD_TIME_0 and )
return (last_frame_end - bit_start > (RWD_TIME_0 + RWD_TIME_1) / 2); return (last_frame_end - bit_start > (RWD_TIME_0 + RWD_TIME_1) / 2);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -119,21 +121,22 @@ static inline int8_t rx_bit() {
// Note: The Subcarrier is not disabled during bits to prevent glitches. This is // 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 // not mandatory but results in a cleaner signal. tx_frame will disable
// the subcarrier when the frame is done. // the subcarrier when the frame is done.
static inline void tx_bit(bool bit) { static inline void tx_bit(bool bit)
LED_C_ON(); {
LED_C_ON();
if (bit) { if (bit) {
// modulate subcarrier // modulate subcarrier
HIGH(GPIO_SSC_DOUT); HIGH(GPIO_SSC_DOUT);
} else { } else {
// do not modulate subcarrier // do not modulate subcarrier
LOW(GPIO_SSC_DOUT); LOW(GPIO_SSC_DOUT);
} }
// wait for tx timeslot to end // wait for tx timeslot to end
last_frame_end += TAG_BIT_PERIOD; last_frame_end += TAG_BIT_PERIOD;
while (GetCountSspClk() < last_frame_end) { }; while (GetCountSspClk() < last_frame_end) { };
LED_C_OFF(); LED_C_OFF();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -146,49 +149,51 @@ static inline void tx_bit(bool bit) {
// and depends only the command received (IV, ACK, READ or WRITE). // 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; // wait for next tx timeslot
legic_prng_forward(TAG_FRAME_WAIT/TAG_BIT_PERIOD - 1); last_frame_end += TAG_FRAME_WAIT;
while (GetCountSspClk() < last_frame_end) { }; legic_prng_forward(TAG_FRAME_WAIT / TAG_BIT_PERIOD - 1);
while (GetCountSspClk() < last_frame_end) { };
// backup ts for trace log // backup ts for trace log
uint32_t last_frame_start = last_frame_end; uint32_t last_frame_start = last_frame_end;
// transmit frame, MSB first // transmit frame, MSB first
for (uint8_t i = 0; i < len; ++i) { for (uint8_t i = 0; i < len; ++i) {
bool bit = (frame >> i) & 0x01; bool bit = (frame >> i) & 0x01;
tx_bit(bit ^ legic_prng_get_bit()); tx_bit(bit ^ legic_prng_get_bit());
legic_prng_forward(1); legic_prng_forward(1);
}; };
// disable subcarrier // disable subcarrier
LOW(GPIO_SSC_DOUT); LOW(GPIO_SSC_DOUT);
// log // log
uint8_t cmdbytes[] = {len, BYTEx(frame, 0), BYTEx(frame, 1)}; uint8_t cmdbytes[] = {len, BYTEx(frame, 0), BYTEx(frame, 1)};
LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, false); 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; // wait for ack timeslot
legic_prng_forward(TAG_ACK_WAIT/TAG_BIT_PERIOD - 1); last_frame_end += TAG_ACK_WAIT;
while (GetCountSspClk() < last_frame_end) { }; legic_prng_forward(TAG_ACK_WAIT / TAG_BIT_PERIOD - 1);
while (GetCountSspClk() < last_frame_end) { };
// backup ts for trace log // backup ts for trace log
uint32_t last_frame_start = last_frame_end; uint32_t last_frame_start = last_frame_end;
// transmit ack (ack is not encrypted) // transmit ack (ack is not encrypted)
tx_bit(true); tx_bit(true);
legic_prng_forward(1); legic_prng_forward(1);
// disable subcarrier // disable subcarrier
LOW(GPIO_SSC_DOUT); LOW(GPIO_SSC_DOUT);
// log // log
uint8_t cmdbytes[] = {1, 1}; uint8_t cmdbytes[] = {1, 1};
LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, false); LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, false);
} }
// Returns a demedulated frame or -1 on code violation // Returns a demedulated frame or -1 on code violation
@ -198,126 +203,129 @@ static void tx_ack() {
// - forward prng based on ts/TAG_BIT_PERIOD // - forward prng based on ts/TAG_BIT_PERIOD
// - receive the frame // - receive the frame
// - detect end of frame (last pause) // - 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; {
int32_t frame = 0;
// add 2 SSP clock cycles (1 for tx and 1 for rx pipeline delay) // add 2 SSP clock cycles (1 for tx and 1 for rx pipeline delay)
// those will be substracted at the end of the rx phase // those will be substracted at the end of the rx phase
last_frame_end -= 2; last_frame_end -= 2;
// wait for first pause (start of frame) // wait for first pause (start of frame)
for (uint8_t i = 0; true; ++i) { for (uint8_t i = 0; true; ++i) {
// increment prng every TAG_BIT_PERIOD // increment prng every TAG_BIT_PERIOD
last_frame_end += TAG_BIT_PERIOD; last_frame_end += TAG_BIT_PERIOD;
legic_prng_forward(1); legic_prng_forward(1);
// if start of frame was received exit delay loop // if start of frame was received exit delay loop
if (wait_for(RWD_PAUSE, last_frame_end)) { if (wait_for(RWD_PAUSE, last_frame_end)) {
last_frame_end = GetCountSspClk(); last_frame_end = GetCountSspClk();
break; break;
}
// check for code violation
if (i > RWD_CMD_TIMEOUT) {
return -1;
}
} }
// check for code violation // backup ts for trace log
if (i > RWD_CMD_TIMEOUT) { uint32_t last_frame_start = last_frame_end;
return -1;
}
}
// backup ts for trace log // receive frame
uint32_t last_frame_start = last_frame_end; for (*len = 0; true; ++(*len)) {
// receive next bit
LED_B_ON();
int8_t bit = rx_bit();
LED_B_OFF();
// receive frame // check for code violation and to short / long frame
for (*len = 0; true; ++(*len)) { if ((bit < 0) && ((*len < RWD_MIN_FRAME_LEN) || (*len > RWD_MAX_FRAME_LEN))) {
// receive next bit return -1;
LED_B_ON(); }
int8_t bit = rx_bit();
LED_B_OFF();
// check for code violation and to short / long frame // check for code violation caused by end of frame
if ((bit < 0) && ((*len < RWD_MIN_FRAME_LEN) || (*len > RWD_MAX_FRAME_LEN))) { if (bit < 0) {
return -1; break;
}
// append bit
frame |= (bit ^ legic_prng_get_bit()) << (*len);
legic_prng_forward(1);
} }
// check for code violation caused by end of frame // rx_bit sets coordination timestamp to start of pause, append pause duration
if (bit < 0) { // and substract 2 SSP clock cycles (1 for rx and 1 for tx pipeline delay) to
break; // obtain exact end of frame.
} last_frame_end += RWD_TIME_PAUSE - 2;
// append bit // log
frame |= (bit ^ legic_prng_get_bit()) << (*len); uint8_t cmdbytes[] = {*len, BYTEx(frame, 0), BYTEx(frame, 1), BYTEx(frame, 2)};
legic_prng_forward(1); LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, true);
} return frame;
// rx_bit sets coordination timestamp to start of pause, append pause duration
// and substract 2 SSP clock cycles (1 for rx and 1 for tx pipeline delay) to
// obtain exact end of frame.
last_frame_end += RWD_TIME_PAUSE - 2;
// log
uint8_t cmdbytes[] = {*len, BYTEx(frame, 0), BYTEx(frame, 1), BYTEx(frame, 2)};
LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, true);
return frame;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Legic Simulator // 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; {
p_card->tagtype = cardtype;
switch (p_card->tagtype) { switch (p_card->tagtype) {
case 0: case 0:
p_card->cmdsize = 6; p_card->cmdsize = 6;
p_card->addrsize = 5; p_card->addrsize = 5;
p_card->cardsize = 22; p_card->cardsize = 22;
break; break;
case 1: case 1:
p_card->cmdsize = 9; p_card->cmdsize = 9;
p_card->addrsize = 8; p_card->addrsize = 8;
p_card->cardsize = 256; p_card->cardsize = 256;
break; break;
case 2: case 2:
p_card->cmdsize = 11; p_card->cmdsize = 11;
p_card->addrsize = 10; p_card->addrsize = 10;
p_card->cardsize = 1024; p_card->cardsize = 1024;
break; break;
default: default:
p_card->cmdsize = 0; p_card->cmdsize = 0;
p_card->addrsize = 0; p_card->addrsize = 0;
p_card->cardsize = 0; p_card->cardsize = 0;
return 2; return 2;
} }
return 0; return 0;
} }
static void init_tag() { static void init_tag()
// configure FPGA {
FpgaDownloadAndGo(FPGA_BITSTREAM_HF); // configure FPGA
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
| FPGA_HF_SIMULATOR_MODULATE_212K); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR
SetAdcMuxFor(GPIO_MUXSEL_HIPKD); | FPGA_HF_SIMULATOR_MODULATE_212K);
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
// configure SSC with defaults // configure SSC with defaults
FpgaSetupSsc(); FpgaSetupSsc();
// first pull output to low to prevent glitches then re-claim GPIO_SSC_DOUT // first pull output to low to prevent glitches then re-claim GPIO_SSC_DOUT
LOW(GPIO_SSC_DOUT); LOW(GPIO_SSC_DOUT);
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
// reserve a cardmem, meaning we can use the tracelog function in bigbuff easier. // reserve a cardmem, meaning we can use the tracelog function in bigbuff easier.
legic_mem = BigBuf_get_EM_addr(); legic_mem = BigBuf_get_EM_addr();
// start trace // start trace
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
// init crc calculator // init crc calculator
crc_init(&legic_crc, 4, 0x19 >> 1, 0x05, 0); crc_init(&legic_crc, 4, 0x19 >> 1, 0x05, 0);
// start 212kHz timer (running from SSP Clock) // start 212kHz timer (running from SSP Clock)
StartCountSspClk(); StartCountSspClk();
} }
// Setup reader to card connection // Setup reader to card connection
@ -326,119 +334,122 @@ static void init_tag() {
// - Receive initialisation vector 7 bits // - Receive initialisation vector 7 bits
// - Transmit card type 6 bits // - Transmit card type 6 bits
// - Receive Acknowledge 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; {
uint8_t len = 0;
// init coordination timestamp // init coordination timestamp
last_frame_end = GetCountSspClk(); last_frame_end = GetCountSspClk();
// reset prng // reset prng
legic_prng_init(0); legic_prng_init(0);
// wait for iv // wait for iv
int32_t iv = rx_frame(&len); int32_t iv = rx_frame(&len);
if ((len != 7) || (iv < 0)) { if ((len != 7) || (iv < 0)) {
return -1; return -1;
}
// configure prng
legic_prng_init(iv);
// reply with card type
switch (p_card->tagtype) {
case 0:
tx_frame(0x0D, 6);
break;
case 1:
tx_frame(0x1D, 6);
break;
case 2:
tx_frame(0x3D, 6);
break;
}
// wait for ack
int32_t ack = rx_frame(&len);
if ((len != 6) || (ack < 0)) {
return -1;
}
// validate data
switch (p_card->tagtype) {
case 0:
if(ack != 0x19) return -1;
break;
case 1:
if(ack != 0x39) return -1;
break;
case 2:
if(ack != 0x39) return -1;
break;
}
// During rx the prng is clocked using the variable reader period.
// Since rx_frame detects end of frame by detecting a code violation,
// the prng is off by one bit period after each rx phase. Hence, tx
// code advances the prng by (TAG_FRAME_WAIT/TAG_BIT_PERIOD - 1).
// This is not possible for back to back rx, so this quirk reduces
// the gap by one period.
last_frame_end += TAG_BIT_PERIOD;
return 0;
}
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) {
uint8_t len = 0;
// wait for command
int32_t cmd = rx_frame(&len);
if (cmd < 0) {
return -1;
}
// check if command is LEGIC_READ
if (len == p_card->cmdsize) {
// prepare data
uint8_t byte = legic_mem[cmd >> 1];
uint8_t crc = calc_crc4(cmd, p_card->cmdsize, byte);
// transmit data
tx_frame((crc << 8) | byte, 12);
return 0;
}
// check if command is LEGIC_WRITE
if (len == p_card->cmdsize + 8 + 4) {
// decode data
uint16_t mask = (1 << p_card->addrsize) - 1;
uint16_t addr = (cmd >> 1) & mask;
uint8_t byte = (cmd >> p_card->cmdsize) & 0xff;
uint8_t crc = (cmd >> (p_card->cmdsize + 8)) & 0xf;
// check received against calculated crc
uint8_t calc_crc = calc_crc4(addr << 1, p_card->cmdsize, byte);
if (calc_crc != crc) {
Dbprintf("!!! crc mismatch: %x != %x !!!", calc_crc, crc);
return -1;
} }
// store data // configure prng
legic_mem[addr] = byte; legic_prng_init(iv);
// transmit ack // reply with card type
tx_ack(); switch (p_card->tagtype) {
case 0:
tx_frame(0x0D, 6);
break;
case 1:
tx_frame(0x1D, 6);
break;
case 2:
tx_frame(0x3D, 6);
break;
}
// wait for ack
int32_t ack = rx_frame(&len);
if ((len != 6) || (ack < 0)) {
return -1;
}
// validate data
switch (p_card->tagtype) {
case 0:
if (ack != 0x19) return -1;
break;
case 1:
if (ack != 0x39) return -1;
break;
case 2:
if (ack != 0x39) return -1;
break;
}
// During rx the prng is clocked using the variable reader period.
// Since rx_frame detects end of frame by detecting a code violation,
// the prng is off by one bit period after each rx phase. Hence, tx
// code advances the prng by (TAG_FRAME_WAIT/TAG_BIT_PERIOD - 1).
// This is not possible for back to back rx, so this quirk reduces
// the gap by one period.
last_frame_end += TAG_BIT_PERIOD;
return 0; return 0;
} }
return -1; 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)
{
uint8_t len = 0;
// wait for command
int32_t cmd = rx_frame(&len);
if (cmd < 0) {
return -1;
}
// check if command is LEGIC_READ
if (len == p_card->cmdsize) {
// prepare data
uint8_t byte = legic_mem[cmd >> 1];
uint8_t crc = calc_crc4(cmd, p_card->cmdsize, byte);
// transmit data
tx_frame((crc << 8) | byte, 12);
return 0;
}
// check if command is LEGIC_WRITE
if (len == p_card->cmdsize + 8 + 4) {
// decode data
uint16_t mask = (1 << p_card->addrsize) - 1;
uint16_t addr = (cmd >> 1) & mask;
uint8_t byte = (cmd >> p_card->cmdsize) & 0xff;
uint8_t crc = (cmd >> (p_card->cmdsize + 8)) & 0xf;
// check received against calculated crc
uint8_t calc_crc = calc_crc4(addr << 1, p_card->cmdsize, byte);
if (calc_crc != crc) {
Dbprintf("!!! crc mismatch: %x != %x !!!", calc_crc, crc);
return -1;
}
// store data
legic_mem[addr] = byte;
// transmit ack
tx_ack();
return 0;
}
return -1;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -447,39 +458,40 @@ static int32_t connected_phase(legic_card_select_t *p_card) {
// Only this function is public / called from appmain.c // 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(); // configure ARM and FPGA
init_tag();
// verify command line input // verify command line input
if (init_card(cardtype, &card) != 0) { if (init_card(cardtype, &card) != 0) {
DbpString("Unknown tagtype."); DbpString("Unknown tagtype.");
goto OUT; goto OUT;
}
LED_A_ON();
DbpString("Starting Legic emulator, press button to end");
while (!BUTTON_PRESS() && !usb_poll_validate_length()) {
WDT_HIT();
// wait for carrier, restart after timeout
if (!wait_for(RWD_PULSE, GetCountSspClk() + TAG_BIT_PERIOD)) {
continue;
} }
// wait for connection, restart on error LED_A_ON();
if (setup_phase(&card)) { DbpString("Starting Legic emulator, press button to end");
continue; while (!BUTTON_PRESS() && !usb_poll_validate_length()) {
} WDT_HIT();
// conection is established, process commands until one fails // wait for carrier, restart after timeout
while (!connected_phase(&card)) { if (!wait_for(RWD_PULSE, GetCountSspClk() + TAG_BIT_PERIOD)) {
WDT_HIT(); continue;
}
// wait for connection, restart on error
if (setup_phase(&card)) {
continue;
}
// conection is established, process commands until one fails
while (!connected_phase(&card)) {
WDT_HIT();
}
} }
}
OUT: OUT:
DbpString("Stopped"); DbpString("Stopped");
switch_off(); switch_off();
StopTicks(); StopTicks();
} }

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

View file

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

View file

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

View file

@ -13,7 +13,8 @@
int MF_DBGLEVEL = MF_DBG_ERROR; int MF_DBGLEVEL = MF_DBG_ERROR;
// crypto1 helpers // 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; uint8_t bt = 0;
int i; int i;
@ -30,11 +31,13 @@ void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, u
return; 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); 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; uint8_t bt = 0;
int i; int i;
par[0] = 0; 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++) { for (i = 0; i < len; i++) {
bt = data[i]; bt = data[i];
data[i] = crypto1_byte(pcs, 0x00, 0) ^ 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 ] = 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; uint8_t bt = 0;
bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 0)) << 0; bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 0)) << 0;
bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 1)) << 1; 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 // 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) { 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]; {
uint8_t dcmd[data_size + 3];
dcmd[0] = cmd; dcmd[0] = cmd;
memcpy(dcmd+1, data, data_size); memcpy(dcmd + 1, data, data_size);
AddCrc14A(dcmd, data_size+1); AddCrc14A(dcmd, data_size + 1);
ReaderTransmit(dcmd, sizeof(dcmd), timing); ReaderTransmit(dcmd, sizeof(dcmd), timing);
int len = ReaderReceive(answer, answer_parity); int len = ReaderReceive(answer, answer_parity);
if(!len) { if (!len) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("%02X Cmd failed. Card timeout.", cmd); 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; return len;
} }
// send 2 byte commands // 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; uint16_t pos, res;
uint8_t dcmd[4] = {cmd, data, 0x00, 0x00}; uint8_t dcmd[4] = {cmd, data, 0x00, 0x00};
uint8_t ecmd[4] = {0x00, 0x00, 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; par[0] = 0;
for (pos = 0; pos < 4; pos++) { for (pos = 0; pos < 4; pos++) {
ecmd[pos] = crypto1_byte(pcs, 0x00, 0) ^ dcmd[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); ReaderTransmitPar(ecmd, sizeof(ecmd), par, timing);
} else { } else {
@ -113,21 +119,23 @@ int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd,
} }
// mifare classic commands // 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); 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; int len;
uint32_t pos, nt, ntpp; // Supplied tag nonce uint32_t pos, nt, ntpp; // Supplied tag nonce
uint8_t par[1] = {0x00}; uint8_t par[1] = {0x00};
uint8_t nr[4]; 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 receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
// "random" reader nonce: // "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 // Transmit MIFARE_CLASSIC_AUTH
len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing); len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing);
@ -163,7 +171,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
par[0] = 0; par[0] = 0;
for (pos = 0; pos < 4; pos++) { for (pos = 0; pos < 4; pos++) {
mf_nr_ar[pos] = crypto1_byte(pcs, nr[pos], 0) ^ nr[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 // 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 // ar+parity
for (pos = 4; pos < 8; pos++) { for (pos = 4; pos < 8; pos++) {
nt = prng_successor(nt,8); nt = prng_successor(nt, 8);
mf_nr_ar[pos] = crypto1_byte(pcs,0x00,0) ^ (nt & 0xff); mf_nr_ar[pos] = crypto1_byte(pcs, 0x00, 0) ^ (nt & 0xff);
par[0] |= (((filter(pcs->odd) ^ oddparity8(nt & 0xff)) & 0x01) << (7-pos)); par[0] |= (((filter(pcs->odd) ^ oddparity8(nt & 0xff)) & 0x01) << (7 - pos));
} }
// Transmit reader nonce and reader answer // 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; 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 (ntpp != bytes_to_num(receivedAnswer, 4)) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication failed. Error card response."); 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; 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; int len;
uint8_t bt[2] = {0x00, 0x00}; 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 // 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; uint16_t len = 0;
uint8_t resp[4] = {0x00, 0x00, 0x00, 0x00}; 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) 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); memcpy(pack, resp, 4);
return 1; return 1;
} }
int mifare_ultra_auth(uint8_t *keybytes){ int mifare_ultra_auth(uint8_t *keybytes)
{
/// 3des2k /// 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 random_b[8] = {0x00};
uint8_t enc_random_b[8] = {0x00}; uint8_t enc_random_b[8] = {0x00};
uint8_t rnd_ab[16] = {0x00}; uint8_t rnd_ab[16] = {0x00};
@ -262,36 +273,36 @@ int mifare_ultra_auth(uint8_t *keybytes){
uint16_t len = 0; uint16_t len = 0;
uint8_t resp[19] = {0x00}; uint8_t resp[19] = {0x00};
uint8_t respPar[3] = {0,0,0}; uint8_t respPar[3] = {0, 0, 0};
// REQUEST AUTHENTICATION // 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 (len != 11) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]); if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]);
return 0; return 0;
} }
// tag nonce. // tag nonce.
memcpy(enc_random_b,resp+1,8); memcpy(enc_random_b, resp + 1, 8);
// decrypt nonce. // decrypt nonce.
tdes_2key_dec((void*)random_b, (void*)enc_random_b, sizeof(random_b), (const void*)key, IV ); tdes_2key_dec((void *)random_b, (void *)enc_random_b, sizeof(random_b), (const void *)key, IV);
rol(random_b,8); rol(random_b, 8);
memcpy(rnd_ab ,random_a,8); memcpy(rnd_ab, random_a, 8);
memcpy(rnd_ab+8,random_b,8); memcpy(rnd_ab + 8, random_b, 8);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
Dbprintf("enc_B: %02x %02x %02x %02x %02x %02x %02x %02x", 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", 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", 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", 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 // encrypt out, in, length, key, iv
@ -303,38 +314,39 @@ int mifare_ultra_auth(uint8_t *keybytes){
return 0; return 0;
} }
uint8_t enc_resp[8] = { 0,0,0,0,0,0,0,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 }; uint8_t resp_random_a[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
memcpy(enc_resp, resp+1, 8); memcpy(enc_resp, resp + 1, 8);
// decrypt out, in, length, key, iv // decrypt out, in, length, key, iv
tdes_2key_dec(resp_random_a, enc_resp, 8, key, enc_random_b); 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"); if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("failed authentication");
return 0; return 0;
} }
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", 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[0], rnd_ab[1], rnd_ab[2], rnd_ab[3],
rnd_ab[4],rnd_ab[5],rnd_ab[6],rnd_ab[7]); rnd_ab[4], rnd_ab[5], rnd_ab[6], rnd_ab[7]);
Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", 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[8], rnd_ab[9], rnd_ab[10], rnd_ab[11],
rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15]); rnd_ab[12], rnd_ab[13], rnd_ab[14], rnd_ab[15]);
Dbprintf("a: %02x %02x %02x %02x %02x %02x %02x %02x", Dbprintf("a: %02x %02x %02x %02x %02x %02x %02x %02x",
random_a[0],random_a[1],random_a[2],random_a[3], 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[4], random_a[5], random_a[6], random_a[7]);
Dbprintf("b: %02x %02x %02x %02x %02x %02x %02x %02x", 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[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[4], resp_random_a[5], resp_random_a[6], resp_random_a[7]);
} }
return 1; 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; uint16_t len = 0;
uint8_t bt[2] = {0x00, 0x00}; uint8_t bt[2] = {0x00, 0x00};
uint8_t receivedAnswer[MAX_FRAME_SIZE] = {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); memcpy(blockData, receivedAnswer, 14);
return 0; return 0;
} }
int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData) { int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData)
#define MFU_MAX_RETRIES 5 {
#define MFU_MAX_RETRIES 5
uint8_t res; uint8_t res;
for (uint8_t retries = 0; retries < MFU_MAX_RETRIES; ++retries) { for (uint8_t retries = 0; retries < MFU_MAX_RETRIES; ++retries) {
res = mifare_ultra_readblockEx(blockNo, blockData); res = mifare_ultra_readblockEx(blockNo, blockData);
// break if OK, or NACK. // break if OK, or NACK.
switch ( res ) { switch (res) {
case 0: case 0:
case 1: case 1:
return res; return res;
@ -379,7 +392,8 @@ int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData) {
return res; 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 // variables
uint16_t len = 0; uint16_t len = 0;
uint32_t pos = 0; uint32_t pos = 0;
@ -404,7 +418,7 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
// crypto // crypto
for (pos = 0; pos < 18; pos++) { for (pos = 0; pos < 18; pos++) {
d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[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); 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; uint16_t len = 0;
uint8_t block[5] = {blockNo, 0x00, 0x00, 0x00, 0x00 }; uint8_t block[5] = {blockNo, 0x00, 0x00, 0x00, 0x00 };
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
// command MIFARE_CLASSIC_WRITEBLOCK // 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 (receivedAnswer[0] != 0x0A) { // 0x0a - ACK
if (MF_DBGLEVEL >= MF_DBG_ERROR) 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 1;
} }
return 0; 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}; 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); uint16_t len = mifare_sendcmd_short(pcs, (pcs == NULL) ? CRYPT_NONE : CRYPT_ALL, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL);
if (len != 0) { if (len != 0) {
@ -484,11 +500,13 @@ int mifare_classic_halt_ex(struct Crypto1State *pcs) {
} }
return 0; 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); return mifare_classic_halt_ex(pcs);
} }
int mifare_ultra_halt() { int mifare_ultra_halt()
{
uint16_t len = 0; uint16_t len = 0;
uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00}; uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00};
len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL); len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL);
@ -502,56 +520,64 @@ int mifare_ultra_halt() {
// Mifare Memory Structure: up to 32 Sectors with 4 blocks each (1k and 2k cards), // Mifare Memory Structure: up to 32 Sectors with 4 blocks each (1k and 2k cards),
// plus evtl. 8 sectors with 16 blocks each (4k cards) // plus evtl. 8 sectors with 16 blocks each (4k cards)
uint8_t NumBlocksPerSector(uint8_t sectorNo) { uint8_t NumBlocksPerSector(uint8_t sectorNo)
{
return (sectorNo < 32) ? 4 : 16; return (sectorNo < 32) ? 4 : 16;
} }
uint8_t FirstBlockOfSector(uint8_t sectorNo) { uint8_t FirstBlockOfSector(uint8_t sectorNo)
{
if (sectorNo < 32) if (sectorNo < 32)
return sectorNo * 4; return sectorNo * 4;
else else
return 32*4 + (sectorNo - 32) * 16; return 32 * 4 + (sectorNo - 32) * 16;
} }
// work with emulator memory // work with emulator memory
void emlSetMem(uint8_t *data, int blockNum, int blocksCount) { void emlSetMem(uint8_t *data, int blockNum, int blocksCount)
{
emlSetMem_xt(data, blockNum, blocksCount, 16); emlSetMem_xt(data, blockNum, blocksCount, 16);
} }
void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth) { void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth)
uint8_t* emCARD = BigBuf_get_EM_addr(); {
uint8_t *emCARD = BigBuf_get_EM_addr();
memcpy(emCARD + blockNum * blockBtWidth, data, blocksCount * blockBtWidth); memcpy(emCARD + blockNum * blockBtWidth, data, blocksCount * blockBtWidth);
} }
void emlGetMem(uint8_t *data, int blockNum, int blocksCount) { void emlGetMem(uint8_t *data, int blockNum, int blocksCount)
uint8_t* emCARD = BigBuf_get_EM_addr(); {
uint8_t *emCARD = BigBuf_get_EM_addr();
memcpy(data, emCARD + blockNum * 16, blocksCount * 16); memcpy(data, emCARD + blockNum * 16, blocksCount * 16);
} }
void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount) { void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount)
uint8_t* emCARD = BigBuf_get_EM_addr(); {
uint8_t *emCARD = BigBuf_get_EM_addr();
memcpy(data, emCARD + bytePtr, byteCount); memcpy(data, emCARD + bytePtr, byteCount);
} }
int emlCheckValBl(int blockNum) { int emlCheckValBl(int blockNum)
uint8_t* emCARD = BigBuf_get_EM_addr(); {
uint8_t* data = emCARD + blockNum * 16; uint8_t *emCARD = BigBuf_get_EM_addr();
uint8_t *data = emCARD + blockNum * 16;
if ((data[0] != (data[4] ^ 0xff)) || (data[0] != data[8]) || if ((data[0] != (data[4] ^ 0xff)) || (data[0] != data[8]) ||
(data[1] != (data[5] ^ 0xff)) || (data[1] != data[9]) || (data[1] != (data[5] ^ 0xff)) || (data[1] != data[9]) ||
(data[2] != (data[6] ^ 0xff)) || (data[2] != data[10]) || (data[2] != (data[6] ^ 0xff)) || (data[2] != data[10]) ||
(data[3] != (data[7] ^ 0xff)) || (data[3] != data[11]) || (data[3] != (data[7] ^ 0xff)) || (data[3] != data[11]) ||
(data[12] != (data[13] ^ 0xff)) || (data[12] != data[14]) || (data[12] != (data[13] ^ 0xff)) || (data[12] != data[14]) ||
(data[12] != (data[15] ^ 0xff)) (data[12] != (data[15] ^ 0xff))
) )
return 1; return 1;
return 0; return 0;
} }
int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) { int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum)
uint8_t* emCARD = BigBuf_get_EM_addr(); {
uint8_t* data = emCARD + blockNum * 16; uint8_t *emCARD = BigBuf_get_EM_addr();
uint8_t *data = emCARD + blockNum * 16;
if (emlCheckValBl(blockNum)) if (emlCheckValBl(blockNum))
return 1; return 1;
@ -561,9 +587,10 @@ int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) {
return 0; return 0;
} }
int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) { int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum)
uint8_t* emCARD = BigBuf_get_EM_addr(); {
uint8_t* data = emCARD + blockNum * 16; uint8_t *emCARD = BigBuf_get_EM_addr();
uint8_t *data = emCARD + blockNum * 16;
memcpy(data + 0, &blReg, 4); memcpy(data + 0, &blReg, 4);
memcpy(data + 8, &blReg, 4); memcpy(data + 8, &blReg, 4);
@ -578,21 +605,23 @@ int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) {
return 0; return 0;
} }
uint64_t emlGetKey(int sectorNum, int keyType) { uint64_t emlGetKey(int sectorNum, int keyType)
{
uint8_t key[6] = {0x00}; 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); memcpy(key, emCARD + 16 * (FirstBlockOfSector(sectorNum) + NumBlocksPerSector(sectorNum) - 1) + keyType * 10, 6);
return bytes_to_num(key, 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 trailer[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x80, 0x69, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
const uint8_t uid[] = {0xe6, 0x84, 0x87, 0xf3, 0x16, 0x88, 0x04, 0x00, 0x46, 0x8e, 0x45, 0x55, 0x4d, 0x70, 0x41, 0x04}; const uint8_t uid[] = {0xe6, 0x84, 0x87, 0xf3, 0x16, 0x88, 0x04, 0x00, 0x46, 0x8e, 0x45, 0x55, 0x4d, 0x70, 0x41, 0x04};
uint8_t* emCARD = BigBuf_get_EM_addr(); uint8_t *emCARD = BigBuf_get_EM_addr();
memset(emCARD, 0, CARD_MEMORY_SIZE); memset(emCARD, 0, CARD_MEMORY_SIZE);
// fill sectors trailer data // 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); emlSetMem((uint8_t *)trailer, b, 1);
// uid // uid
@ -602,43 +631,46 @@ void emlClearMem(void) {
// Mifare desfire commands // 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}; uint8_t dcmd[5] = {cmd, data[0], data[1], 0x00, 0x00};
AddCrc14A(dcmd, 3); AddCrc14A(dcmd, 3);
ReaderTransmit(dcmd, sizeof(dcmd), NULL); ReaderTransmit(dcmd, sizeof(dcmd), NULL);
int len = ReaderReceive(answer, answer_parity); int len = ReaderReceive(answer, answer_parity);
if(!len) { if (!len) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed. Card timeout."); if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed. Card timeout.");
return 1; return 1;
} }
return len; 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}; uint8_t dcmd[20] = {0x00};
dcmd[0] = cmd; dcmd[0] = cmd;
memcpy(dcmd+1,data,17); memcpy(dcmd + 1, data, 17);
AddCrc14A(dcmd, 18); AddCrc14A(dcmd, 18);
ReaderTransmit(dcmd, sizeof(dcmd), NULL); ReaderTransmit(dcmd, sizeof(dcmd), NULL);
int len = ReaderReceive(answer, answer_parity); int len = ReaderReceive(answer, answer_parity);
if(!len){ if (!len) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed. Card timeout."); if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed. Card timeout.");
return 1; return 1;
} }
return len; 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; int len;
// load key, keynumber // 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 receivedAnswer[MAX_FRAME_SIZE] = {0x00};
uint8_t receivedAnswerPar[MAX_PARITY_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 (len == 1) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) if (MF_DBGLEVEL >= MF_DBG_ERROR)
Dbprintf("Cmd Error: %02x", receivedAnswer[0]); Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
@ -648,26 +680,27 @@ int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData){
if (len == 12) { if (len == 12) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
Dbprintf("Auth1 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", Dbprintf("Auth1 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4], receivedAnswer[0], receivedAnswer[1], receivedAnswer[2], receivedAnswer[3], receivedAnswer[4],
receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9], receivedAnswer[5], receivedAnswer[6], receivedAnswer[7], receivedAnswer[8], receivedAnswer[9],
receivedAnswer[10],receivedAnswer[11]); receivedAnswer[10], receivedAnswer[11]);
} }
memcpy(blockData, receivedAnswer, 12); memcpy(blockData, receivedAnswer, 12);
return 0; return 0;
} }
return 1; 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; int len;
uint8_t data[17] = {MFDES_AUTHENTICATION_FRAME}; 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 receivedAnswer[MAX_FRAME_SIZE] = {0x00};
uint8_t receivedAnswerPar[MAX_PARITY_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 ((receivedAnswer[0] == 0x03) && (receivedAnswer[1] == 0xae)) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) if (MF_DBGLEVEL >= MF_DBG_ERROR)
@ -675,13 +708,13 @@ int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){
return 1; return 1;
} }
if (len == 12){ if (len == 12) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
Dbprintf("Auth2 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", Dbprintf("Auth2 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4], receivedAnswer[0], receivedAnswer[1], receivedAnswer[2], receivedAnswer[3], receivedAnswer[4],
receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9], receivedAnswer[5], receivedAnswer[6], receivedAnswer[7], receivedAnswer[8], receivedAnswer[9],
receivedAnswer[10],receivedAnswer[11]); receivedAnswer[10], receivedAnswer[11]);
} }
memcpy(blockData, receivedAnswer, 12); memcpy(blockData, receivedAnswer, 12);
return 0; return 0;
} }

View file

@ -58,12 +58,12 @@
#define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF(); #define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF();
//functions //functions
int mifare_sendcmd(uint8_t cmd, uint8_t *data, uint8_t data_size, 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); 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 // 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_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested);
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing); int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing);
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid);
int mifare_classic_halt_ex(struct Crypto1State *pcs); 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(); int mifare_ultra_halt();
// desfire // desfire
int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_sendcmd_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer,uint8_t *answer_parity, uint32_t *timing); int mifare_sendcmd_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData); int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData);
int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData); int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData);

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); uint8_t Tt = 1 & opt_T(s);
successor->t = (s->t >> 1); 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 = s->b >> 1;
successor->b |= (opt_B(s) ^ (s->r & 0x1)) << 7; successor->b |= (opt_B(s) ^ (s->r & 0x1)) << 7;
successor->r = (k[opt__select(Tt,y,s->r)] ^ successor->b) + s->l ; successor->r = (k[opt__select(Tt, y, s->r)] ^ successor->b) + s->l ;
successor->l = successor->r+s->r; 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; State x2;
int i; int i;
uint8_t head = 0; 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 times = 0;
uint8_t bout = 0; uint8_t bout = 0;
State temp = {0,0,0,0}; State temp = {0, 0, 0, 0};
for ( ; times < 4; times++) { for (; times < 4; times++) {
bout =0; bout = 0;
bout |= (s->r & 0x4) << 5; bout |= (s->r & 0x4) << 5;
opt_successor(k, s, 0, &temp); opt_successor(k, s, 0, &temp);
bout |= (temp.r & 0x4) << 4; bout |= (temp.r & 0x4) << 4;
@ -174,54 +177,59 @@ 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 = { State _init = {
((k[0] ^ 0x4c) + 0xEC) & 0xFF,// l ((k[0] ^ 0x4c) + 0xEC) & 0xFF,// l
((k[0] ^ 0x4c) + 0x21) & 0xFF,// r ((k[0] ^ 0x4c) + 0x21) & 0xFF,// r
0x4c, // b 0x4c, // b
0xE012 // t 0xE012 // t
}; };
opt_suc(k,&_init,input,12, false); opt_suc(k, &_init, input, 12, false);
opt_output(k,&_init, out); 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 & 0xF0) >> 4 | (b & 0x0F) << 4;
b = (b & 0xCC) >> 2 | (b & 0x33) << 2; b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
b = (b & 0xAA) >> 1 | (b & 0x55) << 1; b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
return b; 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; uint8_t i;
for ( i =0; i< len ; i++) for (i = 0; i < len ; i++)
dest[i] = rev_byte(src[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]; static uint8_t cc_nr[12];
opt_reverse_arraybytecpy(cc_nr, cc_nr_p, 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); opt_MAC(div_key_p, cc_nr, dest);
//The output MAC must also be reversed //The output MAC must also be reversed
opt_reverse_arraybytecpy(mac, dest, 4); opt_reverse_arraybytecpy(mac, dest, 4);
return; return;
} }
void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[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]; {
static uint8_t cc_nr[8 + 4 + 4];
opt_reverse_arraybytecpy(cc_nr, cc_p, 12); opt_reverse_arraybytecpy(cc_nr, cc_p, 12);
State _init = { State _init = {
((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l ((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l
((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF,// r ((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF,// r
0x4c, // b 0x4c, // b
0xE012 // t 0xE012 // t
}; };
opt_suc(div_key_p, &_init, cc_nr, 12, true); 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); opt_output(div_key_p, &_init, dest);
//The output MAC must also be reversed //The output MAC must also be reversed
opt_reverse_arraybytecpy(mac, dest,4); opt_reverse_arraybytecpy(mac, dest, 4);
return; return;
} }
@ -233,15 +241,16 @@ void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]) {
* @param div_key_p * @param div_key_p
* @return the cipher state * @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]; static uint8_t cc_nr[8];
opt_reverse_arraybytecpy(cc_nr, cc_p, 8); opt_reverse_arraybytecpy(cc_nr, cc_p, 8);
State _init = { State _init = {
((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l ((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l
((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF,// r ((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF,// r
0x4c, // b 0x4c, // b
0xE012 // t 0xE012 // t
}; };
opt_suc(div_key_p, &_init, cc_nr, 8, false); opt_suc(div_key_p, &_init, cc_nr, 8, false);
return _init; return _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 mac - where to store the MAC
* @param div_key_p - the key to use * @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]; static uint8_t _nr[4];
opt_reverse_arraybytecpy(_nr, 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); opt_output(div_key_p, &_init, dest);
//The output MAC must also be reversed //The output MAC must also be reversed
opt_reverse_arraybytecpy(mac, dest,4); opt_reverse_arraybytecpy(mac, dest, 4);
return; 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 mac - where to store the MAC
* @param div_key_p - the key to use * @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 #endif // OPTIMIZED_CIPHER_H

View file

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

View file

@ -11,10 +11,10 @@ size_t DemodPCF7931(uint8_t **outBlocks);
bool IsBlock0PCF7931(uint8_t *Block); bool IsBlock0PCF7931(uint8_t *Block);
bool IsBlock1PCF7931(uint8_t *Block); bool IsBlock1PCF7931(uint8_t *Block);
void ReadPCF7931(); void ReadPCF7931();
void SendCmdPCF7931(uint32_t * tab); void SendCmdPCF7931(uint32_t *tab);
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);
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);
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);
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);
#endif #endif

View file

@ -128,282 +128,301 @@ kvsprintf(char const *fmt, void *arg, int radix, va_list ap)
for (;;) { for (;;) {
padc = ' '; padc = ' ';
width = 0; width = 0;
while ((ch = (u_char)*fmt++) != '%' || stop) { while ((ch = (u_char) * fmt++) != '%' || stop) {
PCHAR(ch); PCHAR(ch);
if (ch == '\0') if (ch == '\0')
return (retval); return (retval);
} }
percent = fmt - 1; percent = fmt - 1;
qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; qflag = 0;
sign = 0; dot = 0; dwidth = 0; upper = 0; lflag = 0;
cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0; ladjust = 0;
reswitch: switch (ch = (u_char)*fmt++) { sharpflag = 0;
case '.': neg = 0;
dot = 1; sign = 0;
goto reswitch; dot = 0;
case '#': dwidth = 0;
sharpflag = 1; upper = 0;
goto reswitch; cflag = 0;
case '+': hflag = 0;
sign = 1; jflag = 0;
goto reswitch; tflag = 0;
case '-': zflag = 0;
ladjust = 1; reswitch:
goto reswitch; switch (ch = (u_char) * fmt++) {
case '%': case '.':
PCHAR(ch); dot = 1;
break;
case '*':
if (!dot) {
width = va_arg(ap, int);
if (width < 0) {
ladjust = !ladjust;
width = -width;
}
} else {
dwidth = va_arg(ap, int);
}
goto reswitch;
case '0':
if (!dot) {
padc = '0';
goto reswitch; goto reswitch;
} case '#':
case '1': case '2': case '3': case '4': sharpflag = 1;
case '5': case '6': case '7': case '8': case '9': goto reswitch;
case '+':
sign = 1;
goto reswitch;
case '-':
ladjust = 1;
goto reswitch;
case '%':
PCHAR(ch);
break;
case '*':
if (!dot) {
width = va_arg(ap, int);
if (width < 0) {
ladjust = !ladjust;
width = -width;
}
} else {
dwidth = va_arg(ap, int);
}
goto reswitch;
case '0':
if (!dot) {
padc = '0';
goto reswitch;
}
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
for (n = 0;; ++fmt) { for (n = 0;; ++fmt) {
n = n * 10 + ch - '0'; n = n * 10 + ch - '0';
ch = *fmt; ch = *fmt;
if (ch < '0' || ch > '9') if (ch < '0' || ch > '9')
break; break;
} }
if (dot) if (dot)
dwidth = n; dwidth = n;
else else
width = n; width = n;
goto reswitch; goto reswitch;
case 'b': case 'b':
num = (u_int)va_arg(ap, int); num = (u_int)va_arg(ap, int);
p = va_arg(ap, char *); p = va_arg(ap, char *);
for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;) for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
PCHAR(*q--); PCHAR(*q--);
if (num == 0) if (num == 0)
break; break;
for (tmp = 0; *p;) { for (tmp = 0; *p;) {
n = *p++; n = *p++;
if (num & (1 << (n - 1))) { if (num & (1 << (n - 1))) {
PCHAR(tmp ? ',' : '<'); PCHAR(tmp ? ',' : '<');
for (; (n = *p) > ' '; ++p) for (; (n = *p) > ' '; ++p)
PCHAR(n); PCHAR(n);
tmp = 1; tmp = 1;
} else } else
for (; *p > ' '; ++p) for (; *p > ' '; ++p)
continue; continue;
}
if (tmp)
PCHAR('>');
break;
case 'c':
PCHAR(va_arg(ap, int));
break;
case 'D':
up = va_arg(ap, u_char *);
p = va_arg(ap, char *);
if (!width)
width = 16;
while(width--) {
PCHAR(hex2ascii(*up >> 4));
PCHAR(hex2ascii(*up & 0x0f));
up++;
if (width)
for (q=p;*q;q++)
PCHAR(*q);
}
break;
case 'd':
case 'i':
base = 10;
sign = 1;
goto handle_sign;
case 'h':
if (hflag) {
hflag = 0;
cflag = 1;
} else
hflag = 1;
goto reswitch;
case 'j':
jflag = 1;
goto reswitch;
case 'l':
if (lflag) {
lflag = 0;
qflag = 1;
} else
lflag = 1;
goto reswitch;
case 'n':
if (jflag)
*(va_arg(ap, intmax_t *)) = retval;
else if (qflag)
*(va_arg(ap, quad_t *)) = retval;
else if (lflag)
*(va_arg(ap, long *)) = retval;
else if (zflag)
*(va_arg(ap, size_t *)) = retval;
else if (hflag)
*(va_arg(ap, short *)) = retval;
else if (cflag)
*(va_arg(ap, char *)) = retval;
else
*(va_arg(ap, int *)) = retval;
break;
case 'o':
base = 8;
goto handle_nosign;
case 'p':
base = 16;
sharpflag = (width == 0);
sign = 0;
num = (uintptr_t)va_arg(ap, void *);
goto number;
case 'q':
qflag = 1;
goto reswitch;
case 'r':
base = radix;
if (sign)
goto handle_sign;
goto handle_nosign;
case 's':
p = va_arg(ap, char *);
if (p == NULL)
p = "(null)";
if (!dot)
n = strlen (p);
else
for (n = 0; n < dwidth && p[n]; n++)
continue;
width -= n;
if (!ladjust && width > 0)
while (width--)
PCHAR(padc);
while (n--)
PCHAR(*p++);
if (ladjust && width > 0)
while (width--)
PCHAR(padc);
break;
case 't':
tflag = 1;
goto reswitch;
case 'u':
base = 10;
goto handle_nosign;
case 'X':
upper = 1;
case 'x':
base = 16;
goto handle_nosign;
case 'y':
base = 16;
sign = 1;
goto handle_sign;
case 'z':
zflag = 1;
goto reswitch;
handle_nosign:
sign = 0;
if (jflag)
num = va_arg(ap, uintmax_t);
else if (qflag)
num = va_arg(ap, u_quad_t);
else if (tflag)
num = va_arg(ap, ptrdiff_t);
else if (lflag)
num = va_arg(ap, u_long);
else if (zflag)
num = va_arg(ap, size_t);
else if (hflag)
num = (u_short)va_arg(ap, int);
else if (cflag)
num = (u_char)va_arg(ap, int);
else
num = va_arg(ap, u_int);
goto number;
handle_sign:
if (jflag)
num = va_arg(ap, intmax_t);
else if (qflag)
num = va_arg(ap, quad_t);
else if (tflag)
num = va_arg(ap, ptrdiff_t);
else if (lflag)
num = va_arg(ap, long);
else if (zflag)
num = va_arg(ap, ssize_t);
else if (hflag)
num = (short)va_arg(ap, int);
else if (cflag)
num = (char)va_arg(ap, int);
else
num = va_arg(ap, int);
number:
if (sign && (intmax_t)num < 0) {
neg = 1;
num = -(intmax_t)num;
}
p = ksprintn(nbuf, num, base, &tmp, upper);
if (sharpflag && num != 0) {
if (base == 8)
tmp++;
else if (base == 16)
tmp += 2;
}
if (neg)
tmp++;
if (!ladjust && padc != '0' && width
&& (width -= tmp) > 0)
while (width--)
PCHAR(padc);
if (neg)
PCHAR('-');
if (sharpflag && num != 0) {
if (base == 8) {
PCHAR('0');
} else if (base == 16) {
PCHAR('0');
PCHAR('x');
} }
} if (tmp)
if (!ladjust && width && (width -= tmp) > 0) PCHAR('>');
while (width--) break;
PCHAR(padc); case 'c':
PCHAR(va_arg(ap, int));
break;
case 'D':
up = va_arg(ap, u_char *);
p = va_arg(ap, char *);
if (!width)
width = 16;
while (width--) {
PCHAR(hex2ascii(*up >> 4));
PCHAR(hex2ascii(*up & 0x0f));
up++;
if (width)
for (q = p; *q; q++)
PCHAR(*q);
}
break;
case 'd':
case 'i':
base = 10;
sign = 1;
goto handle_sign;
case 'h':
if (hflag) {
hflag = 0;
cflag = 1;
} else
hflag = 1;
goto reswitch;
case 'j':
jflag = 1;
goto reswitch;
case 'l':
if (lflag) {
lflag = 0;
qflag = 1;
} else
lflag = 1;
goto reswitch;
case 'n':
if (jflag)
*(va_arg(ap, intmax_t *)) = retval;
else if (qflag)
*(va_arg(ap, quad_t *)) = retval;
else if (lflag)
*(va_arg(ap, long *)) = retval;
else if (zflag)
*(va_arg(ap, size_t *)) = retval;
else if (hflag)
*(va_arg(ap, short *)) = retval;
else if (cflag)
*(va_arg(ap, char *)) = retval;
else
*(va_arg(ap, int *)) = retval;
break;
case 'o':
base = 8;
goto handle_nosign;
case 'p':
base = 16;
sharpflag = (width == 0);
sign = 0;
num = (uintptr_t)va_arg(ap, void *);
goto number;
case 'q':
qflag = 1;
goto reswitch;
case 'r':
base = radix;
if (sign)
goto handle_sign;
goto handle_nosign;
case 's':
p = va_arg(ap, char *);
if (p == NULL)
p = "(null)";
if (!dot)
n = strlen(p);
else
for (n = 0; n < dwidth && p[n]; n++)
continue;
while (*p) width -= n;
PCHAR(*p--);
if (ladjust && width && (width -= tmp) > 0) if (!ladjust && width > 0)
while (width--) while (width--)
PCHAR(padc); PCHAR(padc);
while (n--)
PCHAR(*p++);
if (ladjust && width > 0)
while (width--)
PCHAR(padc);
break;
case 't':
tflag = 1;
goto reswitch;
case 'u':
base = 10;
goto handle_nosign;
case 'X':
upper = 1;
case 'x':
base = 16;
goto handle_nosign;
case 'y':
base = 16;
sign = 1;
goto handle_sign;
case 'z':
zflag = 1;
goto reswitch;
handle_nosign:
sign = 0;
if (jflag)
num = va_arg(ap, uintmax_t);
else if (qflag)
num = va_arg(ap, u_quad_t);
else if (tflag)
num = va_arg(ap, ptrdiff_t);
else if (lflag)
num = va_arg(ap, u_long);
else if (zflag)
num = va_arg(ap, size_t);
else if (hflag)
num = (u_short)va_arg(ap, int);
else if (cflag)
num = (u_char)va_arg(ap, int);
else
num = va_arg(ap, u_int);
goto number;
handle_sign:
if (jflag)
num = va_arg(ap, intmax_t);
else if (qflag)
num = va_arg(ap, quad_t);
else if (tflag)
num = va_arg(ap, ptrdiff_t);
else if (lflag)
num = va_arg(ap, long);
else if (zflag)
num = va_arg(ap, ssize_t);
else if (hflag)
num = (short)va_arg(ap, int);
else if (cflag)
num = (char)va_arg(ap, int);
else
num = va_arg(ap, int);
number:
if (sign && (intmax_t)num < 0) {
neg = 1;
num = -(intmax_t)num;
}
p = ksprintn(nbuf, num, base, &tmp, upper);
if (sharpflag && num != 0) {
if (base == 8)
tmp++;
else if (base == 16)
tmp += 2;
}
if (neg)
tmp++;
break; if (!ladjust && padc != '0' && width
default: && (width -= tmp) > 0)
while (percent < fmt) while (width--)
PCHAR(*percent++); PCHAR(padc);
/* if (neg)
* Since we ignore an formatting argument it is no PCHAR('-');
* longer safe to obey the remaining formatting if (sharpflag && num != 0) {
* arguments as the arguments will no longer match if (base == 8) {
* the format specs. PCHAR('0');
*/ } else if (base == 16) {
stop = 1; PCHAR('0');
break; PCHAR('x');
}
}
if (!ladjust && width && (width -= tmp) > 0)
while (width--)
PCHAR(padc);
while (*p)
PCHAR(*p--);
if (ladjust && width && (width -= tmp) > 0)
while (width--)
PCHAR(padc);
break;
default:
while (percent < fmt)
PCHAR(*percent++);
/*
* Since we ignore an formatting argument it is no
* longer safe to obey the remaining formatting
* arguments as the arguments will no longer match
* the format specs.
*/
stop = 1;
break;
} }
} }
PCHAR(0); PCHAR(0);

View file

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

View file

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

View file

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

View file

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

View file

@ -11,7 +11,8 @@
#include "ticks.h" #include "ticks.h"
// attempt at high resolution microsecond timer // attempt at high resolution microsecond timer
// beware: timer counts in 21.3uS increments (1024/48Mhz) // beware: timer counts in 21.3uS increments (1024/48Mhz)
void SpinDelayUs(int us) { void SpinDelayUs(int us)
{
int ticks = (48 * us) >> 10; int ticks = (48 * us) >> 10;
// Borrow a PWM unit for my real-time clock // 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; uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
for(;;) { for (;;) {
uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
if (now == (uint16_t)(start + ticks)) if (now == (uint16_t)(start + ticks))
return; 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); // convert to uS and call microsecond delay function
SpinDelayUs(ms * 1000);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// timer lib // timer lib
@ -46,26 +48,29 @@ void SpinDelay(int ms) {
// SpinDelay(1000); // SpinDelay(1000);
// ti = GetTickCount() - ti; // ti = GetTickCount() - ti;
// Dbprintf("timer(1s): %d t=%d", ti, GetTickCount()); // 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. // 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. // 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 uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & 0xffff; // = 16 * main clock frequency (16MHz) / slow clock frequency
// set RealTimeCounter divider to count at 1kHz: // 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% // note: worst case precision is approx 2.5%
} }
/* /*
* Get the current count. * Get the current count.
*/ */
uint32_t RAMFUNC GetTickCount(void){ uint32_t RAMFUNC GetTickCount(void)
{
return AT91C_BASE_RTTC->RTTC_RTVR;// was * 2; return AT91C_BASE_RTTC->RTTC_RTVR;// was * 2;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// microseconds timer // microseconds timer
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void StartCountUS(void) { void StartCountUS(void)
{
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); 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; AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
@ -73,8 +78,8 @@ void StartCountUS(void) {
// tick=1.5mks // tick=1.5mks
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32 AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32
AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_ACPA_CLEAR | AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_ACPA_CLEAR |
AT91C_TC_ACPC_SET | AT91C_TC_ASWTRG_SET; AT91C_TC_ACPC_SET | AT91C_TC_ASWTRG_SET;
AT91C_BASE_TC0->TC_RA = 1; AT91C_BASE_TC0->TC_RA = 1;
AT91C_BASE_TC0->TC_RC = 0xBFFF + 1; // 0xC000 AT91C_BASE_TC0->TC_RC = 0xBFFF + 1; // 0xC000
@ -88,7 +93,8 @@ void StartCountUS(void) {
while (AT91C_BASE_TC1->TC_CV > 0); 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); //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 // 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; return ((uint32_t)AT91C_BASE_TC1->TC_CV) * 0x8000 + (((uint32_t)AT91C_BASE_TC0->TC_CV) * 2) / 3;
@ -97,40 +103,41 @@ uint32_t RAMFUNC GetCountUS(void){
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Timer for iso14443 commands. Uses ssp_clk from FPGA // 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_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_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_TIOA1 // XC0 Clock = TIOA1
| AT91C_TCB_TC1XC1S_NONE // XC1 Clock = none | AT91C_TCB_TC1XC1S_NONE // XC1 Clock = none
| AT91C_TCB_TC2XC2S_TIOA0; // XC2 Clock = TIOA0 | AT91C_TCB_TC2XC2S_TIOA0; // XC2 Clock = TIOA0
// configure TC1 to create a short pulse on TIOA1 when a rising edge on TIOB1 (= ssp_clk from FPGA) occurs: // configure TC1 to create a short pulse on TIOA1 when a rising edge on TIOB1 (= ssp_clk from FPGA) occurs:
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // disable TC1 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // disable TC1
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK // TC1 Clock = MCK(48MHz)/2 = 24MHz AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK // TC1 Clock = MCK(48MHz)/2 = 24MHz
| AT91C_TC_CPCSTOP // Stop clock on RC compare | AT91C_TC_CPCSTOP // Stop clock on RC compare
| AT91C_TC_EEVTEDG_RISING // Trigger on rising edge of Event | AT91C_TC_EEVTEDG_RISING // Trigger on rising edge of Event
| AT91C_TC_EEVT_TIOB // Event-Source: TIOB1 (= ssp_clk from FPGA = 13,56MHz/16) | AT91C_TC_EEVT_TIOB // Event-Source: TIOB1 (= ssp_clk from FPGA = 13,56MHz/16)
| AT91C_TC_ENETRG // Enable external trigger event | AT91C_TC_ENETRG // Enable external trigger event
| AT91C_TC_WAVESEL_UP // Upmode without automatic trigger on RC compare | AT91C_TC_WAVESEL_UP // Upmode without automatic trigger on RC compare
| AT91C_TC_WAVE // Waveform Mode | AT91C_TC_WAVE // Waveform Mode
| AT91C_TC_AEEVT_SET // Set TIOA1 on external event | AT91C_TC_AEEVT_SET // Set TIOA1 on external event
| AT91C_TC_ACPC_CLEAR; // Clear TIOA1 on RC Compare | AT91C_TC_ACPC_CLEAR; // Clear TIOA1 on RC Compare
AT91C_BASE_TC1->TC_RC = 0x04; // RC Compare value = 0x04 AT91C_BASE_TC1->TC_RC = 0x04; // RC Compare value = 0x04
// use TC0 to count TIOA1 pulses // use TC0 to count TIOA1 pulses
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // disable TC0 AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // disable TC0
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_XC0 // TC0 clock = XC0 clock = TIOA1 AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_XC0 // TC0 clock = XC0 clock = TIOA1
| AT91C_TC_WAVE // Waveform Mode | AT91C_TC_WAVE // Waveform Mode
| AT91C_TC_WAVESEL_UP // just count | AT91C_TC_WAVESEL_UP // just count
| AT91C_TC_ACPA_CLEAR // Clear TIOA0 on RA Compare | AT91C_TC_ACPA_CLEAR // Clear TIOA0 on RA Compare
| AT91C_TC_ACPC_SET; // Set TIOA0 on RC Compare | AT91C_TC_ACPC_SET; // Set TIOA0 on RC Compare
AT91C_BASE_TC0->TC_RA = 1; // RA Compare value = 1; pulse width to TC2 AT91C_BASE_TC0->TC_RA = 1; // RA Compare value = 1; pulse width to TC2
AT91C_BASE_TC0->TC_RC = 0; // RC Compare value = 0; increment TC2 on overflow AT91C_BASE_TC0->TC_RC = 0; // RC Compare value = 0; increment TC2 on overflow
// use TC2 to count TIOA0 pulses (giving us a 32bit counter (TC0/TC2) clocked by ssp_clk) // use TC2 to count TIOA0 pulses (giving us a 32bit counter (TC0/TC2) clocked by ssp_clk)
AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKDIS; // disable TC2 AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKDIS; // disable TC2
AT91C_BASE_TC2->TC_CMR = AT91C_TC_CLKS_XC2 // TC2 clock = XC2 clock = TIOA0 AT91C_BASE_TC2->TC_CMR = AT91C_TC_CLKS_XC2 // TC2 clock = XC2 clock = TIOA0
| AT91C_TC_WAVE // Waveform Mode | AT91C_TC_WAVE // Waveform Mode
| AT91C_TC_WAVESEL_UP; // just count | AT91C_TC_WAVESEL_UP; // just count
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // enable and reset TC0 AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // enable and reset TC0
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // enable and reset TC1 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // enable and reset TC1
@ -138,9 +145,9 @@ void StartCountSspClk(void) {
// synchronize the counter with the ssp_frame signal. // synchronize the counter with the ssp_frame signal.
// Note: FPGA must be in any iso14443 mode, otherwise the frame signal would not be present // 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 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_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_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 // 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 // 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. // Therefore need to wait quite some time before we can use the counter.
while (AT91C_BASE_TC2->TC_CV > 0); while (AT91C_BASE_TC2->TC_CV > 0);
} }
void ResetSspClk(void) { void ResetSspClk(void)
{
//enable clock of timer and software trigger //enable clock of timer and software trigger
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
AT91C_BASE_TC1->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; AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
while (AT91C_BASE_TC2->TC_CV > 0); 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; 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 if ((tmp_count & 0x0000ffff) == 0) //small chance that we may have missed an increment in TC2
return (AT91C_BASE_TC2->TC_CV << 16); 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 // Timer for bitbanging, or LF stuff when you need a very precis timer
// 1us = 1.5ticks // 1us = 1.5ticks
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void StartTicks(void){ void StartTicks(void)
{
// initialization of the timer // initialization of the timer
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); 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; 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); while (AT91C_BASE_TC0->TC_CV > 0);
} }
uint32_t GetTicks(void) { uint32_t GetTicks(void)
{
uint32_t hi, lo; uint32_t hi, lo;
do { do {
hi = AT91C_BASE_TC1->TC_CV; hi = AT91C_BASE_TC1->TC_CV;
lo = AT91C_BASE_TC0->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; return (hi << 16) | lo;
} }
// Wait - Spindelay in ticks. // Wait - Spindelay in ticks.
// if called with a high number, this will trigger the WDT... // if called with a high number, this will trigger the WDT...
void WaitTicks(uint32_t ticks){ void WaitTicks(uint32_t ticks)
if ( ticks == 0 ) return; {
if (ticks == 0) return;
ticks += GetTicks(); ticks += GetTicks();
while (GetTicks() < ticks); while (GetTicks() < ticks);
} }
// Wait / Spindelay in us (microseconds) // Wait / Spindelay in us (microseconds)
// 1us = 1.5ticks. // 1us = 1.5ticks.
void WaitUS(uint16_t us){ void WaitUS(uint16_t us)
WaitTicks( (uint32_t)us * 3/2 ); {
WaitTicks((uint32_t)us * 3 / 2);
} }
void WaitMS(uint16_t ms){ void WaitMS(uint16_t ms)
WaitTicks( (uint32_t)ms * 1500 ); {
WaitTicks((uint32_t)ms * 1500);
} }
// stop clock // stop clock
void StopTicks(void){ void StopTicks(void)
{
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
} }

View file

@ -9,8 +9,9 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "util.h" #include "util.h"
size_t nbytes(size_t nbits) { size_t nbytes(size_t nbits)
return (nbits >> 3)+((nbits % 8) > 0); {
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. Returns the value v with the bottom b [0,32] bits reflected.
Example: reflect(0x3e23L,3) == 0x3e26 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; uint32_t t = v;
for ( int i = 0; i < b; ++i) { for (int i = 0; i < b; ++i) {
if (t & 1) if (t & 1)
v |= BITMASK((b-1)-i); v |= BITMASK((b - 1) - i);
else else
v &= ~BITMASK((b-1)-i); v &= ~BITMASK((b - 1) - i);
t>>=1; t >>= 1;
} }
return v; return v;
} }
uint8_t reflect8(uint8_t b) { uint8_t reflect8(uint8_t b)
{
return ((b * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32; return ((b * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
} }
uint16_t reflect16(uint16_t b) { uint16_t reflect16(uint16_t b)
{
uint16_t v = 0; uint16_t v = 0;
v |= (b & 0x8000) >> 15; v |= (b & 0x8000) >> 15;
v |= (b & 0x4000) >> 13; v |= (b & 0x4000) >> 13;
@ -55,14 +59,16 @@ uint16_t reflect16(uint16_t b) {
return v; 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--) { while (len--) {
dest[len] = (uint8_t) n; dest[len] = (uint8_t) n;
n >>= 8; 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; uint64_t num = 0;
while (len--) { while (len--) {
num = (num << 8) | (*src); num = (num << 8) | (*src);
@ -72,56 +78,93 @@ uint64_t bytes_to_num(uint8_t* src, size_t len) {
} }
// RotateLeft - Ultralight, Desfire // 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]; uint8_t first = data[0];
for (size_t i = 0; i < len-1; i++) { for (size_t i = 0; i < len - 1; i++) {
data[i] = data[i+1]; 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++) { 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; 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]; return (data[2] << 16) | (data[1] << 8) | data[0];
} }
//convert hex digit to integer //convert hex digit to integer
uint8_t hex2int(char hexchar){ uint8_t hex2int(char hexchar)
switch(hexchar){ {
case '0': return 0; break; switch (hexchar) {
case '1': return 1; break; case '0':
case '2': return 2; break; return 0;
case '3': return 3; break; break;
case '4': return 4; break; case '1':
case '5': return 5; break; return 1;
case '6': return 6; break; break;
case '7': return 7; break; case '2':
case '8': return 8; break; return 2;
case '9': return 9; break; 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':
case 'A': return 10; break; case 'A':
return 10;
break;
case 'b': case 'b':
case 'B': return 11; break; case 'B':
return 11;
break;
case 'c': case 'c':
case 'C': return 12; break; case 'C':
return 12;
break;
case 'd': case 'd':
case 'D': return 13; break; case 'D':
return 13;
break;
case 'e': case 'e':
case 'E': return 14; break; case 'E':
return 14;
break;
case 'f': case 'f':
case 'F': return 15; break; case 'F':
return 15;
break;
default: default:
return 0; return 0;
} }
} }
void LEDsoff() { void LEDsoff()
{
LED_A_OFF(); LED_A_OFF();
LED_B_OFF(); LED_B_OFF();
LED_C_OFF(); LED_C_OFF();
@ -129,7 +172,8 @@ void LEDsoff() {
} }
// LEDs: R(C) O(A) G(B) -- R(D) [1, 2, 4 and 8] // 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) if (led & LED_RED)
LED_C_ON(); LED_C_ON();
if (led & LED_ORANGE) if (led & LED_ORANGE)
@ -154,7 +198,8 @@ void LED(int led, int ms) {
LED_D_OFF(); LED_D_OFF();
} }
void SpinOff(uint32_t pause) { void SpinOff(uint32_t pause)
{
LED_A_OFF(); LED_A_OFF();
LED_B_OFF(); LED_B_OFF();
LED_C_OFF(); LED_C_OFF();
@ -163,29 +208,30 @@ void SpinOff(uint32_t pause) {
} }
// 0=A, 1=B, 2=C, 3=D // 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); SpinOff(speed);
NTIME(times) NTIME(times) {
{
switch (led) { switch (led) {
case 0: case 0:
LED_A_INV(); LED_A_INV();
break; break;
case 1: case 1:
LED_B_INV(); LED_B_INV();
break; break;
case 2: case 2:
LED_C_INV(); LED_C_INV();
break; break;
case 3: case 3:
LED_D_INV(); LED_D_INV();
break; break;
} }
SpinDelay(speed); SpinDelay(speed);
} }
} }
void SpinDown(uint32_t speed) { void SpinDown(uint32_t speed)
{
SpinOff(speed); SpinOff(speed);
LED_D_ON(); LED_D_ON();
SpinDelay(speed); SpinDelay(speed);
@ -201,7 +247,8 @@ void SpinDown(uint32_t speed) {
LED_A_OFF(); LED_A_OFF();
} }
void SpinUp(uint32_t speed) { void SpinUp(uint32_t speed)
{
SpinOff(speed); SpinOff(speed);
LED_A_ON(); LED_A_ON();
SpinDelay(speed); SpinDelay(speed);
@ -222,7 +269,8 @@ void SpinUp(uint32_t speed) {
// not clicked, or held down (for ms || 1sec) // not clicked, or held down (for ms || 1sec)
// In general, don't use this function unless you expect a // In general, don't use this function unless you expect a
// double click, otherwise it will waste 500ms -- use BUTTON_HELD instead // 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 // Up to 500ms in between clicks to mean a double click
int ticks = (48000 * (ms ? ms : 1000)) >> 10; 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; uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
int letoff = 0; int letoff = 0;
for(;;) for (;;) {
{
uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
// We haven't let off the button yet // We haven't let off the button yet
if (!letoff) if (!letoff) {
{
// We just let it off! // We just let it off!
if (!BUTTON_PRESS()) if (!BUTTON_PRESS()) {
{
letoff = 1; letoff = 1;
// reset our timer for 500ms // reset our timer for 500ms
@ -270,11 +315,10 @@ int BUTTON_CLICKED(int ms) {
if (BUTTON_PRESS()) if (BUTTON_PRESS())
return BUTTON_DOUBLE_CLICK; return BUTTON_DOUBLE_CLICK;
// Have we ran out of time to double click? // Have we ran out of time to double click?
else else if (now == (uint16_t)(start + ticks))
if (now == (uint16_t)(start + ticks)) // At least we did a single click
// At least we did a single click return BUTTON_SINGLE_CLICK;
return BUTTON_SINGLE_CLICK;
WDT_HIT(); WDT_HIT();
} }
@ -284,7 +328,8 @@ int BUTTON_CLICKED(int ms) {
} }
// Determine if a button is held down // Determine if a button is held down
int BUTTON_HELD(int ms) { int BUTTON_HELD(int ms)
{
// If button is held for one second // If button is held for one second
int ticks = (48000 * (ms ? ms : 1000)) >> 10; 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; uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
for(;;) for (;;) {
{
uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
// As soon as our button let go, we didn't hold long enough // As soon as our button let go, we didn't hold long enough
@ -310,9 +354,8 @@ int BUTTON_HELD(int ms) {
return BUTTON_SINGLE_CLICK; return BUTTON_SINGLE_CLICK;
// Have we waited the full second? // Have we waited the full second?
else else if (now == (uint16_t)(start + ticks))
if (now == (uint16_t)(start + ticks)) return BUTTON_HOLD;
return BUTTON_HOLD;
WDT_HIT(); WDT_HIT();
} }
@ -326,10 +369,11 @@ int BUTTON_HELD(int ms) {
* verifies the magic properties, then stores a formatted string, prefixed by * verifies the magic properties, then stores a formatted string, prefixed by
* prefix in dst. * prefix in dst.
*/ */
void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information) { void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information)
struct version_information *v = (struct version_information*)version_information; {
struct version_information *v = (struct version_information *)version_information;
dst[0] = 0; dst[0] = 0;
strncat(dst, prefix, len-1); strncat(dst, prefix, len - 1);
if (v->magic != VERSION_INFORMATION_MAGIC) { if (v->magic != VERSION_INFORMATION_MAGIC) {
strncat(dst, "Missing/Invalid version information\n", len - strlen(dst) - 1); strncat(dst, "Missing/Invalid version information\n", len - strlen(dst) - 1);
return; 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 uint8_t reflect8(uint8_t b); // dedicated 8bit reversal
extern uint16_t reflect16(uint16_t b); // dedicated 16bit reversal extern uint16_t reflect16(uint16_t b); // dedicated 16bit reversal
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest); void num_to_bytes(uint64_t n, size_t len, uint8_t *dest);
uint64_t bytes_to_num(uint8_t* src, size_t len); uint64_t bytes_to_num(uint8_t *src, size_t len);
void rol(uint8_t *data, const size_t len); void rol(uint8_t *data, const size_t len);
void lsl (uint8_t *data, size_t len); void lsl(uint8_t *data, size_t len);
int32_t le24toh (uint8_t data[3]); int32_t le24toh(uint8_t data[3]);
uint8_t hex2int(char hexchar); uint8_t hex2int(char hexchar);
void LED(int led, int ms); 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(P, BUF, SIZ) (P)->uart_write(BUF, SIZ, (P)->extobj)
#define UART_WRITE(BUF) DbprintfEx(FLAG_RAWPRINT, "%s", BUF) #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->uart_write = uart_write;
p->extobj = extobj; p->extobj = extobj;
return 0; 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]; char buf[1 + 8];
buf[0] = ESC; buf[0] = ESC;
buf[1] = '['; buf[1] = '[';
@ -58,7 +60,8 @@ int vtsend_cursor_position(vtsend_t *p, const int column, const int line) {
return 0; 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]; char buf[1 + 5];
buf[0] = ESC; buf[0] = ESC;
buf[1] = '['; buf[1] = '[';
@ -71,7 +74,8 @@ int vtsend_cursor_up(vtsend_t *p, const int n) {
return 0; 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]; char buf[1 + 5];
buf[0] = ESC; buf[0] = ESC;
buf[1] = '['; buf[1] = '[';
@ -84,7 +88,8 @@ int vtsend_cursor_down(vtsend_t *p, const int n) {
return 0; 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]; char buf[1 + 5];
buf[0] = ESC; buf[0] = ESC;
buf[1] = '['; buf[1] = '[';
@ -97,7 +102,8 @@ int vtsend_cursor_forward(vtsend_t *p, const int n) {
return 0; 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]; char buf[1 + 5];
buf[0] = ESC; buf[0] = ESC;
buf[1] = '['; buf[1] = '[';
@ -110,7 +116,8 @@ int vtsend_cursor_backward(vtsend_t *p, const int n) {
return 0; return 0;
} }
int vtsend_cursor_position_save(vtsend_t *p) { int vtsend_cursor_position_save(vtsend_t *p)
{
char buf[1 + 3]; char buf[1 + 3];
buf[0] = ESC; buf[0] = ESC;
buf[1] = '['; buf[1] = '[';
@ -121,7 +128,8 @@ int vtsend_cursor_position_save(vtsend_t *p) {
return 0; return 0;
} }
int vtsend_cursor_position_restore(vtsend_t *p) { int vtsend_cursor_position_restore(vtsend_t *p)
{
char buf[1 + 3]; char buf[1 + 3];
buf[0] = ESC; buf[0] = ESC;
buf[1] = '['; buf[1] = '[';
@ -132,7 +140,8 @@ int vtsend_cursor_position_restore(vtsend_t *p) {
return 0; return 0;
} }
int vtsend_erase_display(vtsend_t *p) { int vtsend_erase_display(vtsend_t *p)
{
char buf[1 + 4]; char buf[1 + 4];
buf[0] = ESC; buf[0] = ESC;
buf[1] = '['; buf[1] = '[';
@ -144,7 +153,8 @@ int vtsend_erase_display(vtsend_t *p) {
return 0; return 0;
} }
int vtsend_erase_line(vtsend_t *p) { int vtsend_erase_line(vtsend_t *p)
{
char buf[1 + 4]; char buf[1 + 4];
buf[0] = ESC; buf[0] = ESC;
buf[1] = '['; buf[1] = '[';
@ -156,7 +166,8 @@ int vtsend_erase_line(vtsend_t *p) {
return 0; 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]; char buf[1 + 5];
buf[0] = ESC; buf[0] = ESC;
buf[1] = '['; buf[1] = '[';
@ -169,7 +180,8 @@ int vtsend_set_color_foreground(vtsend_t *p, const int color) {
return 0; 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]; char buf[1 + 5];
buf[0] = ESC; buf[0] = ESC;
buf[1] = '['; buf[1] = '[';
@ -182,7 +194,8 @@ int vtsend_set_color_background(vtsend_t *p, const int color) {
return 0; 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]; char buf[1 + 5];
buf[0] = ESC; buf[0] = ESC;
buf[1] = '['; buf[1] = '[';
@ -195,7 +208,8 @@ int vtsend_set_attribute(vtsend_t *p, const int attr) {
return 0; 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]; char buf[1 + 8];
buf[0] = ESC; buf[0] = ESC;
buf[1] = '['; buf[1] = '[';
@ -211,7 +225,8 @@ int vtsend_set_scroll_region(vtsend_t *p, const int top, const int bottom) {
return 0; return 0;
} }
int vtsend_set_cursor(vtsend_t *p, const int visible) { int vtsend_set_cursor(vtsend_t *p, const int visible)
{
if (visible) { if (visible) {
char buf[1 + 6]; char buf[1 + 6];
buf[0] = ESC; buf[0] = ESC;
@ -238,7 +253,8 @@ int vtsend_set_cursor(vtsend_t *p, const int visible) {
return 0; return 0;
} }
int vtsend_reset(vtsend_t *p) { int vtsend_reset(vtsend_t *p)
{
char buf[1 + 2]; char buf[1 + 2];
buf[0] = ESC; buf[0] = ESC;
buf[1] = 'c'; buf[1] = 'c';
@ -248,7 +264,8 @@ int vtsend_reset(vtsend_t *p) {
return 0; 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; int i;
vtsend_cursor_position(p, x1, y1); 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; 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; int i, j;
for (i = y1; i <= y2; i++) { for (i = y1; i <= y2; i++) {
vtsend_cursor_position(p, x1, i); vtsend_cursor_position(p, x1, i);

View file

@ -78,11 +78,11 @@ int vtsend_set_cursor(vtsend_t *p, const int visible);
int vtsend_reset(vtsend_t *p); int vtsend_reset(vtsend_t *p);
int vtsend_draw_box( int vtsend_draw_box(
vtsend_t *p, vtsend_t *p,
const int x1, const int y1, const int x2, const int y2); const int x1, const int y1, const int x2, const int y2);
int vtsend_fill_box( int vtsend_fill_box(
vtsend_t *p, vtsend_t *p,
const int x1, const int y1, const int x2, const int y2); const int x1, const int y1, const int x2, const int y2);
#ifdef __cplusplus #ifdef __cplusplus
} }

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 char _bootrom_start, _bootrom_end, _flash_start, _flash_end;
extern uint32_t _osimage_entry; extern uint32_t _osimage_entry;
void DbpString(char *str) { void DbpString(char *str)
{
byte_t len = 0; byte_t len = 0;
while (str[len] != 0x00) while (str[len] != 0x00)
len++; 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 // we are using a 16 MHz crystal as the basis for everything
// slow clock runs at 32Khz typical regardless of crystal // slow clock runs at 32Khz typical regardless of crystal
@ -32,12 +34,12 @@ static void ConfigClocks(void) {
// enable the clock to the following peripherals // enable the clock to the following peripherals
AT91C_BASE_PMC->PMC_PCER = AT91C_BASE_PMC->PMC_PCER =
(1<<AT91C_ID_PIOA) | (1 << AT91C_ID_PIOA) |
(1<<AT91C_ID_ADC) | (1 << AT91C_ID_ADC) |
(1<<AT91C_ID_SPI) | (1 << AT91C_ID_SPI) |
(1<<AT91C_ID_SSC) | (1 << AT91C_ID_SSC) |
(1<<AT91C_ID_PWMC) | (1 << AT91C_ID_PWMC) |
(1<<AT91C_ID_UDP); (1 << AT91C_ID_UDP);
// worst case scenario, with MAINCK = 16Mhz xtal, startup delay is 1.4ms // 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 // 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); PMC_MAIN_OSC_STARTUP_DELAY(8);
// wait for main oscillator to stabilize // 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 80 - 160 MHz needs CKGR_PLL = 00
// PLL output clock frequency in range 150 - 180 MHz needs CKGR_PLL = 10 // 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); PMC_PLL_USB_DIVISOR(1);
// wait for PLL to lock // 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 // we want a master clock (MCK) to be PLL clock / 2 = 96Mhz / 2 = 48Mhz
// datasheet recommends that this register is programmed in two operations // datasheet recommends that this register is programmed in two operations
@ -71,84 +73,90 @@ static void ConfigClocks(void) {
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2; AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2;
// wait for main clock ready signal // 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 // set the source to PLL
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2 | AT91C_PMC_CSS_PLL_CLK; AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2 | AT91C_PMC_CSS_PLL_CLK;
// wait for main clock ready signal // 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) { static void Fatal(void)
for(;;) {}; {
for (;;) {};
} }
void UsbPacketReceived(uint8_t *packet, int len) { void UsbPacketReceived(uint8_t *packet, int len)
{
int i, dont_ack = 0; int i, dont_ack = 0;
UsbCommand* c = (UsbCommand *)packet; UsbCommand *c = (UsbCommand *)packet;
volatile uint32_t *p; volatile uint32_t *p;
//if ( len != sizeof(UsbCommand)) Fatal(); //if ( len != sizeof(UsbCommand)) Fatal();
uint32_t arg0 = (uint32_t)c->arg[0]; uint32_t arg0 = (uint32_t)c->arg[0];
switch(c->cmd) { switch (c->cmd) {
case CMD_DEVICE_INFO: { case CMD_DEVICE_INFO: {
dont_ack = 1; dont_ack = 1;
arg0 = DEVICE_INFO_FLAG_BOOTROM_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM | arg0 = DEVICE_INFO_FLAG_BOOTROM_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM |
DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH; DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH;
if(common_area.flags.osimage_present) if (common_area.flags.osimage_present)
arg0 |= DEVICE_INFO_FLAG_OSIMAGE_PRESENT; arg0 |= DEVICE_INFO_FLAG_OSIMAGE_PRESENT;
cmd_send(CMD_DEVICE_INFO,arg0,1,2,0,0); cmd_send(CMD_DEVICE_INFO, arg0, 1, 2, 0, 0);
} break; }
break;
case CMD_SETUP_WRITE: { case CMD_SETUP_WRITE: {
/* The temporary write buffer of the embedded flash controller is mapped to the /* The temporary write buffer of the embedded flash controller is mapped to the
* whole memory region, only the last 8 bits are decoded. * whole memory region, only the last 8 bits are decoded.
*/ */
p = (volatile uint32_t *)&_flash_start; p = (volatile uint32_t *)&_flash_start;
for(i = 0; i < 12; i++) for (i = 0; i < 12; i++)
p[i+arg0] = c->d.asDwords[i]; p[i + arg0] = c->d.asDwords[i];
} break; }
break;
case CMD_FINISH_WRITE: { case CMD_FINISH_WRITE: {
uint32_t* flash_mem = (uint32_t*)(&_flash_start); uint32_t *flash_mem = (uint32_t *)(&_flash_start);
for ( int j=0; j<2; j++) { for (int j = 0; j < 2; j++) {
for(i = 0+(64*j); i < 64+(64*j); i++) { for (i = 0 + (64 * j); i < 64 + (64 * j); i++) {
flash_mem[i] = c->d.asDwords[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 */ /* 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 */ /* Disallow write */
dont_ack = 1; dont_ack = 1;
cmd_send(CMD_NACK,0,0,0,0,0); cmd_send(CMD_NACK, 0, 0, 0, 0, 0);
} else { } else {
uint32_t page_n = (flash_address - ((uint32_t)flash_mem)) / AT91C_IFLASH_PAGE_SIZE; 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 */ /* Translate address to flash page and do flash, update here for the 512k part */
AT91C_BASE_EFC0->EFC_FCR = MC_FLASH_COMMAND_KEY | AT91C_BASE_EFC0->EFC_FCR = MC_FLASH_COMMAND_KEY |
MC_FLASH_COMMAND_PAGEN(page_n) | MC_FLASH_COMMAND_PAGEN(page_n) |
AT91C_MC_FCMD_START_PROG; AT91C_MC_FCMD_START_PROG;
} }
// Wait until flashing of page finishes // Wait until flashing of page finishes
uint32_t sr; uint32_t sr;
while(!((sr = AT91C_BASE_EFC0->EFC_FSR) & AT91C_MC_FRDY)); while (!((sr = AT91C_BASE_EFC0->EFC_FSR) & AT91C_MC_FRDY));
if(sr & (AT91C_MC_LOCKE | AT91C_MC_PROGE)) { if (sr & (AT91C_MC_LOCKE | AT91C_MC_PROGE)) {
dont_ack = 1; 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: { case CMD_HARDWARE_RESET: {
usb_disable(); usb_disable();
AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST; AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
} break; }
break;
case CMD_START_FLASH: { case CMD_START_FLASH: {
if (c->arg[2] == START_FLASH_MAGIC) 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 /* 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. * 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_start >= allow_start) &&
(cmd_end <= allow_end) ) { (cmd_end <= allow_end)) {
start_addr = cmd_start; start_addr = cmd_start;
end_addr = cmd_end; end_addr = cmd_end;
} else { } else {
start_addr = end_addr = 0; start_addr = end_addr = 0;
dont_ack = 1; dont_ack = 1;
cmd_send(CMD_NACK,0,0,0,0,0); cmd_send(CMD_NACK, 0, 0, 0, 0, 0);
} }
} break; }
break;
default: { default: {
Fatal(); Fatal();
} break; }
break;
} }
if (!dont_ack) 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; start_addr = 0;
end_addr = 0; end_addr = 0;
bootrom_unlocked = 0; bootrom_unlocked = 0;
@ -196,14 +207,14 @@ static void flash_mode(int externally_entered) {
usb_enable(); usb_enable();
// wait for reset to be complete? // 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(); WDT_HIT();
// Check if there is a usb packet available // Check if there is a usb packet available
if (usb_poll_validate_length()) { if (usb_poll_validate_length()) {
if (usb_read(rx, sizeof(rx)) ) if (usb_read(rx, sizeof(rx)))
UsbPacketReceived(rx, sizeof(rx)); UsbPacketReceived(rx, sizeof(rx));
} }
@ -212,7 +223,7 @@ static void flash_mode(int externally_entered) {
usb_disable(); usb_disable();
LED_B_ON(); LED_B_ON();
AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST; AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
for(;;) {}; for (;;) {};
} }
if (externally_entered && BUTTON_PRESS()) { if (externally_entered && BUTTON_PRESS()) {
/* Let the user's button press override the automatic leave */ /* 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 // First set up all the I/O pins; GPIOs configured directly, other ones
// just need to be assigned to the appropriate peripheral. // just need to be assigned to the appropriate peripheral.
@ -246,7 +258,7 @@ void BootROM(void) {
GPIO_MUXSEL_LORAW | GPIO_MUXSEL_LORAW |
GPIO_RELAY | GPIO_RELAY |
GPIO_NVDD_ON; GPIO_NVDD_ON;
// (and add GPIO_FPGA_ON) // (and add GPIO_FPGA_ON)
// These pins are outputs // These pins are outputs
AT91C_BASE_PIOA->PIO_OER = AT91C_BASE_PIOA->PIO_OER =
GPIO_LED_A | GPIO_LED_A |
@ -274,8 +286,8 @@ void BootROM(void) {
AT91C_BASE_EFC0->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48); AT91C_BASE_EFC0->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48);
// 9 = 256, 10+ is 512kb // 9 = 256, 10+ is 512kb
uint8_t id = ( *(AT91C_DBGU_CIDR) & 0xF00) >> 8; uint8_t id = (*(AT91C_DBGU_CIDR) & 0xF00) >> 8;
if ( id > 9 ) if (id > 9)
AT91C_BASE_EFC1->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48); AT91C_BASE_EFC1->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48);
// Initialize all system clocks // Initialize all system clocks
@ -285,23 +297,23 @@ void BootROM(void) {
int common_area_present = 0; int common_area_present = 0;
switch (AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_RSTTYP) { switch (AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_RSTTYP) {
case AT91C_RSTC_RSTTYP_WATCHDOG: case AT91C_RSTC_RSTTYP_WATCHDOG:
case AT91C_RSTC_RSTTYP_SOFTWARE: case AT91C_RSTC_RSTTYP_SOFTWARE:
case AT91C_RSTC_RSTTYP_USER: case AT91C_RSTC_RSTTYP_USER:
/* In these cases the common_area in RAM should be ok, retain it if it's there */ /* 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; common_area_present = 1;
break; break;
default: /* Otherwise, initialize it from scratch */ default: /* Otherwise, initialize it from scratch */
break; break;
} }
if (!common_area_present){ if (!common_area_present) {
/* Common area not ok, initialize it */ /* Common area not ok, initialize it */
int i; int i;
/* Makeshift memset, no need to drag util.c into this */ /* Makeshift memset, no need to drag util.c into this */
for(i=0; i<sizeof(common_area); i++) for (i = 0; i < sizeof(common_area); i++)
((char*)&common_area)[i] = 0; ((char *)&common_area)[i] = 0;
common_area.magic = COMMON_AREA_MAGIC; common_area.magic = COMMON_AREA_MAGIC;
common_area.version = 1; common_area.version = 1;
@ -318,6 +330,6 @@ void BootROM(void) {
flash_mode(1); flash_mode(1);
} else { } else {
// jump to Flash address of the osimage entry point (LSBit set for thumb mode) // 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_DATA 0x008
#define HMAC_POS_TAG 0x1B4 #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); memcpy(key + 0x00, dump + 0x029, 0x02);
memset(key + 0x02, 0x00, 0x0E); memset(key + 0x02, 0x00, 0x0E);
memcpy(key + 0x10, dump + 0x1D4, 0x08); 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); 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]; uint8_t seed[NFC3D_KEYGEN_SEED_SIZE];
nfc3d_amiibo_calc_seed(dump, seed); nfc3d_amiibo_calc_seed(dump, seed);
nfc3d_keygen(masterKeys, seed, derivedKeys); 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; mbedtls_aes_context aes;
size_t nc_off = 0; size_t nc_off = 0;
unsigned char nonce_counter[16]; unsigned char nonce_counter[16];
unsigned char stream_block[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(nonce_counter, 0, sizeof(nonce_counter));
memset(stream_block, 0, sizeof(stream_block)); memset(stream_block, 0, sizeof(stream_block));
memcpy(nonce_counter, keys->aesIV, sizeof(nonce_counter)); 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); memcpy(out + 0x000, in + 0x000, 0x008);
// Data signature NOT copied // 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); 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 + 0x000, tag + 0x008, 0x008);
memcpy(intl + 0x008, tag + 0x080, 0x020); memcpy(intl + 0x008, tag + 0x080, 0x020);
memcpy(intl + 0x028, tag + 0x010, 0x024); 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); 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 + 0x008, intl + 0x000, 0x008);
memcpy(tag + 0x080, intl + 0x008, 0x020); memcpy(tag + 0x080, intl + 0x008, 0x020);
memcpy(tag + 0x010, intl + 0x028, 0x024); 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); 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]; uint8_t internal[NFC3D_AMIIBO_SIZE];
nfc3d_keygen_derivedkeys dataKeys; nfc3d_keygen_derivedkeys dataKeys;
nfc3d_keygen_derivedkeys tagKeys; 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); nfc3d_amiibo_cipher(&dataKeys, internal, plain);
// Regenerate tag HMAC. Note: order matters, data HMAC depends on tag HMAC! // 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), mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey),
plain + 0x1D4, 0x34, plain + HMAC_POS_TAG ); plain + 0x1D4, 0x34, plain + HMAC_POS_TAG);
// Regenerate data HMAC // Regenerate data HMAC
mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), dataKeys.hmacKey, sizeof(dataKeys.hmacKey), mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), dataKeys.hmacKey, sizeof(dataKeys.hmacKey),
plain + 0x029, 0x1DF, plain + HMAC_POS_DATA ); plain + 0x029, 0x1DF, plain + HMAC_POS_DATA);
return return
memcmp(plain + HMAC_POS_DATA, internal + HMAC_POS_DATA, 32) == 0 && memcmp(plain + HMAC_POS_DATA, internal + HMAC_POS_DATA, 32) == 0 &&
memcmp(plain + HMAC_POS_TAG, internal + HMAC_POS_TAG, 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]; uint8_t cipher[NFC3D_AMIIBO_SIZE];
nfc3d_keygen_derivedkeys tagKeys; nfc3d_keygen_derivedkeys tagKeys;
nfc3d_keygen_derivedkeys dataKeys; 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); nfc3d_amiibo_keygen(&amiiboKeys->data, plain, &dataKeys);
// Generate tag HMAC // Generate tag HMAC
mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey), mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey),
plain + 0x1D4, 0x34, cipher + HMAC_POS_TAG ); plain + 0x1D4, 0x34, cipher + HMAC_POS_TAG);
// Init mbedtls HMAC context // Init mbedtls HMAC context
mbedtls_md_context_t ctx; mbedtls_md_context_t ctx;
mbedtls_md_init( &ctx ); mbedtls_md_init(&ctx);
mbedtls_md_setup( &ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1 ); mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1);
// Generate data HMAC // Generate data HMAC
mbedtls_md_hmac_starts( &ctx, dataKeys.hmacKey, sizeof(dataKeys.hmacKey) ); mbedtls_md_hmac_starts(&ctx, dataKeys.hmacKey, sizeof(dataKeys.hmacKey));
mbedtls_md_hmac_update( &ctx, plain + 0x029, 0x18B ); // Data 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, cipher + HMAC_POS_TAG, 0x20); // Tag HMAC
mbedtls_md_hmac_update( &ctx, plain + 0x1D4, 0x34 ); // Here be dragons 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 // HMAC cleanup
mbedtls_md_free( &ctx ); mbedtls_md_free(&ctx);
// Encrypt // Encrypt
nfc3d_amiibo_cipher(&dataKeys, plain, cipher); 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); nfc3d_amiibo_internal_to_tag(cipher, tag);
} }
bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys * amiiboKeys, const char * path) { bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys *amiiboKeys, const char *path)
FILE * f = fopen(path, "rb"); {
FILE *f = fopen(path, "rb");
if (!f) { if (!f) {
return false; return false;
} }
@ -152,7 +160,8 @@ bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys * amiiboKeys, const char * path) {
return true; 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); //uint16_t *ami_nb_wr = (uint16_t*)(dst + 0x29);
@ -162,8 +171,8 @@ void nfc3d_amiibo_copy_app_data(const uint8_t * src, uint8_t * dst) {
//*ami_nb_wr = htobe16(be16toh(*ami_nb_wr) + 1); //*ami_nb_wr = htobe16(be16toh(*ami_nb_wr) + 1);
//*cfg_nb_wr = htobe16(be16toh(*cfg_nb_wr) + 1); //*cfg_nb_wr = htobe16(be16toh(*cfg_nb_wr) + 1);
uint16_t ami_nb_wr = ((uint16_t)bytes_to_num(dst + 0x29, 2)) + 1; uint16_t ami_nb_wr = ((uint16_t)bytes_to_num(dst + 0x29, 2)) + 1;
uint16_t cfg_nb_wr = ((uint16_t)bytes_to_num(dst + 0xB4, 2)) + 1; uint16_t cfg_nb_wr = ((uint16_t)bytes_to_num(dst + 0xB4, 2)) + 1;
num_to_bytes(ami_nb_wr, 2, dst + 0x29); num_to_bytes(ami_nb_wr, 2, dst + 0x29);
num_to_bytes(cfg_nb_wr, 2, dst + 0xB4); num_to_bytes(cfg_nb_wr, 2, dst + 0xB4);

View file

@ -24,9 +24,9 @@ typedef struct {
} nfc3d_amiibo_keys; } nfc3d_amiibo_keys;
#pragma pack() #pragma pack()
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);
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);
bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys * amiiboKeys, const char * path); 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); void nfc3d_amiibo_copy_app_data(const uint8_t *src, uint8_t *dst);
#endif #endif

View file

@ -12,27 +12,29 @@
#define NTAG215_SIZE 540 #define NTAG215_SIZE 540
static char * self; static char *self;
void amiitool_usage() { void amiitool_usage()
{
fprintf(stderr, fprintf(stderr,
"amiitool build %i (commit %s-%08x)\n" "amiitool build %i (commit %s-%08x)\n"
"by Marcos Del Sol Vives <marcos@dracon.es>\n" "by Marcos Del Sol Vives <marcos@dracon.es>\n"
"\n" "\n"
"Usage: %s (-e|-d|-c) -k keyfile [-i input] [-s input2] [-o output]\n" "Usage: %s (-e|-d|-c) -k keyfile [-i input] [-s input2] [-o output]\n"
" -e encrypt and sign amiibo\n" " -e encrypt and sign amiibo\n"
" -d decrypt and test amiibo\n" " -d decrypt and test amiibo\n"
" -c decrypt, copy AppData and encrypt amiibo\n" " -c decrypt, copy AppData and encrypt amiibo\n"
" -k key set file. For retail amiibo, use \"retail unfixed\" key set\n" " -k key set file. For retail amiibo, use \"retail unfixed\" key set\n"
" -i input file. If not specified, stdin will be used.\n" " -i input file. If not specified, stdin will be used.\n"
" -s input save file, save from this file will replace input file ones.\n" " -s input save file, save from this file will replace input file ones.\n"
" -o output file. If not specified, stdout will be used.\n" " -o output file. If not specified, stdout will be used.\n"
" -l decrypt files with invalid signatures.\n", " -l decrypt files with invalid signatures.\n",
, self , self
); );
} }
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)) { if (!nfc3d_amiibo_load_keys(&keys, keyfile)) {
PrintAndLogEx(ERR, "Could not load keys from '%s'", 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; return true;
} }
int main(int argc, char ** argv) { int main(int argc, char **argv)
{
self = argv[0]; self = argv[0];
char * infile = NULL; char *infile = NULL;
char * savefile = NULL; char *savefile = NULL;
char * outfile = NULL; char *outfile = NULL;
char * keyfile = NULL; char *keyfile = NULL;
char op = '\0'; char op = '\0';
bool lenient = false; bool lenient = false;
@ -88,7 +91,7 @@ int main(int argc, char ** argv) {
uint8_t original[NTAG215_SIZE]; uint8_t original[NTAG215_SIZE];
uint8_t modified[NFC3D_AMIIBO_SIZE]; uint8_t modified[NFC3D_AMIIBO_SIZE];
FILE * f = stdin; FILE *f = stdin;
if (infile) { if (infile) {
f = fopen(infile, "rb"); f = fopen(infile, "rb");
if (!f) { if (!f) {

View file

@ -10,7 +10,8 @@
#include <string.h> #include <string.h>
#include <mbedtls/md.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(ctx != NULL);
assert(hmacKey != NULL); assert(hmacKey != NULL);
assert(seed != 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); 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(ctx != NULL);
assert(output != 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); 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); assert(ctx != NULL);
mbedtls_md_free(&ctx->hmacCtx); 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]; uint8_t temp[NFC3D_DRBG_OUTPUT_SIZE];
nfc3d_drbg_ctx rngCtx; nfc3d_drbg_ctx rngCtx;

View file

@ -24,10 +24,10 @@ typedef struct {
size_t bufferSize; size_t bufferSize;
} nfc3d_drbg_ctx; } 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_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_step(nfc3d_drbg_ctx *ctx, uint8_t *output);
void nfc3d_drbg_cleanup(nfc3d_drbg_ctx * ctx); 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_generate_bytes(const uint8_t *hmacKey, size_t hmacKeySize, const uint8_t *seed, size_t seedSize, uint8_t *output, size_t outputSize);
#endif #endif

View file

@ -10,13 +10,14 @@
#include <stdio.h> #include <stdio.h>
#include <string.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(baseKeys != NULL);
assert(baseSeed != NULL); assert(baseSeed != NULL);
assert(output != NULL); assert(output != NULL);
assert(outputSize != NULL); assert(outputSize != NULL);
uint8_t * start = output; uint8_t *start = output;
// 1: Copy whole type string // 1: Copy whole type string
output = memccpy(output, baseKeys->typeString, '\0', sizeof(baseKeys->typeString)); 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; *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]; uint8_t preparedSeed[NFC3D_DRBG_MAX_SEED_SIZE];
size_t preparedSeedSize; size_t preparedSeedSize;

View file

@ -29,6 +29,6 @@ typedef struct {
} nfc3d_keygen_derivedkeys; } nfc3d_keygen_derivedkeys;
#pragma pack() #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 #endif

View file

@ -13,46 +13,45 @@
#include "cmdmain.h" #include "cmdmain.h"
#define HANDLE_ERROR if (error_occured) { \ #define HANDLE_ERROR if (error_occured) { \
error_occured = 0;\ error_occured = 0;\
break;\ break;\
} }
int main(int argc, char **argv) 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\tusage: cli <command 1> <command 2> [logfile (default cli.log)]\n"); printf("\n");
printf("\n"); printf("\texample: cli hi14asnoop hi14alist h14a.log\n");
printf("\texample: cli hi14asnoop hi14alist h14a.log\n"); printf("\n");
printf("\n"); return -1;
return -1;
}
usb_init();
if (argc == 4)
SetLogFilename(argv[3]);
else
SetLogFilename("cli.log");
return_on_error = 1;
while (1) {
while (!OpenProxmark()) { sleep(1); }
while (1) {
UsbCommand cmdbuf;
CommandReceived(argv[1]);
HANDLE_ERROR;
ReceiveCommand(&cmdbuf);
HANDLE_ERROR;
for (int i = 0; i < 5; ++i) {
ReceiveCommandPoll(&cmdbuf);
}
HANDLE_ERROR;
CommandReceived(argv[2]);
HANDLE_ERROR;
} }
}
CloseProxmark(); usb_init();
return 0; if (argc == 4)
SetLogFilename(argv[3]);
else
SetLogFilename("cli.log");
return_on_error = 1;
while (1) {
while (!OpenProxmark()) { sleep(1); }
while (1) {
UsbCommand cmdbuf;
CommandReceived(argv[1]);
HANDLE_ERROR;
ReceiveCommand(&cmdbuf);
HANDLE_ERROR;
for (int i = 0; i < 5; ++i) {
ReceiveCommandPoll(&cmdbuf);
}
HANDLE_ERROR;
CommandReceived(argv[2]);
HANDLE_ERROR;
}
}
CloseProxmark();
return 0;
} }

File diff suppressed because it is too large Load diff

View file

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

View file

@ -19,7 +19,8 @@ char *programHint = NULL;
char *programHelp = NULL; char *programHelp = NULL;
char buf[500] = {0}; char buf[500] = {0};
int CLIParserInit(char *vprogramName, char *vprogramHint, char *vprogramHelp) { int CLIParserInit(char *vprogramName, char *vprogramHint, char *vprogramHelp)
{
argtable = NULL; argtable = NULL;
argtableLen = 0; argtableLen = 0;
programName = vprogramName; programName = vprogramName;
@ -30,7 +31,8 @@ int CLIParserInit(char *vprogramName, char *vprogramHint, char *vprogramHelp) {
return 0; 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; int nerrors;
argtable = vargtable; argtable = vargtable;
@ -46,7 +48,7 @@ int CLIParserParseArg(int argc, char **argv, void* vargtable[], size_t vargtable
nerrors = arg_parse(argc, argv, argtable); nerrors = arg_parse(argc, argv, argtable);
/* special case: '--help' takes precedence over error reporting */ /* 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); printf("Usage: %s", programName);
arg_print_syntaxv(stdout, argtable, "\n"); arg_print_syntaxv(stdout, argtable, "\n");
if (programHint) if (programHint)
@ -79,11 +81,13 @@ enum ParserState {
#define isSpace(c)(c == ' ' || c == '\t') #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); 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; int argc = 0;
char *argv[200] = {NULL}; char *argv[200] = {NULL};
@ -101,9 +105,9 @@ int CLIParserParseStringEx(const char* str, void* vargtable[], size_t vargtableL
// parse params // parse params
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
switch(state){ switch (state) {
case PS_FIRST: // first char 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; state = PS_OPTION;
if (spaceptr) { if (spaceptr) {
@ -125,7 +129,7 @@ int CLIParserParseStringEx(const char* str, void* vargtable[], size_t vargtableL
bufptr++; bufptr++;
break; break;
case PS_OPTION: case PS_OPTION:
if (isSpace(str[i])){ if (isSpace(str[i])) {
state = PS_FIRST; state = PS_FIRST;
*bufptr = 0x00; *bufptr = 0x00;
@ -143,7 +147,8 @@ int CLIParserParseStringEx(const char* str, void* vargtable[], size_t vargtableL
return CLIParserParseArg(argc, argv, vargtable, vargtableLen, allowEmptyExec); return CLIParserParseArg(argc, argv, vargtable, vargtableLen, allowEmptyExec);
} }
void CLIParserFree() { void CLIParserFree()
{
arg_freetable(argtable, argtableLen); arg_freetable(argtable, argtableLen);
argtable = NULL; argtable = NULL;
@ -151,7 +156,8 @@ void CLIParserFree() {
} }
// convertors // 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; *datalen = 0;
int ibuf = 0; int ibuf = 0;
@ -160,22 +166,23 @@ int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
if (res || !ibuf) if (res || !ibuf)
return res; 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: case 1:
printf("Parameter error: Invalid HEX value.\n"); printf("Parameter error: Invalid HEX value.\n");
return 1; return 1;
case 2: case 2:
printf("Parameter error: parameter too large.\n"); printf("Parameter error: parameter too large.\n");
return 2; return 2;
case 3: case 3:
printf("Parameter error: Hex string must have even number of digits.\n"); printf("Parameter error: Hex string must have even number of digits.\n");
return 3; return 3;
} }
return 0; 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; *datalen = 0;
if (!argstr->count) if (!argstr->count)
return 0; 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;} #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 CLIParserInit(char *vprogramName, char *vprogramHint, char *vprogramHelp);
extern int CLIParserParseString(const char* str, 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 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 CLIParserParseArg(int argc, char **argv, void *argtable[], size_t vargtableLen, bool allowEmptyExec);
extern void CLIParserFree(); extern void CLIParserFree();
extern int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); extern int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen);

View file

@ -60,13 +60,13 @@ struct option {
}; };
__BEGIN_DECLS __BEGIN_DECLS
int getopt_long(int, char * const *, const char *, int getopt_long(int, char *const *, const char *,
const struct option *, int *); 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 *); const struct option *, int *);
#ifndef _GETOPT_DECLARED #ifndef _GETOPT_DECLARED
#define _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 char *optarg; /* getopt(3) external variables */
extern int optind, opterr, optopt; extern int optind, opterr, optopt;

View file

@ -11,7 +11,8 @@
static int CmdHelp(const char *Cmd); 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, "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, "needed to generate that LRC with a rolling XOR. All bytes should be specified in HEX.");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
@ -25,7 +26,8 @@ int usage_analyse_lcr(void) {
PrintAndLogEx(NORMAL, "expected output: Target (BA) requires final LRC XOR byte value: 5A"); PrintAndLogEx(NORMAL, "expected output: Target (BA) requires final LRC XOR byte value: 5A");
return 0; 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, "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, "Finally compute ones' complement of the least significant bytes");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
@ -41,7 +43,8 @@ int usage_analyse_checksum(void) {
PrintAndLogEx(NORMAL, "expected output: 0x61"); PrintAndLogEx(NORMAL, "expected output: 0x61");
return 0; 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, "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, "");
PrintAndLogEx(NORMAL, "Usage: analyse crc [h] <bytes>"); PrintAndLogEx(NORMAL, "Usage: analyse crc [h] <bytes>");
@ -53,7 +56,8 @@ int usage_analyse_crc(void){
PrintAndLogEx(NORMAL, " analyse crc 137AF00A0A0D"); PrintAndLogEx(NORMAL, " analyse crc 137AF00A0A0D");
return 0; return 0;
} }
int usage_analyse_nuid(void){ int usage_analyse_nuid(void)
{
PrintAndLogEx(NORMAL, "Generate 4byte NUID from 7byte UID"); PrintAndLogEx(NORMAL, "Generate 4byte NUID from 7byte UID");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: analyse hid [h] <bytes>"); PrintAndLogEx(NORMAL, "Usage: analyse hid [h] <bytes>");
@ -65,7 +69,8 @@ int usage_analyse_nuid(void){
PrintAndLogEx(NORMAL, " analyse nuid 11223344556677"); PrintAndLogEx(NORMAL, " analyse nuid 11223344556677");
return 0; return 0;
} }
int usage_analyse_a(void) { int usage_analyse_a(void)
{
PrintAndLogEx(NORMAL, "Iceman's personal garbage test command"); PrintAndLogEx(NORMAL, "Iceman's personal garbage test command");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: analyse a [h] d <bytes>"); PrintAndLogEx(NORMAL, "Usage: analyse a [h] d <bytes>");
@ -78,7 +83,8 @@ int usage_analyse_a(void) {
return 0; 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; uint8_t LRC = 0;
for (uint8_t i = 0; i < len; i++) for (uint8_t i = 0; i < len; i++)
LRC ^= bytes[i]; LRC ^= bytes[i];
@ -102,7 +108,8 @@ static uint16_t shiftadd ( uint8_t* bytes, uint8_t len){
return 0; 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; uint16_t sum = 0;
for (uint8_t i = 0; i < len; i++) { for (uint8_t i = 0; i < len; i++) {
sum += CRUMB(bytes[i], 0); sum += CRUMB(bytes[i], 0);
@ -113,10 +120,12 @@ static uint16_t calcSumCrumbAdd( uint8_t* bytes, uint8_t len, uint32_t mask) {
sum &= mask; sum &= mask;
return sum; 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); 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; uint16_t sum = 0;
for (uint8_t i = 0; i < len; i++) { for (uint8_t i = 0; i < len; i++) {
sum += NIBBLE_LOW(bytes[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; sum &= mask;
return sum; 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); 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; uint16_t sum = 0;
for (uint8_t i = 0; i < len; i++) { for (uint8_t i = 0; i < len; i++) {
sum ^= CRUMB(bytes[i], 0); sum ^= CRUMB(bytes[i], 0);
@ -139,7 +150,8 @@ static uint16_t calcSumCrumbXor( uint8_t* bytes, uint8_t len, uint32_t mask) {
sum &= mask; sum &= mask;
return sum; 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; uint16_t sum = 0;
for (uint8_t i = 0; i < len; i++) { for (uint8_t i = 0; i < len; i++) {
sum ^= NIBBLE_LOW(bytes[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; sum &= mask;
return sum; 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; uint16_t sum = 0;
for (uint8_t i = 0; i < len; i++) { for (uint8_t i = 0; i < len; i++) {
sum ^= bytes[i]; sum ^= bytes[i];
@ -156,7 +169,8 @@ static uint16_t calcSumByteXor( uint8_t* bytes, uint8_t len, uint32_t mask) {
sum &= mask; sum &= mask;
return sum; 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; uint16_t sum = 0;
for (uint8_t i = 0; i < len; i++) { for (uint8_t i = 0; i < len; i++) {
sum += bytes[i]; sum += bytes[i];
@ -165,11 +179,13 @@ static uint16_t calcSumByteAdd( uint8_t* bytes, uint8_t len, uint32_t mask) {
return sum; return sum;
} }
// Ones complement // 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); 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; uint8_t sum = 0;
for (uint8_t i = 0; i < len; i++) { for (uint8_t i = 0; i < len; i++) {
sum -= bytes[i]; sum -= bytes[i];
@ -177,10 +193,12 @@ static uint16_t calcSumByteSub( uint8_t* bytes, uint8_t len, uint32_t mask) {
sum &= mask; sum &= mask;
return sum; 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); 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; uint8_t sum = 0;
for (uint8_t i = 0; i < len; i++) { for (uint8_t i = 0; i < len; i++) {
sum -= NIBBLE_LOW(bytes[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; sum &= mask;
return sum; 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); return (~calcSumNibbleSub(bytes, len, mask) & mask);
} }
// BSD shift checksum 8bit version // 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; 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 = ((sum & 0xFF) >> 1) | ((sum & 0x1) << 7); // rotate accumulator
sum += bytes[i]; // add next byte sum += bytes[i]; // add next byte
sum &= 0xFF; // sum &= 0xFF; //
@ -205,9 +225,10 @@ static uint16_t calcBSDchecksum8( uint8_t* bytes, uint8_t len, uint32_t mask){
return sum; return sum;
} }
// BSD shift checksum 4bit version // 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; 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 = ((sum & 0xF) >> 1) | ((sum & 0x1) << 3); // rotate accumulator
sum += NIBBLE_HIGH(bytes[i]); // add high nibble sum += NIBBLE_HIGH(bytes[i]); // add high nibble
sum &= 0xF; // sum &= 0xF; //
@ -220,7 +241,8 @@ static uint16_t calcBSDchecksum4( uint8_t* bytes, uint8_t len, uint32_t mask){
} }
// measuring LFSR maximum length // 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 start_state = 0; /* Any nonzero start state will work. */
uint16_t lfsr = start_state; uint16_t lfsr = start_state;
@ -230,7 +252,7 @@ int CmdAnalyseLfsr(const char *Cmd){
uint8_t find = param_get8ex(Cmd, 1, 0, 16); uint8_t find = param_get8ex(Cmd, 1, 0, 16);
PrintAndLogEx(NORMAL, "LEGIC LFSR IV 0x%02X: \n", iv); 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) { for (uint8_t i = 0x01; i < 0x30; i += 1) {
//period = 0; //period = 0;
@ -238,50 +260,52 @@ int CmdAnalyseLfsr(const char *Cmd){
legic_prng_forward(i); legic_prng_forward(i);
lfsr = legic_prng_get_bits(12); 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; return 0;
} }
int CmdAnalyseLCR(const char *Cmd) { int CmdAnalyseLCR(const char *Cmd)
{
uint8_t data[50]; uint8_t data[50];
char cmdp = tolower(param_getchar(Cmd, 0)); 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; int len = 0;
switch (param_gethex_to_eol(Cmd, 0, data, sizeof(data), &len)) { switch (param_gethex_to_eol(Cmd, 0, data, sizeof(data), &len)) {
case 1: case 1:
PrintAndLogEx(WARNING, "Invalid HEX value."); PrintAndLogEx(WARNING, "Invalid HEX value.");
return 1; return 1;
case 2: case 2:
PrintAndLogEx(WARNING, "Too many bytes. Max %d bytes", sizeof(data)); PrintAndLogEx(WARNING, "Too many bytes. Max %d bytes", sizeof(data));
return 1; return 1;
case 3: case 3:
PrintAndLogEx(WARNING, "Hex must have even number of digits."); PrintAndLogEx(WARNING, "Hex must have even number of digits.");
return 1; return 1;
} }
uint8_t finalXor = calculateLRC(data, len); 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; return 0;
} }
int CmdAnalyseCRC(const char *Cmd) { int CmdAnalyseCRC(const char *Cmd)
{
char cmdp = tolower(param_getchar(Cmd, 0)); char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_analyse_crc(); if (strlen(Cmd) == 0 || cmdp == 'h') return usage_analyse_crc();
int len = strlen(Cmd); int len = strlen(Cmd);
if ( len & 1 ) return usage_analyse_crc(); if (len & 1) return usage_analyse_crc();
// add 1 for null terminator. // add 1 for null terminator.
uint8_t *data = calloc(len+1, sizeof(uint8_t)); uint8_t *data = calloc(len + 1, sizeof(uint8_t));
if ( !data ) return 1; if (!data) return 1;
if ( param_gethex(Cmd, 0, data, len)) { if (param_gethex(Cmd, 0, data, len)) {
free(data); free(data);
return usage_analyse_crc(); return usage_analyse_crc();
} }
len >>= 1; 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 // 51 f5 7a d6
uint8_t uid[] = {0x51, 0xf5, 0x7a, 0xd6}; //12 34 56 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, "FeliCa | %X ", crc16_xmodem(data, len));
PrintAndLogEx(NORMAL, "\nTests of reflection. Current methods in source code"); 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, " reflect8(0x80) is %02X == 0x01", reflect8(0x80));
PrintAndLogEx(NORMAL, " reflect16(0x8000) is %04X == 0x0001", reflect16(0xc6c6)); 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); compute_crc(CRC_14443_B, data, len, &b1, &b2);
uint16_t crcBB_1 = b1 << 8 | b2; uint16_t crcBB_1 = b1 << 8 | b2;
uint16_t bbb = crc(CRC_14443_B, data, len); 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. // Test of CRC16, '123456789' string.
// //
PrintAndLogEx(NORMAL, "\n\nStandard test with 31 32 33 34 35 36 37 38 39 '123456789'\n\n"); 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)); legic8 = CRC8Legic(dataStr, sizeof(dataStr));
//these below has been tested OK. //these below has been tested OK.
@ -323,33 +347,33 @@ int CmdAnalyseCRC(const char *Cmd) {
// input from commandline // input from commandline
PrintAndLogEx(NORMAL, "CCITT | %X (29B1 expected)", crc(CRC_CCITT, dataStr, sizeof(dataStr))); 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}; 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 (B37F expected)", crc(CRC_FELICA, poll + 2, sizeof(poll) - 4));
PrintAndLogEx(NORMAL, "FeliCa | %04X (0000 expected)", crc(CRC_FELICA, poll+2, sizeof(poll)-2)); 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}; 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"); PrintAndLogEx(NORMAL, "---------------------------------------------------------------\n\n\n");
// ISO14443 crc A // ISO14443 crc A
compute_crc(CRC_14443_A, dataStr, sizeof(dataStr), &b1, &b2); compute_crc(CRC_14443_A, dataStr, sizeof(dataStr), &b1, &b2);
uint16_t crcAA = b1 << 8 | 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 // ISO14443 crc B
compute_crc(CRC_14443_B, dataStr, sizeof(dataStr), &b1, &b2); compute_crc(CRC_14443_B, dataStr, sizeof(dataStr), &b1, &b2);
uint16_t crcBB = b1 << 8 | 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) // ISO15693 crc (x.25)
compute_crc(CRC_15693, dataStr, sizeof(dataStr), &b1, &b2); compute_crc(CRC_15693, dataStr, sizeof(dataStr), &b1, &b2);
uint16_t crcCC = b1 << 8 | 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 // ICLASS
compute_crc(CRC_ICLASS, dataStr, sizeof(dataStr), &b1, &b2); compute_crc(CRC_ICLASS, dataStr, sizeof(dataStr), &b1, &b2);
uint16_t crcDD = b1 << 8 | 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 // FeliCa
compute_crc(CRC_FELICA, dataStr, sizeof(dataStr), &b1, &b2); compute_crc(CRC_FELICA, dataStr, sizeof(dataStr), &b1, &b2);
@ -359,7 +383,8 @@ int CmdAnalyseCRC(const char *Cmd) {
free(data); free(data);
return 0; return 0;
} }
int CmdAnalyseCHKSUM(const char *Cmd){ int CmdAnalyseCHKSUM(const char *Cmd)
{
uint8_t data[50]; uint8_t data[50];
uint8_t cmdp = 0; uint8_t cmdp = 0;
@ -369,36 +394,36 @@ int CmdAnalyseCHKSUM(const char *Cmd){
int len = 0; int len = 0;
memset(data, 0x0, sizeof(data)); memset(data, 0x0, sizeof(data));
while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch(param_getchar(Cmd, cmdp)) { switch (param_getchar(Cmd, cmdp)) {
case 'b': case 'b':
case 'B': case 'B':
param_gethex_ex(Cmd, cmdp+1, data, &len); param_gethex_ex(Cmd, cmdp + 1, data, &len);
if ( len%2 ) errors = true; if (len % 2) errors = true;
len >>= 1; len >>= 1;
cmdp += 2; cmdp += 2;
break; break;
case 'm': case 'm':
case 'M': case 'M':
mask = param_get32ex(Cmd, cmdp+1, 0, 16); mask = param_get32ex(Cmd, cmdp + 1, 0, 16);
cmdp += 2; cmdp += 2;
break; break;
case 'v': case 'v':
case 'V': case 'V':
useHeader = true; useHeader = true;
cmdp++; cmdp++;
break; break;
case 'h': case 'h':
case 'H': case 'H':
return usage_analyse_checksum(); return usage_analyse_checksum();
default: default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true; errors = true;
break; break;
} }
} }
//Validations //Validations
if (errors || cmdp == 0 ) return usage_analyse_checksum(); if (errors || cmdp == 0) return usage_analyse_checksum();
if (useHeader) { if (useHeader) {
PrintAndLogEx(NORMAL, " add | sub | add 1's compl | sub 1's compl | xor"); PrintAndLogEx(NORMAL, " add | sub | add 1's compl | sub 1's compl | xor");
@ -407,51 +432,53 @@ int CmdAnalyseCHKSUM(const char *Cmd){
} }
PrintAndLogEx(NORMAL, "0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X |\n", PrintAndLogEx(NORMAL, "0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X |\n",
calcSumByteAdd(data, len, mask) calcSumByteAdd(data, len, mask)
, calcSumNibbleAdd(data, len, mask) , calcSumNibbleAdd(data, len, mask)
, calcSumCrumbAdd(data, len, mask) , calcSumCrumbAdd(data, len, mask)
, calcSumByteSub(data, len, mask) , calcSumByteSub(data, len, mask)
, calcSumNibbleSub(data, len, mask) , calcSumNibbleSub(data, len, mask)
, calcSumByteAddOnes(data, len, mask) , calcSumByteAddOnes(data, len, mask)
, calcSumNibbleAddOnes(data, len, mask) , calcSumNibbleAddOnes(data, len, mask)
, calcSumCrumbAddOnes(data, len, mask) , calcSumCrumbAddOnes(data, len, mask)
, calcSumByteSubOnes(data, len, mask) , calcSumByteSubOnes(data, len, mask)
, calcSumNibbleSubOnes(data, len, mask) , calcSumNibbleSubOnes(data, len, mask)
, calcSumByteXor(data, len, mask) , calcSumByteXor(data, len, mask)
, calcSumNibbleXor(data, len, mask) , calcSumNibbleXor(data, len, mask)
, calcSumCrumbXor(data, len, mask) , calcSumCrumbXor(data, len, mask)
, calcBSDchecksum8(data, len, mask) , calcBSDchecksum8(data, len, mask)
, calcBSDchecksum4(data, len, mask) , calcBSDchecksum4(data, len, mask)
); );
return 0; return 0;
} }
int CmdAnalyseDates(const char *Cmd){ int CmdAnalyseDates(const char *Cmd)
{
// look for datestamps in a given array of bytes // look for datestamps in a given array of bytes
PrintAndLogEx(NORMAL, "To be implemented. Feel free to contribute!"); PrintAndLogEx(NORMAL, "To be implemented. Feel free to contribute!");
return 0; return 0;
} }
int CmdAnalyseTEASelfTest(const char *Cmd){ int CmdAnalyseTEASelfTest(const char *Cmd)
{
uint8_t v[8], v_le[8]; uint8_t v[8], v_le[8];
memset(v, 0x00, sizeof(v)); memset(v, 0x00, sizeof(v));
memset(v_le, 0x00, sizeof(v_le)); memset(v_le, 0x00, sizeof(v_le));
uint8_t* v_ptr = v_le; uint8_t *v_ptr = v_le;
uint8_t cmdlen = strlen(Cmd); 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); PrintAndLogEx(WARNING, "Can't read hex chars, uneven? :: %u", cmdlen);
return 1; return 1;
} }
SwapEndian64ex(v , 8, 4, v_ptr); SwapEndian64ex(v, 8, 4, v_ptr);
// ENCRYPTION KEY: // 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 keyle[16];
uint8_t* key_ptr = keyle; uint8_t *key_ptr = keyle;
SwapEndian64ex(key , sizeof(key), 4, key_ptr); SwapEndian64ex(key, sizeof(key), 4, key_ptr);
PrintAndLogEx(NORMAL, "TEST LE enc| %s", sprint_hex(v_ptr, 8)); PrintAndLogEx(NORMAL, "TEST LE enc| %s", sprint_hex(v_ptr, 8));
@ -465,7 +492,8 @@ int CmdAnalyseTEASelfTest(const char *Cmd){
return 0; return 0;
} }
char* pb(uint32_t b) { char *pb(uint32_t b)
{
static char buf1[33] = {0}; static char buf1[33] = {0};
static char buf2[33] = {0}; static char buf2[33] = {0};
static char *s; static char *s;
@ -478,14 +506,15 @@ char* pb(uint32_t b) {
memset(s, 0, sizeof(buf1)); memset(s, 0, sizeof(buf1));
uint32_t mask = 0x80000000; uint32_t mask = 0x80000000;
for (uint8_t i=0; i<32;i++) { for (uint8_t i = 0; i < 32; i++) {
s[i] = (mask & b)?'1':'0'; s[i] = (mask & b) ? '1' : '0';
mask >>= 1; mask >>= 1;
} }
return s; return s;
} }
int CmdAnalyseA(const char *Cmd){ int CmdAnalyseA(const char *Cmd)
{
int hexlen = 0; int hexlen = 0;
uint8_t cmdp = 0; uint8_t cmdp = 0;
@ -494,24 +523,24 @@ int CmdAnalyseA(const char *Cmd){
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) { switch (tolower(param_getchar(Cmd, cmdp))) {
case 'd': case 'd':
param_gethex_ex(Cmd, cmdp+1, data, &hexlen); param_gethex_ex(Cmd, cmdp + 1, data, &hexlen);
hexlen >>= 1; hexlen >>= 1;
if ( hexlen != sizeof(data) ) { if (hexlen != sizeof(data)) {
PrintAndLogEx(WARNING, "Read %d bytes of %u", hexlen, sizeof(data) ); PrintAndLogEx(WARNING, "Read %d bytes of %u", hexlen, sizeof(data));
} }
cmdp += 2; cmdp += 2;
break; break;
case 'h': case 'h':
return usage_analyse_a(); return usage_analyse_a();
default: default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true; errors = true;
break; break;
} }
} }
//Validations //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}}; 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) // Sequence X followed by Sequence Y followed by Sequence Z (111100x1 11111111 00x11111)
// we therefore look for a ...xx1111 11111111 00x11111xxxxxx... pattern // 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) // (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); uint32_t shiftReg = param_get32ex(Cmd, 0, 0xb24d, 16);
uint8_t bt = param_get8ex(Cmd, 1, 0xBB, 16); uint8_t bt = param_get8ex(Cmd, 1, 0xBB, 16);
uint8_t byte_offset = 99; uint8_t byte_offset = 99;
@ -550,100 +579,100 @@ int CmdAnalyseA(const char *Cmd){
uint8_t n0 = 0, n1 = 0; 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))); 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 0) 0xB24D 0b1011001001001101
hex(0xb24d shr 1) 0x5926 hex(0xb24d shr 1) 0x5926
hex(0xb24d shr 2) 0x2C93 hex(0xb24d shr 2) 0x2C93
*/ */
for ( int i =0; i< 16; i++) { for (int i = 0; i < 16; i++) {
PrintAndLogEx(NORMAL, " (shiftReg >> %d) & 0xFFFF == %08x ---", i, (( shiftReg >> i) & 0xFFFF )); PrintAndLogEx(NORMAL, " (shiftReg >> %d) & 0xFFFF == %08x ---", i, ((shiftReg >> i) & 0xFFFF));
// kolla om SYNC_PATTERN finns. // kolla om SYNC_PATTERN finns.
if ((( shiftReg >> 7) & 0xFFFF ) == SYNC_16BIT) byte_offset = 7; if (((shiftReg >> 7) & 0xFFFF) == SYNC_16BIT) byte_offset = 7;
else if ((( shiftReg >> 6) & 0xFFFF ) == SYNC_16BIT) byte_offset = 6; else if (((shiftReg >> 6) & 0xFFFF) == SYNC_16BIT) byte_offset = 6;
else if ((( shiftReg >> 5) & 0xFFFF ) == SYNC_16BIT) byte_offset = 5; else if (((shiftReg >> 5) & 0xFFFF) == SYNC_16BIT) byte_offset = 5;
else if ((( shiftReg >> 4) & 0xFFFF ) == SYNC_16BIT) byte_offset = 4; else if (((shiftReg >> 4) & 0xFFFF) == SYNC_16BIT) byte_offset = 4;
else if ((( shiftReg >> 3) & 0xFFFF ) == SYNC_16BIT) byte_offset = 3; else if (((shiftReg >> 3) & 0xFFFF) == SYNC_16BIT) byte_offset = 3;
else if ((( shiftReg >> 2) & 0xFFFF ) == SYNC_16BIT) byte_offset = 2; else if (((shiftReg >> 2) & 0xFFFF) == SYNC_16BIT) byte_offset = 2;
else if ((( shiftReg >> 1) & 0xFFFF ) == SYNC_16BIT) byte_offset = 1; else if (((shiftReg >> 1) & 0xFFFF) == SYNC_16BIT) byte_offset = 1;
else if ((( shiftReg >> 0) & 0xFFFF ) == SYNC_16BIT) byte_offset = 0; else if (((shiftReg >> 0) & 0xFFFF) == SYNC_16BIT) byte_offset = 0;
PrintAndLogEx(NORMAL, "Offset %u \n", byte_offset); PrintAndLogEx(NORMAL, "Offset %u \n", byte_offset);
if ( byte_offset != 99 ) if (byte_offset != 99)
break; break;
shiftReg >>=1; shiftReg >>= 1;
} }
uint8_t p1 = (rev & (uint8_t)(~(0xFF << byte_offset))); 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;
for (uint8_t m=0; m<8; m++) {
offset = m;
n0 = (rev & (uint8_t)(~(0xFF >> (8-offset)))) >> offset;
n1 = (n1 << offset) | (rev & (uint8_t)(~(0xFF << offset)));
PrintAndLogEx(NORMAL, "rev %02X | %02X %s | %02X %s |\n", rev, n0, pb(n0), n1, pb(n1) );
n0 = 0, n1 = 0;
// PrintAndLogEx(NORMAL, " (0xFF >> offset) == %s |\n", pb( (0xFF >> offset)) );
//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;
// from A -- x bits into B and the rest into C.
for ( uint8_t i=0; i<8; i++){
PrintAndLogEx(NORMAL, "%u | %02X %s | %02X %s |\n", i, a, pb(a), b, pb(b) );
b = a & (a & (0xFF >> (8-i)));
a >>=1;
}
*/ */
return 0; return 0;
/*
// split byte into two parts.
uint8_t offset = 3, n0 = 0, n1 = 0;
rev = 0xB2;
for (uint8_t m=0; m<8; m++) {
offset = m;
n0 = (rev & (uint8_t)(~(0xFF >> (8-offset)))) >> offset;
n1 = (n1 << offset) | (rev & (uint8_t)(~(0xFF << offset)));
PrintAndLogEx(NORMAL, "rev %02X | %02X %s | %02X %s |\n", rev, n0, pb(n0), n1, pb(n1) );
n0 = 0, n1 = 0;
// PrintAndLogEx(NORMAL, " (0xFF >> offset) == %s |\n", pb( (0xFF >> offset)) );
//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;
// from A -- x bits into B and the rest into C.
for ( uint8_t i=0; i<8; i++){
PrintAndLogEx(NORMAL, "%u | %02X %s | %02X %s |\n", i, a, pb(a), b, pb(b) );
b = a & (a & (0xFF >> (8-i)));
a >>=1;
}
*/
return 0;
// 14443-A // 14443-A
uint8_t u14_c[] = {0x09, 0x78, 0x00, 0x92, 0x02, 0x54, 0x13, 0x02, 0x04, 0x2d, 0xe8 }; // atqs w crc 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 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(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(SUCCESS, "14a check correct crc | %s\n", (check_crc(CRC_14443_A, u14_c, sizeof(u14_c))) ? "YES" : "NO");
// 14443-B // 14443-B
uint8_t u14b[] = {0x05,0x00,0x08,0x39,0x73}; 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"); PrintAndLogEx(NORMAL, "14b check crc | %s\n", (check_crc(CRC_14443_B, u14b, sizeof(u14b))) ? "YES" : "NO");
// 15693 test // 15693 test
uint8_t u15_c[] = {0x05,0x00,0x08,0x39,0x73}; // correct uint8_t u15_c[] = {0x05, 0x00, 0x08, 0x39, 0x73}; // correct
uint8_t u15_w[] = {0x05,0x00,0x08,0x39,0x72}; // wrong 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(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"); 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. // iCLASS test - wrong crc , swapped bytes.
uint8_t iclass_w[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x01, 0x43}; 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}; 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(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(SUCCESS, "iCLASS check correct crc | %s\n", (check_crc(CRC_ICLASS, iclass_c, sizeof(iclass_c))) ? "YES" : "NO");
// FeliCa test // 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_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}; 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(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(SUCCESS, "FeliCa check correct crc | %s\n", (check_crc(CRC_FELICA, felica_c, sizeof(felica_c))) ? "YES" : "NO");
PrintAndLogEx(NORMAL, "\n\n"); PrintAndLogEx(NORMAL, "\n\n");
@ -687,27 +716,35 @@ return 0;
//uint64_t d1[] = {0x6e442129, 0x8f699195, 0x0000001, 0x090d0b0305020f02}; //uint64_t d1[] = {0x6e442129, 0x8f699195, 0x0000001, 0x090d0b0305020f02};
//uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0x00040f0f0305030e}; //uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0x00040f0f0305030e};
/* /*
uid(3e172b29) nt(039b7bd2) ks(0c0e0f0505080800) nr(00000001) uid(3e172b29) nt(039b7bd2) ks(0c0e0f0505080800) nr(00000001)
uid(3e172b29) nt(039b7bd2) ks(0e06090d03000b0f) nr(00000002) uid(3e172b29) nt(039b7bd2) ks(0e06090d03000b0f) nr(00000002)
*/ */
uint64_t *keylistA = NULL, *keylistB = NULL; uint64_t *keylistA = NULL, *keylistB = NULL;
uint32_t keycountA = 0, keycountB = 0; uint32_t keycountA = 0, keycountB = 0;
// uint64_t d1[] = {0x3e172b29, 0x039b7bd2, 0x0000001, 0, 0x0c0e0f0505080800}; // uint64_t d1[] = {0x3e172b29, 0x039b7bd2, 0x0000001, 0, 0x0c0e0f0505080800};
// uint64_t d2[] = {0x3e172b29, 0x039b7bd2, 0x0000002, 0, 0x0e06090d03000b0f}; // uint64_t d2[] = {0x3e172b29, 0x039b7bd2, 0x0000002, 0, 0x0e06090d03000b0f};
uint64_t d1[] = {0x6e442129, 0x8f699195, 0x0000001, 0, 0x090d0b0305020f02}; uint64_t d1[] = {0x6e442129, 0x8f699195, 0x0000001, 0, 0x090d0b0305020f02};
uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e}; 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); keycountB = nonce2key(d2[0], d2[1], d2[2], 0, d2[3], d2[4], &keylistB);
switch (keycountA) { switch (keycountA) {
case 0: PrintAndLogEx(FAILED, "Key test A failed\n"); break; case 0:
case 1: PrintAndLogEx(SUCCESS, "KEY A | %012" PRIX64 " ", keylistA[0]); break; PrintAndLogEx(FAILED, "Key test A failed\n");
break;
case 1:
PrintAndLogEx(SUCCESS, "KEY A | %012" PRIX64 " ", keylistA[0]);
break;
} }
switch (keycountB) { switch (keycountB) {
case 0: PrintAndLogEx(FAILED, "Key test B failed\n"); break; case 0:
case 1: PrintAndLogEx(SUCCESS, "KEY B | %012" PRIX64 " ", keylistB[0]); break; PrintAndLogEx(FAILED, "Key test B failed\n");
break;
case 1:
PrintAndLogEx(SUCCESS, "KEY B | %012" PRIX64 " ", keylistB[0]);
break;
} }
free(keylistA); free(keylistA);
@ -843,7 +880,8 @@ uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e};
return 0; return 0;
} }
void generate4bNUID(uint8_t *uid, uint8_t *nuid){ void generate4bNUID(uint8_t *uid, uint8_t *nuid)
{
uint16_t crc; uint16_t crc;
uint8_t b1, b2; uint8_t b1, b2;
@ -857,12 +895,13 @@ void generate4bNUID(uint8_t *uid, uint8_t *nuid){
nuid[3] = crc & 0xFF; nuid[3] = crc & 0xFF;
} }
int CmdAnalyseNuid(const char *Cmd){ int CmdAnalyseNuid(const char *Cmd)
{
uint8_t nuid[4] = {0}; uint8_t nuid[4] = {0};
uint8_t uid[7] = {0}; uint8_t uid[7] = {0};
int len = 0; int len = 0;
char cmdp = tolower(param_getchar(Cmd, 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 */ /* src: https://www.nxp.com/docs/en/application-note/AN10927.pdf */
/* selftest1 UID 040D681AB52281 -> NUID 8F430FEF */ /* selftest1 UID 040D681AB52281 -> NUID 8F430FEF */
@ -872,7 +911,7 @@ int CmdAnalyseNuid(const char *Cmd){
generate4bNUID(uid, nuid); generate4bNUID(uid, nuid);
bool test1 = (0 == memcmp(nuid, "\x8f\x43\x0f\xef", 4)); 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); memcpy(uid, "\x04\x18\x3f\x09\x32\x1b\x85", 7);
generate4bNUID(uid, nuid); generate4bNUID(uid, nuid);
@ -882,7 +921,7 @@ int CmdAnalyseNuid(const char *Cmd){
} }
param_gethex_ex(Cmd, 0, uid, &len); 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); generate4bNUID(uid, nuid);
@ -903,13 +942,15 @@ static command_t CommandTable[] = {
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };
int CmdAnalyse(const char *Cmd) { int CmdAnalyse(const char *Cmd)
{
clearCommandBuffer(); clearCommandBuffer();
CmdsParse(CommandTable, Cmd); CmdsParse(CommandTable, Cmd);
return 0; return 0;
} }
int CmdHelp(const char *Cmd) { int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable); CmdsHelp(CommandTable);
return 0; return 0;
} }

View file

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

View file

@ -26,7 +26,8 @@
static int CmdHelp(const char *Cmd); 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, "Usage: mem spibaud [h] <baudrate>");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help"); PrintAndLogEx(NORMAL, " h this help");
@ -40,7 +41,8 @@ int usage_flashmem_spibaud(void){
return 0; return 0;
} }
int usage_flashmem_read(void){ int usage_flashmem_read(void)
{
PrintAndLogEx(NORMAL, "Read flash memory on device"); PrintAndLogEx(NORMAL, "Read flash memory on device");
PrintAndLogEx(NORMAL, "Usage: mem read o <offset> l <len>"); PrintAndLogEx(NORMAL, "Usage: mem read o <offset> l <len>");
PrintAndLogEx(NORMAL, " o <offset> : offset in memory"); 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 PrintAndLogEx(NORMAL, " mem read o 1024 l 10"); // read 10 bytes starting at offset 1024
return 0; return 0;
} }
int usage_flashmem_load(void){ int usage_flashmem_load(void)
{
PrintAndLogEx(NORMAL, "Loads binary file into flash memory on device"); 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, "Usage: mem load o <offset> f <file name> m t i");
PrintAndLogEx(NORMAL, " o <offset> : offset in memory"); 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"); PrintAndLogEx(NORMAL, " mem load f default_iclass_keys i");
return 0; return 0;
} }
int usage_flashmem_save(void){ int usage_flashmem_save(void)
{
PrintAndLogEx(NORMAL, "Saves flash memory on device into the file"); PrintAndLogEx(NORMAL, "Saves flash memory on device into the file");
PrintAndLogEx(NORMAL, " Usage: mem save o <offset> l <length> f <file name>"); PrintAndLogEx(NORMAL, " Usage: mem save o <offset> l <length> f <file name>");
PrintAndLogEx(NORMAL, " o <offset> : offset in memory"); 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 PrintAndLogEx(NORMAL, " mem save f myfile o 1024 l 4096"); // downlowd 4096 bytes from offset 1024 to file myfile
return 0; return 0;
} }
int usage_flashmem_wipe(void){ int usage_flashmem_wipe(void)
{
PrintAndLogEx(WARNING, "[OBS] use with caution."); PrintAndLogEx(WARNING, "[OBS] use with caution.");
PrintAndLogEx(NORMAL, "Wipe flash memory on device, which fills memory with 0xFF\n"); 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. PrintAndLogEx(NORMAL, " mem wipe p 0"); // wipes first page.
return 0; 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, "Collect signature and verify it from flash memory\n");
PrintAndLogEx(NORMAL, " Usage: mem info [h|s|w]"); PrintAndLogEx(NORMAL, " Usage: mem info [h|s|w]");
PrintAndLogEx(NORMAL, " s : create a signature"); PrintAndLogEx(NORMAL, " s : create a signature");
@ -107,7 +113,8 @@ int usage_flashmem_info(void){
return 0; return 0;
} }
int CmdFlashMemRead(const char *Cmd) { int CmdFlashMemRead(const char *Cmd)
{
uint8_t cmdp = 0; uint8_t cmdp = 0;
bool errors = false; bool errors = false;
@ -115,25 +122,25 @@ int CmdFlashMemRead(const char *Cmd) {
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) { switch (tolower(param_getchar(Cmd, cmdp))) {
case 'o': case 'o':
start_index = param_get32ex(Cmd, cmdp+1, 0, 10); start_index = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2; cmdp += 2;
break; break;
case 'l': case 'l':
len = param_get32ex(Cmd, cmdp+1, 0, 10); len = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2; cmdp += 2;
break; break;
case 'h': case 'h':
return usage_flashmem_read(); return usage_flashmem_read();
default: default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true; errors = true;
break; break;
} }
} }
//Validations //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) { if (start_index + len > FLASH_MEM_MAX_SIZE) {
PrintAndLogDevice(WARNING, "error, start_index + length is larger than available memory"); PrintAndLogDevice(WARNING, "error, start_index + length is larger than available memory");
@ -146,19 +153,21 @@ int CmdFlashMemRead(const char *Cmd) {
return 0; return 0;
} }
int CmdFlashmemSpiBaudrate(const char *Cmd) { int CmdFlashmemSpiBaudrate(const char *Cmd)
{
char ctmp = tolower(param_getchar(Cmd, 0)); char ctmp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) < 1 || ctmp == 'h') return usage_flashmem_spibaud(); if (strlen(Cmd) < 1 || ctmp == 'h') return usage_flashmem_spibaud();
uint32_t baudrate = param_get32ex(Cmd, 0, 0, 10); uint32_t baudrate = param_get32ex(Cmd, 0, 0, 10);
baudrate = baudrate * 1000000; 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}}; UsbCommand c = {CMD_FLASHMEM_SET_SPIBAUDRATE, {baudrate, 0, 0}};
SendCommand(&c); SendCommand(&c);
return 0; return 0;
} }
int CmdFlashMemLoad(const char *Cmd){ int CmdFlashMemLoad(const char *Cmd)
{
uint32_t start_index = 0; uint32_t start_index = 0;
char filename[FILE_PATH_SIZE] = {0}; char filename[FILE_PATH_SIZE] = {0};
@ -168,41 +177,41 @@ int CmdFlashMemLoad(const char *Cmd){
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) { switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h': case 'h':
return usage_flashmem_load(); return usage_flashmem_load();
case 'f': 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"); PrintAndLogEx(FAILED, "Filename too long");
errors = true;
break;
}
cmdp += 2;
break;
case 'o':
start_index = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
break;
case 'm':
d = DICTIONARY_MIFARE;
cmdp++;
break;
case 't':
d = DICTIONARY_T55XX;
cmdp++;
break;
case 'i':
d = DICTIONARY_ICLASS;
cmdp++;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true; errors = true;
break; break;
}
cmdp += 2;
break;
case 'o':
start_index = param_get32ex(Cmd, cmdp+1, 0, 10);
cmdp += 2;
break;
case 'm':
d = DICTIONARY_MIFARE;
cmdp++;
break;
case 't':
d = DICTIONARY_T55XX;
cmdp++;
break;
case 'i':
d = DICTIONARY_ICLASS;
cmdp++;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
} }
} }
//Validations //Validations
if (errors || cmdp == 0 ) return usage_flashmem_load(); if (errors || cmdp == 0) return usage_flashmem_load();
size_t datalen = 0; size_t datalen = 0;
uint16_t keycount = 0; uint16_t keycount = 0;
@ -212,8 +221,8 @@ int CmdFlashMemLoad(const char *Cmd){
switch (d) { switch (d) {
case DICTIONARY_MIFARE: case DICTIONARY_MIFARE:
start_index = DEFAULT_MF_KEYS_OFFSET; start_index = DEFAULT_MF_KEYS_OFFSET;
res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 6, &keycount ); res = loadFileDICTIONARY(filename, "dic", data + 2, &datalen, 6, &keycount);
if ( res || !keycount) { if (res || !keycount) {
free(data); free(data);
return 1; return 1;
} }
@ -223,8 +232,8 @@ int CmdFlashMemLoad(const char *Cmd){
break; break;
case DICTIONARY_T55XX: case DICTIONARY_T55XX:
start_index = DEFAULT_T55XX_KEYS_OFFSET; start_index = DEFAULT_T55XX_KEYS_OFFSET;
res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 4, &keycount ); res = loadFileDICTIONARY(filename, "dic", data + 2, &datalen, 4, &keycount);
if ( res || !keycount) { if (res || !keycount) {
free(data); free(data);
return 1; return 1;
} }
@ -234,8 +243,8 @@ int CmdFlashMemLoad(const char *Cmd){
break; break;
case DICTIONARY_ICLASS: case DICTIONARY_ICLASS:
start_index = DEFAULT_ICLASS_KEYS_OFFSET; start_index = DEFAULT_ICLASS_KEYS_OFFSET;
res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 8, &keycount ); res = loadFileDICTIONARY(filename, "dic", data + 2, &datalen, 8, &keycount);
if ( res || !keycount) { if (res || !keycount) {
free(data); free(data);
return 1; return 1;
} }
@ -247,7 +256,7 @@ int CmdFlashMemLoad(const char *Cmd){
res = loadFile(filename, "bin", data, &datalen); res = loadFile(filename, "bin", data, &datalen);
//int res = loadFileEML( filename, "eml", data, &datalen); //int res = loadFileEML( filename, "eml", data, &datalen);
if ( res ) { if (res) {
free(data); free(data);
return 1; return 1;
} }
@ -266,7 +275,7 @@ int CmdFlashMemLoad(const char *Cmd){
uint32_t bytes_sent = 0; uint32_t bytes_sent = 0;
uint32_t bytes_remaining = datalen; 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); 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}}; 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; bytes_sent += bytes_in_packet;
UsbCommand resp; UsbCommand resp;
if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply."); PrintAndLogEx(WARNING, "timeout while waiting for reply.");
free(data); free(data);
return 1; return 1;
@ -295,7 +304,8 @@ int CmdFlashMemLoad(const char *Cmd){
PrintAndLogEx(SUCCESS, "Wrote %u bytes to offset %u", datalen, start_index); PrintAndLogEx(SUCCESS, "Wrote %u bytes to offset %u", datalen, start_index);
return 0; return 0;
} }
int CmdFlashMemSave(const char *Cmd){ int CmdFlashMemSave(const char *Cmd)
{
char filename[FILE_PATH_SIZE] = {0}; char filename[FILE_PATH_SIZE] = {0};
uint8_t cmdp = 0; uint8_t cmdp = 0;
@ -304,42 +314,43 @@ int CmdFlashMemSave(const char *Cmd){
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) { switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h': return usage_flashmem_save(); case 'h':
case 'l': return usage_flashmem_save();
len = param_get32ex(Cmd, cmdp+1, FLASH_MEM_MAX_SIZE, 10); case 'l':
cmdp += 2; len = param_get32ex(Cmd, cmdp + 1, FLASH_MEM_MAX_SIZE, 10);
break; cmdp += 2;
case 'o': break;
start_index = param_get32ex(Cmd, cmdp+1, 0, 10); case 'o':
cmdp += 2; start_index = param_get32ex(Cmd, cmdp + 1, 0, 10);
break; cmdp += 2;
case 'f': break;
//File handling case 'f':
if ( param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE ) { //File handling
PrintAndLogEx(FAILED, "Filename too long"); if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) {
PrintAndLogEx(FAILED, "Filename too long");
errors = true;
break;
}
cmdp += 2;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true; errors = true;
break; break;
}
cmdp += 2;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
} }
} }
//Validations //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) { if (!dump) {
PrintAndLogDevice(WARNING, "error, cannot allocate memory "); PrintAndLogDevice(WARNING, "error, cannot allocate memory ");
return 1; return 1;
} }
PrintAndLogEx(NORMAL, "downloading %u bytes from flashmem", len); 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"); PrintAndLogEx(FAILED, "ERROR; downloading flashmem");
free(dump); free(dump);
return 1; return 1;
@ -350,7 +361,8 @@ int CmdFlashMemSave(const char *Cmd){
free(dump); free(dump);
return 0; return 0;
} }
int CmdFlashMemWipe(const char *Cmd){ int CmdFlashMemWipe(const char *Cmd)
{
uint8_t cmdp = 0; uint8_t cmdp = 0;
bool errors = false; bool errors = false;
@ -358,35 +370,36 @@ int CmdFlashMemWipe(const char *Cmd){
uint8_t page = 0; uint8_t page = 0;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) { switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h': return usage_flashmem_wipe(); case 'h':
case 'p': return usage_flashmem_wipe();
page = param_get8ex(Cmd, cmdp+1, 0, 10); case 'p':
if ( page > 2 ) { page = param_get8ex(Cmd, cmdp + 1, 0, 10);
PrintAndLogEx(WARNING, "page must be 0, 1 or 2"); if (page > 2) {
PrintAndLogEx(WARNING, "page must be 0, 1 or 2");
errors = true;
break;
}
cmdp += 2;
break;
case 'i':
initalwipe = true;
cmdp++;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true; errors = true;
break; break;
}
cmdp += 2;
break;
case 'i':
initalwipe = true;
cmdp++;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
} }
} }
//Validations //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}}; UsbCommand c = {CMD_FLASHMEM_WIPE, {page, initalwipe, 0}};
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
UsbCommand resp; UsbCommand resp;
if ( !WaitForResponseTimeout(CMD_ACK, &resp, 8000) ) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 8000)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply."); PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return 1; return 1;
} }
@ -398,7 +411,8 @@ int CmdFlashMemWipe(const char *Cmd){
return 0; return 0;
} }
int CmdFlashMemInfo(const char *Cmd){ int CmdFlashMemInfo(const char *Cmd)
{
uint8_t sha_hash[20] = {0}; uint8_t sha_hash[20] = {0};
mbedtls_rsa_context rsa; mbedtls_rsa_context rsa;
@ -407,31 +421,32 @@ int CmdFlashMemInfo(const char *Cmd){
bool errors = false, shall_write = false, shall_sign = false; bool errors = false, shall_write = false, shall_sign = false;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) { switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h': return usage_flashmem_info(); case 'h':
case 's': { return usage_flashmem_info();
shall_sign = true; case 's': {
cmdp++; shall_sign = true;
break; cmdp++;
} break;
case 'w': }
shall_write = true; case 'w':
cmdp++; shall_write = true;
break; cmdp++;
default: break;
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); default:
errors = true; PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
break; errors = true;
break;
} }
} }
//Validations //Validations
if (errors ) return usage_flashmem_info(); if (errors) return usage_flashmem_info();
UsbCommand c = {CMD_FLASHMEM_INFO, {0, 0, 0}}; UsbCommand c = {CMD_FLASHMEM_INFO, {0, 0, 0}};
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
UsbCommand resp; UsbCommand resp;
if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply."); PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return 1; return 1;
} }
@ -447,15 +462,15 @@ int CmdFlashMemInfo(const char *Cmd){
memcpy(&mem, (rdv40_validation_t *)resp.d.asBytes, sizeof(rdv40_validation_t)); memcpy(&mem, (rdv40_validation_t *)resp.d.asBytes, sizeof(rdv40_validation_t));
// Flash ID hash (sha1) // Flash ID hash (sha1)
mbedtls_sha1( mem.flashid, sizeof(mem.flashid), sha_hash ); mbedtls_sha1(mem.flashid, sizeof(mem.flashid), sha_hash);
// print header // print header
PrintAndLogEx(INFO, "\n--- Flash memory Information ---------"); PrintAndLogEx(INFO, "\n--- Flash memory Information ---------");
PrintAndLogEx(INFO, "-------------------------------------------------------------"); 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, "SHA1 | %s", sprint_hex(sha_hash, sizeof(sha_hash)));
PrintAndLogEx(INFO, "RSA SIGNATURE |"); 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) // Example RSA-1024 keypair, for test purposes (from common/polarssl/rsa.c)
@ -463,53 +478,53 @@ int CmdFlashMemInfo(const char *Cmd){
// public key modulus N // public key modulus N
#define RSA_N "9292758453063D803DD603D5E777D788" \ #define RSA_N "9292758453063D803DD603D5E777D788" \
"8ED1D5BF35786190FA2F23EBC0848AEA" \ "8ED1D5BF35786190FA2F23EBC0848AEA" \
"DDA92CA6C3D80B32C4D109BE0F36D6AE" \ "DDA92CA6C3D80B32C4D109BE0F36D6AE" \
"7130B9CED7ACDF54CFC7555AC14EEBAB" \ "7130B9CED7ACDF54CFC7555AC14EEBAB" \
"93A89813FBF3C4F8066D2D800F7C38A8" \ "93A89813FBF3C4F8066D2D800F7C38A8" \
"1AE31942917403FF4946B0A83D3D3E05" \ "1AE31942917403FF4946B0A83D3D3E05" \
"EE57C6F5F5606FB5D4BC6CD34EE0801A" \ "EE57C6F5F5606FB5D4BC6CD34EE0801A" \
"5E94BB77B07507233A0BC7BAC8F90F79" "5E94BB77B07507233A0BC7BAC8F90F79"
// public key Exponent E // public key Exponent E
#define RSA_E "10001" #define RSA_E "10001"
// private key Exponent D // private key Exponent D
#define RSA_D "24BF6185468786FDD303083D25E64EFC" \ #define RSA_D "24BF6185468786FDD303083D25E64EFC" \
"66CA472BC44D253102F8B4A9D3BFA750" \ "66CA472BC44D253102F8B4A9D3BFA750" \
"91386C0077937FE33FA3252D28855837" \ "91386C0077937FE33FA3252D28855837" \
"AE1B484A8A9A45F7EE8C0C634F99E8CD" \ "AE1B484A8A9A45F7EE8C0C634F99E8CD" \
"DF79C5CE07EE72C7F123142198164234" \ "DF79C5CE07EE72C7F123142198164234" \
"CABB724CF78B8173B9F880FC86322407" \ "CABB724CF78B8173B9F880FC86322407" \
"AF1FEDFDDE2BEB674CA15F3E81A1521E" \ "AF1FEDFDDE2BEB674CA15F3E81A1521E" \
"071513A1E85B5DFA031F21ECAE91A34D" "071513A1E85B5DFA031F21ECAE91A34D"
// prime P // prime P
#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ #define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
"2C01CAD19EA484A87EA4377637E75500" \ "2C01CAD19EA484A87EA4377637E75500" \
"FCB2005C5C7DD6EC4AC023CDA285D796" \ "FCB2005C5C7DD6EC4AC023CDA285D796" \
"C3D9E75E1EFC42488BB4F1D13AC30A57" "C3D9E75E1EFC42488BB4F1D13AC30A57"
// prime Q // prime Q
#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ #define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \
"E211C2B9E5DB1ED0BF61D0D9899620F4" \ "E211C2B9E5DB1ED0BF61D0D9899620F4" \
"910E4168387E3C30AA1E00C339A79508" \ "910E4168387E3C30AA1E00C339A79508" \
"8452DD96A9A5EA5D9DCA68DA636032AF" "8452DD96A9A5EA5D9DCA68DA636032AF"
#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \ #define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \
"3C94D22288ACD763FD8E5600ED4A702D" \ "3C94D22288ACD763FD8E5600ED4A702D" \
"F84198A5F06C2E72236AE490C93F07F8" \ "F84198A5F06C2E72236AE490C93F07F8" \
"3CC559CD27BC2D1CA488811730BB5725" "3CC559CD27BC2D1CA488811730BB5725"
#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \ #define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \
"D8AAEA56749EA28623272E4F7D0592AF" \ "D8AAEA56749EA28623272E4F7D0592AF" \
"7C1F1313CAC9471B5C523BFE592F517B" \ "7C1F1313CAC9471B5C523BFE592F517B" \
"407A1BD76C164B93DA2D32A383E58357" "407A1BD76C164B93DA2D32A383E58357"
#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \ #define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \
"F38D18D2B2F0E2DD275AA977E2BF4411" \ "F38D18D2B2F0E2DD275AA977E2BF4411" \
"F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \ "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
"A74206CEC169D74BF5A8C50D6F48EA08" "A74206CEC169D74BF5A8C50D6F48EA08"
#define KEY_LEN 128 #define KEY_LEN 128
@ -518,18 +533,18 @@ int CmdFlashMemInfo(const char *Cmd){
rsa.len = KEY_LEN; rsa.len = KEY_LEN;
mbedtls_mpi_read_string( &rsa.N , 16, RSA_N ); mbedtls_mpi_read_string(&rsa.N, 16, RSA_N);
mbedtls_mpi_read_string( &rsa.E , 16, RSA_E ); mbedtls_mpi_read_string(&rsa.E, 16, RSA_E);
mbedtls_mpi_read_string( &rsa.D , 16, RSA_D ); mbedtls_mpi_read_string(&rsa.D, 16, RSA_D);
mbedtls_mpi_read_string( &rsa.P , 16, RSA_P ); mbedtls_mpi_read_string(&rsa.P, 16, RSA_P);
mbedtls_mpi_read_string( &rsa.Q , 16, RSA_Q ); mbedtls_mpi_read_string(&rsa.Q, 16, RSA_Q);
mbedtls_mpi_read_string( &rsa.DP, 16, RSA_DP ); mbedtls_mpi_read_string(&rsa.DP, 16, RSA_DP);
mbedtls_mpi_read_string( &rsa.DQ, 16, RSA_DQ ); mbedtls_mpi_read_string(&rsa.DQ, 16, RSA_DQ);
mbedtls_mpi_read_string( &rsa.QP, 16, RSA_QP ); mbedtls_mpi_read_string(&rsa.QP, 16, RSA_QP);
PrintAndLogEx(INFO, "KEY length | %d", KEY_LEN); 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) if (is_keyok)
PrintAndLogEx(SUCCESS, "RSA key validation ok"); PrintAndLogEx(SUCCESS, "RSA key validation ok");
else else
@ -548,7 +563,7 @@ int CmdFlashMemInfo(const char *Cmd){
// Signing (private key) // Signing (private key)
if (shall_sign) { 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) if (is_signed == 0)
PrintAndLogEx(SUCCESS, "RSA Signing ok"); PrintAndLogEx(SUCCESS, "RSA Signing ok");
else else
@ -556,11 +571,11 @@ int CmdFlashMemInfo(const char *Cmd){
if (shall_write) { if (shall_write) {
// save to mem // 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)); memcpy(c.d.asBytes, sign, sizeof(sign));
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply."); PrintAndLogEx(WARNING, "timeout while waiting for reply.");
} else { } else {
@ -572,11 +587,11 @@ int CmdFlashMemInfo(const char *Cmd){
} }
} }
PrintAndLogEx(INFO, "Signed | "); PrintAndLogEx(INFO, "Signed | ");
print_hex_break( sign, sizeof(sign), 32); print_hex_break(sign, sizeof(sign), 32);
} }
// Verify (public key) // 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) if (is_verified == 0)
PrintAndLogEx(SUCCESS, "RSA Verification ok"); PrintAndLogEx(SUCCESS, "RSA Verification ok");
else else
@ -597,13 +612,15 @@ static command_t CommandTable[] = {
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };
int CmdFlashMem(const char *Cmd) { int CmdFlashMem(const char *Cmd)
{
clearCommandBuffer(); clearCommandBuffer();
CmdsParse(CommandTable, Cmd); CmdsParse(CommandTable, Cmd);
return 0; return 0;
} }
int CmdHelp(const char *Cmd) { int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable); CmdsHelp(CommandTable);
return 0; return 0;
} }

View file

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

View file

@ -12,7 +12,8 @@
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
int usage_hf_search(){ int usage_hf_search()
{
PrintAndLogEx(NORMAL, "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, "Will try to find a HF read out of the unknown tag. Stops when found.");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "Options:");
@ -20,7 +21,8 @@ int usage_hf_search(){
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
return 0; return 0;
} }
int usage_hf_snoop(){ int usage_hf_snoop()
{
PrintAndLogEx(NORMAL, "Usage: hf snoop <skip pairs> <skip triggers>"); 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, "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"); 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; return 0;
} }
int CmdHFSearch(const char *Cmd){ int CmdHFSearch(const char *Cmd)
{
char cmdp = tolower(param_getchar(Cmd, 0)); char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_hf_search(); if (cmdp == 'h') return usage_hf_search();
@ -52,7 +55,7 @@ int CmdHFSearch(const char *Cmd){
return ans; return ans;
} }
ans = HFLegicReader("", false); ans = HFLegicReader("", false);
if ( ans == 0) { if (ans == 0) {
PrintAndLogEx(SUCCESS, "\nValid LEGIC Tag Found\n"); PrintAndLogEx(SUCCESS, "\nValid LEGIC Tag Found\n");
return 1; return 1;
} }
@ -85,7 +88,8 @@ int CmdHFSearch(const char *Cmd){
return 0; return 0;
} }
int CmdHFTune(const char *Cmd) { int CmdHFTune(const char *Cmd)
{
PrintAndLogEx(SUCCESS, "Measuring HF antenna, press button to exit"); PrintAndLogEx(SUCCESS, "Measuring HF antenna, press button to exit");
UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING_HF}; UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING_HF};
clearCommandBuffer(); clearCommandBuffer();
@ -93,7 +97,8 @@ int CmdHFTune(const char *Cmd) {
return 0; return 0;
} }
int CmdHFSnoop(const char *Cmd) { int CmdHFSnoop(const char *Cmd)
{
char cmdp = tolower(param_getchar(Cmd, 0)); char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_hf_snoop(); if (cmdp == 'h') return usage_hf_snoop();
@ -128,13 +133,15 @@ static command_t CommandTable[] = {
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };
int CmdHF(const char *Cmd) { int CmdHF(const char *Cmd)
{
clearCommandBuffer(); clearCommandBuffer();
CmdsParse(CommandTable, Cmd); CmdsParse(CommandTable, Cmd);
return 0; return 0;
} }
int CmdHelp(const char *Cmd) { int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable); CmdsHelp(CommandTable);
return 0; return 0;
} }

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

@ -42,14 +42,14 @@ extern int CmdHF14BList(const char *Cmd);
extern int CmdHF14BInfo(const char *Cmd); extern int CmdHF14BInfo(const char *Cmd);
extern int CmdHF14BSim(const char *Cmd); extern int CmdHF14BSim(const char *Cmd);
extern int CmdHF14BSniff(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 CmdHF14BReader(const char *Cmd);
extern int CmdHF14BDump(const char *Cmd); extern int CmdHF14BDump(const char *Cmd);
extern bool HF14BInfo(bool verbose); extern bool HF14BInfo(bool verbose);
extern bool HF14BReader(bool verbose); extern bool HF14BReader(bool verbose);
extern int CmdHF14BCmdRaw (const char *Cmd); extern int CmdHF14BCmdRaw(const char *Cmd);
// SRi ST Microelectronics read/write // SRi ST Microelectronics read/write
extern int CmdHF14BReadSri(const char *Cmd); extern int CmdHF14BReadSri(const char *Cmd);

File diff suppressed because it is too large Load diff

View file

@ -37,13 +37,13 @@ extern int CmdHF15Record(const char *Cmd);
extern int CmdHF15Reader(const char *Cmd); extern int CmdHF15Reader(const char *Cmd);
extern int CmdHF15Sim(const char *Cmd); extern int CmdHF15Sim(const char *Cmd);
extern int CmdHF15Afi(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 CmdHF15Raw(const char *cmd);
extern int CmdHF15Readmulti(const char *Cmd); extern int CmdHF15Readmulti(const char *Cmd);
extern int CmdHF15Read(const char *Cmd); extern int CmdHF15Read(const char *Cmd);
extern int CmdHF15Write(const char *Cmd); extern int CmdHF15Write(const char *Cmd);
extern int CmdHF15Help(const char*Cmd); extern int CmdHF15Help(const char *Cmd);
// usages // usages
extern int usage_15_demod(void); extern int usage_15_demod(void);

View file

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

View file

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

View file

@ -49,7 +49,8 @@
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
int CmdHFFidoInfo(const char *cmd) { int CmdHFFidoInfo(const char *cmd)
{
if (cmd && strlen(cmd) > 0) if (cmd && strlen(cmd) > 0)
PrintAndLog("WARNING: command don't have any parameters.\n"); PrintAndLog("WARNING: command don't have any parameters.\n");
@ -104,7 +105,7 @@ int CmdHFFidoInfo(const char *cmd) {
return 0; return 0;
} }
if(buf[0]) { if (buf[0]) {
PrintAndLog("FIDO2 ger version error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); PrintAndLog("FIDO2 ger version error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0]));
return 0; return 0;
} }
@ -124,12 +125,13 @@ int CmdHFFidoInfo(const char *cmd) {
return 0; 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_t *root = NULL;
json_error_t error; json_error_t error;
*err = false; *err = false;
uint8_t jsonname[250] ={0}; uint8_t jsonname[250] = {0};
char *cjsonname = (char *)jsonname; char *cjsonname = (char *)jsonname;
int jsonnamelen = 0; int jsonnamelen = 0;
@ -168,7 +170,8 @@ json_t *OpenJson(int paramnum, char *fname, void* argtable[], bool *err) {
return root; return root;
} }
int CmdHFFidoRegister(const char *cmd) { int CmdHFFidoRegister(const char *cmd)
{
uint8_t data[64] = {0}; uint8_t data[64] = {0};
int chlen = 0; int chlen = 0;
uint8_t cdata[250] = {0}; uint8_t cdata[250] = {0};
@ -177,12 +180,12 @@ int CmdHFFidoRegister(const char *cmd) {
json_t *root = NULL; json_t *root = NULL;
CLIParserInit("hf fido reg", CLIParserInit("hf fido reg",
"Initiate a U2F token registration. Needs two 32-byte hash number. \nchallenge parameter (32b) and application parameter (32b).", "Initiate a U2F token registration. Needs two 32-byte hash number. \nchallenge parameter (32b) and application parameter (32b).",
"Usage:\n\thf fido reg -> execute command with 2 parameters, filled 0x00\n" "Usage:\n\thf fido reg -> execute command with 2 parameters, filled 0x00\n"
"\thf fido reg 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters" "\thf fido reg 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters"
"\thf fido reg -p s0 s1 -> execute command with plain parameters"); "\thf fido reg -p s0 s1 -> execute command with plain parameters");
void* argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("aA", "apdu", "show APDU reqests and responses"),
arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), 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}; char fname[250] = {0};
bool err; bool err;
root = OpenJson(5, fname, argtable, &err); root = OpenJson(5, fname, argtable, &err);
if(err) if (err)
return 1; return 1;
if (root) { if (root) {
size_t jlen; size_t jlen;
@ -345,19 +348,19 @@ int CmdHFFidoRegister(const char *cmd) {
uint8_t xbuf[4096] = {0}; uint8_t xbuf[4096] = {0};
size_t xbuflen = 0; size_t xbuflen = 0;
res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen,
"\x00", 1, "\x00", 1,
&data[32], 32, // application parameter &data[32], 32, // application parameter
&data[0], 32, // challenge parameter &data[0], 32, // challenge parameter
&buf[67], keyHandleLen, // keyHandle &buf[67], keyHandleLen, // keyHandle
&buf[1], 65, // user public key &buf[1], 65, // user public key
NULL, 0); NULL, 0);
//PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); //PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen));
res = ecdsa_signature_verify(public_key, xbuf, xbuflen, &buf[hashp], len - hashp); res = ecdsa_signature_verify(public_key, xbuf, xbuflen, &buf[hashp], len - hashp);
if (res) { if (res) {
if (res == -0x4e00) { if (res == -0x4e00) {
PrintAndLog("Signature is NOT VALID."); PrintAndLog("Signature is NOT VALID.");
} else { } 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 { } else {
PrintAndLog("Signature is OK."); PrintAndLog("Signature is OK.");
@ -368,11 +371,11 @@ int CmdHFFidoRegister(const char *cmd) {
} }
PrintAndLog("\nauth command: "); PrintAndLog("\nauth command: ");
printf("hf fido auth %s%s", paramsPlain?"-p ":"", sprint_hex_inrow(&buf[67], keyHandleLen)); printf("hf fido auth %s%s", paramsPlain ? "-p " : "", sprint_hex_inrow(&buf[67], keyHandleLen));
if(chlen || applen) if (chlen || applen)
printf(" %s", paramsPlain?(char *)cdata:sprint_hex_inrow(cdata, 32)); printf(" %s", paramsPlain ? (char *)cdata : sprint_hex_inrow(cdata, 32));
if(applen) if (applen)
printf(" %s", paramsPlain?(char *)adata:sprint_hex_inrow(adata, 32)); printf(" %s", paramsPlain ? (char *)adata : sprint_hex_inrow(adata, 32));
printf("\n"); printf("\n");
if (root) { if (root) {
@ -397,7 +400,8 @@ int CmdHFFidoRegister(const char *cmd) {
return 0; return 0;
}; };
int CmdHFFidoAuthenticate(const char *cmd) { int CmdHFFidoAuthenticate(const char *cmd)
{
uint8_t data[512] = {0}; uint8_t data[512] = {0};
uint8_t hdata[250] = {0}; uint8_t hdata[250] = {0};
bool public_key_loaded = false; bool public_key_loaded = false;
@ -407,12 +411,12 @@ int CmdHFFidoAuthenticate(const char *cmd) {
json_t *root = NULL; json_t *root = NULL;
CLIParserInit("hf fido auth", CLIParserInit("hf fido auth",
"Initiate a U2F token authentication. Needs key handle and two 32-byte hash number. \nkey handle(var 0..255), challenge parameter (32b) and application parameter (32b).", "Initiate a U2F token authentication. Needs key handle and two 32-byte hash number. \nkey handle(var 0..255), challenge parameter (32b) and application parameter (32b).",
"Usage:\n\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with 2 parameters, filled 0x00 and key handle\n" "Usage:\n\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with 2 parameters, filled 0x00 and key handle\n"
"\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f " "\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f "
"000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters"); "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters");
void* argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("aA", "apdu", "show APDU reqests and responses"),
arg_lit0("vV", "verbose", "show technical data"), arg_lit0("vV", "verbose", "show technical data"),
@ -441,7 +445,7 @@ int CmdHFFidoAuthenticate(const char *cmd) {
char fname[250] = {0}; char fname[250] = {0};
bool err; bool err;
root = OpenJson(7, fname, argtable, &err); root = OpenJson(7, fname, argtable, &err);
if(err) if (err)
return 1; return 1;
if (root) { if (root) {
size_t jlen; size_t jlen;
@ -554,8 +558,8 @@ int CmdHFFidoAuthenticate(const char *cmd) {
} }
PrintAndLog("---------------------------------------------------------------"); 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); uint32_t cntr = (uint32_t)bytes_to_num(&buf[1], 4);
PrintAndLog("Counter: %d", cntr); PrintAndLog("Counter: %d", cntr);
PrintAndLog("Hash[%d]: %s", len - 5, sprint_hex(&buf[5], len - 5)); PrintAndLog("Hash[%d]: %s", len - 5, sprint_hex(&buf[5], len - 5));
@ -572,18 +576,18 @@ int CmdHFFidoAuthenticate(const char *cmd) {
uint8_t xbuf[4096] = {0}; uint8_t xbuf[4096] = {0};
size_t xbuflen = 0; size_t xbuflen = 0;
res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen,
&data[32], 32, // application parameter &data[32], 32, // application parameter
&buf[0], 1, // user presence &buf[0], 1, // user presence
&buf[1], 4, // counter &buf[1], 4, // counter
data, 32, // challenge parameter data, 32, // challenge parameter
NULL, 0); NULL, 0);
//PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); //PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen));
res = ecdsa_signature_verify(public_key, xbuf, xbuflen, &buf[5], len - 5); res = ecdsa_signature_verify(public_key, xbuf, xbuflen, &buf[5], len - 5);
if (res) { if (res) {
if (res == -0x4e00) { if (res == -0x4e00) {
PrintAndLog("Signature is NOT VALID."); PrintAndLog("Signature is NOT VALID.");
} else { } 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 { } else {
PrintAndLog("Signature is OK."); PrintAndLog("Signature is OK.");
@ -615,13 +619,15 @@ int CmdHFFidoAuthenticate(const char *cmd) {
return 0; return 0;
}; };
void CheckSlash(char *fileName) { void CheckSlash(char *fileName)
{
if ((fileName[strlen(fileName) - 1] != '/') && if ((fileName[strlen(fileName) - 1] != '/') &&
(fileName[strlen(fileName) - 1] != '\\')) (fileName[strlen(fileName) - 1] != '\\'))
strcat(fileName, "/"); strcat(fileName, "/");
} }
int GetExistsFileNameJson(char *prefixDir, char *reqestedFileName, char *fileName) { int GetExistsFileNameJson(char *prefixDir, char *reqestedFileName, char *fileName)
{
fileName[0] = 0x00; fileName[0] = 0x00;
strcpy(fileName, get_my_executable_directory()); strcpy(fileName, get_my_executable_directory());
CheckSlash(fileName); CheckSlash(fileName);
@ -648,17 +654,18 @@ int GetExistsFileNameJson(char *prefixDir, char *reqestedFileName, char *fileNam
return 0; return 0;
} }
int CmdHFFido2MakeCredential(const char *cmd) { int CmdHFFido2MakeCredential(const char *cmd)
{
json_error_t error; json_error_t error;
json_t *root = NULL; json_t *root = NULL;
char fname[300] = {0}; char fname[300] = {0};
CLIParserInit("hf fido make", CLIParserInit("hf fido make",
"Execute a FIDO2 Make Credentional command. Needs json file with parameters. Sample file `fido2.json`. File can be placed in proxmark directory or in `proxmark/fido` directory.", "Execute a FIDO2 Make Credentional command. Needs json file with parameters. Sample file `fido2.json`. File can be placed in proxmark directory or in `proxmark/fido` directory.",
"Usage:\n\thf fido make -> execute command default parameters file `fido2.json`\n" "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`"); "\thf fido make test.json -> execute command with parameters file `text.json`");
void* argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("aA", "apdu", "show APDU reqests and responses"),
arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), 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 showDERTLV = arg_get_lit(3);
bool showCBOR = arg_get_lit(4); bool showCBOR = arg_get_lit(4);
uint8_t jsonname[250] ={0}; uint8_t jsonname[250] = {0};
char *cjsonname = (char *)jsonname; char *cjsonname = (char *)jsonname;
int jsonnamelen = 0; int jsonnamelen = 0;
CLIGetStrWithReturn(5, jsonname, &jsonnamelen); CLIGetStrWithReturn(5, jsonname, &jsonnamelen);
@ -690,7 +697,7 @@ int CmdHFFido2MakeCredential(const char *cmd) {
SetAPDULogging(APDULogging); SetAPDULogging(APDULogging);
int res = GetExistsFileNameJson("fido", cjsonname, fname); int res = GetExistsFileNameJson("fido", cjsonname, fname);
if(res) { if (res) {
PrintAndLog("ERROR: Can't found the json file."); PrintAndLog("ERROR: Can't found the json file.");
return res; return res;
} }
@ -745,7 +752,7 @@ int CmdHFFido2MakeCredential(const char *cmd) {
return 3; return 3;
} }
if(buf[0]) { if (buf[0]) {
PrintAndLog("FIDO2 make credential error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); PrintAndLog("FIDO2 make credential error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0]));
return 0; return 0;
} }
@ -775,17 +782,18 @@ int CmdHFFido2MakeCredential(const char *cmd) {
return 0; return 0;
}; };
int CmdHFFido2GetAssertion(const char *cmd) { int CmdHFFido2GetAssertion(const char *cmd)
{
json_error_t error; json_error_t error;
json_t *root = NULL; json_t *root = NULL;
char fname[300] = {0}; char fname[300] = {0};
CLIParserInit("hf fido assert", CLIParserInit("hf fido assert",
"Execute a FIDO2 Get Assertion command. Needs json file with parameters. Sample file `fido2.json`. File can be placed in proxmark directory or in `proxmark/fido` directory.", "Execute a FIDO2 Get Assertion command. Needs json file with parameters. Sample file `fido2.json`. File can be placed in proxmark directory or in `proxmark/fido` directory.",
"Usage:\n\thf fido assert -> execute command default parameters file `fido2.json`\n" "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"); "\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_param_begin,
arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("aA", "apdu", "show APDU reqests and responses"),
arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), 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 showCBOR = arg_get_lit(3);
bool createAllowList = arg_get_lit(4); bool createAllowList = arg_get_lit(4);
uint8_t jsonname[250] ={0}; uint8_t jsonname[250] = {0};
char *cjsonname = (char *)jsonname; char *cjsonname = (char *)jsonname;
int jsonnamelen = 0; int jsonnamelen = 0;
CLIGetStrWithReturn(5, jsonname, &jsonnamelen); CLIGetStrWithReturn(5, jsonname, &jsonnamelen);
@ -817,7 +825,7 @@ int CmdHFFido2GetAssertion(const char *cmd) {
SetAPDULogging(APDULogging); SetAPDULogging(APDULogging);
int res = GetExistsFileNameJson("fido", "fido2", fname); int res = GetExistsFileNameJson("fido", "fido2", fname);
if(res) { if (res) {
PrintAndLog("ERROR: Can't found the json file."); PrintAndLog("ERROR: Can't found the json file.");
return res; return res;
} }
@ -872,7 +880,7 @@ int CmdHFFido2GetAssertion(const char *cmd) {
return 3; return 3;
} }
if(buf[0]) { if (buf[0]) {
PrintAndLog("FIDO2 get assertion error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); PrintAndLog("FIDO2 get assertion error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0]));
return 0; return 0;
} }
@ -902,24 +910,25 @@ int CmdHFFido2GetAssertion(const char *cmd) {
return 0; return 0;
}; };
static command_t CommandTable[] = static command_t CommandTable[] = {
{ {"help", CmdHelp, 1, "This help."},
{"help", CmdHelp, 1, "This help."}, {"info", CmdHFFidoInfo, 0, "Info about FIDO tag."},
{"info", CmdHFFidoInfo, 0, "Info about FIDO tag."}, {"reg", CmdHFFidoRegister, 0, "FIDO U2F Registration Message."},
{"reg", CmdHFFidoRegister, 0, "FIDO U2F Registration Message."}, {"auth", CmdHFFidoAuthenticate, 0, "FIDO U2F Authentication Message."},
{"auth", CmdHFFidoAuthenticate, 0, "FIDO U2F Authentication Message."}, {"make", CmdHFFido2MakeCredential, 0, "FIDO2 MakeCredential command."},
{"make", CmdHFFido2MakeCredential, 0, "FIDO2 MakeCredential command."}, {"assert", CmdHFFido2GetAssertion, 0, "FIDO2 GetAssertion command."},
{"assert", CmdHFFido2GetAssertion, 0, "FIDO2 GetAssertion command."}, {NULL, NULL, 0, NULL}
{NULL, NULL, 0, NULL}
}; };
int CmdHFFido(const char *Cmd) { int CmdHFFido(const char *Cmd)
{
(void)WaitForResponseTimeout(CMD_ACK, NULL, 100); (void)WaitForResponseTimeout(CMD_ACK, NULL, 100);
CmdsParse(CommandTable, Cmd); CmdsParse(CommandTable, Cmd);
return 0; return 0;
} }
int CmdHelp(const char *Cmd) { int CmdHelp(const char *Cmd)
CmdsHelp(CommandTable); {
return 0; 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 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); void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite);
int LoadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt); 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 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 ); 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 PrintPreCalcMac(uint8_t *keys, int keycnt, iclass_premac_t *pre_list);
void PrintPreCalc(iclass_prekey_t* list, int itemcnt); void PrintPreCalc(iclass_prekey_t *list, int itemcnt);
#endif #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; } TAuthData;
extern void ClearAuthData(); extern void ClearAuthData();
extern uint8_t iso14443A_CRC_check(bool isResponse, uint8_t* data, uint8_t len); 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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); 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 CmdHFMF(const char *Cmd);
extern int CmdHF14AMfList(const char *Cmd); extern int CmdHF14AMfList(const char *Cmd);
extern int CmdHF14AMfDbg(const char* cmd); extern int CmdHF14AMfDbg(const char *cmd);
extern int CmdHF14AMfRdBl(const char* cmd); extern int CmdHF14AMfRdBl(const char *cmd);
extern int CmdHF14AMfURdBl(const char* cmd); extern int CmdHF14AMfURdBl(const char *cmd);
extern int CmdHF14AMfRdSc(const char* cmd); extern int CmdHF14AMfRdSc(const char *cmd);
extern int CmdHF14SMfURdCard(const char* cmd); extern int CmdHF14SMfURdCard(const char *cmd);
extern int CmdHF14AMfDump(const char* cmd); extern int CmdHF14AMfDump(const char *cmd);
extern int CmdHF14AMfRestore(const char* cmd); extern int CmdHF14AMfRestore(const char *cmd);
extern int CmdHF14AMfWrBl(const char* cmd); extern int CmdHF14AMfWrBl(const char *cmd);
extern int CmdHF14AMfUWrBl(const char* cmd); extern int CmdHF14AMfUWrBl(const char *cmd);
extern int CmdHF14AMfChk(const char* cmd); extern int CmdHF14AMfChk(const char *cmd);
extern int CmdHF14AMfDarkside(const char* cmd); extern int CmdHF14AMfDarkside(const char *cmd);
extern int CmdHF14AMfNested(const char* cmd); extern int CmdHF14AMfNested(const char *cmd);
extern int CmdHF14AMfNestedHard(const char *Cmd); extern int CmdHF14AMfNestedHard(const char *Cmd);
//extern int CmdHF14AMfSniff(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 CmdHF14AMfKeyBrute(const char *Cmd);
extern int CmdHF14AMfEClear(const char* cmd); extern int CmdHF14AMfEClear(const char *cmd);
extern int CmdHF14AMfEGet(const char* cmd); extern int CmdHF14AMfEGet(const char *cmd);
extern int CmdHF14AMfESet(const char* cmd); extern int CmdHF14AMfESet(const char *cmd);
extern int CmdHF14AMfELoad(const char* cmd); extern int CmdHF14AMfELoad(const char *cmd);
extern int CmdHF14AMfESave(const char* cmd); extern int CmdHF14AMfESave(const char *cmd);
extern int CmdHF14AMfECFill(const char* cmd); extern int CmdHF14AMfECFill(const char *cmd);
extern int CmdHF14AMfEKeyPrn(const char* cmd); extern int CmdHF14AMfEKeyPrn(const char *cmd);
extern int CmdHF14AMfCSetUID(const char* cmd); extern int CmdHF14AMfCSetUID(const char *cmd);
extern int CmdHF14AMfCSetBlk(const char* cmd); extern int CmdHF14AMfCSetBlk(const char *cmd);
extern int CmdHF14AMfCGetBlk(const char* cmd); extern int CmdHF14AMfCGetBlk(const char *cmd);
extern int CmdHF14AMfCGetSc(const char* cmd); extern int CmdHF14AMfCGetSc(const char *cmd);
extern int CmdHF14AMfCLoad(const char* cmd); extern int CmdHF14AMfCLoad(const char *cmd);
extern int CmdHF14AMfCSave(const char* cmd); extern int CmdHF14AMfCSave(const char *cmd);
extern int CmdHf14MfDecryptBytes(const char *Cmd); extern int CmdHf14MfDecryptBytes(const char *Cmd);
extern int CmdHf14AMfSetMod(const char *Cmd); extern int CmdHf14AMfSetMod(const char *Cmd);
extern int CmdHf14AMfNack(const char *Cmd); extern int CmdHf14AMfNack(const char *Cmd);
void showSectorTable(void); void showSectorTable(void);
void readerAttack(nonces_t data, bool setEmulatorMem, bool verbose); void readerAttack(nonces_t data, bool setEmulatorMem, bool verbose);
void printKeyTable( uint8_t sectorscnt, sector_t *e_sector ); 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_fast(uint8_t sectorscnt, icesector_t *e_sector, uint64_t bar, uint64_t foo);
#endif #endif

View file

@ -30,57 +30,57 @@ uint8_t LENPOS = 1;
uint8_t key_zero_data[16] = { 0x00 }; uint8_t key_zero_data[16] = { 0x00 };
uint8_t key_ones_data[16] = { 0x01 }; 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_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_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); static int CmdHelp(const char *Cmd);
int CmdHF14ADesWb(const char *Cmd) int CmdHF14ADesWb(const char *Cmd)
{ {
/* uint8_t blockNo = 0; /* uint8_t blockNo = 0;
uint8_t keyType = 0; uint8_t keyType = 0;
uint8_t key[6] = {0, 0, 0, 0, 0, 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}; uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
char cmdp = 0x00; char cmdp = 0x00;
if (strlen(Cmd)<3) { if (strlen(Cmd)<3) {
PrintAndLogEx(NORMAL, "Usage: hf mf wrbl <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)>"); PrintAndLogEx(NORMAL, "Usage: hf mf wrbl <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)>");
PrintAndLogEx(NORMAL, " sample: hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F"); PrintAndLogEx(NORMAL, " sample: hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F");
return 0; return 0;
} }
blockNo = param_get8(Cmd, 0); blockNo = param_get8(Cmd, 0);
cmdp = param_getchar(Cmd, 1); cmdp = param_getchar(Cmd, 1);
if (cmdp == 0x00) { if (cmdp == 0x00) {
PrintAndLogEx(NORMAL, "Key type must be A or B"); PrintAndLogEx(NORMAL, "Key type must be A or B");
return 1; return 1;
} }
if (cmdp != 'A' && cmdp != 'a') keyType = 1; if (cmdp != 'A' && cmdp != 'a') keyType = 1;
if (param_gethex(Cmd, 2, key, 12)) { if (param_gethex(Cmd, 2, key, 12)) {
PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols"); PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols");
return 1; return 1;
} }
if (param_gethex(Cmd, 3, bldata, 32)) { if (param_gethex(Cmd, 3, bldata, 32)) {
PrintAndLogEx(NORMAL, "Block data must include 32 HEX symbols"); PrintAndLogEx(NORMAL, "Block data must include 32 HEX symbols");
return 1; return 1;
} }
PrintAndLogEx(NORMAL, "--block no:%02x key type:%02x key:%s", blockNo, keyType, sprint_hex(key, 6)); PrintAndLogEx(NORMAL, "--block no:%02x key type:%02x key:%s", blockNo, keyType, sprint_hex(key, 6));
PrintAndLogEx(NORMAL, "--data: %s", sprint_hex(bldata, 16)); PrintAndLogEx(NORMAL, "--data: %s", sprint_hex(bldata, 16));
UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}}; UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};
memcpy(c.d.asBytes, key, 6); memcpy(c.d.asBytes, key, 6);
memcpy(c.d.asBytes + 10, bldata, 16); memcpy(c.d.asBytes + 10, bldata, 16);
SendCommand(&c); SendCommand(&c);
UsbCommand resp; UsbCommand resp;
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
uint8_t isOK = resp.arg[0] & 0xff; uint8_t isOK = resp.arg[0] & 0xff;
PrintAndLogEx(NORMAL, "isOk:%02x", isOK); PrintAndLogEx(NORMAL, "isOk:%02x", isOK);
} else { } else {
PrintAndLogEx(NORMAL, "Command execute timeout"); PrintAndLogEx(NORMAL, "Command execute timeout");
} }
*/ */
return 0; return 0;
} }
@ -94,87 +94,91 @@ int CmdHF14ADesRb(const char *Cmd)
// if (strlen(Cmd)<3) { // if (strlen(Cmd)<3) {
// PrintAndLogEx(NORMAL, "Usage: hf mf rdbl <block number> <key A/B> <key (12 hex symbols)>"); // PrintAndLogEx(NORMAL, "Usage: hf mf rdbl <block number> <key A/B> <key (12 hex symbols)>");
// PrintAndLogEx(NORMAL, " sample: hf mf rdbl 0 A FFFFFFFFFFFF "); // PrintAndLogEx(NORMAL, " sample: hf mf rdbl 0 A FFFFFFFFFFFF ");
// return 0; // return 0;
// } // }
// blockNo = param_get8(Cmd, 0); // blockNo = param_get8(Cmd, 0);
// cmdp = param_getchar(Cmd, 1); // cmdp = param_getchar(Cmd, 1);
// if (cmdp == 0x00) { // if (cmdp == 0x00) {
// PrintAndLogEx(NORMAL, "Key type must be A or B"); // PrintAndLogEx(NORMAL, "Key type must be A or B");
// return 1; // return 1;
// } // }
// if (cmdp != 'A' && cmdp != 'a') keyType = 1; // if (cmdp != 'A' && cmdp != 'a') keyType = 1;
// if (param_gethex(Cmd, 2, key, 12)) { // if (param_gethex(Cmd, 2, key, 12)) {
// PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols"); // PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols");
// return 1; // return 1;
// } // }
// PrintAndLogEx(NORMAL, "--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6)); // PrintAndLogEx(NORMAL, "--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6));
// UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}}; // UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};
// memcpy(c.d.asBytes, key, 6); // memcpy(c.d.asBytes, key, 6);
// SendCommand(&c); // SendCommand(&c);
// UsbCommand resp; // UsbCommand resp;
// if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { // if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
// uint8_t isOK = resp.arg[0] & 0xff; // uint8_t isOK = resp.arg[0] & 0xff;
// uint8_t * data = resp.d.asBytes; // uint8_t * data = resp.d.asBytes;
// if (isOK) // if (isOK)
// PrintAndLogEx(NORMAL, "isOk:%02x data:%s", isOK, sprint_hex(data, 16)); // PrintAndLogEx(NORMAL, "isOk:%02x data:%s", isOK, sprint_hex(data, 16));
// else // else
// PrintAndLogEx(NORMAL, "isOk:%02x", isOK); // PrintAndLogEx(NORMAL, "isOk:%02x", isOK);
// } else { // } else {
// PrintAndLogEx(NORMAL, "Command execute timeout"); // PrintAndLogEx(NORMAL, "Command execute timeout");
// } // }
return 0; return 0;
} }
int CmdHF14ADesInfo(const char *Cmd){ int CmdHF14ADesInfo(const char *Cmd)
{
UsbCommand c = {CMD_MIFARE_DESFIRE_INFO}; UsbCommand c = {CMD_MIFARE_DESFIRE_INFO};
SendCommand(&c); SendCommand(&c);
UsbCommand resp; UsbCommand resp;
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
PrintAndLogEx(WARNING, "Command execute timeout"); PrintAndLogEx(WARNING, "Command execute timeout");
return 0; return 0;
} }
uint8_t isOK = resp.arg[0] & 0xff; uint8_t isOK = resp.arg[0] & 0xff;
if ( !isOK ){ if (!isOK) {
switch ( resp.arg[1] ) { switch (resp.arg[1]) {
case 1: case 1:
PrintAndLogEx(WARNING, "Can't select card"); break; PrintAndLogEx(WARNING, "Can't select card");
break;
case 2: 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: case 3:
default: default:
PrintAndLogEx(WARNING, "Command unsuccessful"); break; PrintAndLogEx(WARNING, "Command unsuccessful");
break;
} }
return 0; return 0;
} }
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "-- Desfire Information --------------------------------------"); PrintAndLogEx(NORMAL, "-- Desfire Information --------------------------------------");
PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); PrintAndLogEx(NORMAL, "-------------------------------------------------------------");
PrintAndLogEx(NORMAL, " UID : %s",sprint_hex(resp.d.asBytes, 7)); PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(resp.d.asBytes, 7));
PrintAndLogEx(NORMAL, " Batch number : %s",sprint_hex(resp.d.asBytes+28,5)); 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, " Production date : week %02x, 20%02x", resp.d.asBytes[33], resp.d.asBytes[34]);
PrintAndLogEx(NORMAL, " -----------------------------------------------------------"); PrintAndLogEx(NORMAL, " -----------------------------------------------------------");
PrintAndLogEx(NORMAL, " Hardware Information"); PrintAndLogEx(NORMAL, " Hardware Information");
PrintAndLogEx(NORMAL, " Vendor Id : %s", getTagInfo(resp.d.asBytes[7])); PrintAndLogEx(NORMAL, " Vendor Id : %s", getTagInfo(resp.d.asBytes[7]));
PrintAndLogEx(NORMAL, " Type : 0x%02X",resp.d.asBytes[8]); PrintAndLogEx(NORMAL, " Type : 0x%02X", resp.d.asBytes[8]);
PrintAndLogEx(NORMAL, " Subtype : 0x%02X",resp.d.asBytes[9]); PrintAndLogEx(NORMAL, " Subtype : 0x%02X", resp.d.asBytes[9]);
PrintAndLogEx(NORMAL, " Version : %s",GetVersionStr(resp.d.asBytes[10], resp.d.asBytes[11]) ); 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, " Storage size : %s", GetCardSizeStr(resp.d.asBytes[12]));
PrintAndLogEx(NORMAL, " Protocol : %s",GetProtocolStr(resp.d.asBytes[13])); PrintAndLogEx(NORMAL, " Protocol : %s", GetProtocolStr(resp.d.asBytes[13]));
PrintAndLogEx(NORMAL, " -----------------------------------------------------------"); PrintAndLogEx(NORMAL, " -----------------------------------------------------------");
PrintAndLogEx(NORMAL, " Software Information"); PrintAndLogEx(NORMAL, " Software Information");
PrintAndLogEx(NORMAL, " Vendor Id : %s", getTagInfo(resp.d.asBytes[14])); PrintAndLogEx(NORMAL, " Vendor Id : %s", getTagInfo(resp.d.asBytes[14]));
PrintAndLogEx(NORMAL, " Type : 0x%02X",resp.d.asBytes[15]); PrintAndLogEx(NORMAL, " Type : 0x%02X", resp.d.asBytes[15]);
PrintAndLogEx(NORMAL, " Subtype : 0x%02X",resp.d.asBytes[16]); PrintAndLogEx(NORMAL, " Subtype : 0x%02X", resp.d.asBytes[16]);
PrintAndLogEx(NORMAL, " Version : %d.%d",resp.d.asBytes[17], resp.d.asBytes[18]); 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, " storage size : %s", GetCardSizeStr(resp.d.asBytes[19]));
PrintAndLogEx(NORMAL, " Protocol : %s", GetProtocolStr(resp.d.asBytes[20])); PrintAndLogEx(NORMAL, " Protocol : %s", GetProtocolStr(resp.d.asBytes[20]));
PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); PrintAndLogEx(NORMAL, "-------------------------------------------------------------");
@ -188,13 +192,13 @@ int CmdHF14ADesInfo(const char *Cmd){
c.arg[1] = 0x01; c.arg[1] = 0x01;
c.d.asBytes[0] = GET_FREE_MEMORY; c.d.asBytes[0] = GET_FREE_MEMORY;
SendCommand(&c); SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500)) if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500))
return 0; return 0;
uint8_t tmp[3]; 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, "-------------------------------------------------------------"); 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). 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'. 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}; static char buf[30] = {0x00};
char *retStr = buf; char *retStr = buf;
uint16_t usize = 1 << ((fsize >>1) + 1); uint16_t usize = 1 << ((fsize >> 1) + 1);
uint16_t lsize = 1 << (fsize >>1); uint16_t lsize = 1 << (fsize >> 1);
// is LSB set? // is LSB set?
if ( fsize & 1 ) if (fsize & 1)
sprintf(retStr, "0x%02X (%d - %d bytes)",fsize, usize, lsize); sprintf(retStr, "0x%02X (%d - %d bytes)", fsize, usize, lsize);
else else
sprintf(retStr, "0x%02X (%d bytes)", fsize, lsize); sprintf(retStr, "0x%02X (%d bytes)", fsize, lsize);
return buf; return buf;
} }
char * GetProtocolStr(uint8_t id){ char *GetProtocolStr(uint8_t id)
{
static char buf[30] = {0x00}; static char buf[30] = {0x00};
char *retStr = buf; char *retStr = buf;
if ( id == 0x05) if (id == 0x05)
sprintf(retStr,"0x%02X (ISO 14443-3, 14443-4)", id); sprintf(retStr, "0x%02X (ISO 14443-3, 14443-4)", id);
else else
sprintf(retStr,"0x%02X (Unknown)", id); sprintf(retStr, "0x%02X (Unknown)", id);
return buf; return buf;
} }
char * GetVersionStr(uint8_t major, uint8_t minor){ char *GetVersionStr(uint8_t major, uint8_t minor)
{
static char buf[30] = {0x00}; static char buf[30] = {0x00};
char *retStr = buf; char *retStr = buf;
if ( major == 0x00) if (major == 0x00)
sprintf(retStr,"%d.%d (Desfire MF3ICD40)", major, minor); sprintf(retStr, "%d.%d (Desfire MF3ICD40)", major, minor);
else if ( major == 0x01 && minor == 0x00) else if (major == 0x01 && minor == 0x00)
sprintf(retStr,"%d.%d (Desfire EV1)", major, minor); sprintf(retStr, "%d.%d (Desfire EV1)", major, minor);
else if ( major == 0x12 && minor == 0x00) else if (major == 0x12 && minor == 0x00)
sprintf(retStr,"%d.%d (Desfire EV2)", major, minor); sprintf(retStr, "%d.%d (Desfire EV2)", major, minor);
else else
sprintf(retStr,"%d.%d (Unknown)", major, minor); sprintf(retStr, "%d.%d (Unknown)", major, minor);
return buf; return buf;
} }
void GetKeySettings( uint8_t *aid){ void GetKeySettings(uint8_t *aid)
{
char messStr[512] = {0x00}; char messStr[512] = {0x00};
char *str = messStr; char *str = messStr;
@ -276,36 +284,36 @@ void GetKeySettings( uint8_t *aid){
//memset(messStr, 0x00, 512); //memset(messStr, 0x00, 512);
if ( aid == NULL ){ if (aid == NULL) {
PrintAndLogEx(NORMAL, " CMK - PICC, Card Master Key settings "); PrintAndLogEx(NORMAL, " CMK - PICC, Card Master Key settings ");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
c.arg[CMDPOS] = (INIT | DISCONNECT); c.arg[CMDPOS] = (INIT | DISCONNECT);
c.arg[LENPOS] = 0x01; c.arg[LENPOS] = 0x01;
c.d.asBytes[0] = GET_KEY_SETTINGS; // 0x45 c.d.asBytes[0] = GET_KEY_SETTINGS; // 0x45
SendCommand(&c); SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;} if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;}
isOK = resp.arg[0] & 0xff; isOK = resp.arg[0] & 0xff;
if ( !isOK ){ if (!isOK) {
PrintAndLogEx(WARNING, " Can't select master application"); PrintAndLogEx(WARNING, " Can't select master application");
return; 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); PrintAndLogEx(NORMAL, " [0x08] Configuration changeable : %s", str);
str = (resp.d.asBytes[3] & (1 << 2 )) ? "NO":"YES"; str = (resp.d.asBytes[3] & (1 << 2)) ? "NO" : "YES";
PrintAndLogEx(NORMAL, " [0x04] CMK required for create/delete : %s",str); PrintAndLogEx(NORMAL, " [0x04] CMK required for create/delete : %s", str);
str = (resp.d.asBytes[3] & (1 << 1 )) ? "NO":"YES"; str = (resp.d.asBytes[3] & (1 << 1)) ? "NO" : "YES";
PrintAndLogEx(NORMAL, " [0x02] Directory list access with CMK : %s",str); 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 << 0)) ? "YES" : "NO";
PrintAndLogEx(NORMAL, " [0x01] CMK is changeable : %s", str); PrintAndLogEx(NORMAL, " [0x01] CMK is changeable : %s", str);
c.arg[LENPOS] = 0x02; //LEN c.arg[LENPOS] = 0x02; //LEN
c.d.asBytes[0] = GET_KEY_VERSION; //0x64 c.d.asBytes[0] = GET_KEY_VERSION; //0x64
c.d.asBytes[1] = 0x00; c.d.asBytes[1] = 0x00;
SendCommand(&c); SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) { return; } if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) { return; }
isOK = resp.arg[0] & 0xff; isOK = resp.arg[0] & 0xff;
if ( !isOK ){ if (!isOK) {
PrintAndLogEx(WARNING, " Can't read key-version"); PrintAndLogEx(WARNING, " Can't read key-version");
return; return;
} }
@ -318,21 +326,21 @@ void GetKeySettings( uint8_t *aid){
c.d.asBytes[0] = AUTHENTICATE; //0x0A c.d.asBytes[0] = AUTHENTICATE; //0x0A
c.d.asBytes[1] = 0x00; // KEY 0 c.d.asBytes[1] = 0x00; // KEY 0
SendCommand(&c); SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;} if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;}
isOK = resp.d.asBytes[2] & 0xff; 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 c.d.asBytes[0] = AUTHENTICATE_ISO; //0x1A
SendCommand(&c); SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;} if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;}
isOK = resp.d.asBytes[2] & 0xff; 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 c.d.asBytes[0] = AUTHENTICATE_AES; //0xAA
SendCommand(&c); SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;} if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;}
isOK = resp.d.asBytes[2] & 0xff; 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, "");
PrintAndLogEx(NORMAL, " ----------------------------------------------------------"); PrintAndLogEx(NORMAL, " ----------------------------------------------------------");
@ -343,16 +351,16 @@ void GetKeySettings( uint8_t *aid){
c.arg[0] = (INIT | CLEARTRACE); c.arg[0] = (INIT | CLEARTRACE);
c.arg[LENPOS] = 0x04; c.arg[LENPOS] = 0x04;
c.d.asBytes[0] = SELECT_APPLICATION; // 0x5a c.d.asBytes[0] = SELECT_APPLICATION; // 0x5a
memcpy(c.d.asBytes+1, aid, 3); memcpy(c.d.asBytes + 1, aid, 3);
SendCommand(&c); SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
PrintAndLogEx(WARNING, " Timed-out"); PrintAndLogEx(WARNING, " Timed-out");
return; return;
} }
isOK = resp.arg[0] & 0xff; isOK = resp.arg[0] & 0xff;
if ( !isOK ){ if (!isOK) {
PrintAndLogEx(WARNING, " Can't select AID: %s",sprint_hex(aid,3)); PrintAndLogEx(WARNING, " Can't select AID: %s", sprint_hex(aid, 3));
return; return;
} }
@ -362,16 +370,16 @@ void GetKeySettings( uint8_t *aid){
c.arg[LENPOS] = 0x01; c.arg[LENPOS] = 0x01;
c.d.asBytes[0] = GET_KEY_SETTINGS; // 0x45 c.d.asBytes[0] = GET_KEY_SETTINGS; // 0x45
SendCommand(&c); SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
return; return;
} }
isOK = resp.arg[0] & 0xff; isOK = resp.arg[0] & 0xff;
if ( !isOK ){ if (!isOK) {
PrintAndLogEx(WARNING, " Can't read Application Master key settings"); PrintAndLogEx(WARNING, " Can't read Application Master key settings");
} else { } else {
// Access rights. // Access rights.
uint8_t rights = (resp.d.asBytes[3] >> 4 & 0xff); uint8_t rights = (resp.d.asBytes[3] >> 4 & 0xff);
switch (rights){ switch (rights) {
case 0x00: case 0x00:
str = "AMK authentication is necessary to change any key (default)"; str = "AMK authentication is necessary to change any key (default)";
break; break;
@ -386,16 +394,16 @@ void GetKeySettings( uint8_t *aid){
break; break;
} }
PrintAndLogEx(NORMAL, "Changekey Access rights"); PrintAndLogEx(NORMAL, "Changekey Access rights");
PrintAndLogEx(NORMAL, "-- %s",str); PrintAndLogEx(NORMAL, "-- %s", str);
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
// same as CMK // 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); PrintAndLogEx(NORMAL, " 0x08 Configuration changeable : %s", str);
str = (resp.d.asBytes[3] & (1 << 2 )) ? "NO":"YES"; str = (resp.d.asBytes[3] & (1 << 2)) ? "NO" : "YES";
PrintAndLogEx(NORMAL, " 0x04 AMK required for create/delete : %s",str); PrintAndLogEx(NORMAL, " 0x04 AMK required for create/delete : %s", str);
str = (resp.d.asBytes[3] & (1 << 1 )) ? "NO":"YES"; str = (resp.d.asBytes[3] & (1 << 1)) ? "NO" : "YES";
PrintAndLogEx(NORMAL, " 0x02 Directory list access with AMK : %s",str); 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 << 0)) ? "YES" : "NO";
PrintAndLogEx(NORMAL, " 0x01 AMK is changeable : %s", str); 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[0] = GET_KEY_VERSION; //0x64
c.d.asBytes[1] = 0x00; c.d.asBytes[1] = 0x00;
SendCommand(&c); SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
PrintAndLogEx(WARNING, " Timed-out"); PrintAndLogEx(WARNING, " Timed-out");
return; return;
} }
@ -413,21 +421,20 @@ void GetKeySettings( uint8_t *aid){
int numOfKeys; int numOfKeys;
isOK = resp.arg[0] & 0xff; isOK = resp.arg[0] & 0xff;
if ( !isOK ){ if (!isOK) {
PrintAndLogEx(WARNING, " Can't read Application Master key version. Trying all keys"); PrintAndLogEx(WARNING, " Can't read Application Master key version. Trying all keys");
numOfKeys = MAX_NUM_KEYS; numOfKeys = MAX_NUM_KEYS;
} } else {
else{
numOfKeys = resp.d.asBytes[4]; numOfKeys = resp.d.asBytes[4];
PrintAndLogEx(NORMAL, ""); 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, " Application Master key Version : %d (0x%02x)", resp.d.asBytes[3], resp.d.asBytes[3]);
PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); PrintAndLogEx(NORMAL, "-------------------------------------------------------------");
} }
// LOOP over numOfKeys that we got before. // LOOP over numOfKeys that we got before.
// From 0x01 to numOfKeys. We already got 0x00. (AMK) // 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 isOK = 0x00;
uint8_t aid[3]; uint8_t aid[3];
uint32_t options = (INIT | DISCONNECT); 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 c.d.asBytes[0] = GET_APPLICATION_IDS; //0x6a
SendCommand(&c); SendCommand(&c);
UsbCommand resp; UsbCommand resp;
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
return 0; return 0;
} }
isOK = resp.arg[0] & 0xff; isOK = resp.arg[0] & 0xff;
if ( !isOK ){ if (!isOK) {
PrintAndLogEx(NORMAL, "Command unsuccessful"); PrintAndLogEx(NORMAL, "Command unsuccessful");
return 0; return 0;
} }
@ -463,15 +471,15 @@ int CmdHF14ADesEnumApplications(const char *Cmd){
UsbCommand respFiles; UsbCommand respFiles;
uint8_t num = 0; 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){ 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]); PrintAndLogEx(NORMAL, " Aid %d : %02X %02X %02X ", num, resp.d.asBytes[i], resp.d.asBytes[i + 1], resp.d.asBytes[i + 2]);
num++; num++;
aid[0] = resp.d.asBytes[i]; aid[0] = resp.d.asBytes[i];
aid[1] = resp.d.asBytes[i+1]; aid[1] = resp.d.asBytes[i + 1];
aid[2] = resp.d.asBytes[i+2]; aid[2] = resp.d.asBytes[i + 2];
GetKeySettings(aid); GetKeySettings(aid);
// Select Application // Select Application
@ -479,17 +487,17 @@ int CmdHF14ADesEnumApplications(const char *Cmd){
c.arg[LENPOS] = 0x04; c.arg[LENPOS] = 0x04;
c.d.asBytes[0] = SELECT_APPLICATION; // 0x5a c.d.asBytes[0] = SELECT_APPLICATION; // 0x5a
c.d.asBytes[1] = resp.d.asBytes[i]; c.d.asBytes[1] = resp.d.asBytes[i];
c.d.asBytes[2] = resp.d.asBytes[i+1]; c.d.asBytes[2] = resp.d.asBytes[i + 1];
c.d.asBytes[3] = resp.d.asBytes[i+2]; c.d.asBytes[3] = resp.d.asBytes[i + 2];
SendCommand(&c); SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK,&respAid,1500) ) { if (!WaitForResponseTimeout(CMD_ACK, &respAid, 1500)) {
PrintAndLogEx(WARNING, " Timed-out"); PrintAndLogEx(WARNING, " Timed-out");
continue; continue;
} }
isOK = respAid.d.asBytes[2] & 0xff; isOK = respAid.d.asBytes[2] & 0xff;
if ( isOK != 0x00 ){ if (isOK != 0x00) {
PrintAndLogEx(WARNING, " Can't select AID: %s",sprint_hex(resp.d.asBytes+i,3)); PrintAndLogEx(WARNING, " Can't select AID: %s", sprint_hex(resp.d.asBytes + i, 3));
continue; continue;
} }
@ -499,17 +507,17 @@ int CmdHF14ADesEnumApplications(const char *Cmd){
c.d.asBytes[0] = GET_FILE_IDS; // 0x6f c.d.asBytes[0] = GET_FILE_IDS; // 0x6f
SendCommand(&c); SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&respFiles,1500) ) { if (!WaitForResponseTimeout(CMD_ACK, &respFiles, 1500)) {
PrintAndLogEx(WARNING, " Timed-out"); PrintAndLogEx(WARNING, " Timed-out");
continue; continue;
} else { } else {
isOK = respFiles.d.asBytes[2] & 0xff; isOK = respFiles.d.asBytes[2] & 0xff;
if ( !isOK ){ if (!isOK) {
PrintAndLogEx(WARNING, " Can't get file ids "); PrintAndLogEx(WARNING, " Can't get file ids ");
} else { } else {
int respfileLen = resp.arg[1]-3-2; int respfileLen = resp.arg[1] - 3 - 2;
for (int j=0; j< respfileLen; ++j){ for (int j = 0; j < respfileLen; ++j) {
PrintAndLogEx(NORMAL, " Fileid %d :", resp.d.asBytes[j+3]); 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 c.d.asBytes[0] = GET_ISOFILE_IDS; // 0x61
SendCommand(&c); SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&respFiles,1500) ) { if (!WaitForResponseTimeout(CMD_ACK, &respFiles, 1500)) {
PrintAndLogEx(WARNING, " Timed-out"); PrintAndLogEx(WARNING, " Timed-out");
continue; continue;
} else { } else {
isOK = respFiles.d.asBytes[2] & 0xff; isOK = respFiles.d.asBytes[2] & 0xff;
if ( !isOK ){ if (!isOK) {
PrintAndLogEx(WARNING, " Can't get ISO file ids "); PrintAndLogEx(WARNING, " Can't get ISO file ids ");
} else { } else {
int respfileLen = resp.arg[1]-3-2; int respfileLen = resp.arg[1] - 3 - 2;
for (int j=0; j< respfileLen; ++j){ for (int j = 0; j < respfileLen; ++j) {
PrintAndLogEx(NORMAL, " ISO Fileid %d :", resp.d.asBytes[j+3]); PrintAndLogEx(NORMAL, " ISO Fileid %d :", resp.d.asBytes[j + 3]);
} }
} }
} }
@ -546,7 +554,8 @@ int CmdHF14ADesEnumApplications(const char *Cmd){
// MIAFRE DesFire Authentication // MIAFRE DesFire Authentication
// //
#define BUFSIZE 256 #define BUFSIZE 256
int CmdHF14ADesAuth(const char *Cmd){ int CmdHF14ADesAuth(const char *Cmd)
{
// NR DESC KEYLENGHT // NR DESC KEYLENGHT
// ------------------------ // ------------------------
@ -558,7 +567,7 @@ int CmdHF14ADesAuth(const char *Cmd){
uint8_t keylength = 8; uint8_t keylength = 8;
unsigned char key[24]; 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, "Usage: hf mfdes auth <1|2|3> <1|2|3|4> <keyno> <key> ");
PrintAndLogEx(NORMAL, " Auth modes"); PrintAndLogEx(NORMAL, " Auth modes");
PrintAndLogEx(NORMAL, " 1 = normal, 2 = iso, 3 = aes"); 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"); PrintAndLogEx(NORMAL, " hf mfdes auth 3 4 0 404142434445464748494a4b4c4d4e4f");
return 0; return 0;
} }
uint8_t cmdAuthMode = param_get8(Cmd,0); uint8_t cmdAuthMode = param_get8(Cmd, 0);
uint8_t cmdAuthAlgo = param_get8(Cmd,1); uint8_t cmdAuthAlgo = param_get8(Cmd, 1);
uint8_t cmdKeyNo = param_get8(Cmd,2); uint8_t cmdKeyNo = param_get8(Cmd, 2);
switch (cmdAuthMode) switch (cmdAuthMode) {
{
case 1: case 1:
if ( cmdAuthAlgo != 1 && cmdAuthAlgo != 2) { if (cmdAuthAlgo != 1 && cmdAuthAlgo != 2) {
PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth mode"); PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth mode");
return 1; return 1;
} }
break; break;
case 2: 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"); PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth mode");
return 1; return 1;
} }
break; break;
case 3: case 3:
if ( cmdAuthAlgo != 4) { if (cmdAuthAlgo != 4) {
PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth mode"); PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth mode");
return 1; return 1;
} }
@ -600,7 +608,7 @@ int CmdHF14ADesAuth(const char *Cmd){
break; break;
} }
switch (cmdAuthAlgo){ switch (cmdAuthAlgo) {
case 2: case 2:
keylength = 16; keylength = 16;
PrintAndLogEx(NORMAL, "3DES selected"); PrintAndLogEx(NORMAL, "3DES selected");
@ -621,7 +629,7 @@ int CmdHF14ADesAuth(const char *Cmd){
} }
// key // 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); PrintAndLogEx(WARNING, "Key must include %d HEX symbols", keylength);
return 1; return 1;
} }
@ -629,25 +637,25 @@ int CmdHF14ADesAuth(const char *Cmd){
UsbCommand c = {CMD_MIFARE_DESFIRE_AUTH1, { cmdAuthMode, cmdAuthAlgo, cmdKeyNo }}; UsbCommand c = {CMD_MIFARE_DESFIRE_AUTH1, { cmdAuthMode, cmdAuthAlgo, cmdKeyNo }};
c.d.asBytes[0] = keylength; c.d.asBytes[0] = keylength;
memcpy(c.d.asBytes+1, key, keylength); memcpy(c.d.asBytes + 1, key, keylength);
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
UsbCommand resp; UsbCommand resp;
if (!WaitForResponseTimeout(CMD_ACK,&resp,3000)) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) {
PrintAndLogEx(WARNING, "Client command execute timeout"); PrintAndLogEx(WARNING, "Client command execute timeout");
return 0; return 0;
} }
uint8_t isOK = resp.arg[0] & 0xff; uint8_t isOK = resp.arg[0] & 0xff;
if ( isOK) { if (isOK) {
uint8_t * data= resp.d.asBytes; uint8_t *data = resp.d.asBytes;
PrintAndLogEx(NORMAL, " Key :%s",sprint_hex(key, keylength)); PrintAndLogEx(NORMAL, " Key :%s", sprint_hex(key, keylength));
PrintAndLogEx(NORMAL, " SESSION :%s",sprint_hex(data, keylength)); PrintAndLogEx(NORMAL, " SESSION :%s", sprint_hex(data, keylength));
PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); PrintAndLogEx(NORMAL, "-------------------------------------------------------------");
//PrintAndLogEx(NORMAL, " Expected :B5 21 9E E8 1A A7 49 9D 21 96 68 7E 13 97 38 56"); //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, "Client command failed.");
} }
PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); PrintAndLogEx(NORMAL, "-------------------------------------------------------------");
@ -656,23 +664,25 @@ int CmdHF14ADesAuth(const char *Cmd){
static command_t CommandTable[] = { static command_t CommandTable[] = {
{"help", CmdHelp, 1, "This help"}, {"help", CmdHelp, 1, "This help"},
{"info", CmdHF14ADesInfo, 0, "Tag information"}, {"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"}, {"auth", CmdHF14ADesAuth, 0, "Tries a MIFARE DesFire Authentication"},
{"rdbl", CmdHF14ADesRb, 0, "Read MIFARE DesFire block"}, {"rdbl", CmdHF14ADesRb, 0, "Read MIFARE DesFire block"},
{"wrbl", CmdHF14ADesWb, 0, "write MIFARE DesFire block"}, {"wrbl", CmdHF14ADesWb, 0, "write MIFARE DesFire block"},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };
int CmdHFMFDes(const char *Cmd) { int CmdHFMFDes(const char *Cmd)
// flush {
// flush
clearCommandBuffer(); clearCommandBuffer();
CmdsParse(CommandTable, Cmd); CmdsParse(CommandTable, Cmd);
return 0; return 0;
} }
int CmdHelp(const char *Cmd) { int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable); CmdsHelp(CommandTable);
return 0; return 0;
} }

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