Added a new function to read ISO14443-B ST Microelectronics SRI512 memory tags.

I have a problem with CRC though: sometimes it works, sometimes not, I have no
clue why, I must be doing something wrong with the CRC calculation routine...
This commit is contained in:
edouard@lafargue.name 2009-04-16 08:37:24 +00:00
parent 30f2a7d38f
commit fb25b48308
6 changed files with 192 additions and 64 deletions

View file

@ -612,6 +612,10 @@ void UsbPacketReceived(BYTE *packet, int len)
AcquireRawAdcSamplesIso14443(c->ext1); AcquireRawAdcSamplesIso14443(c->ext1);
break; break;
case CMD_READ_SRI512_TAG:
ReadSRI512Iso14443(c->ext1);
break;
case CMD_READER_ISO_14443a: case CMD_READER_ISO_14443a:
ReaderIso14443a(c->ext1); ReaderIso14443a(c->ext1);
break; break;

View file

@ -60,6 +60,7 @@ void SetAdcMuxFor(int whichGpio);
/// iso14443.h /// iso14443.h
void SimulateIso14443Tag(void); void SimulateIso14443Tag(void);
void AcquireRawAdcSamplesIso14443(DWORD parameter); void AcquireRawAdcSamplesIso14443(DWORD parameter);
void ReadSRI512Iso14443(DWORD parameter);
void SnoopIso14443(void); void SnoopIso14443(void);
/// iso14443a.h /// iso14443a.h

View file

@ -575,7 +575,7 @@ static BOOL Handle14443SamplesDemod(int ci, int cq)
return FALSE; return FALSE;
} }
static void GetSamplesFor14443Demod(BOOL weTx, int n) static void GetSamplesFor14443Demod(BOOL weTx, int n, BOOL quiet)
{ {
int max = 0; int max = 0;
BOOL gotFrame = FALSE; BOOL gotFrame = FALSE;
@ -649,7 +649,7 @@ static void GetSamplesFor14443Demod(BOOL weTx, int n)
} }
} }
PDC_CONTROL(SSC_BASE) = PDC_RX_DISABLE; PDC_CONTROL(SSC_BASE) = PDC_RX_DISABLE;
DbpIntegers(max, gotFrame, -1); if (!quiet) DbpIntegers(max, gotFrame, Demod.len);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -788,10 +788,11 @@ void CodeIso14443bAsReader(const BYTE *cmd, int len)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Read an ISO 14443 tag. We send it some set of commands, and record the // Read an ISO 14443 tag. We send it some set of commands, and record the
// responses. // responses.
// The command name is misleading, it actually decodes the reponse in HEX
// into the output buffer (read the result using hexsamples, not hisamples)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void AcquireRawAdcSamplesIso14443(DWORD parameter) void AcquireRawAdcSamplesIso14443(DWORD parameter)
{ {
// BYTE cmd1[] = { 0x05, 0x00, 0x00, 0x71, 0xff };
BYTE cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 }; BYTE cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 };
// Make sure that we start from off, since the tags are stateful; // Make sure that we start from off, since the tags are stateful;
@ -811,10 +812,118 @@ void AcquireRawAdcSamplesIso14443(DWORD parameter)
CodeIso14443bAsReader(cmd1, sizeof(cmd1)); CodeIso14443bAsReader(cmd1, sizeof(cmd1));
TransmitFor14443(); TransmitFor14443();
LED_A_ON(); LED_A_ON();
GetSamplesFor14443Demod(TRUE, 2000); GetSamplesFor14443Demod(TRUE, 2000, FALSE);
LED_A_OFF(); LED_A_OFF();
} }
//-----------------------------------------------------------------------------
// Read a SRI512 ISO 14443 tag.
//
// SRI512 tags are just simple memory tags, here we're looking at making a dump
// of the contents of the memory. No anticollision algorithm is done, we assume
// we have a single tag in the field.
//
// I tried to be systematic and check every answer of the tag, every CRC, etc...
//-----------------------------------------------------------------------------
void ReadSRI512Iso14443(DWORD parameter)
{
BYTE i = 0x00;
// Make sure that we start from off, since the tags are stateful;
// confusing things will happen if we don't reset them between reads.
LED_D_OFF();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelay(200);
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
FpgaSetupSsc();
// Now give it time to spin up.
FpgaWriteConfWord(
FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);
SpinDelay(200);
// First command: wake up the tag using the INITIATE command
BYTE cmd1[] = { 0x06, 0x00, 0x97, 0x5b};
CodeIso14443bAsReader(cmd1, sizeof(cmd1));
TransmitFor14443();
LED_A_ON();
GetSamplesFor14443Demod(TRUE, 2000,TRUE);
LED_A_OFF();
if (Demod.len == 0) {
DbpString("No response from tag");
return;
} else {
DbpString("Randomly generated UID from tag (+ 2 byte CRC):");
DbpIntegers(Demod.output[0], Demod.output[1],Demod.output[2]);
}
// There is a response, SELECT the uid
DbpString("Now SELECT tag:");
cmd1[0] = 0x0E; // 0x0E is SELECT
cmd1[1] = Demod.output[0];
ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);
CodeIso14443bAsReader(cmd1, sizeof(cmd1));
TransmitFor14443();
LED_A_ON();
GetSamplesFor14443Demod(TRUE, 2000,TRUE);
LED_A_OFF();
if (Demod.len != 3) {
DbpString("Expected 3 bytes from tag, got:");
DbpIntegers(Demod.len,0x0,0x0);
return;
}
// Check the CRC of the answer:
ComputeCrc14443(CRC_14443_B, Demod.output, 1 , &cmd1[2], &cmd1[3]);
if(cmd1[2] != Demod.output[1] || cmd1[3] != Demod.output[2]) {
DbpString("CRC Error reading select response.");
return;
}
// Check response from the tag: should be the same UID as the command we just sent:
if (cmd1[1] != Demod.output[0]) {
DbpString("Bad response to SELECT from Tag, aborting:");
DbpIntegers(cmd1[1],Demod.output[0],0x0);
return;
}
// Tag is now selected,
// loop to read all 16 blocks, address from 0 to 15
DbpString("Tag memory dump, block 0 to 15");
cmd1[0] = 0x08;
i = 0x00;
for (;;) {
if (i == 0x10) {
DbpString("System area block (0xff):");
i = 0xff;
}
cmd1[1] = i;
ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);
CodeIso14443bAsReader(cmd1, sizeof(cmd1));
TransmitFor14443();
LED_A_ON();
GetSamplesFor14443Demod(TRUE, 2000,TRUE);
LED_A_OFF();
if (Demod.len != 6) { // Check if we got an answer from the tag
DbpString("Expected 6 bytes from tag, got less...");
return;
}
// The check the CRC of the answer (use cmd1 as temporary variable):
ComputeCrc14443(CRC_14443_B, Demod.output, 4, &cmd1[2], &cmd1[3]);
if(cmd1[2] != Demod.output[4] || cmd1[3] != Demod.output[5]) {
DbpString("CRC Error reading block! - Below: expected, got, 0x0: ");
DbpIntegers( (cmd1[2]<<8)+cmd1[3], (Demod.output[4]<<8)+Demod.output[5],0);
// Do not return;, let's go on... (we should retry, maybe ?)
}
// Now print out the memory location:
DbpString("Address , Contents, CRC");
DbpIntegers(i, (Demod.output[0]<<24) + (Demod.output[1]<<16) + (Demod.output[2]<<8) + Demod.output[3], (Demod.output[4]<<8)+Demod.output[5]);
if (i == 0xff) {
break;
}
i++;
}
}
//============================================================================= //=============================================================================
// Finally, the `sniffer' combines elements from both the reader and // Finally, the `sniffer' combines elements from both the reader and
// simulated tag, to show both sides of the conversation. // simulated tag, to show both sides of the conversation.

View file

@ -51,6 +51,7 @@ typedef struct {
#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300 #define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300
#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443 0x0301 #define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443 0x0301
#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM 0x0302 #define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM 0x0302
#define CMD_READ_SRI512_TAG 0x0303
#define CMD_READER_ISO_15693 0x0310 // ## New command to act like a 15693 reader - greg #define CMD_READER_ISO_15693 0x0310 // ## New command to act like a 15693 reader - greg
#define CMD_SIMTAG_ISO_15693 0x0311 // ## New command to act like a 15693 reader - greg #define CMD_SIMTAG_ISO_15693 0x0311 // ## New command to act like a 15693 reader - greg

View file

@ -76,6 +76,19 @@ static void CmdHi14read(char *str)
SendCommand(&c, FALSE); SendCommand(&c, FALSE);
} }
/* New command to read the contents of a SRI512 tag
* SRI512 tags are ISO14443-B modulated memory tags,
* this command just dumps the contents of the memory/
*/
static void CmdSri512read(char *str)
{
UsbCommand c;
c.cmd = CMD_READ_SRI512_TAG;
c.ext1 = atoi(str);
SendCommand(&c, FALSE);
}
// ## New command // ## New command
static void CmdHi14areader(char *str) static void CmdHi14areader(char *str)
{ {
@ -1845,69 +1858,69 @@ static void CmdSweepLF(char *str)
} }
typedef void HandlerFunction(char *cmdline); typedef void HandlerFunction(char *cmdline);
static struct { static struct {
char *name; char *name;
HandlerFunction *handler; HandlerFunction *handler;
int offline; // 1 if the command can be used when in offline mode
char *docString; char *docString;
} CommandTable[] = { } CommandTable[] = {
"tune", CmdTune, "measure antenna tuning", "tune", CmdTune,0, "measure antenna tuning",
"tiread", CmdTiread, "read a TI-type 134 kHz tag", "tiread", CmdTiread,0, "read a TI-type 134 kHz tag",
"tibits", CmdTibits, "get raw bits for TI-type LF tag", "tibits", CmdTibits,0, "get raw bits for TI-type LF tag",
"tidemod", CmdTidemod, "demod raw bits for TI-type LF tag", "tidemod", CmdTidemod,0, "demod raw bits for TI-type LF tag",
"vchdemod", CmdVchdemod, "demod samples for VeriChip", "vchdemod", CmdVchdemod,0, "demod samples for VeriChip",
"plot", CmdPlot, "show graph window", "plot", CmdPlot,1, "show graph window",
"hide", CmdHide, "hide graph window", "hide", CmdHide,1, "hide graph window",
"losim", CmdLosim, "simulate LF tag", "losim", CmdLosim,0, "simulate LF tag",
"loread", CmdLoread, "read (125/134 kHz) LF ID-only tag", "loread", CmdLoread,0, "read (125/134 kHz) LF ID-only tag",
"losamples", CmdLosamples, "get raw samples for LF tag", "losamples", CmdLosamples,0, "get raw samples for LF tag",
"hisamples", CmdHisamples, "get raw samples for HF tag", "hisamples", CmdHisamples,0, "get raw samples for HF tag",
"hisampless", CmdHisampless, "get signed raw samples, HF tag", "hisampless", CmdHisampless,0, "get signed raw samples, HF tag",
"hisamplest", CmdHi14readt, "get samples HF, for testing", "hisamplest", CmdHi14readt,0, "get samples HF, for testing",
"higet", CmdHi14read_sim, "get samples HF, 'analog'", "higet", CmdHi14read_sim,0, "get samples HF, 'analog'",
"bitsamples", CmdBitsamples, "get raw samples as bitstring", "bitsamples", CmdBitsamples,0, "get raw samples as bitstring",
"hexsamples", CmdHexsamples, "dump big buffer as hex bytes", "hexsamples", CmdHexsamples,0, "dump big buffer as hex bytes",
"hi15read", CmdHi15read, "read HF tag (ISO 15693)", "hi15read", CmdHi15read,0, "read HF tag (ISO 15693)",
"hi15reader", CmdHi15reader, "act like an ISO15693 reader", // new command greg "hi15reader", CmdHi15reader,0, "act like an ISO15693 reader", // new command greg
"hi15sim", CmdHi15tag, "fake an ISO15693 tag", // new command greg "hi15sim", CmdHi15tag,0, "fake an ISO15693 tag", // new command greg
"hi14read", CmdHi14read, "read HF tag (ISO 14443)", "hi14read", CmdHi14read,0, "read HF tag (ISO 14443)",
"hi14areader", CmdHi14areader, "act like an ISO14443 Type A reader", // ## New reader command "sri512read", CmdSri512read,0, "Read contents of a SRI512 tag",
"hi15demod", CmdHi15demod, "demod ISO15693 from tag", "hi14areader", CmdHi14areader,0, "act like an ISO14443 Type A reader", // ## New reader command
"hi14bdemod", CmdHi14bdemod, "demod ISO14443 Type B from tag", "hi15demod", CmdHi15demod,1, "demod ISO15693 from tag",
"autocorr", CmdAutoCorr, "autocorrelation over window", "hi14bdemod", CmdHi14bdemod,1, "demod ISO14443 Type B from tag",
"norm", CmdNorm, "normalize max/min to +/-500", "autocorr", CmdAutoCorr,1, "autocorrelation over window",
"dec", CmdDec, "decimate", "norm", CmdNorm,1, "normalize max/min to +/-500",
"hpf", CmdHpf, "remove DC offset from trace", "dec", CmdDec,1, "decimate",
"zerocrossings", CmdZerocrossings, "count time between zero-crossings", "hpf", CmdHpf,1, "remove DC offset from trace",
"ltrim", CmdLtrim, "trim from left of trace", "zerocrossings", CmdZerocrossings,1, "count time between zero-crossings",
"scale", CmdScale, "set cursor display scale", "ltrim", CmdLtrim,1, "trim from left of trace",
"flexdemod", CmdFlexdemod, "demod samples for FlexPass", "scale", CmdScale,1, "set cursor display scale",
"indalademod", CmdIndalademod, "demod samples for Indala", "flexdemod", CmdFlexdemod,1, "demod samples for FlexPass",
"save", CmdSave, "save trace (from graph window)", "save", CmdSave,1, "save trace (from graph window)",
"load", CmdLoad, "load trace (to graph window", "load", CmdLoad,1, "load trace (to graph window",
"hisimlisten", CmdHisimlisten, "get HF samples as fake tag", "hisimlisten", CmdHisimlisten,0, "get HF samples as fake tag",
"hi14sim", CmdHi14sim, "fake ISO 14443 tag", "hi14sim", CmdHi14sim,0, "fake ISO 14443 tag",
"hi14asim", CmdHi14asim, "fake ISO 14443a tag", // ## Simulate 14443a tag "hi14asim", CmdHi14asim,0, "fake ISO 14443a tag", // ## Simulate 14443a tag
"hi14snoop", CmdHi14snoop, "eavesdrop ISO 14443", "hi14snoop", CmdHi14snoop,0, "eavesdrop ISO 14443",
"hi14asnoop", CmdHi14asnoop, "eavesdrop ISO 14443 Type A", // ## New snoop command "hi14asnoop", CmdHi14asnoop,0, "eavesdrop ISO 14443 Type A", // ## New snoop command
"hi14list", CmdHi14list, "list ISO 14443 history", "hi14list", CmdHi14list,0, "list ISO 14443 history",
"hi14alist", CmdHi14alist, "list ISO 14443a history", // ## New list command "hi14alist", CmdHi14alist,0, "list ISO 14443a history", // ## New list command
"hiddemod", CmdHiddemod, "HID Prox Card II (not optimal)", "hiddemod", CmdHiddemod,1, "HID Prox Card II (not optimal)",
"hidfskdemod", CmdHIDdemodFSK, "HID FSK demodulator", "hidfskdemod", CmdHIDdemodFSK,0, "HID FSK demodulator",
"askdemod", Cmdaskdemod, "Attempt to demodulate simple ASK tags", "askdemod", Cmdaskdemod,1, "Attempt to demodulate simple ASK tags",
"hidsimtag", CmdHIDsimTAG, "HID tag simulator", "hidsimtag", CmdHIDsimTAG,0, "HID tag simulator",
"mandemod", Cmdmanchesterdemod, "Try a Manchester demodulation on a binary stream", "mandemod", Cmdmanchesterdemod,1, "Try a Manchester demodulation on a binary stream",
"fpgaoff", CmdFPGAOff, "set FPGA off", // ## FPGA Control "fpgaoff", CmdFPGAOff,0, "set FPGA off", // ## FPGA Control
"lcdreset", CmdLcdReset, "Hardware reset LCD", "lcdreset", CmdLcdReset,0, "Hardware reset LCD",
"lcd", CmdLcd, "Send command/data to LCD", "lcd", CmdLcd,0, "Send command/data to LCD",
"test", CmdTest, "Placeholder command for testing new code", "setlfdivisor", CmdSetDivisor,0, "Drive LF antenna at 12Mhz/(divisor+1)",
"setlfdivisor", CmdSetDivisor, "Drive LF antenna at 12Mhz/(divisor+1)", "sweeplf", CmdSweepLF,0, "Sweep through LF freq range and store results in buffer",
"sweeplf", CmdSweepLF, "Sweep through LF freq range and store results in buffer", "quit", CmdQuit,0, "quit program"
"quit", CmdQuit, "quit program"
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Entry point into our code: called whenever the user types a command and // Entry point into our code: called whenever the user types a command and
// then presses Enter, which the full command line that they typed. // then presses Enter, which the full command line that they typed.