AT91C_BASE_SSC->SSC_THR = 0x43;
}
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
- int8_t b;
- b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
+ int8_t b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
// The samples are correlations against I and Q versions of the
// tone that the tag AM-modulates, so every other sample is I,
// every other is Q. We just want power, so abs(I) + abs(Q) is
// close to what we want.
- if(getNext) {
- int8_t r;
-
- if(b < 0) {
- r = -b;
- } else {
- r = b;
- }
- if(prev < 0) {
- r -= prev;
- } else {
- r += prev;
- }
+ if (getNext) {
- dest[c++] = (uint8_t)r;
+ dest[c++] = abs(b) + abs(prev);
if(c >= 20000) {
break;
// Now the VICC>VCD responses when we are simulating a tag
static void BuildInventoryResponse( uint8_t *uid)
{
- uint8_t cmd[13];
+ uint8_t cmd[12];
uint16_t crc;
// one sub-carrier, inventory, 1 slot, fast rate
// AFI is at bit 5 (1<<4) when doing an INVENTORY
- cmd[0] = 0x0d; // COM LEN? Data 8 + 4 //(1 << 2) | (1 << 5) | (1 << 1);
- cmd[1] = 0; // com_Adr
- cmd[2] = 0; // status 00 = success
+ //(1 << 2) | (1 << 5) | (1 << 1);
+ cmd[0] = 0; //
+ cmd[1] = 0; // DSFID (data storage format identifier). 0x00 = not supported
// 64-bit UID
- cmd[3] = uid[7]; //0x32;
- cmd[4] = uid[6]; //0x4b;
- cmd[5] = uid[5]; //0x03;
- cmd[6] = uid[4]; //0x01;
- cmd[7] = uid[3]; //0x00;
- cmd[8] = uid[2]; //0x10;
- cmd[9] = uid[1]; //0x05;
- cmd[10] = uid[0]; //0xe0;
+ cmd[2] = uid[7]; //0x32;
+ cmd[3] = uid[6]; //0x4b;
+ cmd[4] = uid[5]; //0x03;
+ cmd[5] = uid[4]; //0x01;
+ cmd[6] = uid[3]; //0x00;
+ cmd[7] = uid[2]; //0x10;
+ cmd[8] = uid[1]; //0x05;
+ cmd[9] = uid[0]; //0xe0;
//Now the CRC
crc = Crc(cmd, 10);
- cmd[11] = crc & 0xff;
- cmd[12] = crc >> 8;
+ cmd[10] = crc & 0xff;
+ cmd[11] = crc >> 8;
CodeIso15693AsReader(cmd, sizeof(cmd));
}
memset(buf, 0x00, 100);
- // Inventory response
- BuildInventoryResponse(uid);
-
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
{
// Build a suitable reponse to the reader INVENTORY cocmmand
// not so obsvious, but in the call to BuildInventoryResponse, the command is copied to the global ToSend buffer used below.
+
+ BuildInventoryResponse(uid);
+
TransmitTo15693Reader(ToSend, ToSendMax, &tsamples, &wait);
}
buf[0], buf[1], buf[2], buf[3],
buf[4], buf[5], buf[6], buf[7], buf[8]);
+ Dbprintf("Simulationg uid: %x %x %x %x %x %x %x %x",
+ uid[0], uid[1], uid[2], uid[3],
+ uid[4], uid[5], uid[6], uid[7]);
+
LED_A_OFF();
LED_B_OFF();
LED_C_OFF();
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
- SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
-
+ //FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);
+
+ // Connect the A/D to the peak-detected low-frequency path.
+ //SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
+
// Configure output and enable pin that is connected to the FPGA (for modulating)
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT | GPIO_SSC_CLK;
- AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
-
- AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_CLK;
+ AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; // (PIO_PER) PIO Enable Register ,
+ AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; // (PIO_OER) Output Enable Register
+ AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_CLK; // (PIO_ODR) Output Disable Register
// Give it a bit of time for the resonant antenna to settle.
- SpinDelay(30);
+ SpinDelay(150);
+
+ 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 low
+
+ while(!BUTTON_PRESS()) {
+ WDT_HIT();
- for(;;) {
-
- while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) {
+ // PIO_PDSR = Pin Data Status Register
+ // GPIO_SSC_CLK = SSC Transmit Clock
+ while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) { // wait for ssp_clk to go high
if(BUTTON_PRESS()) {
DbpString("Stopped at 0");
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
WDT_HIT();
}
- if ( buff[i] )
- OPEN_COIL();
- else
- SHORT_COIL();
-
- while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) {
+ // PIO_CODR = Clear Output Data Register
+ // PIO_SODR = Set Output Data Register
+ //#define LOW(x) AT91C_BASE_PIOA->PIO_CODR = (x)
+ //#define HIGH(x) AT91C_BASE_PIOA->PIO_SODR = (x)
+
+ if ( buff[i] > 0 ){
+ HIGH(GPIO_SSC_DOUT);
+ //FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
+ //FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);
+ } else {
+ LOW(GPIO_SSC_DOUT);
+ //FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ }
+
+ while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) { // wait for ssp_clk to go low
if(BUTTON_PRESS()) {
DbpString("Stopped at 1");
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
}
WDT_HIT();
}
-
+
+ //SpinDelayUs(512);
+
++i;
if(i == period) {
i = 0;
if (gap) {
// turn of modulation
- SHORT_COIL();
+ LOW(GPIO_SSC_DOUT);
// wait
SpinDelay(gap);
}
}
}
+ DbpString("Stopped");
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ return;
}
#define DEBUG_FRAME_CONTENTS 1
#include "cmdmain.h"
#include "cmddata.h"
+
static int CmdHelp(const char *Cmd);
int CmdAmp(const char *Cmd)
// At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
// Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
// to stop output at the final bitidx2 value, not bitidx
- for (i = 0; i < bitidx; i += 2) {
+
+ //http://www.proxmark.org/forum/viewtopic.php?id=403
+ for (i = 1; i < bitidx; i += 2) {
if ((BitStream[i] == 0) && (BitStream[i+1] == 1)) {
BitStream[bit2idx++] = 1 ^ invert;
} else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) {
BitStream[i+14],
BitStream[i+15]);
}
- return 0;
+ return bit2idx;
}
/* Modulate our data into manchester */
{
{"help", CmdHelp, 1, "This help"},
{"amp", CmdAmp, 1, "Amplify peaks"},
- {"askdemod", Cmdaskdemod, 1, "<0 or 1> -- Attempt to demodulate simple ASK tags"},
+ {"askdemod", Cmdaskdemod, 1, "<0|1> -- Attempt to demodulate simple ASK tags"},
{"autocorr", CmdAutoCorr, 1, "<window length> -- Autocorrelation over window"},
{"bitsamples", CmdBitsamples, 0, "Get raw samples as bitstring"},
{"bitstream", CmdBitstream, 1, "[clock rate] -- Convert waveform into a bitstream"},
switch (card->sak) {
case 0x00: PrintAndLog("TYPE : NXP MIFARE Ultralight | Ultralight C"); break;
+ case 0x01: PrintAndLog("TYPE : NXP TNP3xxx Activision Game Appliance"); break;
case 0x04: PrintAndLog("TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); break;
case 0x08: PrintAndLog("TYPE : NXP MIFARE CLASSIC 1k | Plus 2k SL1"); break;
case 0x09: PrintAndLog("TYPE : NXP MIFARE Mini 0.3k"); break;
PrintAndLog("Thought we had a valid tag but failed at word %d (i=%d)", rows + 1, i);
/* Start back rows * 5 + 9 header bits, -1 to not start at same place */
- i -= 9 + (5 * rows) -2;
+ i -= 9 + (5 * rows) -5;
rows = header = 0;
}
int clock = 64;
/* clear our graph */
- ClearGraph(1);
+ ClearGraph(0);
/* write it out a few times */
- for (h = 0; h < 4; h++)
- {
+ //for (h = 0; h < 4; h++)
+ //{
/* write 9 start bits */
for (i = 0; i < 9; i++)
AppendGraph(0, clock, 1);
/* stop bit */
AppendGraph(0, clock, 0);
- }
+ //}
/* modulate that biatch */
- CmdManchesterMod("64");
+ //CmdManchesterMod("64");
/* booyah! */
RepaintGraphWindow();
}
CmdLFRead(read_h ? "h" : "");
- CmdSamples("16000");
+ CmdSamples("6000");
} while (
!CmdEM410xRead("")
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
+
{"410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag"},
{"410xsim", CmdEM410xSim, 0, "<UID> -- Simulate EM410x tag"},
+ {"replay", MWRem4xReplay, 0, "Watches for tag and simulates manchester encoded em4x tag"},
{"410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
{"410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" },
{"410xwrite", CmdEM410xWrite, 1, "<UID> <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"},
{NULL, NULL, 0, NULL}
};
+
+//Confirms the parity of a bitstream as well as obtaining the data (TagID) from within the appropriate memory space.
+//Arguments:
+// Pointer to a string containing the desired bitsream
+// Pointer to a string that will receive the decoded tag ID
+// Length of the bitsream pointed at in the first argument, char* _strBitStream
+//Retuns:
+//1 Parity confirmed
+//0 Parity not confirmed
+int ConfirmEm410xTagParity( char* _strBitStream, char* pID, int LengthOfBitstream )
+{
+ int i = 0;
+ int rows = 0;
+ int Parity[4] = {0x00};
+ char ID[11] = {0x00};
+ int k = 0;
+ int BitStream[70] = {0x00};
+ int counter = 0;
+ //prepare variables
+ for ( i = 0; i <= LengthOfBitstream; i++)
+ {
+ if (_strBitStream[i] == '1')
+ {
+ k =1;
+ memcpy(&BitStream[i], &k,4);
+ }
+ else if (_strBitStream[i] == '0')
+ {
+ k = 0;
+ memcpy(&BitStream[i], &k,4);
+ }
+ }
+ while ( counter < 2 )
+ {
+ //set/reset variables and counters
+ memset(ID,0x00,sizeof(ID));
+ memset(Parity,0x00,sizeof(Parity));
+ rows = 0;
+ for ( i = 9; i <= LengthOfBitstream; i++)
+ {
+ if ( rows < 10 )
+ {
+ if ((BitStream[i] ^ BitStream[i+1] ^ BitStream[i+2] ^ BitStream[i+3]) == BitStream[i+4])
+ {
+ sprintf(ID+rows, "%x", (8 * BitStream[i]) + (4 * BitStream[i+1]) + (2 * BitStream[i+2]) + (1 * BitStream[i+3]));
+ rows++;
+ /* Keep parity info and move four bits ahead*/
+ Parity[0] ^= BitStream[i];
+ Parity[1] ^= BitStream[i+1];
+ Parity[2] ^= BitStream[i+2];
+ Parity[3] ^= BitStream[i+3];
+ i += 4;
+ }
+ }
+ if ( rows == 10 )
+ {
+ if ( BitStream[i] == Parity[0] && BitStream[i+1] == Parity[1] &&
+ BitStream[i+2] == Parity[2] && BitStream[i+3] == Parity[3] &&
+ BitStream[i+4] == 0)
+ {
+ memcpy(pID,ID,strlen(ID));
+ return 1;
+ }
+ }
+ }
+ printf("[PARITY ->]Failed. Flipping Bits, and rechecking parity for bitstream:\n[PARITY ->]");
+ for (k = 0; k < LengthOfBitstream; k++)
+ {
+ BitStream[k] ^= 1;
+ printf("%i", BitStream[k]);
+ }
+ puts(" ");
+ counter++;
+ }
+ return 0;
+}
+//Reads and demodulates an em410x RFID tag. It further allows slight modification to the decoded bitstream
+//Once a suitable bitstream has been identified, and if needed, modified, it is replayed. Allowing emulation of the
+//"stolen" rfid tag.
+//No meaningful returns or arguments.
+int MWRem4xReplay(const char* Cmd)
+{
+ // //header traces
+ // static char ArrayTraceZero[] = { '0','0','0','0','0','0','0','0','0' };
+ // static char ArrayTraceOne[] = { '1','1','1','1','1','1','1','1','1' };
+ // //local string variables
+ // char strClockRate[10] = {0x00};
+ // char strAnswer[4] = {0x00};
+ // char strTempBufferMini[2] = {0x00};
+ // //our outbound bit-stream
+ // char strSimulateBitStream[65] = {0x00};
+ // //integers
+ // int iClockRate = 0;
+ // int needle = 0;
+ // int j = 0;
+ // int iFirstHeaderOffset = 0x00000000;
+ // int numManchesterDemodBits=0;
+ // //boolean values
+ // bool bInverted = false;
+ // //pointers to strings. memory will be allocated.
+ // char* pstrInvertBitStream = 0x00000000;
+ // char* pTempBuffer = 0x00000000;
+ // char* pID = 0x00000000;
+ // char* strBitStreamBuffer = 0x00000000;
+
+
+ // puts("###################################");
+ // puts("#### Em4x Replay ##");
+ // puts("#### R.A.M. June 2013 ##");
+ // puts("###################################");
+ // //initialize
+ // CmdLFRead("");
+ // //Collect ourselves 10,000 samples
+ // CmdSamples("10000");
+ // puts("[->]preforming ASK demodulation\n");
+ // //demodulate ask
+ // Cmdaskdemod("0");
+ // iClockRate = DetectClock(0);
+ // sprintf(strClockRate, "%i\n",iClockRate);
+ // printf("[->]Detected ClockRate: %s\n", strClockRate);
+
+ // //If detected clock rate is something completely unreasonable, dont go ahead
+ // if ( iClockRate < 0xFFFE )
+ // {
+ // pTempBuffer = (char*)malloc(MAX_GRAPH_TRACE_LEN);
+ // if (pTempBuffer == 0x00000000)
+ // return 0;
+ // memset(pTempBuffer,0x00,MAX_GRAPH_TRACE_LEN);
+ // //Preform manchester de-modulation and display in a single line.
+ // numManchesterDemodBits = CmdManchesterDemod( strClockRate );
+ // //note: numManchesterDemodBits is set above in CmdManchesterDemod()
+ // if ( numManchesterDemodBits == 0 )
+ // return 0;
+ // strBitStreamBuffer = malloc(numManchesterDemodBits+1);
+ // if ( strBitStreamBuffer == 0x00000000 )
+ // return 0;
+ // memset(strBitStreamBuffer, 0x00, (numManchesterDemodBits+1));
+ // //fill strBitStreamBuffer with demodulated, string formatted bits.
+ // for ( j = 0; j <= numManchesterDemodBits; j++ )
+ // {
+ // sprintf(strTempBufferMini, "%i",BitStream[j]);
+ // strcat(strBitStreamBuffer,strTempBufferMini);
+ // }
+ // printf("[->]Demodulated Bitstream: \n%s\n", strBitStreamBuffer);
+ // //Reset counter and select most probable bit stream
+ // j = 0;
+ // while ( j < numManchesterDemodBits )
+ // {
+ // memset(strSimulateBitStream,0x00,64);
+ // //search for header of nine (9) 0's : 000000000 or nine (9) 1's : 1111 1111 1
+ // if ( ( strncmp(strBitStreamBuffer+j, ArrayTraceZero, sizeof(ArrayTraceZero)) == 0 ) ||
+ // ( strncmp(strBitStreamBuffer+j, ArrayTraceOne, sizeof(ArrayTraceOne)) == 0 ) )
+ // {
+ // iFirstHeaderOffset = j;
+ // memcpy(strSimulateBitStream, strBitStreamBuffer+j,64);
+ // printf("[->]Offset of Header");
+ // if ( strncmp(strBitStreamBuffer+iFirstHeaderOffset, "0", 1) == 0 )
+ // printf("'%s'", ArrayTraceZero );
+ // else
+ // printf("'%s'", ArrayTraceOne );
+ // printf(": %i\nHighlighted string : %s\n",iFirstHeaderOffset,strSimulateBitStream);
+ // //allow us to escape loop or choose another frame
+ // puts("[<-]Are we happy with this sample? [Y]es/[N]o");
+ // gets(strAnswer);
+ // if ( ( strncmp(strAnswer,"y",1) == 0 ) || ( strncmp(strAnswer,"Y",1) == 0 ) )
+ // {
+ // j = numManchesterDemodBits+1;
+ // break;
+ // }
+ // }
+ // j++;
+ // }
+ // }
+ // else return 0;
+
+ // //Do we want the buffer inverted?
+ // memset(strAnswer, 0x00, sizeof(strAnswer));
+ // printf("[<-]Do you wish to invert the highlighted bitstream? [Y]es/[N]o\n");
+ // gets(strAnswer);
+ // if ( ( strncmp("y", strAnswer,1) == 0 ) || ( strncmp("Y", strAnswer, 1 ) == 0 ) )
+ // {
+ // //allocate heap memory
+ // pstrInvertBitStream = (char*)malloc(numManchesterDemodBits);
+ // if ( pstrInvertBitStream != 0x00000000 )
+ // {
+ // memset(pstrInvertBitStream,0x00,numManchesterDemodBits);
+ // bInverted = true;
+ // //Invert Bitstream
+ // for ( needle = 0; needle <= numManchesterDemodBits; needle++ )
+ // {
+ // if (strSimulateBitStream[needle] == '0')
+ // strcat(pstrInvertBitStream,"1");
+ // else if (strSimulateBitStream[needle] == '1')
+ // strcat(pstrInvertBitStream,"0");
+ // }
+ // printf("[->]Inverted bitstream: %s\n", pstrInvertBitStream);
+ // }
+ // }
+ // //Confirm parity of selected string
+ // pID = (char*)malloc(11);
+ // if (pID != 0x00000000)
+ // {
+ // memset(pID, 0x00, 11);
+ // if (ConfirmEm410xTagParity(strSimulateBitStream,pID, 64) == 1)
+ // {
+ // printf("[->]Parity confirmed for selected bitstream!\n");
+ // printf("[->]Tag ID was detected as: [hex]:%s\n",pID );
+ // }
+ // else
+ // printf("[->]Parity check failed for the selected bitstream!\n");
+ // }
+
+ // //Spoof
+ // memset(strAnswer, 0x00, sizeof(strAnswer));
+ // printf("[<-]Do you wish to continue with the EM4x simulation? [Y]es/[N]o\n");
+ // gets(strAnswer);
+ // if ( ( strncmp(strAnswer,"y",1) == 0 ) || ( strncmp(strAnswer,"Y",1) == 0 ) )
+ // {
+ // strcat(pTempBuffer, strClockRate);
+ // strcat(pTempBuffer, " ");
+ // if (bInverted == true)
+ // strcat(pTempBuffer,pstrInvertBitStream);
+ // if (bInverted == false)
+ // strcat(pTempBuffer,strSimulateBitStream);
+ // //inform the user
+ // puts("[->]Starting simulation now: \n");
+ // //Simulate tag with prepared buffer.
+ // CmdLFSimManchester(pTempBuffer);
+ // }
+ // else if ( ( strcmp("n", strAnswer) == 0 ) || ( strcmp("N", strAnswer ) == 0 ) )
+ // printf("[->]Exiting procedure now...\n");
+ // else
+ // printf("[->]Erroneous selection\nExiting procedure now....\n");
+
+ // //Clean up -- Exit function
+ // //clear memory, then release pointer.
+ // if ( pstrInvertBitStream != 0x00000000 )
+ // {
+ // memset(pstrInvertBitStream,0x00,numManchesterDemodBits);
+ // free(pstrInvertBitStream);
+ // }
+ // if ( pTempBuffer != 0x00000000 )
+ // {
+ // memset(pTempBuffer,0x00,MAX_GRAPH_TRACE_LEN);
+ // free(pTempBuffer);
+ // }
+ // if ( pID != 0x00000000 )
+ // {
+ // memset(pID,0x00,11);
+ // free(pID);
+ // }
+ // if ( strBitStreamBuffer != 0x00000000 )
+ // {
+ // memset(strBitStreamBuffer,0x00,numManchesterDemodBits);
+ // free(strBitStreamBuffer);
+ // }
+ return 0;
+}
+
int CmdLFEM4X(const char *Cmd)
{
CmdsParse(CommandTable, Cmd);
int CmdReadWordPWD(const char *Cmd);
int CmdWriteWord(const char *Cmd);
int CmdWriteWordPWD(const char *Cmd);
+int MWRem4xReplay(const char* Cmd);
#endif
case 1: clock--; break;
case 2: clock -= 2; break;
}
+ if ( clock < 32)
+ clock = 32;
+
printf("- adjusted it to %d \n", clock);
return clock;
}
return "UNKNOWN"
}
+ add("04,,,Mifare TNP3xxx Activision 1K,0f01,01");
add("04,,,Mifare Mini,0004,09");
add("04,,,Mifare Classic 1k/Mifare Plus(4 byte UID) 2K SL1,0004,08");
add("04,,,Mifare Plus (4 byte UID) 2K SL2,0004,10");
--- /dev/null
+local md5 = {
+ _VERSION = "md5.lua 0.5.0",
+ _DESCRIPTION = "MD5 computation in Lua (5.1)",
+ _URL = "https://github.com/kikito/md5.lua",
+ _LICENSE = [[
+ MIT LICENSE
+
+ Copyright (c) 2013 Enrique GarcÃa Cota + Adam Baldwin + hanzao + Equi 4 Software
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ ]]
+}
+
+-- bit lib implementions
+
+local floor, abs, max = math.floor, math.abs, math.max
+local char, byte, format, rep, sub =
+ string.char, string.byte, string.format, string.rep, string.sub
+
+local function check_int(n)
+ -- checking not float
+ if(n - floor(n) > 0) then
+ error("trying to use bitwise operation on non-integer!")
+ end
+end
+
+local function tbl2number(tbl)
+ local n = #tbl
+
+ local rslt = 0
+ local power = 1
+ for i = 1, n do
+ rslt = rslt + tbl[i]*power
+ power = power*2
+ end
+
+ return rslt
+end
+
+local function expand(tbl_m, tbl_n)
+ local big = {}
+ local small = {}
+ if(#tbl_m > #tbl_n) then
+ big = tbl_m
+ small = tbl_n
+ else
+ big = tbl_n
+ small = tbl_m
+ end
+ -- expand small
+ for i = #small + 1, #big do
+ small[i] = 0
+ end
+
+end
+
+local to_bits -- needs to be declared before bit_not
+
+local function bit_not(n)
+ local tbl = to_bits(n)
+ local size = max(#tbl, 32)
+ for i = 1, size do
+ if(tbl[i] == 1) then
+ tbl[i] = 0
+ else
+ tbl[i] = 1
+ end
+ end
+ return tbl2number(tbl)
+end
+
+-- defined as local above
+to_bits = function (n)
+ check_int(n)
+ if(n < 0) then
+ -- negative
+ return to_bits(bit_not(abs(n)) + 1)
+ end
+ -- to bits table
+ local tbl = {}
+ local cnt = 1
+ while (n > 0) do
+ local last = math.fmod(n,2)
+ if(last == 1) then
+ tbl[cnt] = 1
+ else
+ tbl[cnt] = 0
+ end
+ n = (n-last)/2
+ cnt = cnt + 1
+ end
+
+ return tbl
+end
+
+local function bit_or(m, n)
+ local tbl_m = to_bits(m)
+ local tbl_n = to_bits(n)
+ expand(tbl_m, tbl_n)
+
+ local tbl = {}
+ local rslt = max(#tbl_m, #tbl_n)
+ for i = 1, rslt do
+ if(tbl_m[i]== 0 and tbl_n[i] == 0) then
+ tbl[i] = 0
+ else
+ tbl[i] = 1
+ end
+ end
+
+ return tbl2number(tbl)
+end
+
+local function bit_and(m, n)
+ local tbl_m = to_bits(m)
+ local tbl_n = to_bits(n)
+ expand(tbl_m, tbl_n)
+
+ local tbl = {}
+ local rslt = max(#tbl_m, #tbl_n)
+ for i = 1, rslt do
+ if(tbl_m[i]== 0 or tbl_n[i] == 0) then
+ tbl[i] = 0
+ else
+ tbl[i] = 1
+ end
+ end
+
+ return tbl2number(tbl)
+end
+
+local function bit_xor(m, n)
+ local tbl_m = to_bits(m)
+ local tbl_n = to_bits(n)
+ expand(tbl_m, tbl_n)
+
+ local tbl = {}
+ local rslt = max(#tbl_m, #tbl_n)
+ for i = 1, rslt do
+ if(tbl_m[i] ~= tbl_n[i]) then
+ tbl[i] = 1
+ else
+ tbl[i] = 0
+ end
+ end
+
+ return tbl2number(tbl)
+end
+
+local function bit_rshift(n, bits)
+ check_int(n)
+
+ local high_bit = 0
+ if(n < 0) then
+ -- negative
+ n = bit_not(abs(n)) + 1
+ high_bit = 2147483648 -- 0x80000000
+ end
+
+ for i=1, bits do
+ n = n/2
+ n = bit_or(floor(n), high_bit)
+ end
+ return floor(n)
+end
+
+local function bit_lshift(n, bits)
+ check_int(n)
+
+ if(n < 0) then
+ -- negative
+ n = bit_not(abs(n)) + 1
+ end
+
+ for i=1, bits do
+ n = n*2
+ end
+ return bit_and(n, 4294967295) -- 0xFFFFFFFF
+end
+
+-- convert little-endian 32-bit int to a 4-char string
+local function lei2str(i)
+ local f=function (s) return char( bit_and( bit_rshift(i, s), 255)) end
+ return f(0)..f(8)..f(16)..f(24)
+end
+
+-- convert raw string to big-endian int
+local function str2bei(s)
+ local v=0
+ for i=1, #s do
+ v = v * 256 + byte(s, i)
+ end
+ return v
+end
+
+-- convert raw string to little-endian int
+local function str2lei(s)
+ local v=0
+ for i = #s,1,-1 do
+ v = v*256 + byte(s, i)
+ end
+ return v
+end
+
+-- cut up a string in little-endian ints of given size
+local function cut_le_str(s,...)
+ local o, r = 1, {}
+ local args = {...}
+ for i=1, #args do
+ table.insert(r, str2lei(sub(s, o, o + args[i] - 1)))
+ o = o + args[i]
+ end
+ return r
+end
+
+local swap = function (w) return str2bei(lei2str(w)) end
+
+local function hex2binaryaux(hexval)
+ return char(tonumber(hexval, 16))
+end
+
+local function hex2binary(hex)
+ local result, _ = hex:gsub('..', hex2binaryaux)
+ return result
+end
+
+-- An MD5 mplementation in Lua, requires bitlib (hacked to use LuaBit from above, ugh)
+-- 10/02/2001 jcw@equi4.com
+
+local FF = 0xffffffff
+local CONSTS = {
+ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
+ 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+ 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+ 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+ 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
+ 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
+ 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+ 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+ 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+ 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+ 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
+ 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+ 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
+ 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+ 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+ 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
+ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476
+}
+
+local f=function (x,y,z) return bit_or(bit_and(x,y),bit_and(-x-1,z)) end
+local g=function (x,y,z) return bit_or(bit_and(x,z),bit_and(y,-z-1)) end
+local h=function (x,y,z) return bit_xor(x,bit_xor(y,z)) end
+local i=function (x,y,z) return bit_xor(y,bit_or(x,-z-1)) end
+local z=function (f,a,b,c,d,x,s,ac)
+ a=bit_and(a+f(b,c,d)+x+ac,FF)
+ -- be *very* careful that left shift does not cause rounding!
+ return bit_or(bit_lshift(bit_and(a,bit_rshift(FF,s)),s),bit_rshift(a,32-s))+b
+end
+
+local function transform(A,B,C,D,X)
+ local a,b,c,d=A,B,C,D
+ local t=CONSTS
+
+ a=z(f,a,b,c,d,X[ 0], 7,t[ 1])
+ d=z(f,d,a,b,c,X[ 1],12,t[ 2])
+ c=z(f,c,d,a,b,X[ 2],17,t[ 3])
+ b=z(f,b,c,d,a,X[ 3],22,t[ 4])
+ a=z(f,a,b,c,d,X[ 4], 7,t[ 5])
+ d=z(f,d,a,b,c,X[ 5],12,t[ 6])
+ c=z(f,c,d,a,b,X[ 6],17,t[ 7])
+ b=z(f,b,c,d,a,X[ 7],22,t[ 8])
+ a=z(f,a,b,c,d,X[ 8], 7,t[ 9])
+ d=z(f,d,a,b,c,X[ 9],12,t[10])
+ c=z(f,c,d,a,b,X[10],17,t[11])
+ b=z(f,b,c,d,a,X[11],22,t[12])
+ a=z(f,a,b,c,d,X[12], 7,t[13])
+ d=z(f,d,a,b,c,X[13],12,t[14])
+ c=z(f,c,d,a,b,X[14],17,t[15])
+ b=z(f,b,c,d,a,X[15],22,t[16])
+
+ a=z(g,a,b,c,d,X[ 1], 5,t[17])
+ d=z(g,d,a,b,c,X[ 6], 9,t[18])
+ c=z(g,c,d,a,b,X[11],14,t[19])
+ b=z(g,b,c,d,a,X[ 0],20,t[20])
+ a=z(g,a,b,c,d,X[ 5], 5,t[21])
+ d=z(g,d,a,b,c,X[10], 9,t[22])
+ c=z(g,c,d,a,b,X[15],14,t[23])
+ b=z(g,b,c,d,a,X[ 4],20,t[24])
+ a=z(g,a,b,c,d,X[ 9], 5,t[25])
+ d=z(g,d,a,b,c,X[14], 9,t[26])
+ c=z(g,c,d,a,b,X[ 3],14,t[27])
+ b=z(g,b,c,d,a,X[ 8],20,t[28])
+ a=z(g,a,b,c,d,X[13], 5,t[29])
+ d=z(g,d,a,b,c,X[ 2], 9,t[30])
+ c=z(g,c,d,a,b,X[ 7],14,t[31])
+ b=z(g,b,c,d,a,X[12],20,t[32])
+
+ a=z(h,a,b,c,d,X[ 5], 4,t[33])
+ d=z(h,d,a,b,c,X[ 8],11,t[34])
+ c=z(h,c,d,a,b,X[11],16,t[35])
+ b=z(h,b,c,d,a,X[14],23,t[36])
+ a=z(h,a,b,c,d,X[ 1], 4,t[37])
+ d=z(h,d,a,b,c,X[ 4],11,t[38])
+ c=z(h,c,d,a,b,X[ 7],16,t[39])
+ b=z(h,b,c,d,a,X[10],23,t[40])
+ a=z(h,a,b,c,d,X[13], 4,t[41])
+ d=z(h,d,a,b,c,X[ 0],11,t[42])
+ c=z(h,c,d,a,b,X[ 3],16,t[43])
+ b=z(h,b,c,d,a,X[ 6],23,t[44])
+ a=z(h,a,b,c,d,X[ 9], 4,t[45])
+ d=z(h,d,a,b,c,X[12],11,t[46])
+ c=z(h,c,d,a,b,X[15],16,t[47])
+ b=z(h,b,c,d,a,X[ 2],23,t[48])
+
+ a=z(i,a,b,c,d,X[ 0], 6,t[49])
+ d=z(i,d,a,b,c,X[ 7],10,t[50])
+ c=z(i,c,d,a,b,X[14],15,t[51])
+ b=z(i,b,c,d,a,X[ 5],21,t[52])
+ a=z(i,a,b,c,d,X[12], 6,t[53])
+ d=z(i,d,a,b,c,X[ 3],10,t[54])
+ c=z(i,c,d,a,b,X[10],15,t[55])
+ b=z(i,b,c,d,a,X[ 1],21,t[56])
+ a=z(i,a,b,c,d,X[ 8], 6,t[57])
+ d=z(i,d,a,b,c,X[15],10,t[58])
+ c=z(i,c,d,a,b,X[ 6],15,t[59])
+ b=z(i,b,c,d,a,X[13],21,t[60])
+ a=z(i,a,b,c,d,X[ 4], 6,t[61])
+ d=z(i,d,a,b,c,X[11],10,t[62])
+ c=z(i,c,d,a,b,X[ 2],15,t[63])
+ b=z(i,b,c,d,a,X[ 9],21,t[64])
+
+ return A+a,B+b,C+c,D+d
+end
+
+----------------------------------------------------------------
+
+function md5.sumhexa(s)
+ local msgLen = #s
+ local padLen = 56 - msgLen % 64
+
+ if msgLen % 64 > 56 then padLen = padLen + 64 end
+
+ if padLen == 0 then padLen = 64 end
+
+ s = s .. char(128) .. rep(char(0),padLen-1) .. lei2str(8*msgLen) .. lei2str(0)
+
+ assert(#s % 64 == 0)
+
+ local t = CONSTS
+ local a,b,c,d = t[65],t[66],t[67],t[68]
+
+ for i=1,#s,64 do
+ local X = cut_le_str(sub(s,i,i+63),4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4)
+ assert(#X == 16)
+ X[0] = table.remove(X,1) -- zero based!
+ a,b,c,d = transform(a,b,c,d,X)
+ end
+
+ return format("%08x%08x%08x%08x",swap(a),swap(b),swap(c),swap(d))
+end
+
+function md5.sum(s)
+ return hex2binary(md5.sumhexa(s))
+end
+
+return md5
'200000000000',
'a00000000000',
'b00000000000',
- }
+
+ --[[
+ Should be for Mifare TNP3xxx tags A KEY.
+ --]]
+ '4b0b20107ccb',
+
+}
---
-- The keys above have just been pasted in, for completeness sake. They contain duplicates.
local ISO14443a_TYPES = {}
ISO14443a_TYPES[0x00] = "NXP MIFARE Ultralight | Ultralight C"
+ISO14443a_TYPES[0x01] = "NXP MIFARE TNP3xxx Activision Game Appliance"
ISO14443a_TYPES[0x04] = "NXP MIFARE (various !DESFire !DESFire EV1)"
ISO14443a_TYPES[0x08] = "NXP MIFARE CLASSIC 1k | Plus 2k"
ISO14443a_TYPES[0x09] = "NXP MIFARE Mini 0.3k"
#include "util.h"
#include "nonce2key/nonce2key.h"
#include "../common/iso15693tools.h"
+#include <openssl/aes.h>
/**
* The following params expected:
* UsbCommand c
return 1;
}
+/*
+ Simple AES 128 cbc hook up to OpenSSL.
+ params: key, input
+*/
+static int l_aes(lua_State *L)
+{
+ //Check number of arguments
+ int i;
+ size_t size;
+ const char *p_key = luaL_checklstring(L, 1, &size);
+ if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size);
+
+ const char *p_encTxt = luaL_checklstring(L, 2, &size);
+
+ unsigned char indata[AES_BLOCK_SIZE] = {0x00};
+ unsigned char outdata[AES_BLOCK_SIZE] = {0x00};
+ unsigned char aes_key[AES_BLOCK_SIZE] = {0x00};
+ unsigned char iv[AES_BLOCK_SIZE] = {0x00};
+
+ // convert key to bytearray
+ for (i = 0; i < 32; i += 2) {
+ sscanf(&p_encTxt[i], "%02x", (unsigned int *)&indata[i / 2]);
+ }
+
+ // convert input to bytearray
+ for (i = 0; i < 32; i += 2) {
+ sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]);
+ }
+
+ AES_KEY key;
+ AES_set_decrypt_key(aes_key, 128, &key);
+ AES_cbc_encrypt(indata, outdata, sizeof(indata), &key, iv, AES_DECRYPT);
+
+ //Push decrypted array as a string
+ lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
+ return 1;// return 1 to signal one return value
+}
+
/**
* @brief Sets the lua path to include "./lualibs/?.lua", in order for a script to be
* able to do "require('foobar')" if foobar.lua is within lualibs folder.
{"foobar", l_foobar},
{"ukbhit", l_ukbhit},
{"clearCommandBuffer", l_clearCommandBuffer},
- {"console", l_CmdConsole},
- {"iso15693_crc", l_iso15693_crc},
+ {"console", l_CmdConsole},
+ {"iso15693_crc", l_iso15693_crc},
+ {"aes", l_aes},
{NULL, NULL}
};
typ = 0
elseif 0x10 == sak then-- "NXP MIFARE Plus 2k"
typ = 2
+ elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K"
+ typ = 1
else
print("I don't know how many sectors there are on this type of card, defaulting to 16")
end
--- /dev/null
+local cmds = require('commands')
+local getopt = require('getopt')
+local bin = require('bin')
+local lib14a = require('read14a')
+local utils = require('utils')
+local md5 = require('md5')
+
+example =[[
+ 1. script run tnp3
+ 2. script run tnp3 -k aabbccddeeff
+]]
+author = "Iceman"
+usage = "script run tnp3 -k <key>"
+desc =[[
+This script will try to dump the contents of a Mifare TNP3xxx card.
+It will need a valid KeyA in order to find the other keys and decode the card.
+Arguments:
+ -h - this help
+ -k <key> - Sector 0 Key A.
+]]
+
+local hashconstant = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
+
+local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
+local DEBUG = true -- the debug flag
+local numBlocks = 64
+local numSectors = 16
+---
+-- A debug printout-function
+function dbg(args)
+ if not DEBUG then
+ return
+ end
+
+ if type(args) == "table" then
+ local i = 1
+ while result[i] do
+ dbg(result[i])
+ i = i+1
+ end
+ else
+ print("###", args)
+ end
+end
+---
+-- This is only meant to be used when errors occur
+function oops(err)
+ print("ERROR: ",err)
+end
+---
+-- Usage help
+function help()
+ print(desc)
+ print("Example usage")
+ print(example)
+end
+--
+-- Exit message
+function ExitMsg(msg)
+ print( string.rep('--',20) )
+ print( string.rep('--',20) )
+ print(msg)
+ print()
+end
+
+local function show(data)
+ if DEBUG then
+ local formatString = ("H%d"):format(string.len(data))
+ local _,hexdata = bin.unpack(formatString, data)
+ dbg("Hexdata" , hexdata)
+ end
+end
+
+function waitCmd()
+ local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
+ if response then
+ local count,cmd,arg0 = bin.unpack('LL',response)
+ if(arg0==1) then
+ local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
+ return data:sub(1,32)
+ else
+ return nil, "Couldn't read block.."
+ end
+ end
+ return nil, "No response from device"
+end
+
+local function main(args)
+
+ print( string.rep('--',20) )
+ print( string.rep('--',20) )
+ print()
+
+ local keyA
+ local cmd
+ local err
+ local cmdReadBlockString = 'hf mf rdbl %d A %s'
+
+ -- Arguments for the script
+ for o, a in getopt.getopt(args, 'hk:') do
+ if o == "h" then return help() end
+ if o == "k" then keyA = a end
+ end
+
+ -- validate input args.
+ keyA = keyA or '4b0b20107ccb'
+ if #(keyA) ~= 12 then
+ return oops( string.format('Wrong length of write key (was %d) expected 12', #keyA))
+ end
+
+ result, err = lib14a.read1443a(false)
+ if not result then
+ print(err)
+ return
+ end
+ print((" Found tag : %s"):format(result.name))
+
+ core.clearCommandBuffer()
+
+ if 0x01 ~= result.sak then -- NXP MIFARE TNP3xxx
+ print("This is not a TNP3xxx tag. aborting.")
+ return
+ end
+
+ -- Show info
+ print(('Using keyA : %s'):format(keyA))
+ print( string.rep('--',20) )
+
+ local cmdNestedString = 'hf mf nested 1 0 A %s d'
+ local cmdDumpString = 'hf mf dump'
+ --core.console(cmdNestedString.format(keyA) )
+ --core.console(cmdDumpString)
+
+ print('Reading data need to dump data')
+
+ -- Read block 0
+ cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0,arg2 = 0,arg3 = 0, data = keyA}
+ err = core.SendCommand(cmd:getBytes())
+ if err then return oops(err) end
+ local block0, err = waitCmd()
+ if err then return oops(err) end
+
+ -- Read block 1
+ cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 1,arg2 = 0,arg3 = 0, data = keyA}
+ local err = core.SendCommand(cmd:getBytes())
+ if err then return oops(err) end
+ local block1, err = waitCmd()
+ if err then return oops(err) end
+
+
+ -- Read block 9
+ cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 9,arg2 = 0,arg3 = 0, data = '56f6313550f9'}
+ local err = core.SendCommand(cmd:getBytes())
+ if err then return oops(err) end
+ local block9, err = waitCmd()
+ if err then return oops(err) end
+
+ -- main loop
+ print('BLOCK MD5 DECRYPTED ASCII' )
+
+ for block=0,numBlocks-1,1 do
+
+ if math.fmod(block,4) then
+
+ end
+
+ local base = ('%s%s%02d%s'):format(block0, block1, block, hashconstant)
+ local md5hash = md5.sumhexa(base)
+ local aestest = core.aes(md5hash, block9 )
+
+ local _,hex = bin.unpack(("H%d"):format(16),aestest)
+
+
+ local hexascii = string.gsub(hex, '(%x%x)',
+ function(value)
+ return string.char(tonumber(value, 16))
+ end
+ )
+
+ print( block .. ' :: ' .. md5hash .. ' :: ' .. hex .. ' :: ' .. hexascii )
+
+ -- if core.ukbhit() then
+ -- print("aborted by user")
+ -- break
+ -- end
+ end
+end
+
+main(args)
\ No newline at end of file
#define PIO_PDR (AT91_CAST(AT91_REG *) 0x00000004) // (PIO_PDR) PIO Disable Register
#define PIO_PSR (AT91_CAST(AT91_REG *) 0x00000008) // (PIO_PSR) PIO Status Register
#define PIO_OER (AT91_CAST(AT91_REG *) 0x00000010) // (PIO_OER) Output Enable Register
-#define PIO_ODR (AT91_CAST(AT91_REG *) 0x00000014) // (PIO_ODR) Output Disable Registerr
+#define PIO_ODR (AT91_CAST(AT91_REG *) 0x00000014) // (PIO_ODR) Output Disable Register
#define PIO_OSR (AT91_CAST(AT91_REG *) 0x00000018) // (PIO_OSR) Output Status Register
#define PIO_IFER (AT91_CAST(AT91_REG *) 0x00000020) // (PIO_IFER) Input Filter Enable Register
#define PIO_IFDR (AT91_CAST(AT91_REG *) 0x00000024) // (PIO_IFDR) Input Filter Disable Register