SRC_LF = lfops.c hitag2.c lfsampling.c
SRC_ISO15693 = iso15693.c iso15693tools.c
SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c
-SRC_ISO14443b = iso14443.c
+SRC_ISO14443b = iso14443b.c
SRC_CRAPTO1 = crapto1.c crypto1.c des.c aes.c
SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c
}
-void SimulateTagHfListen(void)
-{
- // ToDo: historically this used the free buffer, which was 2744 Bytes long.
- // There might be a better size to be defined:
- #define HF_14B_SNOOP_BUFFER_SIZE 2744
- uint8_t *dest = BigBuf_malloc(HF_14B_SNOOP_BUFFER_SIZE);
- uint8_t v = 0;
- int i;
- int p = 0;
-
- // We're using this mode just so that I can test it out; the simulated
- // tag mode would work just as well and be simpler.
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP);
-
- // We need to listen to the high-frequency, peak-detected path.
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
-
- FpgaSetupSsc();
-
- i = 0;
- for(;;) {
- if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = 0xff;
- }
- if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
- uint8_t r = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
-
- v <<= 1;
- if(r & 1) {
- v |= 1;
- }
- p++;
-
- if(p >= 8) {
- dest[i] = v;
- v = 0;
- p = 0;
- i++;
-
- if(i >= HF_14B_SNOOP_BUFFER_SIZE) {
- break;
- }
- }
- }
- }
- DbpString("simulate tag (now type bitsamples)");
-}
-
void ReadMem(int addr)
{
const uint8_t *data = ((uint8_t *)addr);
#endif
#ifdef WITH_ISO14443b
- case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443:
- AcquireRawAdcSamplesIso14443(c->arg[0]);
- break;
case CMD_READ_SRI512_TAG:
- ReadSTMemoryIso14443(0x0F);
+ ReadSTMemoryIso14443b(0x0F);
break;
case CMD_READ_SRIX4K_TAG:
- ReadSTMemoryIso14443(0x7F);
+ ReadSTMemoryIso14443b(0x7F);
break;
- case CMD_SNOOP_ISO_14443:
- SnoopIso14443();
+ case CMD_SNOOP_ISO_14443B:
+ SnoopIso14443b();
break;
- case CMD_SIMULATE_TAG_ISO_14443:
- SimulateIso14443Tag();
+ case CMD_SIMULATE_TAG_ISO_14443B:
+ SimulateIso14443bTag();
break;
case CMD_ISO_14443B_COMMAND:
SendRawCommand14443B(c->arg[0],c->arg[1],c->arg[2],c->d.asBytes);
break;
#endif
- case CMD_SIMULATE_TAG_HF_LISTEN:
- SimulateTagHfListen();
- break;
-
case CMD_BUFF_CLEAR:
BigBuf_Clear();
break;
void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode);
/// iso14443.h
-void SimulateIso14443Tag(void);
-void AcquireRawAdcSamplesIso14443(uint32_t parameter);
-void ReadSTMemoryIso14443(uint32_t);
-void RAMFUNC SnoopIso14443(void);
+void SimulateIso14443bTag(void);
+void AcquireRawAdcSamplesIso14443b(uint32_t parameter);
+void ReadSTMemoryIso14443b(uint32_t);
+void RAMFUNC SnoopIso14443b(void);
void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]);
/// iso14443a.h
+++ /dev/null
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, split Nov 2006
-//
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Routines to support ISO 14443. This includes both the reader software and
-// the `fake tag' modes. At the moment only the Type B modulation is
-// supported.
-//-----------------------------------------------------------------------------
-
-#include "proxmark3.h"
-#include "apps.h"
-#include "util.h"
-#include "string.h"
-
-#include "iso14443crc.h"
-
-//static void GetSamplesFor14443(int weTx, int n);
-
-/*#define DEMOD_TRACE_SIZE 4096
-#define READER_TAG_BUFFER_SIZE 2048
-#define TAG_READER_BUFFER_SIZE 2048
-#define DEMOD_DMA_BUFFER_SIZE 1024
-*/
-
-#define RECEIVE_SAMPLES_TIMEOUT 2000
-
-//=============================================================================
-// An ISO 14443 Type B tag. We listen for commands from the reader, using
-// a UART kind of thing that's implemented in software. When we get a
-// frame (i.e., a group of bytes between SOF and EOF), we check the CRC.
-// If it's good, then we can do something appropriate with it, and send
-// a response.
-//=============================================================================
-
-//-----------------------------------------------------------------------------
-// Code up a string of octets at layer 2 (including CRC, we don't generate
-// that here) so that they can be transmitted to the reader. Doesn't transmit
-// them yet, just leaves them ready to send in ToSend[].
-//-----------------------------------------------------------------------------
-static void CodeIso14443bAsTag(const uint8_t *cmd, int len)
-{
- int i;
-
- ToSendReset();
-
- // Transmit a burst of ones, as the initial thing that lets the
- // reader get phase sync. This (TR1) must be > 80/fs, per spec,
- // but tag that I've tried (a Paypass) exceeds that by a fair bit,
- // so I will too.
- for(i = 0; i < 20; i++) {
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- }
-
- // Send SOF.
- for(i = 0; i < 10; i++) {
- ToSendStuffBit(0);
- ToSendStuffBit(0);
- ToSendStuffBit(0);
- ToSendStuffBit(0);
- }
- for(i = 0; i < 2; i++) {
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- }
-
- for(i = 0; i < len; i++) {
- int j;
- uint8_t b = cmd[i];
-
- // Start bit
- ToSendStuffBit(0);
- ToSendStuffBit(0);
- ToSendStuffBit(0);
- ToSendStuffBit(0);
-
- // Data bits
- for(j = 0; j < 8; j++) {
- if(b & 1) {
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- } else {
- ToSendStuffBit(0);
- ToSendStuffBit(0);
- ToSendStuffBit(0);
- ToSendStuffBit(0);
- }
- b >>= 1;
- }
-
- // Stop bit
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- }
-
- // Send SOF.
- for(i = 0; i < 10; i++) {
- ToSendStuffBit(0);
- ToSendStuffBit(0);
- ToSendStuffBit(0);
- ToSendStuffBit(0);
- }
- for(i = 0; i < 10; i++) {
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- }
-
- // Convert from last byte pos to length
- ToSendMax++;
-
- // Add a few more for slop
- ToSendMax += 2;
-}
-
-//-----------------------------------------------------------------------------
-// The software UART that receives commands from the reader, and its state
-// variables.
-//-----------------------------------------------------------------------------
-static struct {
- enum {
- STATE_UNSYNCD,
- STATE_GOT_FALLING_EDGE_OF_SOF,
- STATE_AWAITING_START_BIT,
- STATE_RECEIVING_DATA,
- STATE_ERROR_WAIT
- } state;
- uint16_t shiftReg;
- int bitCnt;
- int byteCnt;
- int byteCntMax;
- int posCnt;
- uint8_t *output;
-} Uart;
-
-/* Receive & handle a bit coming from the reader.
- *
- * LED handling:
- * LED A -> ON once we have received the SOF and are expecting the rest.
- * LED A -> OFF once we have received EOF or are in error state or unsynced
- *
- * Returns: true if we received a EOF
- * false if we are still waiting for some more
- */
-static int Handle14443UartBit(int bit)
-{
- switch(Uart.state) {
- case STATE_UNSYNCD:
- LED_A_OFF();
- if(!bit) {
- // we went low, so this could be the beginning
- // of an SOF
- Uart.state = STATE_GOT_FALLING_EDGE_OF_SOF;
- Uart.posCnt = 0;
- Uart.bitCnt = 0;
- }
- break;
-
- case STATE_GOT_FALLING_EDGE_OF_SOF:
- Uart.posCnt++;
- if(Uart.posCnt == 2) {
- if(bit) {
- if(Uart.bitCnt >= 10) {
- // we've seen enough consecutive
- // zeros that it's a valid SOF
- Uart.posCnt = 0;
- Uart.byteCnt = 0;
- Uart.state = STATE_AWAITING_START_BIT;
- LED_A_ON(); // Indicate we got a valid SOF
- } else {
- // didn't stay down long enough
- // before going high, error
- Uart.state = STATE_ERROR_WAIT;
- }
- } else {
- // do nothing, keep waiting
- }
- Uart.bitCnt++;
- }
- if(Uart.posCnt >= 4) Uart.posCnt = 0;
- if(Uart.bitCnt > 14) {
- // Give up if we see too many zeros without
- // a one, too.
- Uart.state = STATE_ERROR_WAIT;
- }
- break;
-
- case STATE_AWAITING_START_BIT:
- Uart.posCnt++;
- if(bit) {
- if(Uart.posCnt > 25) {
- // stayed high for too long between
- // characters, error
- Uart.state = STATE_ERROR_WAIT;
- }
- } else {
- // falling edge, this starts the data byte
- Uart.posCnt = 0;
- Uart.bitCnt = 0;
- Uart.shiftReg = 0;
- Uart.state = STATE_RECEIVING_DATA;
- LED_A_ON(); // Indicate we're receiving
- }
- break;
-
- case STATE_RECEIVING_DATA:
- Uart.posCnt++;
- if(Uart.posCnt == 2) {
- // time to sample a bit
- Uart.shiftReg >>= 1;
- if(bit) {
- Uart.shiftReg |= 0x200;
- }
- Uart.bitCnt++;
- }
- if(Uart.posCnt >= 4) {
- Uart.posCnt = 0;
- }
- if(Uart.bitCnt == 10) {
- if((Uart.shiftReg & 0x200) && !(Uart.shiftReg & 0x001))
- {
- // this is a data byte, with correct
- // start and stop bits
- Uart.output[Uart.byteCnt] = (Uart.shiftReg >> 1) & 0xff;
- Uart.byteCnt++;
-
- if(Uart.byteCnt >= Uart.byteCntMax) {
- // Buffer overflowed, give up
- Uart.posCnt = 0;
- Uart.state = STATE_ERROR_WAIT;
- } else {
- // so get the next byte now
- Uart.posCnt = 0;
- Uart.state = STATE_AWAITING_START_BIT;
- }
- } else if(Uart.shiftReg == 0x000) {
- // this is an EOF byte
- LED_A_OFF(); // Finished receiving
- return TRUE;
- } else {
- // this is an error
- Uart.posCnt = 0;
- Uart.state = STATE_ERROR_WAIT;
- }
- }
- break;
-
- case STATE_ERROR_WAIT:
- // We're all screwed up, so wait a little while
- // for whatever went wrong to finish, and then
- // start over.
- Uart.posCnt++;
- if(Uart.posCnt > 10) {
- Uart.state = STATE_UNSYNCD;
- }
- break;
-
- default:
- Uart.state = STATE_UNSYNCD;
- break;
- }
-
- // This row make the error blew circular buffer in hf 14b snoop
- //if (Uart.state == STATE_ERROR_WAIT) LED_A_OFF(); // Error
-
- return FALSE;
-}
-
-//-----------------------------------------------------------------------------
-// Receive a command (from the reader to us, where we are the simulated tag),
-// and store it in the given buffer, up to the given maximum length. Keeps
-// spinning, waiting for a well-framed command, until either we get one
-// (returns TRUE) or someone presses the pushbutton on the board (FALSE).
-//
-// Assume that we're called with the SSC (to the FPGA) and ADC path set
-// correctly.
-//-----------------------------------------------------------------------------
-static int GetIso14443CommandFromReader(uint8_t *received, int *len, int maxLen)
-{
- uint8_t mask;
- int i, bit;
-
- // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen
- // only, since we are receiving, not transmitting).
- // Signal field is off with the appropriate LED
- LED_D_OFF();
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION);
-
-
- // Now run a `software UART' on the stream of incoming samples.
- Uart.output = received;
- Uart.byteCntMax = maxLen;
- Uart.state = STATE_UNSYNCD;
-
- for(;;) {
- WDT_HIT();
-
- if(BUTTON_PRESS()) return FALSE;
-
- if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = 0x00;
- }
- if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
- uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
-
- mask = 0x80;
- for(i = 0; i < 8; i++, mask >>= 1) {
- bit = (b & mask);
- if(Handle14443UartBit(bit)) {
- *len = Uart.byteCnt;
- return TRUE;
- }
- }
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Main loop of simulated tag: receive commands from reader, decide what
-// response to send, and send it.
-//-----------------------------------------------------------------------------
-void SimulateIso14443Tag(void)
-{
- static const uint8_t cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 };
- static const uint8_t response1[] = {
- 0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19, 0x22,
- 0x00, 0x21, 0x85, 0x5e, 0xd7
- };
-
- uint8_t *resp;
- int respLen;
-
- uint8_t *resp1 = BigBuf_get_addr() + 800;
- int resp1Len;
-
- uint8_t *receivedCmd = BigBuf_get_addr();
- int len;
-
- int i;
-
- int cmdsRecvd = 0;
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
- memset(receivedCmd, 0x44, 400);
-
- CodeIso14443bAsTag(response1, sizeof(response1));
- memcpy(resp1, ToSend, ToSendMax); resp1Len = ToSendMax;
-
- // We need to listen to the high-frequency, peak-detected path.
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
- FpgaSetupSsc();
-
- cmdsRecvd = 0;
-
- for(;;) {
- uint8_t b1, b2;
-
- if(!GetIso14443CommandFromReader(receivedCmd, &len, 100)) {
- Dbprintf("button pressed, received %d commands", cmdsRecvd);
- break;
- }
-
- // Good, look at the command now.
-
- if(len == sizeof(cmd1) && memcmp(receivedCmd, cmd1, len)==0) {
- resp = resp1; respLen = resp1Len;
- } else {
- Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsRecvd);
- // And print whether the CRC fails, just for good measure
- ComputeCrc14443(CRC_14443_B, receivedCmd, len-2, &b1, &b2);
- if(b1 != receivedCmd[len-2] || b2 != receivedCmd[len-1]) {
- // Not so good, try again.
- DbpString("+++CRC fail");
- } else {
- DbpString("CRC passes");
- }
- break;
- }
-
- memset(receivedCmd, 0x44, 32);
-
- cmdsRecvd++;
-
- if(cmdsRecvd > 0x30) {
- DbpString("many commands later...");
- break;
- }
-
- if(respLen <= 0) continue;
-
- // Modulate BPSK
- // Signal field is off with the appropriate LED
- LED_D_OFF();
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK);
- AT91C_BASE_SSC->SSC_THR = 0xff;
- FpgaSetupSsc();
-
- // Transmit the response.
- i = 0;
- for(;;) {
- if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- uint8_t b = resp[i];
-
- AT91C_BASE_SSC->SSC_THR = b;
-
- i++;
- if(i > respLen) {
- break;
- }
- }
- if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
- volatile uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- (void)b;
- }
- }
- }
-}
-
-//=============================================================================
-// An ISO 14443 Type B reader. We take layer two commands, code them
-// appropriately, and then send them to the tag. We then listen for the
-// tag's response, which we leave in the buffer to be demodulated on the
-// PC side.
-//=============================================================================
-
-static struct {
- enum {
- DEMOD_UNSYNCD,
- DEMOD_PHASE_REF_TRAINING,
- DEMOD_AWAITING_FALLING_EDGE_OF_SOF,
- DEMOD_GOT_FALLING_EDGE_OF_SOF,
- DEMOD_AWAITING_START_BIT,
- DEMOD_RECEIVING_DATA,
- DEMOD_ERROR_WAIT
- } state;
- int bitCount;
- int posCount;
- int thisBit;
- int metric;
- int metricN;
- uint16_t shiftReg;
- uint8_t *output;
- int len;
- int sumI;
- int sumQ;
-} Demod;
-
-/*
- * Handles reception of a bit from the tag
- *
- * LED handling:
- * LED C -> ON once we have received the SOF and are expecting the rest.
- * LED C -> OFF once we have received EOF or are unsynced
- *
- * Returns: true if we received a EOF
- * false if we are still waiting for some more
- *
- */
-static RAMFUNC int Handle14443SamplesDemod(int ci, int cq)
-{
- int v;
-
- // The soft decision on the bit uses an estimate of just the
- // quadrant of the reference angle, not the exact angle.
-#define MAKE_SOFT_DECISION() { \
- if(Demod.sumI > 0) { \
- v = ci; \
- } else { \
- v = -ci; \
- } \
- if(Demod.sumQ > 0) { \
- v += cq; \
- } else { \
- v -= cq; \
- } \
- }
-
- switch(Demod.state) {
- case DEMOD_UNSYNCD:
- v = ci;
- if(v < 0) v = -v;
- if(cq > 0) {
- v += cq;
- } else {
- v -= cq;
- }
- if(v > 40) {
- Demod.posCount = 0;
- Demod.state = DEMOD_PHASE_REF_TRAINING;
- Demod.sumI = 0;
- Demod.sumQ = 0;
- }
- break;
-
- case DEMOD_PHASE_REF_TRAINING:
- if(Demod.posCount < 8) {
- Demod.sumI += ci;
- Demod.sumQ += cq;
- } else if(Demod.posCount > 100) {
- // error, waited too long
- Demod.state = DEMOD_UNSYNCD;
- } else {
- MAKE_SOFT_DECISION();
- if(v < 0) {
- Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF;
- Demod.posCount = 0;
- }
- }
- Demod.posCount++;
- break;
-
- case DEMOD_AWAITING_FALLING_EDGE_OF_SOF:
- MAKE_SOFT_DECISION();
- if(v < 0) {
- Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF;
- Demod.posCount = 0;
- } else {
- if(Demod.posCount > 100) {
- Demod.state = DEMOD_UNSYNCD;
- }
- }
- Demod.posCount++;
- break;
-
- case DEMOD_GOT_FALLING_EDGE_OF_SOF:
- MAKE_SOFT_DECISION();
- if(v > 0) {
- if(Demod.posCount < 12) {
- Demod.state = DEMOD_UNSYNCD;
- } else {
- LED_C_ON(); // Got SOF
- Demod.state = DEMOD_AWAITING_START_BIT;
- Demod.posCount = 0;
- Demod.len = 0;
- Demod.metricN = 0;
- Demod.metric = 0;
- }
- } else {
- if(Demod.posCount > 100) {
- Demod.state = DEMOD_UNSYNCD;
- }
- }
- Demod.posCount++;
- break;
-
- case DEMOD_AWAITING_START_BIT:
- MAKE_SOFT_DECISION();
- if(v > 0) {
- if(Demod.posCount > 10) {
- Demod.state = DEMOD_UNSYNCD;
- }
- } else {
- Demod.bitCount = 0;
- Demod.posCount = 1;
- Demod.thisBit = v;
- Demod.shiftReg = 0;
- Demod.state = DEMOD_RECEIVING_DATA;
- }
- break;
-
- case DEMOD_RECEIVING_DATA:
- MAKE_SOFT_DECISION();
- if(Demod.posCount == 0) {
- Demod.thisBit = v;
- Demod.posCount = 1;
- } else {
- Demod.thisBit += v;
-
- if(Demod.thisBit > 0) {
- Demod.metric += Demod.thisBit;
- } else {
- Demod.metric -= Demod.thisBit;
- }
- (Demod.metricN)++;
-
- Demod.shiftReg >>= 1;
- if(Demod.thisBit > 0) {
- Demod.shiftReg |= 0x200;
- }
-
- Demod.bitCount++;
- if(Demod.bitCount == 10) {
- uint16_t s = Demod.shiftReg;
- if((s & 0x200) && !(s & 0x001)) {
- uint8_t b = (s >> 1);
- Demod.output[Demod.len] = b;
- Demod.len++;
- Demod.state = DEMOD_AWAITING_START_BIT;
- } else if(s == 0x000) {
- // This is EOF
- LED_C_OFF();
- Demod.state = DEMOD_UNSYNCD;
- return TRUE;
- } else {
- Demod.state = DEMOD_UNSYNCD;
- }
- }
- Demod.posCount = 0;
- }
- break;
-
- default:
- Demod.state = DEMOD_UNSYNCD;
- break;
- }
-
- if (Demod.state == DEMOD_UNSYNCD) LED_C_OFF(); // Not synchronized...
- return FALSE;
-}
-static void DemodReset()
-{
- // Clear out the state of the "UART" that receives from the tag.
- Demod.len = 0;
- Demod.state = DEMOD_UNSYNCD;
- memset(Demod.output, 0x00, MAX_FRAME_SIZE);
-}
-static void DemodInit(uint8_t *data)
-{
- Demod.output = data;
- DemodReset();
-}
-
-static void UartReset()
-{
- Uart.byteCntMax = MAX_FRAME_SIZE;
- Uart.state = STATE_UNSYNCD;
- Uart.byteCnt = 0;
- Uart.bitCnt = 0;
-}
-static void UartInit(uint8_t *data)
-{
- Uart.output = data;
- UartReset();
-}
-
-/*
- * Demodulate the samples we received from the tag, also log to tracebuffer
- * weTx: set to 'TRUE' if we behave like a reader
- * set to 'FALSE' if we behave like a snooper
- * quiet: set to 'TRUE' to disable debug output
- */
-static void GetSamplesFor14443Demod(int weTx, int n, int quiet)
-{
- int max = 0;
- int gotFrame = FALSE;
- int lastRxCounter, ci, cq, samples = 0;
-
- // Allocate memory from BigBuf for some buffers
- // free all previous allocations first
- BigBuf_free();
-
- // The response (tag -> reader) that we're receiving.
- uint8_t *receivedResponse = BigBuf_malloc(MAX_FRAME_SIZE);
-
- // The DMA buffer, used to stream samples from the FPGA
- uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
-
- // Set up the demodulator for tag -> reader responses.
- DemodInit(receivedResponse);
-
- // Setup and start DMA.
- FpgaSetupSscDma(dmaBuf, DMA_BUFFER_SIZE);
-
- uint8_t *upTo= dmaBuf;
- lastRxCounter = DMA_BUFFER_SIZE;
-
- // Signal field is ON with the appropriate LED:
- if (weTx) LED_D_ON(); else LED_D_OFF();
- // And put the FPGA in the appropriate mode
- FpgaWriteConfWord(
- FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |
- (weTx ? 0 : FPGA_HF_READER_RX_XCORR_SNOOP));
-
- for(;;) {
- int behindBy = lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR;
- if(behindBy > max) max = behindBy;
-
- while(((lastRxCounter-AT91C_BASE_PDC_SSC->PDC_RCR) & (DMA_BUFFER_SIZE-1))
- > 2)
- {
- ci = upTo[0];
- cq = upTo[1];
- upTo += 2;
- if(upTo >= dmaBuf + DMA_BUFFER_SIZE) {
- upTo = dmaBuf;
- AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo;
- AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
- }
- lastRxCounter -= 2;
- if(lastRxCounter <= 0) {
- lastRxCounter += DMA_BUFFER_SIZE;
- }
-
- samples += 2;
-
- if(Handle14443SamplesDemod(ci, cq)) {
- gotFrame = 1;
- }
- }
-
- if(samples > n) {
- break;
- }
- }
- AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
- if (!quiet) Dbprintf("%x %x %x", max, gotFrame, Demod.len);
- //Tracing
- if (tracing && Demod.len > 0) {
- uint8_t parity[MAX_PARITY_SIZE];
- GetParity(Demod.output, Demod.len, parity);
- LogTrace(Demod.output, Demod.len, 0, 0, parity, FALSE);
- }
-}
-
-//-----------------------------------------------------------------------------
-// Read the tag's response. We just receive a stream of slightly-processed
-// samples from the FPGA, which we will later do some signal processing on,
-// to get the bits.
-//-----------------------------------------------------------------------------
-/*static void GetSamplesFor14443(int weTx, int n)
-{
- uint8_t *dest = (uint8_t *)BigBuf;
- int c;
-
- FpgaWriteConfWord(
- FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |
- (weTx ? 0 : FPGA_HF_READER_RX_XCORR_SNOOP));
-
- c = 0;
- for(;;) {
- if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- 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;
-
- dest[c++] = (uint8_t)b;
-
- if(c >= n) {
- break;
- }
- }
- }
-}*/
-
-//-----------------------------------------------------------------------------
-// Transmit the command (to the tag) that was placed in ToSend[].
-//-----------------------------------------------------------------------------
-static void TransmitFor14443(void)
-{
- int c;
-
- FpgaSetupSsc();
-
- while(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = 0xff;
- }
-
- // Signal field is ON with the appropriate Red LED
- LED_D_ON();
- // Signal we are transmitting with the Green LED
- LED_B_ON();
- FpgaWriteConfWord(
- FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);
-
- for(c = 0; c < 10;) {
- if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = 0xff;
- c++;
- }
- if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
- volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
- (void)r;
- }
- WDT_HIT();
- }
-
- c = 0;
- for(;;) {
- if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = ToSend[c];
- c++;
- if(c >= ToSendMax) {
- break;
- }
- }
- if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
- volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
- (void)r;
- }
- WDT_HIT();
- }
- LED_B_OFF(); // Finished sending
-}
-
-//-----------------------------------------------------------------------------
-// Code a layer 2 command (string of octets, including CRC) into ToSend[],
-// so that it is ready to transmit to the tag using TransmitFor14443().
-//-----------------------------------------------------------------------------
-static void CodeIso14443bAsReader(const uint8_t *cmd, int len)
-{
- int i, j;
- uint8_t b;
-
- ToSendReset();
-
- // Establish initial reference level
- for(i = 0; i < 40; i++) {
- ToSendStuffBit(1);
- }
- // Send SOF
- for(i = 0; i < 10; i++) {
- ToSendStuffBit(0);
- }
-
- for(i = 0; i < len; i++) {
- // Stop bits/EGT
- ToSendStuffBit(1);
- ToSendStuffBit(1);
- // Start bit
- ToSendStuffBit(0);
- // Data bits
- b = cmd[i];
- for(j = 0; j < 8; j++) {
- if(b & 1) {
- ToSendStuffBit(1);
- } else {
- ToSendStuffBit(0);
- }
- b >>= 1;
- }
- }
- // Send EOF
- ToSendStuffBit(1);
- for(i = 0; i < 10; i++) {
- ToSendStuffBit(0);
- }
- for(i = 0; i < 8; i++) {
- ToSendStuffBit(1);
- }
-
- // And then a little more, to make sure that the last character makes
- // it out before we switch to rx mode.
- for(i = 0; i < 24; i++) {
- ToSendStuffBit(1);
- }
-
- // Convert from last character reference to length
- ToSendMax++;
-}
-
-//-----------------------------------------------------------------------------
-// Read an ISO 14443 tag. We send it some set of commands, and record the
-// responses.
-// The command name is misleading, it actually decodes the reponse in HEX
-// into the output buffer (read the result using hexsamples, not hisamples)
-//
-// obsolete function only for test
-//-----------------------------------------------------------------------------
-void AcquireRawAdcSamplesIso14443(uint32_t parameter)
-{
- uint8_t cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 };
-
- SendRawCommand14443B(sizeof(cmd1),1,1,cmd1);
-}
-
-/**
- Convenience function to encode, transmit and trace iso 14443b comms
- **/
-static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len)
-{
- CodeIso14443bAsReader(cmd, len);
- TransmitFor14443();
- if (tracing) {
- uint8_t parity[MAX_PARITY_SIZE];
- GetParity(cmd, len, parity);
- LogTrace(cmd,len, 0, 0, parity, TRUE);
- }
-}
-
-//-----------------------------------------------------------------------------
-// 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 ReadSTMemoryIso14443(uint32_t dwLast)
-{
- clear_trace();
- set_tracing(TRUE);
-
- uint8_t i = 0x00;
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
- // 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.
- // Signal field is on with the appropriate LED
- LED_D_ON();
- 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
- uint8_t cmd1[] = { 0x06, 0x00, 0x97, 0x5b};
-
- CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
-// LED_A_ON();
- GetSamplesFor14443Demod(TRUE, RECEIVE_SAMPLES_TIMEOUT, TRUE);
-// LED_A_OFF();
-
- if (Demod.len == 0) {
- DbpString("No response from tag");
- return;
- } else {
- Dbprintf("Randomly generated UID from tag (+ 2 byte CRC): %x %x %x",
- 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]);
- CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
-
-// LED_A_ON();
- GetSamplesFor14443Demod(TRUE, RECEIVE_SAMPLES_TIMEOUT, TRUE);
-// LED_A_OFF();
- if (Demod.len != 3) {
- Dbprintf("Expected 3 bytes from tag, got %d", Demod.len);
- 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]) {
- Dbprintf("Bad response to SELECT from Tag, aborting: %x %x", cmd1[1], Demod.output[0]);
- return;
- }
- // Tag is now selected,
- // First get the tag's UID:
- cmd1[0] = 0x0B;
- ComputeCrc14443(CRC_14443_B, cmd1, 1 , &cmd1[1], &cmd1[2]);
- CodeAndTransmit14443bAsReader(cmd1, 3); // Only first three bytes for this one
-
-// LED_A_ON();
- GetSamplesFor14443Demod(TRUE, RECEIVE_SAMPLES_TIMEOUT, TRUE);
-// LED_A_OFF();
- if (Demod.len != 10) {
- Dbprintf("Expected 10 bytes from tag, got %d", Demod.len);
- return;
- }
- // The check the CRC of the answer (use cmd1 as temporary variable):
- ComputeCrc14443(CRC_14443_B, Demod.output, 8, &cmd1[2], &cmd1[3]);
- if(cmd1[2] != Demod.output[8] || cmd1[3] != Demod.output[9]) {
- Dbprintf("CRC Error reading block! - Below: expected, got %x %x",
- (cmd1[2]<<8)+cmd1[3], (Demod.output[8]<<8)+Demod.output[9]);
- // Do not return;, let's go on... (we should retry, maybe ?)
- }
- Dbprintf("Tag UID (64 bits): %08x %08x",
- (Demod.output[7]<<24) + (Demod.output[6]<<16) + (Demod.output[5]<<8) + Demod.output[4],
- (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0]);
-
- // Now loop to read all 16 blocks, address from 0 to last block
- Dbprintf("Tag memory dump, block 0 to %d",dwLast);
- cmd1[0] = 0x08;
- i = 0x00;
- dwLast++;
- for (;;) {
- if (i == dwLast) {
- DbpString("System area block (0xff):");
- i = 0xff;
- }
- cmd1[1] = i;
- ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);
- CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
-
-// LED_A_ON();
- GetSamplesFor14443Demod(TRUE, RECEIVE_SAMPLES_TIMEOUT, 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]) {
- Dbprintf("CRC Error reading block! - Below: expected, got %x %x",
- (cmd1[2]<<8)+cmd1[3], (Demod.output[4]<<8)+Demod.output[5]);
- // Do not return;, let's go on... (we should retry, maybe ?)
- }
- // Now print out the memory location:
- Dbprintf("Address=%x, Contents=%x, CRC=%x", i,
- (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0],
- (Demod.output[4]<<8)+Demod.output[5]);
- if (i == 0xff) {
- break;
- }
- i++;
- }
-}
-
-
-//=============================================================================
-// Finally, the `sniffer' combines elements from both the reader and
-// simulated tag, to show both sides of the conversation.
-//=============================================================================
-
-//-----------------------------------------------------------------------------
-// Record the sequence of commands sent by the reader to the tag, with
-// triggering so that we start recording at the point that the tag is moved
-// near the reader.
-//-----------------------------------------------------------------------------
-/*
- * Memory usage for this function, (within BigBuf)
- * 0-4095 : Demodulated samples receive (4096 bytes) - DEMOD_TRACE_SIZE
- * 4096-6143 : Last Received command, 2048 bytes (reader->tag) - READER_TAG_BUFFER_SIZE
- * 6144-8191 : Last Received command, 2048 bytes(tag->reader) - TAG_READER_BUFFER_SIZE
- * 8192-9215 : DMA Buffer, 1024 bytes (samples) - DEMOD_DMA_BUFFER_SIZE
- */
-void RAMFUNC SnoopIso14443(void)
-{
- // 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
- // response from the tag.
- int triggered = TRUE;
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
- BigBuf_free();
-
- clear_trace();
- set_tracing(TRUE);
-
- // The DMA buffer, used to stream samples from the FPGA
- uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
- int lastRxCounter;
- uint8_t *upTo;
- int ci, cq;
- int maxBehindBy = 0;
-
- // Count of samples received so far, so that we can include timing
- // information in the trace buffer.
- int samples = 0;
-
- DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
- UartInit(BigBuf_malloc(MAX_FRAME_SIZE));
-
- // Print some debug information about the buffer sizes
- Dbprintf("Snooping buffers initialized:");
- Dbprintf(" Trace: %i bytes", BigBuf_max_traceLen());
- Dbprintf(" Reader -> tag: %i bytes", MAX_FRAME_SIZE);
- Dbprintf(" tag -> Reader: %i bytes", MAX_FRAME_SIZE);
- Dbprintf(" DMA: %i bytes", DMA_BUFFER_SIZE);
-
- // Signal field is off with the appropriate LED
- LED_D_OFF();
-
- // And put the FPGA in the appropriate mode
- FpgaWriteConfWord(
- FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |
- FPGA_HF_READER_RX_XCORR_SNOOP);
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
-
- // Setup for the DMA.
- FpgaSetupSsc();
- upTo = dmaBuf;
- lastRxCounter = DMA_BUFFER_SIZE;
- FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE);
- uint8_t parity[MAX_PARITY_SIZE];
- LED_A_ON();
-
- // And now we loop, receiving samples.
- for(;;) {
- int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) &
- (DMA_BUFFER_SIZE-1);
- if(behindBy > maxBehindBy) {
- maxBehindBy = behindBy;
- if(behindBy > (9*DMA_BUFFER_SIZE/10)) { // TODO: understand whether we can increase/decrease as we want or not?
- Dbprintf("blew circular buffer! behindBy=0x%x", behindBy);
- break;
- }
- }
- if(behindBy < 2) continue;
-
- ci = upTo[0];
- cq = upTo[1];
- upTo += 2;
- lastRxCounter -= 2;
- if(upTo >= dmaBuf + DMA_BUFFER_SIZE) {
- upTo = dmaBuf;
- lastRxCounter += DMA_BUFFER_SIZE;
- AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf;
- AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
- }
-
- samples += 2;
-
- if(Handle14443UartBit(ci & 1)) {
- if(triggered && tracing) {
- GetParity(Uart.output, Uart.byteCnt, parity);
- LogTrace(Uart.output,Uart.byteCnt,samples, samples,parity,TRUE);
- }
- if(Uart.byteCnt==0) Dbprintf("[1] Error, Uart.byteCnt==0, Uart.bitCnt=%d", Uart.bitCnt);
-
- /* And ready to receive another command. */
- UartReset();
- /* And also reset the demod code, which might have been */
- /* false-triggered by the commands from the reader. */
- DemodReset();
- }
- if(Handle14443UartBit(cq & 1)) {
- if(triggered && tracing) {
- GetParity(Uart.output, Uart.byteCnt, parity);
- LogTrace(Uart.output,Uart.byteCnt,samples, samples,parity,TRUE);
- }
- if(Uart.byteCnt==0) Dbprintf("[2] Error, Uart.byteCnt==0, Uart.bitCnt=%d", Uart.bitCnt);
-
- /* And ready to receive another command. */
- UartReset();
- /* And also reset the demod code, which might have been */
- /* false-triggered by the commands from the reader. */
- DemodReset();
- }
-
- if(Handle14443SamplesDemod(ci, cq)) {
-
- //Use samples as a time measurement
- if(tracing)
- {
- uint8_t parity[MAX_PARITY_SIZE];
- GetParity(Demod.output, Demod.len, parity);
- LogTrace(Demod.output,Demod.len,samples, samples,parity,FALSE);
- }
- triggered = TRUE;
- LED_A_OFF();
- LED_B_ON();
-
- // And ready to receive another response.
- DemodReset();
- }
- WDT_HIT();
-
- if(!tracing) {
- DbpString("Reached trace limit");
- break;
- }
-
- if(BUTTON_PRESS()) {
- DbpString("cancelled");
- break;
- }
- }
- FpgaDisableSscDma();
- LED_A_OFF();
- LED_B_OFF();
- LED_C_OFF();
- AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
- DbpString("Snoop statistics:");
- Dbprintf(" Max behind by: %i", maxBehindBy);
- Dbprintf(" Uart State: %x", Uart.state);
- Dbprintf(" Uart ByteCnt: %i", Uart.byteCnt);
- Dbprintf(" Uart ByteCntMax: %i", Uart.byteCntMax);
- Dbprintf(" Trace length: %i", BigBuf_get_traceLen());
-}
-
-/*
- * Send raw command to tag ISO14443B
- * @Input
- * datalen len of buffer data
- * recv bool when true wait for data from tag and send to client
- * powerfield bool leave the field on when true
- * data buffer with byte to send
- *
- * @Output
- * none
- *
- */
-
-void SendRawCommand14443B(uint32_t datalen, uint32_t recv,uint8_t powerfield, uint8_t data[])
-{
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
- if(!powerfield)
- {
- // Make sure that we start from off, since the tags are stateful;
- // confusing things will happen if we don't reset them between reads.
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LED_D_OFF();
- SpinDelay(200);
- }
-
- if(!GETBIT(GPIO_LED_D))
- {
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
- FpgaSetupSsc();
-
- // Now give it time to spin up.
- // Signal field is on with the appropriate LED
- LED_D_ON();
- FpgaWriteConfWord(
- FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);
- SpinDelay(200);
- }
-
- CodeAndTransmit14443bAsReader(data, datalen);
-
- if(recv)
- {
- GetSamplesFor14443Demod(TRUE, RECEIVE_SAMPLES_TIMEOUT, TRUE);
- uint16_t iLen = MIN(Demod.len,USB_CMD_DATA_SIZE);
- cmd_send(CMD_ACK,iLen,0,0,Demod.output,iLen);
- }
- if(!powerfield)
- {
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LED_D_OFF();
- }
-}
-
--- /dev/null
+//-----------------------------------------------------------------------------
+// Jonathan Westhues, split Nov 2006
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// Routines to support ISO 14443B. This includes both the reader software and
+// the `fake tag' modes.
+//-----------------------------------------------------------------------------
+
+#include "proxmark3.h"
+#include "apps.h"
+#include "util.h"
+#include "string.h"
+
+#include "iso14443crc.h"
+
+#define RECEIVE_SAMPLES_TIMEOUT 2000
+#define ISO14443B_DMA_BUFFER_SIZE 256
+
+//=============================================================================
+// An ISO 14443 Type B tag. We listen for commands from the reader, using
+// a UART kind of thing that's implemented in software. When we get a
+// frame (i.e., a group of bytes between SOF and EOF), we check the CRC.
+// If it's good, then we can do something appropriate with it, and send
+// a response.
+//=============================================================================
+
+//-----------------------------------------------------------------------------
+// Code up a string of octets at layer 2 (including CRC, we don't generate
+// that here) so that they can be transmitted to the reader. Doesn't transmit
+// them yet, just leaves them ready to send in ToSend[].
+//-----------------------------------------------------------------------------
+static void CodeIso14443bAsTag(const uint8_t *cmd, int len)
+{
+ int i;
+
+ ToSendReset();
+
+ // Transmit a burst of ones, as the initial thing that lets the
+ // reader get phase sync. This (TR1) must be > 80/fs, per spec,
+ // but tag that I've tried (a Paypass) exceeds that by a fair bit,
+ // so I will too.
+ for(i = 0; i < 20; i++) {
+ ToSendStuffBit(1);
+ ToSendStuffBit(1);
+ ToSendStuffBit(1);
+ ToSendStuffBit(1);
+ }
+
+ // Send SOF.
+ for(i = 0; i < 10; i++) {
+ ToSendStuffBit(0);
+ ToSendStuffBit(0);
+ ToSendStuffBit(0);
+ ToSendStuffBit(0);
+ }
+ for(i = 0; i < 2; i++) {
+ ToSendStuffBit(1);
+ ToSendStuffBit(1);
+ ToSendStuffBit(1);
+ ToSendStuffBit(1);
+ }
+
+ for(i = 0; i < len; i++) {
+ int j;
+ uint8_t b = cmd[i];
+
+ // Start bit
+ ToSendStuffBit(0);
+ ToSendStuffBit(0);
+ ToSendStuffBit(0);
+ ToSendStuffBit(0);
+
+ // Data bits
+ for(j = 0; j < 8; j++) {
+ if(b & 1) {
+ ToSendStuffBit(1);
+ ToSendStuffBit(1);
+ ToSendStuffBit(1);
+ ToSendStuffBit(1);
+ } else {
+ ToSendStuffBit(0);
+ ToSendStuffBit(0);
+ ToSendStuffBit(0);
+ ToSendStuffBit(0);
+ }
+ b >>= 1;
+ }
+
+ // Stop bit
+ ToSendStuffBit(1);
+ ToSendStuffBit(1);
+ ToSendStuffBit(1);
+ ToSendStuffBit(1);
+ }
+
+ // Send EOF.
+ for(i = 0; i < 10; i++) {
+ ToSendStuffBit(0);
+ ToSendStuffBit(0);
+ ToSendStuffBit(0);
+ ToSendStuffBit(0);
+ }
+ for(i = 0; i < 2; i++) {
+ ToSendStuffBit(1);
+ ToSendStuffBit(1);
+ ToSendStuffBit(1);
+ ToSendStuffBit(1);
+ }
+
+ // Convert from last byte pos to length
+ ToSendMax++;
+}
+
+//-----------------------------------------------------------------------------
+// The software UART that receives commands from the reader, and its state
+// variables.
+//-----------------------------------------------------------------------------
+static struct {
+ enum {
+ STATE_UNSYNCD,
+ STATE_GOT_FALLING_EDGE_OF_SOF,
+ STATE_AWAITING_START_BIT,
+ STATE_RECEIVING_DATA
+ } state;
+ uint16_t shiftReg;
+ int bitCnt;
+ int byteCnt;
+ int byteCntMax;
+ int posCnt;
+ uint8_t *output;
+} Uart;
+
+/* Receive & handle a bit coming from the reader.
+ *
+ * This function is called 4 times per bit (every 2 subcarrier cycles).
+ * Subcarrier frequency fs is 848kHz, 1/fs = 1,18us, i.e. function is called every 2,36us
+ *
+ * LED handling:
+ * LED A -> ON once we have received the SOF and are expecting the rest.
+ * LED A -> OFF once we have received EOF or are in error state or unsynced
+ *
+ * Returns: true if we received a EOF
+ * false if we are still waiting for some more
+ */
+static RAMFUNC int Handle14443bUartBit(uint8_t bit)
+{
+ switch(Uart.state) {
+ case STATE_UNSYNCD:
+ if(!bit) {
+ // we went low, so this could be the beginning
+ // of an SOF
+ Uart.state = STATE_GOT_FALLING_EDGE_OF_SOF;
+ Uart.posCnt = 0;
+ Uart.bitCnt = 0;
+ }
+ break;
+
+ case STATE_GOT_FALLING_EDGE_OF_SOF:
+ Uart.posCnt++;
+ if(Uart.posCnt == 2) { // sample every 4 1/fs in the middle of a bit
+ if(bit) {
+ if(Uart.bitCnt > 9) {
+ // we've seen enough consecutive
+ // zeros that it's a valid SOF
+ Uart.posCnt = 0;
+ Uart.byteCnt = 0;
+ Uart.state = STATE_AWAITING_START_BIT;
+ LED_A_ON(); // Indicate we got a valid SOF
+ } else {
+ // didn't stay down long enough
+ // before going high, error
+ Uart.state = STATE_UNSYNCD;
+ }
+ } else {
+ // do nothing, keep waiting
+ }
+ Uart.bitCnt++;
+ }
+ if(Uart.posCnt >= 4) Uart.posCnt = 0;
+ if(Uart.bitCnt > 12) {
+ // Give up if we see too many zeros without
+ // a one, too.
+ LED_A_OFF();
+ Uart.state = STATE_UNSYNCD;
+ }
+ break;
+
+ case STATE_AWAITING_START_BIT:
+ Uart.posCnt++;
+ if(bit) {
+ if(Uart.posCnt > 50/2) { // max 57us between characters = 49 1/fs, max 3 etus after low phase of SOF = 24 1/fs
+ // stayed high for too long between
+ // characters, error
+ Uart.state = STATE_UNSYNCD;
+ }
+ } else {
+ // falling edge, this starts the data byte
+ Uart.posCnt = 0;
+ Uart.bitCnt = 0;
+ Uart.shiftReg = 0;
+ Uart.state = STATE_RECEIVING_DATA;
+ }
+ break;
+
+ case STATE_RECEIVING_DATA:
+ Uart.posCnt++;
+ if(Uart.posCnt == 2) {
+ // time to sample a bit
+ Uart.shiftReg >>= 1;
+ if(bit) {
+ Uart.shiftReg |= 0x200;
+ }
+ Uart.bitCnt++;
+ }
+ if(Uart.posCnt >= 4) {
+ Uart.posCnt = 0;
+ }
+ if(Uart.bitCnt == 10) {
+ if((Uart.shiftReg & 0x200) && !(Uart.shiftReg & 0x001))
+ {
+ // this is a data byte, with correct
+ // start and stop bits
+ Uart.output[Uart.byteCnt] = (Uart.shiftReg >> 1) & 0xff;
+ Uart.byteCnt++;
+
+ if(Uart.byteCnt >= Uart.byteCntMax) {
+ // Buffer overflowed, give up
+ LED_A_OFF();
+ Uart.state = STATE_UNSYNCD;
+ } else {
+ // so get the next byte now
+ Uart.posCnt = 0;
+ Uart.state = STATE_AWAITING_START_BIT;
+ }
+ } else if (Uart.shiftReg == 0x000) {
+ // this is an EOF byte
+ LED_A_OFF(); // Finished receiving
+ Uart.state = STATE_UNSYNCD;
+ if (Uart.byteCnt != 0) {
+ return TRUE;
+ }
+ } else {
+ // this is an error
+ LED_A_OFF();
+ Uart.state = STATE_UNSYNCD;
+ }
+ }
+ break;
+
+ default:
+ LED_A_OFF();
+ Uart.state = STATE_UNSYNCD;
+ break;
+ }
+
+ return FALSE;
+}
+
+
+static void UartReset()
+{
+ Uart.byteCntMax = MAX_FRAME_SIZE;
+ Uart.state = STATE_UNSYNCD;
+ Uart.byteCnt = 0;
+ Uart.bitCnt = 0;
+}
+
+
+static void UartInit(uint8_t *data)
+{
+ Uart.output = data;
+ UartReset();
+}
+
+
+//-----------------------------------------------------------------------------
+// Receive a command (from the reader to us, where we are the simulated tag),
+// and store it in the given buffer, up to the given maximum length. Keeps
+// spinning, waiting for a well-framed command, until either we get one
+// (returns TRUE) or someone presses the pushbutton on the board (FALSE).
+//
+// Assume that we're called with the SSC (to the FPGA) and ADC path set
+// correctly.
+//-----------------------------------------------------------------------------
+static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len)
+{
+ // Set FPGA mode to "simulated ISO 14443B tag", no modulation (listen
+ // only, since we are receiving, not transmitting).
+ // Signal field is off with the appropriate LED
+ LED_D_OFF();
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION);
+
+ // Now run a `software UART' on the stream of incoming samples.
+ UartInit(received);
+
+ for(;;) {
+ WDT_HIT();
+
+ if(BUTTON_PRESS()) return FALSE;
+
+ if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+ uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
+ for(uint8_t mask = 0x80; mask != 0x00; mask >>= 1) {
+ if(Handle14443bUartBit(b & mask)) {
+ *len = Uart.byteCnt;
+ return TRUE;
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// Main loop of simulated tag: receive commands from reader, decide what
+// response to send, and send it.
+//-----------------------------------------------------------------------------
+void SimulateIso14443bTag(void)
+{
+ // the only commands we understand is REQB, AFI=0, Select All, N=0:
+ static const uint8_t cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 };
+ // ... and REQB, AFI=0, Normal Request, N=0:
+ static const uint8_t cmd2[] = { 0x05, 0x00, 0x00, 0x71, 0xFF };
+
+ // ... and we always respond with ATQB, PUPI = 820de174, Application Data = 0x20381922,
+ // supports only 106kBit/s in both directions, max frame size = 32Bytes,
+ // supports ISO14443-4, FWI=8 (77ms), NAD supported, CID not supported:
+ static const uint8_t response1[] = {
+ 0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19, 0x22,
+ 0x00, 0x21, 0x85, 0x5e, 0xd7
+ };
+
+ clear_trace();
+ set_tracing(TRUE);
+
+ const uint8_t *resp;
+ uint8_t *respCode;
+ uint16_t respLen, respCodeLen;
+
+ // allocate command receive buffer
+ BigBuf_free();
+ uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
+
+ uint16_t len;
+ uint16_t cmdsRecvd = 0;
+
+ FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
+
+ // prepare the (only one) tag answer:
+ CodeIso14443bAsTag(response1, sizeof(response1));
+ uint8_t *resp1Code = BigBuf_malloc(ToSendMax);
+ memcpy(resp1Code, ToSend, ToSendMax);
+ uint16_t resp1CodeLen = ToSendMax;
+
+ // We need to listen to the high-frequency, peak-detected path.
+ SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+ FpgaSetupSsc();
+
+ cmdsRecvd = 0;
+
+ for(;;) {
+
+ if(!GetIso14443bCommandFromReader(receivedCmd, &len)) {
+ Dbprintf("button pressed, received %d commands", cmdsRecvd);
+ break;
+ }
+
+ if (tracing) {
+ uint8_t parity[MAX_PARITY_SIZE];
+ LogTrace(receivedCmd, len, 0, 0, parity, TRUE);
+ }
+
+ // Good, look at the command now.
+ if ( (len == sizeof(cmd1) && memcmp(receivedCmd, cmd1, len) == 0)
+ || (len == sizeof(cmd2) && memcmp(receivedCmd, cmd2, len) == 0) ) {
+ resp = response1;
+ respLen = sizeof(response1);
+ respCode = resp1Code;
+ respCodeLen = resp1CodeLen;
+ } else {
+ Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsRecvd);
+ // And print whether the CRC fails, just for good measure
+ uint8_t b1, b2;
+ ComputeCrc14443(CRC_14443_B, receivedCmd, len-2, &b1, &b2);
+ if(b1 != receivedCmd[len-2] || b2 != receivedCmd[len-1]) {
+ // Not so good, try again.
+ DbpString("+++CRC fail");
+ } else {
+ DbpString("CRC passes");
+ }
+ break;
+ }
+
+ cmdsRecvd++;
+
+ if(cmdsRecvd > 0x30) {
+ DbpString("many commands later...");
+ break;
+ }
+
+ if(respCodeLen <= 0) continue;
+
+ // Modulate BPSK
+ // Signal field is off with the appropriate LED
+ LED_D_OFF();
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK);
+ AT91C_BASE_SSC->SSC_THR = 0xff;
+ FpgaSetupSsc();
+
+ // Transmit the response.
+ uint16_t i = 0;
+ for(;;) {
+ if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+ uint8_t b = respCode[i];
+
+ AT91C_BASE_SSC->SSC_THR = b;
+
+ i++;
+ if(i > respCodeLen) {
+ break;
+ }
+ }
+ if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+ volatile uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
+ (void)b;
+ }
+ }
+
+ // trace the response:
+ if (tracing) {
+ uint8_t parity[MAX_PARITY_SIZE];
+ LogTrace(resp, respLen, 0, 0, parity, FALSE);
+ }
+
+ }
+}
+
+//=============================================================================
+// An ISO 14443 Type B reader. We take layer two commands, code them
+// appropriately, and then send them to the tag. We then listen for the
+// tag's response, which we leave in the buffer to be demodulated on the
+// PC side.
+//=============================================================================
+
+static struct {
+ enum {
+ DEMOD_UNSYNCD,
+ DEMOD_PHASE_REF_TRAINING,
+ DEMOD_AWAITING_FALLING_EDGE_OF_SOF,
+ DEMOD_GOT_FALLING_EDGE_OF_SOF,
+ DEMOD_AWAITING_START_BIT,
+ DEMOD_RECEIVING_DATA
+ } state;
+ int bitCount;
+ int posCount;
+ int thisBit;
+/* this had been used to add RSSI (Received Signal Strength Indication) to traces. Currently not implemented.
+ int metric;
+ int metricN;
+*/
+ uint16_t shiftReg;
+ uint8_t *output;
+ int len;
+ int sumI;
+ int sumQ;
+} Demod;
+
+/*
+ * Handles reception of a bit from the tag
+ *
+ * This function is called 2 times per bit (every 4 subcarrier cycles).
+ * Subcarrier frequency fs is 848kHz, 1/fs = 1,18us, i.e. function is called every 4,72us
+ *
+ * LED handling:
+ * LED C -> ON once we have received the SOF and are expecting the rest.
+ * LED C -> OFF once we have received EOF or are unsynced
+ *
+ * Returns: true if we received a EOF
+ * false if we are still waiting for some more
+ *
+ */
+static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq)
+{
+ int v;
+
+// The soft decision on the bit uses an estimate of just the
+// quadrant of the reference angle, not the exact angle.
+#define MAKE_SOFT_DECISION() { \
+ if(Demod.sumI > 0) { \
+ v = ci; \
+ } else { \
+ v = -ci; \
+ } \
+ if(Demod.sumQ > 0) { \
+ v += cq; \
+ } else { \
+ v -= cq; \
+ } \
+ }
+
+#define SUBCARRIER_DETECT_THRESHOLD 8
+
+// Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by abs(ci) + abs(cq)
+/* #define CHECK_FOR_SUBCARRIER() { \
+ v = ci; \
+ if(v < 0) v = -v; \
+ if(cq > 0) { \
+ v += cq; \
+ } else { \
+ v -= cq; \
+ } \
+ }
+ */
+// Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by max(abs(ci),abs(cq)) + 1/2*min(abs(ci),abs(cq)))
+#define CHECK_FOR_SUBCARRIER() { \
+ if(ci < 0) { \
+ if(cq < 0) { /* ci < 0, cq < 0 */ \
+ if (cq < ci) { \
+ v = -cq - (ci >> 1); \
+ } else { \
+ v = -ci - (cq >> 1); \
+ } \
+ } else { /* ci < 0, cq >= 0 */ \
+ if (cq < -ci) { \
+ v = -ci + (cq >> 1); \
+ } else { \
+ v = cq - (ci >> 1); \
+ } \
+ } \
+ } else { \
+ if(cq < 0) { /* ci >= 0, cq < 0 */ \
+ if (-cq < ci) { \
+ v = ci - (cq >> 1); \
+ } else { \
+ v = -cq + (ci >> 1); \
+ } \
+ } else { /* ci >= 0, cq >= 0 */ \
+ if (cq < ci) { \
+ v = ci + (cq >> 1); \
+ } else { \
+ v = cq + (ci >> 1); \
+ } \
+ } \
+ } \
+ }
+
+ switch(Demod.state) {
+ case DEMOD_UNSYNCD:
+ CHECK_FOR_SUBCARRIER();
+ if(v > SUBCARRIER_DETECT_THRESHOLD) { // subcarrier detected
+ Demod.state = DEMOD_PHASE_REF_TRAINING;
+ Demod.sumI = ci;
+ Demod.sumQ = cq;
+ Demod.posCount = 1;
+ }
+ break;
+
+ case DEMOD_PHASE_REF_TRAINING:
+ if(Demod.posCount < 8) {
+ CHECK_FOR_SUBCARRIER();
+ if (v > SUBCARRIER_DETECT_THRESHOLD) {
+ // set the reference phase (will code a logic '1') by averaging over 32 1/fs.
+ // note: synchronization time > 80 1/fs
+ Demod.sumI += ci;
+ Demod.sumQ += cq;
+ Demod.posCount++;
+ } else { // subcarrier lost
+ Demod.state = DEMOD_UNSYNCD;
+ }
+ } else {
+ Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF;
+ }
+ break;
+
+ case DEMOD_AWAITING_FALLING_EDGE_OF_SOF:
+ MAKE_SOFT_DECISION();
+ if(v < 0) { // logic '0' detected
+ Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF;
+ Demod.posCount = 0; // start of SOF sequence
+ } else {
+ if(Demod.posCount > 200/4) { // maximum length of TR1 = 200 1/fs
+ Demod.state = DEMOD_UNSYNCD;
+ }
+ }
+ Demod.posCount++;
+ break;
+
+ case DEMOD_GOT_FALLING_EDGE_OF_SOF:
+ Demod.posCount++;
+ MAKE_SOFT_DECISION();
+ if(v > 0) {
+ if(Demod.posCount < 9*2) { // low phase of SOF too short (< 9 etu). Note: spec is >= 10, but FPGA tends to "smear" edges
+ Demod.state = DEMOD_UNSYNCD;
+ } else {
+ LED_C_ON(); // Got SOF
+ Demod.state = DEMOD_AWAITING_START_BIT;
+ Demod.posCount = 0;
+ Demod.len = 0;
+/* this had been used to add RSSI (Received Signal Strength Indication) to traces. Currently not implemented.
+ Demod.metricN = 0;
+ Demod.metric = 0;
+*/
+ }
+ } else {
+ if(Demod.posCount > 12*2) { // low phase of SOF too long (> 12 etu)
+ Demod.state = DEMOD_UNSYNCD;
+ LED_C_OFF();
+ }
+ }
+ break;
+
+ case DEMOD_AWAITING_START_BIT:
+ Demod.posCount++;
+ MAKE_SOFT_DECISION();
+ if(v > 0) {
+ if(Demod.posCount > 3*2) { // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs
+ Demod.state = DEMOD_UNSYNCD;
+ LED_C_OFF();
+ }
+ } else { // start bit detected
+ Demod.bitCount = 0;
+ Demod.posCount = 1; // this was the first half
+ Demod.thisBit = v;
+ Demod.shiftReg = 0;
+ Demod.state = DEMOD_RECEIVING_DATA;
+ }
+ break;
+
+ case DEMOD_RECEIVING_DATA:
+ MAKE_SOFT_DECISION();
+ if(Demod.posCount == 0) { // first half of bit
+ Demod.thisBit = v;
+ Demod.posCount = 1;
+ } else { // second half of bit
+ Demod.thisBit += v;
+
+/* this had been used to add RSSI (Received Signal Strength Indication) to traces. Currently not implemented.
+ if(Demod.thisBit > 0) {
+ Demod.metric += Demod.thisBit;
+ } else {
+ Demod.metric -= Demod.thisBit;
+ }
+ (Demod.metricN)++;
+*/
+
+ Demod.shiftReg >>= 1;
+ if(Demod.thisBit > 0) { // logic '1'
+ Demod.shiftReg |= 0x200;
+ }
+
+ Demod.bitCount++;
+ if(Demod.bitCount == 10) {
+ uint16_t s = Demod.shiftReg;
+ if((s & 0x200) && !(s & 0x001)) { // stop bit == '1', start bit == '0'
+ uint8_t b = (s >> 1);
+ Demod.output[Demod.len] = b;
+ Demod.len++;
+ Demod.state = DEMOD_AWAITING_START_BIT;
+ } else {
+ Demod.state = DEMOD_UNSYNCD;
+ LED_C_OFF();
+ if(s == 0x000) {
+ // This is EOF (start, stop and all data bits == '0'
+ return TRUE;
+ }
+ }
+ }
+ Demod.posCount = 0;
+ }
+ break;
+
+ default:
+ Demod.state = DEMOD_UNSYNCD;
+ LED_C_OFF();
+ break;
+ }
+
+ return FALSE;
+}
+
+
+static void DemodReset()
+{
+ // Clear out the state of the "UART" that receives from the tag.
+ Demod.len = 0;
+ Demod.state = DEMOD_UNSYNCD;
+ Demod.posCount = 0;
+ memset(Demod.output, 0x00, MAX_FRAME_SIZE);
+}
+
+
+static void DemodInit(uint8_t *data)
+{
+ Demod.output = data;
+ DemodReset();
+}
+
+
+/*
+ * Demodulate the samples we received from the tag, also log to tracebuffer
+ * quiet: set to 'TRUE' to disable debug output
+ */
+static void GetSamplesFor14443bDemod(int n, bool quiet)
+{
+ int max = 0;
+ bool gotFrame = FALSE;
+ int lastRxCounter, ci, cq, samples = 0;
+
+ // Allocate memory from BigBuf for some buffers
+ // free all previous allocations first
+ BigBuf_free();
+
+ // The response (tag -> reader) that we're receiving.
+ uint8_t *receivedResponse = BigBuf_malloc(MAX_FRAME_SIZE);
+
+ // The DMA buffer, used to stream samples from the FPGA
+ int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE);
+
+ // Set up the demodulator for tag -> reader responses.
+ DemodInit(receivedResponse);
+
+ // Setup and start DMA.
+ FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE);
+
+ int8_t *upTo = dmaBuf;
+ lastRxCounter = ISO14443B_DMA_BUFFER_SIZE;
+
+ // Signal field is ON with the appropriate LED:
+ LED_D_ON();
+ // And put the FPGA in the appropriate mode
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);
+
+ for(;;) {
+ int behindBy = lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR;
+ if(behindBy > max) max = behindBy;
+
+ while(((lastRxCounter-AT91C_BASE_PDC_SSC->PDC_RCR) & (ISO14443B_DMA_BUFFER_SIZE-1)) > 2) {
+ ci = upTo[0];
+ cq = upTo[1];
+ upTo += 2;
+ if(upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) {
+ upTo = dmaBuf;
+ AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo;
+ AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE;
+ }
+ lastRxCounter -= 2;
+ if(lastRxCounter <= 0) {
+ lastRxCounter += ISO14443B_DMA_BUFFER_SIZE;
+ }
+
+ samples += 2;
+
+ if(Handle14443bSamplesDemod(ci, cq)) {
+ gotFrame = TRUE;
+ break;
+ }
+ }
+
+ if(samples > n || gotFrame) {
+ break;
+ }
+ }
+
+ AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
+
+ if (!quiet) Dbprintf("max behindby = %d, samples = %d, gotFrame = %d, Demod.len = %d, Demod.sumI = %d, Demod.sumQ = %d", max, samples, gotFrame, Demod.len, Demod.sumI, Demod.sumQ);
+ //Tracing
+ if (tracing && Demod.len > 0) {
+ uint8_t parity[MAX_PARITY_SIZE];
+ LogTrace(Demod.output, Demod.len, 0, 0, parity, FALSE);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Transmit the command (to the tag) that was placed in ToSend[].
+//-----------------------------------------------------------------------------
+static void TransmitFor14443b(void)
+{
+ int c;
+
+ FpgaSetupSsc();
+
+ while(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+ AT91C_BASE_SSC->SSC_THR = 0xff;
+ }
+
+ // Signal field is ON with the appropriate Red LED
+ LED_D_ON();
+ // Signal we are transmitting with the Green LED
+ LED_B_ON();
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);
+
+ for(c = 0; c < 10;) {
+ if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+ AT91C_BASE_SSC->SSC_THR = 0xff;
+ c++;
+ }
+ if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+ volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
+ (void)r;
+ }
+ WDT_HIT();
+ }
+
+ c = 0;
+ for(;;) {
+ if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+ AT91C_BASE_SSC->SSC_THR = ToSend[c];
+ c++;
+ if(c >= ToSendMax) {
+ break;
+ }
+ }
+ if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+ volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
+ (void)r;
+ }
+ WDT_HIT();
+ }
+ LED_B_OFF(); // Finished sending
+}
+
+
+//-----------------------------------------------------------------------------
+// Code a layer 2 command (string of octets, including CRC) into ToSend[],
+// so that it is ready to transmit to the tag using TransmitFor14443b().
+//-----------------------------------------------------------------------------
+static void CodeIso14443bAsReader(const uint8_t *cmd, int len)
+{
+ int i, j;
+ uint8_t b;
+
+ ToSendReset();
+
+ // Establish initial reference level
+ for(i = 0; i < 40; i++) {
+ ToSendStuffBit(1);
+ }
+ // Send SOF
+ for(i = 0; i < 10; i++) {
+ ToSendStuffBit(0);
+ }
+
+ for(i = 0; i < len; i++) {
+ // Stop bits/EGT
+ ToSendStuffBit(1);
+ ToSendStuffBit(1);
+ // Start bit
+ ToSendStuffBit(0);
+ // Data bits
+ b = cmd[i];
+ for(j = 0; j < 8; j++) {
+ if(b & 1) {
+ ToSendStuffBit(1);
+ } else {
+ ToSendStuffBit(0);
+ }
+ b >>= 1;
+ }
+ }
+ // Send EOF
+ ToSendStuffBit(1);
+ for(i = 0; i < 10; i++) {
+ ToSendStuffBit(0);
+ }
+ for(i = 0; i < 8; i++) {
+ ToSendStuffBit(1);
+ }
+
+ // And then a little more, to make sure that the last character makes
+ // it out before we switch to rx mode.
+ for(i = 0; i < 24; i++) {
+ ToSendStuffBit(1);
+ }
+
+ // Convert from last character reference to length
+ ToSendMax++;
+}
+
+
+/**
+ Convenience function to encode, transmit and trace iso 14443b comms
+ **/
+static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len)
+{
+ CodeIso14443bAsReader(cmd, len);
+ TransmitFor14443b();
+ if (tracing) {
+ uint8_t parity[MAX_PARITY_SIZE];
+ LogTrace(cmd,len, 0, 0, parity, TRUE);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Read a SRI512 ISO 14443B 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 ReadSTMemoryIso14443b(uint32_t dwLast)
+{
+ clear_trace();
+ set_tracing(TRUE);
+
+ uint8_t i = 0x00;
+
+ FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
+ // 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.
+ // Signal field is on with the appropriate LED
+ LED_D_ON();
+ 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
+ uint8_t cmd1[] = {0x06, 0x00, 0x97, 0x5b};
+ CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
+ GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
+
+ if (Demod.len == 0) {
+ DbpString("No response from tag");
+ return;
+ } else {
+ Dbprintf("Randomly generated Chip ID (+ 2 byte CRC): %02x %02x %02x",
+ 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]);
+ CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
+ GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
+ if (Demod.len != 3) {
+ Dbprintf("Expected 3 bytes from tag, got %d", Demod.len);
+ 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]) {
+ Dbprintf("Bad response to SELECT from Tag, aborting: %02x %02x", cmd1[1], Demod.output[0]);
+ return;
+ }
+
+ // Tag is now selected,
+ // First get the tag's UID:
+ cmd1[0] = 0x0B;
+ ComputeCrc14443(CRC_14443_B, cmd1, 1 , &cmd1[1], &cmd1[2]);
+ CodeAndTransmit14443bAsReader(cmd1, 3); // Only first three bytes for this one
+ GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
+ if (Demod.len != 10) {
+ Dbprintf("Expected 10 bytes from tag, got %d", Demod.len);
+ return;
+ }
+ // The check the CRC of the answer (use cmd1 as temporary variable):
+ ComputeCrc14443(CRC_14443_B, Demod.output, 8, &cmd1[2], &cmd1[3]);
+ if(cmd1[2] != Demod.output[8] || cmd1[3] != Demod.output[9]) {
+ Dbprintf("CRC Error reading block! Expected: %04x got: %04x",
+ (cmd1[2]<<8)+cmd1[3], (Demod.output[8]<<8)+Demod.output[9]);
+ // Do not return;, let's go on... (we should retry, maybe ?)
+ }
+ Dbprintf("Tag UID (64 bits): %08x %08x",
+ (Demod.output[7]<<24) + (Demod.output[6]<<16) + (Demod.output[5]<<8) + Demod.output[4],
+ (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0]);
+
+ // Now loop to read all 16 blocks, address from 0 to last block
+ Dbprintf("Tag memory dump, block 0 to %d", dwLast);
+ cmd1[0] = 0x08;
+ i = 0x00;
+ dwLast++;
+ for (;;) {
+ if (i == dwLast) {
+ DbpString("System area block (0xff):");
+ i = 0xff;
+ }
+ cmd1[1] = i;
+ ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);
+ CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
+ GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
+ 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]) {
+ Dbprintf("CRC Error reading block! Expected: %04x got: %04x",
+ (cmd1[2]<<8)+cmd1[3], (Demod.output[4]<<8)+Demod.output[5]);
+ // Do not return;, let's go on... (we should retry, maybe ?)
+ }
+ // Now print out the memory location:
+ Dbprintf("Address=%02x, Contents=%08x, CRC=%04x", i,
+ (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0],
+ (Demod.output[4]<<8)+Demod.output[5]);
+ if (i == 0xff) {
+ break;
+ }
+ i++;
+ }
+}
+
+
+//=============================================================================
+// Finally, the `sniffer' combines elements from both the reader and
+// simulated tag, to show both sides of the conversation.
+//=============================================================================
+
+//-----------------------------------------------------------------------------
+// Record the sequence of commands sent by the reader to the tag, with
+// triggering so that we start recording at the point that the tag is moved
+// near the reader.
+//-----------------------------------------------------------------------------
+/*
+ * Memory usage for this function, (within BigBuf)
+ * Last Received command (reader->tag) - MAX_FRAME_SIZE
+ * Last Received command (tag->reader) - MAX_FRAME_SIZE
+ * DMA Buffer - ISO14443B_DMA_BUFFER_SIZE
+ * Demodulated samples received - all the rest
+ */
+void RAMFUNC SnoopIso14443b(void)
+{
+ // 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
+ // response from the tag.
+ int triggered = TRUE; // TODO: set and evaluate trigger condition
+
+ FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
+ BigBuf_free();
+
+ clear_trace();
+ set_tracing(TRUE);
+
+ // The DMA buffer, used to stream samples from the FPGA
+ int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE);
+ int lastRxCounter;
+ int8_t *upTo;
+ int ci, cq;
+ int maxBehindBy = 0;
+
+ // Count of samples received so far, so that we can include timing
+ // information in the trace buffer.
+ int samples = 0;
+
+ DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
+ UartInit(BigBuf_malloc(MAX_FRAME_SIZE));
+
+ // Print some debug information about the buffer sizes
+ Dbprintf("Snooping buffers initialized:");
+ Dbprintf(" Trace: %i bytes", BigBuf_max_traceLen());
+ Dbprintf(" Reader -> tag: %i bytes", MAX_FRAME_SIZE);
+ Dbprintf(" tag -> Reader: %i bytes", MAX_FRAME_SIZE);
+ Dbprintf(" DMA: %i bytes", ISO14443B_DMA_BUFFER_SIZE);
+
+ // Signal field is off, no reader signal, no tag signal
+ LEDsoff();
+
+ // And put the FPGA in the appropriate mode
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP);
+ SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+
+ // Setup for the DMA.
+ FpgaSetupSsc();
+ upTo = dmaBuf;
+ lastRxCounter = ISO14443B_DMA_BUFFER_SIZE;
+ FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE);
+ uint8_t parity[MAX_PARITY_SIZE];
+
+ bool TagIsActive = FALSE;
+ bool ReaderIsActive = FALSE;
+
+ // And now we loop, receiving samples.
+ for(;;) {
+ int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) &
+ (ISO14443B_DMA_BUFFER_SIZE-1);
+ if(behindBy > maxBehindBy) {
+ maxBehindBy = behindBy;
+ }
+
+ if(behindBy < 2) continue;
+
+ ci = upTo[0];
+ cq = upTo[1];
+ upTo += 2;
+ lastRxCounter -= 2;
+ if(upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) {
+ upTo = dmaBuf;
+ lastRxCounter += ISO14443B_DMA_BUFFER_SIZE;
+ AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf;
+ AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE;
+ WDT_HIT();
+ if(behindBy > (9*ISO14443B_DMA_BUFFER_SIZE/10)) { // TODO: understand whether we can increase/decrease as we want or not?
+ Dbprintf("blew circular buffer! behindBy=%d", behindBy);
+ break;
+ }
+ if(!tracing) {
+ DbpString("Reached trace limit");
+ break;
+ }
+ if(BUTTON_PRESS()) {
+ DbpString("cancelled");
+ break;
+ }
+ }
+
+ samples += 2;
+
+ if (!TagIsActive) { // no need to try decoding reader data if the tag is sending
+ if(Handle14443bUartBit(ci & 0x01)) {
+ if(triggered && tracing) {
+ LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, TRUE);
+ }
+ /* And ready to receive another command. */
+ UartReset();
+ /* And also reset the demod code, which might have been */
+ /* false-triggered by the commands from the reader. */
+ DemodReset();
+ }
+ if(Handle14443bUartBit(cq & 0x01)) {
+ if(triggered && tracing) {
+ LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, TRUE);
+ }
+ /* And ready to receive another command. */
+ UartReset();
+ /* And also reset the demod code, which might have been */
+ /* false-triggered by the commands from the reader. */
+ DemodReset();
+ }
+ ReaderIsActive = (Uart.state > STATE_GOT_FALLING_EDGE_OF_SOF);
+ }
+
+ if(!ReaderIsActive) { // no need to try decoding tag data if the reader is sending - and we cannot afford the time
+ if(Handle14443bSamplesDemod(ci | 0x01, cq | 0x01)) {
+
+ //Use samples as a time measurement
+ if(tracing)
+ {
+ uint8_t parity[MAX_PARITY_SIZE];
+ LogTrace(Demod.output, Demod.len, samples, samples, parity, FALSE);
+ }
+ triggered = TRUE;
+
+ // And ready to receive another response.
+ DemodReset();
+ }
+ TagIsActive = (Demod.state > DEMOD_GOT_FALLING_EDGE_OF_SOF);
+ }
+
+ }
+
+ FpgaDisableSscDma();
+ LEDsoff();
+ AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
+ DbpString("Snoop statistics:");
+ Dbprintf(" Max behind by: %i", maxBehindBy);
+ Dbprintf(" Uart State: %x", Uart.state);
+ Dbprintf(" Uart ByteCnt: %i", Uart.byteCnt);
+ Dbprintf(" Uart ByteCntMax: %i", Uart.byteCntMax);
+ Dbprintf(" Trace length: %i", BigBuf_get_traceLen());
+}
+
+
+/*
+ * Send raw command to tag ISO14443B
+ * @Input
+ * datalen len of buffer data
+ * recv bool when true wait for data from tag and send to client
+ * powerfield bool leave the field on when true
+ * data buffer with byte to send
+ *
+ * @Output
+ * none
+ *
+ */
+void SendRawCommand14443B(uint32_t datalen, uint32_t recv, uint8_t powerfield, uint8_t data[])
+{
+ FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
+ SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+ FpgaSetupSsc();
+
+ set_tracing(TRUE);
+
+ CodeAndTransmit14443bAsReader(data, datalen);
+
+ if(recv) {
+ GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
+ uint16_t iLen = MIN(Demod.len, USB_CMD_DATA_SIZE);
+ cmd_send(CMD_ACK, iLen, 0, 0, Demod.output, iLen);
+ }
+
+ if(!powerfield) {
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ LED_D_OFF();
+ }
+}
+
oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
}
uint8_t parityBits = parityBytes[j>>3];
- if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
+ if (protocol != ISO_14443B && isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]);
} else {
static int CmdHelp(const char *Cmd);
-int CmdHF14BDemod(const char *Cmd)
-{
- int i, j, iold;
- int isum, qsum;
- int outOfWeakAt;
- bool negateI, negateQ;
-
- uint8_t data[256];
- int dataLen = 0;
-
- // As received, the samples are pairs, correlations against I and Q
- // square waves. So estimate angle of initial carrier (or just
- // quadrant, actually), and then do the demod.
-
- // First, estimate where the tag starts modulating.
- for (i = 0; i < GraphTraceLen; i += 2) {
- if (abs(GraphBuffer[i]) + abs(GraphBuffer[i + 1]) > 40) {
- break;
- }
- }
- if (i >= GraphTraceLen) {
- PrintAndLog("too weak to sync");
- return 0;
- }
- PrintAndLog("out of weak at %d", i);
- outOfWeakAt = i;
-
- // Now, estimate the phase in the initial modulation of the tag
- isum = 0;
- qsum = 0;
- for (; i < (outOfWeakAt + 16); i += 2) {
- isum += GraphBuffer[i + 0];
- qsum += GraphBuffer[i + 1];
- }
- negateI = (isum < 0);
- negateQ = (qsum < 0);
-
- // Turn the correlation pairs into soft decisions on the bit.
- j = 0;
- for (i = 0; i < GraphTraceLen / 2; i++) {
- int si = GraphBuffer[j];
- int sq = GraphBuffer[j + 1];
- if (negateI) si = -si;
- if (negateQ) sq = -sq;
- GraphBuffer[i] = si + sq;
- j += 2;
- }
- GraphTraceLen = i;
-
- i = outOfWeakAt / 2;
- while (GraphBuffer[i] > 0 && i < GraphTraceLen)
- i++;
- if (i >= GraphTraceLen) goto demodError;
-
- iold = i;
- while (GraphBuffer[i] < 0 && i < GraphTraceLen)
- i++;
- if (i >= GraphTraceLen) goto demodError;
- if ((i - iold) > 23) goto demodError;
-
- PrintAndLog("make it to demod loop");
-
- for (;;) {
- iold = i;
- while (GraphBuffer[i] >= 0 && i < GraphTraceLen)
- i++;
- if (i >= GraphTraceLen) goto demodError;
- if ((i - iold) > 6) goto demodError;
-
- uint16_t shiftReg = 0;
- if (i + 20 >= GraphTraceLen) goto demodError;
-
- for (j = 0; j < 10; j++) {
- int soft = GraphBuffer[i] + GraphBuffer[i + 1];
-
- if (abs(soft) < (abs(isum) + abs(qsum)) / 20) {
- PrintAndLog("weak bit");
- }
-
- shiftReg >>= 1;
- if(GraphBuffer[i] + GraphBuffer[i+1] >= 0) {
- shiftReg |= 0x200;
- }
-
- i+= 2;
- }
-
- if ((shiftReg & 0x200) && !(shiftReg & 0x001))
- {
- // valid data byte, start and stop bits okay
- PrintAndLog(" %02x", (shiftReg >> 1) & 0xff);
- data[dataLen++] = (shiftReg >> 1) & 0xff;
- if (dataLen >= sizeof(data)) {
- return 0;
- }
- } else if (shiftReg == 0x000) {
- // this is EOF
- break;
- } else {
- goto demodError;
- }
- }
-
- uint8_t first, second;
- ComputeCrc14443(CRC_14443_B, data, dataLen-2, &first, &second);
- PrintAndLog("CRC: %02x %02x (%s)\n", first, second,
- (first == data[dataLen-2] && second == data[dataLen-1]) ?
- "ok" : "****FAIL****");
-
- RepaintGraphWindow();
- return 0;
-
-demodError:
- PrintAndLog("demod error");
- RepaintGraphWindow();
- return 0;
-}
-
int CmdHF14BList(const char *Cmd)
{
PrintAndLog("Deprecated command, use 'hf list 14b' instead");
return 0;
}
-int CmdHF14BRead(const char *Cmd)
-{
- UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443, {strtol(Cmd, NULL, 0), 0, 0}};
- SendCommand(&c);
- return 0;
-}
-
-int CmdHF14Sim(const char *Cmd)
-{
- UsbCommand c={CMD_SIMULATE_TAG_ISO_14443};
- SendCommand(&c);
- return 0;
-}
-int CmdHFSimlisten(const char *Cmd)
+int CmdHF14BSim(const char *Cmd)
{
- UsbCommand c = {CMD_SIMULATE_TAG_HF_LISTEN};
+ UsbCommand c={CMD_SIMULATE_TAG_ISO_14443B};
SendCommand(&c);
return 0;
}
int CmdHF14BSnoop(const char *Cmd)
{
- UsbCommand c = {CMD_SNOOP_ISO_14443};
+ UsbCommand c = {CMD_SNOOP_ISO_14443B};
SendCommand(&c);
return 0;
}
if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
recv = resp.d.asBytes;
PrintAndLog("received %i octets",resp.arg[0]);
- if(!resp.arg[0])
+ if(resp.arg[0] == 0)
return 0;
hexout = (char *)malloc(resp.arg[0] * 3 + 1);
if (hexout != NULL) {
}
PrintAndLog("%s", hexout);
free(hexout);
- ComputeCrc14443(CRC_14443_B, recv, resp.arg[0]-2, &first, &second);
- if(recv[resp.arg[0]-2]==first && recv[resp.arg[0]-1]==second) {
- PrintAndLog("CRC OK");
- } else {
- PrintAndLog("CRC failed");
+ if (resp.arg[0] > 2) {
+ ComputeCrc14443(CRC_14443_B, recv, resp.arg[0]-2, &first, &second);
+ if(recv[resp.arg[0]-2]==first && recv[resp.arg[0]-1]==second) {
+ PrintAndLog("CRC OK");
+ } else {
+ PrintAndLog("CRC failed");
+ }
}
} else {
PrintAndLog("malloc failed your client has low memory?");
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
- {"demod", CmdHF14BDemod, 1, "Demodulate ISO14443 Type B from tag"},
{"list", CmdHF14BList, 0, "[Deprecated] List ISO 14443b history"},
- {"read", CmdHF14BRead, 0, "Read HF tag (ISO 14443)"},
- {"sim", CmdHF14Sim, 0, "Fake ISO 14443 tag"},
- {"simlisten", CmdHFSimlisten, 0, "Get HF samples as fake tag"},
- {"snoop", CmdHF14BSnoop, 0, "Eavesdrop ISO 14443"},
+ {"sim", CmdHF14BSim, 0, "Fake ISO 14443B tag"},
+ {"snoop", CmdHF14BSnoop, 0, "Eavesdrop ISO 14443B"},
{"sri512read", CmdSri512Read, 0, "Read contents of a SRI512 tag"},
{"srix4kread", CmdSrix4kRead, 0, "Read contents of a SRIX4K tag"},
{"raw", CmdHF14BCmdRaw, 0, "Send raw hex data to tag"},
// For the 13.56 MHz tags
#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300
-#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443 0x0301
#define CMD_READ_SRI512_TAG 0x0303
#define CMD_READ_SRIX4K_TAG 0x0304
#define CMD_READER_ISO_15693 0x0310
#define CMD_SIMULATE_HITAG 0x0371
#define CMD_READER_HITAG 0x0372
-#define CMD_SIMULATE_TAG_HF_LISTEN 0x0380
-#define CMD_SIMULATE_TAG_ISO_14443 0x0381
-#define CMD_SNOOP_ISO_14443 0x0382
+#define CMD_SIMULATE_TAG_ISO_14443B 0x0381
+#define CMD_SNOOP_ISO_14443B 0x0382
#define CMD_SNOOP_ISO_14443a 0x0383
#define CMD_SIMULATE_TAG_ISO_14443a 0x0384
#define CMD_READER_ISO_14443a 0x0385
--// For the 13.56 MHz tags
CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 = 0x0300,
- CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443 = 0x0301,
CMD_READ_SRI512_TAG = 0x0303,
CMD_READ_SRIX4K_TAG = 0x0304,
CMD_READER_ISO_15693 = 0x0310,
CMD_SIMULATE_HITAG = 0x0371,
CMD_READER_HITAG = 0x0372,
- CMD_SIMULATE_TAG_HF_LISTEN = 0x0380,
- CMD_SIMULATE_TAG_ISO_14443 = 0x0381,
- CMD_SNOOP_ISO_14443 = 0x0382,
+ CMD_SIMULATE_TAG_ISO_14443B = 0x0381,
+ CMD_SNOOP_ISO_14443B = 0x0382,
CMD_SNOOP_ISO_14443a = 0x0383,
CMD_SIMULATE_TAG_ISO_14443a = 0x0384,
CMD_READER_ISO_14443a = 0x0385,
// and whether to drive the coil (reader) or just short it (snooper)
wire hi_read_rx_xcorr_snoop = conf_word[1];
-// Divide the expected subcarrier frequency for hi_read_rx_xcorr by 4
-wire hi_read_rx_xcorr_quarter = conf_word[2];
-
// For the high-frequency simulated tag: what kind of modulation to use.
wire [2:0] hi_simulate_mod_type = conf_word[2:0];
hrxc_ssp_frame, hrxc_ssp_din, ssp_dout, hrxc_ssp_clk,
cross_hi, cross_lo,
hrxc_dbg,
- hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop, hi_read_rx_xcorr_quarter
+ hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop
);
hi_simulate hs(
ssp_frame, ssp_din, ssp_dout, ssp_clk,
cross_hi, cross_lo,
dbg,
- xcorr_is_848, snoop, xcorr_quarter_freq
+ xcorr_is_848, snoop
);
input pck0, ck_1356meg, ck_1356megb;
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
output ssp_frame, ssp_din, ssp_clk;
input cross_hi, cross_lo;
output dbg;
- input xcorr_is_848, snoop, xcorr_quarter_freq;
+ input xcorr_is_848, snoop;
// Carrier is steady on through this, unless we're snooping.
assign pwr_hi = ck_1356megb & (~snoop);
assign pwr_oe1 = 1'b0;
-assign pwr_oe2 = 1'b0;
assign pwr_oe3 = 1'b0;
assign pwr_oe4 = 1'b0;
-reg ssp_clk;
-reg ssp_frame;
+wire adc_clk = ck_1356megb;
reg fc_div_2;
-always @(posedge ck_1356meg)
- fc_div_2 = ~fc_div_2;
-
-reg fc_div_4;
-always @(posedge fc_div_2)
- fc_div_4 = ~fc_div_4;
-
-reg fc_div_8;
-always @(posedge fc_div_4)
- fc_div_8 = ~fc_div_8;
-
-reg adc_clk;
-
-always @(xcorr_is_848 or xcorr_quarter_freq or ck_1356meg)
- if(~xcorr_quarter_freq)
- begin
- if(xcorr_is_848)
- // The subcarrier frequency is fc/16; we will sample at fc, so that
- // means the subcarrier is 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 ...
- adc_clk <= ck_1356meg;
- else
- // The subcarrier frequency is fc/32; we will sample at fc/2, and
- // the subcarrier will look identical.
- adc_clk <= fc_div_2;
- end
- else
- begin
- if(xcorr_is_848)
- // The subcarrier frequency is fc/64
- adc_clk <= fc_div_4;
- else
- // The subcarrier frequency is fc/128
- adc_clk <= fc_div_8;
- end
+always @(negedge ck_1356megb)
+ fc_div_2 <= fc_div_2 + 1;
// When we're a reader, we just need to do the BPSK demod; but when we're an
// eavesdropper, we also need to pick out the commands sent by the reader,
// using AM. Do this the same way that we do it for the simulated tag.
-reg after_hysteresis, after_hysteresis_prev;
+reg after_hysteresis, after_hysteresis_prev, after_hysteresis_prev_prev;
reg [11:0] has_been_low_for;
always @(negedge adc_clk)
begin
// Let us report a correlation every 4 subcarrier cycles, or 4*16 samples,
// so we need a 6-bit counter.
reg [5:0] corr_i_cnt;
-reg [5:0] corr_q_cnt;
// And a couple of registers in which to accumulate the correlations.
-reg signed [15:0] corr_i_accum;
-reg signed [15:0] corr_q_accum;
+// we would add at most 32 times adc_d, the result can be held in 13 bits.
+// Need one additional bit because it can be negative as well
+reg signed [13:0] corr_i_accum;
+reg signed [13:0] corr_q_accum;
reg signed [7:0] corr_i_out;
reg signed [7:0] corr_q_out;
+// clock and frame signal for communication to ARM
+reg ssp_clk;
+reg ssp_frame;
+
+
+always @(negedge adc_clk)
+begin
+ if (xcorr_is_848 | fc_div_2)
+ corr_i_cnt <= corr_i_cnt + 1;
+end
+
// ADC data appears on the rising edge, so sample it on the falling edge
always @(negedge adc_clk)
// These are the correlators: we correlate against in-phase and quadrature
// versions of our reference signal, and keep the (signed) result to
// send out later over the SSP.
- if(corr_i_cnt == 7'd63)
+ if(corr_i_cnt == 6'd0)
begin
if(snoop)
begin
- corr_i_out <= {corr_i_accum[12:6], after_hysteresis_prev};
- corr_q_out <= {corr_q_accum[12:6], after_hysteresis};
+ // Send only 7 most significant bits of tag signal (signed), LSB is reader signal:
+ corr_i_out <= {corr_i_accum[13:7], after_hysteresis_prev_prev};
+ corr_q_out <= {corr_q_accum[13:7], after_hysteresis_prev};
+ after_hysteresis_prev_prev <= after_hysteresis;
end
else
begin
- // Only correlations need to be delivered.
+ // 8 most significant bits of tag signal
corr_i_out <= corr_i_accum[13:6];
corr_q_out <= corr_q_accum[13:6];
end
corr_i_accum <= adc_d;
corr_q_accum <= adc_d;
- corr_q_cnt <= 4;
- corr_i_cnt <= 0;
end
else
begin
else
corr_i_accum <= corr_i_accum + adc_d;
- if(corr_q_cnt[3])
- corr_q_accum <= corr_q_accum - adc_d;
- else
+ if(corr_i_cnt[3] == corr_i_cnt[2]) // phase shifted by pi/2
corr_q_accum <= corr_q_accum + adc_d;
+ else
+ corr_q_accum <= corr_q_accum - adc_d;
- corr_i_cnt <= corr_i_cnt + 1;
- corr_q_cnt <= corr_q_cnt + 1;
end
// The logic in hi_simulate.v reports 4 samples per bit. We report two
// (I, Q) pairs per bit, so we should do 2 samples per pair.
- if(corr_i_cnt == 6'd31)
+ if(corr_i_cnt == 6'd32)
after_hysteresis_prev <= after_hysteresis;
// Then the result from last time is serialized and send out to the ARM.
end
end
- if(corr_i_cnt[5:2] == 4'b000 || corr_i_cnt[5:2] == 4'b1000)
+ // set ssp_frame signal for corr_i_cnt = 0..3 and corr_i_cnt = 32..35
+ // (send two frames with 8 Bits each)
+ if(corr_i_cnt[5:2] == 4'b0000 || corr_i_cnt[5:2] == 4'b1000)
ssp_frame = 1'b1;
else
ssp_frame = 1'b0;
// Unused.
assign pwr_lo = 1'b0;
+assign pwr_oe2 = 1'b0;
endmodule
// For the 13.56 MHz tags
#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300
-#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443 0x0301
#define CMD_READ_SRI512_TAG 0x0303
#define CMD_READ_SRIX4K_TAG 0x0304
#define CMD_ISO_14443B_COMMAND 0x0305
#define CMD_SIMULATE_HITAG 0x0371
#define CMD_READER_HITAG 0x0372
-#define CMD_SIMULATE_TAG_HF_LISTEN 0x0380
-#define CMD_SIMULATE_TAG_ISO_14443 0x0381
-#define CMD_SNOOP_ISO_14443 0x0382
+#define CMD_SIMULATE_TAG_ISO_14443B 0x0381
+#define CMD_SNOOP_ISO_14443B 0x0382
#define CMD_SNOOP_ISO_14443a 0x0383
#define CMD_SIMULATE_TAG_ISO_14443a 0x0384
#define CMD_READER_ISO_14443a 0x0385