ADD: well, starting with a luascript for reading calypso tags, made me remake the 14b raw command on client and device side. Sorry @marshmellow42 , but this one broke your "hf 14b info" implementation. I fixed the "hf 14b read" and the hf search. So not to bad, but still a bit broken. The 14b raw device side is now very similar to 14a raw. Which is good. There is a Standard 14b 0x050008 detection and STmicroelectronic 0x0600 detection on deviceside. This removes a lot of code client side.

I also made the SRi read functions better by combining them.   The demodulation / uart code should be the same as last summers changes.  The device side code can now be even smaller.
This commit is contained in:
iceman1001 2016-03-20 19:33:07 +01:00
commit 6fc68747f6
17 changed files with 937 additions and 876 deletions

View file

@ -43,7 +43,6 @@ uint8_t *BigBuf_get_addr(void)
return (uint8_t *)BigBuf; return (uint8_t *)BigBuf;
} }
// get the address of the emulator memory. Allocate part of Bigbuf for it, if not yet done // get the address of the emulator memory. Allocate part of Bigbuf for it, if not yet done
uint8_t *BigBuf_get_EM_addr(void) uint8_t *BigBuf_get_EM_addr(void)
{ {
@ -54,12 +53,12 @@ uint8_t *BigBuf_get_EM_addr(void)
return emulator_memory; return emulator_memory;
} }
// clear ALL of BigBuf // clear ALL of BigBuf
void BigBuf_Clear(void) void BigBuf_Clear(void)
{ {
BigBuf_Clear_ext(true); BigBuf_Clear_ext(true);
} }
// clear ALL of BigBuf // clear ALL of BigBuf
void BigBuf_Clear_ext(bool verbose) void BigBuf_Clear_ext(bool verbose)
{ {
@ -86,7 +85,6 @@ uint8_t *BigBuf_malloc(uint16_t chunksize)
} }
} }
// free ALL allocated chunks. The whole BigBuf is available for traces or samples again. // free ALL allocated chunks. The whole BigBuf is available for traces or samples again.
void BigBuf_free(void) void BigBuf_free(void)
{ {
@ -96,7 +94,6 @@ void BigBuf_free(void)
// shouldn't this empty BigBuf also? // shouldn't this empty BigBuf also?
} }
// free allocated chunks EXCEPT the emulator memory // free allocated chunks EXCEPT the emulator memory
void BigBuf_free_keep_EM(void) void BigBuf_free_keep_EM(void)
{ {
@ -254,12 +251,10 @@ int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwP
// Emulator memory // Emulator memory
uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length){ uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length){
uint8_t* mem = BigBuf_get_EM_addr(); uint8_t* mem = BigBuf_get_EM_addr();
if(offset+length < CARD_MEMORY_SIZE) if(offset+length < CARD_MEMORY_SIZE) {
{
memcpy(mem+offset, data, length); memcpy(mem+offset, data, length);
return 0; return 0;
}else } else {
{
Dbprintf("Error, trying to set memory outside of bounds! %d > %d", (offset+length), CARD_MEMORY_SIZE); Dbprintf("Error, trying to set memory outside of bounds! %d > %d", (offset+length), CARD_MEMORY_SIZE);
return 1; return 1;
} }

View file

@ -1008,10 +1008,10 @@ void UsbPacketReceived(uint8_t *packet, int len)
case CMD_TEST_HITAGS_TRACES:// Tests every challenge within the given file case CMD_TEST_HITAGS_TRACES:// Tests every challenge within the given file
check_challenges((bool)c->arg[0],(byte_t*)c->d.asBytes); check_challenges((bool)c->arg[0],(byte_t*)c->d.asBytes);
break; break;
case CMD_READ_HITAG_S://Reader for only Hitag S tags, args = key or challenge case CMD_READ_HITAG_S: //Reader for only Hitag S tags, args = key or challenge
ReadHitagS((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes); ReadHitagS((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes);
break; break;
case CMD_WR_HITAG_S://writer for Hitag tags args=data to write,page and key or challenge case CMD_WR_HITAG_S: //writer for Hitag tags args=data to write,page and key or challenge
WritePageHitagS((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes,c->arg[2]); WritePageHitagS((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes,c->arg[2]);
break; break;
#endif #endif
@ -1059,11 +1059,8 @@ void UsbPacketReceived(uint8_t *packet, int len)
#endif #endif
#ifdef WITH_ISO14443b #ifdef WITH_ISO14443b
case CMD_READ_SRI512_TAG: case CMD_READ_SRI_TAG:
ReadSTMemoryIso14443b(0x0F); ReadSTMemoryIso14443b(c->arg[0]);
break;
case CMD_READ_SRIX4K_TAG:
ReadSTMemoryIso14443b(0x7F);
break; break;
case CMD_SNOOP_ISO_14443B: case CMD_SNOOP_ISO_14443B:
SnoopIso14443b(); SnoopIso14443b();
@ -1072,7 +1069,8 @@ void UsbPacketReceived(uint8_t *packet, int len)
SimulateIso14443bTag(); SimulateIso14443bTag();
break; break;
case CMD_ISO_14443B_COMMAND: case CMD_ISO_14443B_COMMAND:
SendRawCommand14443B(c->arg[0],c->arg[1],c->arg[2],c->d.asBytes); //SendRawCommand14443B(c->arg[0],c->arg[1],c->arg[2],c->d.asBytes);
SendRawCommand14443B_Ex(c);
break; break;
#endif #endif
@ -1086,14 +1084,12 @@ void UsbPacketReceived(uint8_t *packet, int len)
case CMD_SIMULATE_TAG_ISO_14443a: case CMD_SIMULATE_TAG_ISO_14443a:
SimulateIso14443aTag(c->arg[0], c->arg[1], c->d.asBytes); // ## Simulate iso14443a tag - pass tag type & UID SimulateIso14443aTag(c->arg[0], c->arg[1], c->d.asBytes); // ## Simulate iso14443a tag - pass tag type & UID
break; break;
case CMD_EPA_PACE_COLLECT_NONCE: case CMD_EPA_PACE_COLLECT_NONCE:
EPA_PACE_Collect_Nonce(c); EPA_PACE_Collect_Nonce(c);
break; break;
case CMD_EPA_PACE_REPLAY: case CMD_EPA_PACE_REPLAY:
EPA_PACE_Replay(c); EPA_PACE_Replay(c);
break; break;
case CMD_READER_MIFARE: case CMD_READER_MIFARE:
ReaderMifare(c->arg[0], c->arg[1]); ReaderMifare(c->arg[0], c->arg[1]);
break; break;

View file

@ -28,7 +28,7 @@
//#include "des.h" //#include "des.h"
//#include "aes.h" //#include "aes.h"
#include "desfire.h" #include "desfire.h"
#include "iso14443b.h"
extern const uint8_t OddByteParity[256]; extern const uint8_t OddByteParity[256];
extern int rsamples; // = 0; extern int rsamples; // = 0;
@ -101,7 +101,7 @@ void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode
/// iso14443.h /// iso14443.h
void SimulateIso14443bTag(void); void SimulateIso14443bTag(void);
void AcquireRawAdcSamplesIso14443b(uint32_t parameter); void AcquireRawAdcSamplesIso14443b(uint32_t parameter);
void ReadSTMemoryIso14443b(uint32_t); void ReadSTMemoryIso14443b(uint8_t numofblocks);
void RAMFUNC SnoopIso14443b(void); void RAMFUNC SnoopIso14443b(void);
void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]); void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]);

View file

@ -523,30 +523,31 @@ int EPA_Setup()
uint8_t uid[10]; uint8_t uid[10];
uint8_t pps_response[3]; uint8_t pps_response[3];
uint8_t pps_response_par[1]; uint8_t pps_response_par[1];
iso14a_card_select_t card_select_info; iso14a_card_select_t card_a_info;
iso14b_card_select_t card_b_info;
// first, look for type A cards // first, look for type A cards
// power up the field // power up the field
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
// select the card // select the card
return_code = iso14443a_select_card(uid, &card_select_info, NULL, true, 0); return_code = iso14443a_select_card(uid, &card_a_info, NULL, true, 0);
if (return_code == 1) { if (return_code == 1) {
// send the PPS request // send the PPS request
ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL); ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL);
return_code = ReaderReceive(pps_response, pps_response_par); return_code = ReaderReceive(pps_response, pps_response_par);
if (return_code != 3 || pps_response[0] != 0xD0) { if (return_code != 3 || pps_response[0] != 0xD0) {
return return_code == 0 ? 2 : return_code; return return_code == 0 ? 2 : return_code;
} }
Dbprintf("ISO 14443 Type A"); Dbprintf("ISO 14443 Type A");
iso_type = 'a'; iso_type = 'a';
return 0; return 0;
} }
// if we're here, there is no type A card, so we look for type B // if we're here, there is no type A card, so we look for type B
// power up the field // power up the field
iso14443b_setup(); iso14443b_setup();
// select the card // select the card
return_code = iso14443b_select_card(); return_code = iso14443b_select_card( &card_b_info );
if (return_code == 1) { if (return_code == 1) {
Dbprintf("ISO 14443 Type B"); Dbprintf("ISO 14443 Type B");
iso_type = 'b'; iso_type = 'b';

View file

@ -17,6 +17,7 @@
#include "cmd.h" #include "cmd.h"
#include "iso14443crc.h" #include "iso14443crc.h"
#include "iso14443a.h" #include "iso14443a.h"
#include "iso14443b.h"
#include "crapto1.h" #include "crapto1.h"
#include "mifareutil.h" #include "mifareutil.h"
#include "BigBuf.h" #include "BigBuf.h"
@ -187,12 +188,6 @@ void AppendCrc14443a(uint8_t* data, int len)
ComputeCrc14443(CRC_14443_A,data,len,data+len,data+len+1); ComputeCrc14443(CRC_14443_A,data,len,data+len,data+len+1);
} }
void AppendCrc14443b(uint8_t* data, int len)
{
ComputeCrc14443(CRC_14443_B,data,len,data+len,data+len+1);
}
//============================================================================= //=============================================================================
// ISO 14443 Type A - Miller decoder // ISO 14443 Type A - Miller decoder
//============================================================================= //=============================================================================
@ -745,13 +740,12 @@ static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *par
ToSend[++ToSendMax] = SEC_F; ToSend[++ToSendMax] = SEC_F;
// Convert from last byte pos to length // Convert from last byte pos to length
ToSendMax++; ++ToSendMax;
} }
static void CodeIso14443aAsTag(const uint8_t *cmd, uint16_t len) static void CodeIso14443aAsTag(const uint8_t *cmd, uint16_t len)
{ {
uint8_t par[MAX_PARITY_SIZE] = {0}; uint8_t par[MAX_PARITY_SIZE] = {0};
GetParity(cmd, len, par); GetParity(cmd, len, par);
CodeIso14443aAsTagPar(cmd, len, par); CodeIso14443aAsTagPar(cmd, len, par);
} }
@ -1427,7 +1421,7 @@ void PrepareDelayedTransfer(uint16_t delay)
for (i = 0; i < delay; ++i) for (i = 0; i < delay; ++i)
bitmask |= (0x01 << i); bitmask |= (0x01 << i);
ToSend[++ToSendMax] = 0x00; ToSend[++ToSendMax] = 0x00;
for (i = 0; i < ToSendMax; ++i) { for (i = 0; i < ToSendMax; ++i) {
bits_to_shift = ToSend[i] & bitmask; bits_to_shift = ToSend[i] & bitmask;
@ -2052,20 +2046,22 @@ void iso14443a_setup(uint8_t fpga_minor_mode) {
// Signal field is on with the appropriate LED // Signal field is on with the appropriate LED
if (fpga_minor_mode == FPGA_HF_ISO14443A_READER_MOD if (fpga_minor_mode == FPGA_HF_ISO14443A_READER_MOD
|| fpga_minor_mode == FPGA_HF_ISO14443A_READER_LISTEN) { || fpga_minor_mode == FPGA_HF_ISO14443A_READER_LISTEN)
LED_D_ON(); LED_D_ON();
} else { else
LED_D_OFF(); LED_D_OFF();
}
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | fpga_minor_mode); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | fpga_minor_mode);
DemodReset();
UartReset();
iso14a_set_timeout(10*106); // 10ms default
// Start the timer // Start the timer
StartCountSspClk(); StartCountSspClk();
DemodReset();
UartReset();
NextTransferTime = 2*DELAY_ARM2AIR_AS_READER; NextTransferTime = 2*DELAY_ARM2AIR_AS_READER;
iso14a_set_timeout(10*106); // 10ms default
} }
int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data) { int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data) {
@ -2119,13 +2115,14 @@ void ReaderIso14443a(UsbCommand *c)
if (param & ISO14A_REQUEST_TRIGGER) if (param & ISO14A_REQUEST_TRIGGER)
iso14a_set_trigger(TRUE); iso14a_set_trigger(TRUE);
if (param & ISO14A_CONNECT) { if (param & ISO14A_CONNECT) {
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
if(!(param & ISO14A_NO_SELECT)) { if(!(param & ISO14A_NO_SELECT)) {
iso14a_card_select_t *card = (iso14a_card_select_t*)buf; iso14a_card_select_t *card = (iso14a_card_select_t*)buf;
arg0 = iso14443a_select_card(NULL,card,NULL, true, 0); arg0 = iso14443a_select_card(NULL,card,NULL, true, 0);
cmd_send(CMD_ACK,arg0,card->uidlen,0,buf,sizeof(iso14a_card_select_t)); cmd_send(CMD_ACK,arg0,card->uidlen,0,buf,sizeof(iso14a_card_select_t));
// if it fails, the cmdhf14a.c client quites.. however this one still executes.
if ( arg0 == 0 ) return;
} }
} }

View file

@ -8,17 +8,12 @@
// Routines to support ISO 14443B. This includes both the reader software and // Routines to support ISO 14443B. This includes both the reader software and
// the `fake tag' modes. // the `fake tag' modes.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "iso14443b.h"
#include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
#include "iso14443crc.h"
#include "common.h"
#define RECEIVE_SAMPLES_TIMEOUT 20000 #define RECEIVE_SAMPLES_TIMEOUT 20000
#define ISO14443B_DMA_BUFFER_SIZE 256 #define ISO14443B_DMA_BUFFER_SIZE 256
// PCB Block number for APDUs // the block number for the ISO14443-4 PCB (used with APDUs)
static uint8_t pcb_blocknum = 0; static uint8_t pcb_blocknum = 0;
//============================================================================= //=============================================================================
@ -100,7 +95,7 @@ static void DemodReset()
Demod.bitCount = 0; Demod.bitCount = 0;
Demod.thisBit = 0; Demod.thisBit = 0;
Demod.shiftReg = 0; Demod.shiftReg = 0;
memset(Demod.output, 0x00, MAX_FRAME_SIZE); //memset(Demod.output, 0x00, MAX_FRAME_SIZE);
} }
@ -111,6 +106,11 @@ static void DemodInit(uint8_t *data)
} }
void AppendCrc14443b(uint8_t* data, int len)
{
ComputeCrc14443(CRC_14443_B,data,len,data+len,data+len+1);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Code up a string of octets at layer 2 (including CRC, we don't generate // 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 // that here) so that they can be transmitted to the reader. Doesn't transmit
@ -195,7 +195,7 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len)
} }
// Convert from last byte pos to length // Convert from last byte pos to length
ToSendMax++; ++ToSendMax;
} }
@ -372,13 +372,13 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len)
void SimulateIso14443bTag(void) void SimulateIso14443bTag(void)
{ {
// the only commands we understand is WUPB, AFI=0, Select All, N=1: // the only commands we understand is WUPB, AFI=0, Select All, N=1:
static const uint8_t cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 }; // WUPB static const uint8_t cmd1[] = { ISO14443B_REQB, 0x00, 0x08, 0x39, 0x73 }; // WUPB
// ... and REQB, AFI=0, Normal Request, N=1: // ... and REQB, AFI=0, Normal Request, N=1:
static const uint8_t cmd2[] = { 0x05, 0x00, 0x00, 0x71, 0xFF }; // REQB static const uint8_t cmd2[] = { ISO14443B_REQB, 0x00, 0x00, 0x71, 0xFF }; // REQB
// ... and HLTB // ... and HLTB
static const uint8_t cmd3[] = { 0x50, 0xff, 0xff, 0xff, 0xff }; // HLTB static const uint8_t cmd3[] = { ISO14443B_HALT, 0xff, 0xff, 0xff, 0xff }; // HLTB
// ... and ATTRIB // ... and ATTRIB
static const uint8_t cmd4[] = { 0x1D, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; // ATTRIB static const uint8_t cmd4[] = { ISO14443B_ATTRIB, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; // ATTRIB
// ... and we always respond with ATQB, PUPI = 820de174, Application Data = 0x20381922, // ... and we always respond with ATQB, PUPI = 820de174, Application Data = 0x20381922,
// supports only 106kBit/s in both directions, max frame size = 32Bytes, // supports only 106kBit/s in both directions, max frame size = 32Bytes,
@ -390,8 +390,6 @@ void SimulateIso14443bTag(void)
// response to HLTB and ATTRIB // response to HLTB and ATTRIB
static const uint8_t response2[] = {0x00, 0x78, 0xF0}; static const uint8_t response2[] = {0x00, 0x78, 0xF0};
//uint8_t parity[MAX_PARITY_SIZE] = {0x00};
FpgaDownloadAndGo(FPGA_BITSTREAM_HF); FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
clear_trace(); clear_trace();
@ -435,7 +433,6 @@ void SimulateIso14443bTag(void)
} }
if (tracing) if (tracing)
//LogTrace(receivedCmd, len, 0, 0, parity, TRUE);
LogTrace(receivedCmd, len, 0, 0, NULL, TRUE); LogTrace(receivedCmd, len, 0, 0, NULL, TRUE);
@ -454,6 +451,7 @@ void SimulateIso14443bTag(void)
respCodeLen = resp2CodeLen; respCodeLen = resp2CodeLen;
} else { } else {
Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsRecvd); Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsRecvd);
// And print whether the CRC fails, just for good measure // And print whether the CRC fails, just for good measure
uint8_t b1, b2; uint8_t b1, b2;
if (len >= 3){ // if crc exists if (len >= 3){ // if crc exists
@ -475,9 +473,9 @@ void SimulateIso14443bTag(void)
//break; //break;
} }
cmdsRecvd++; ++cmdsRecvd;
if(cmdsRecvd > 0x30) { if(cmdsRecvd > 0xFF) {
DbpString("many commands later..."); DbpString("many commands later...");
break; break;
} }
@ -493,26 +491,25 @@ void SimulateIso14443bTag(void)
// Transmit the response. // Transmit the response.
uint16_t i = 0; uint16_t i = 0;
volatile uint8_t b;
for(;;) { for(;;) {
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
uint8_t b = respCode[i]; uint8_t b = respCode[i];
AT91C_BASE_SSC->SSC_THR = b; AT91C_BASE_SSC->SSC_THR = b;
i++; ++i;
if(i > respCodeLen) { if(i > respCodeLen)
break; break;
}
} }
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
volatile uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
(void)b; (void)b;
} }
} }
// trace the response:
if (tracing) if (tracing)
//LogTrace(resp, respLen, 0, 0, parity, FALSE);
LogTrace(resp, respLen, 0, 0, NULL, FALSE); LogTrace(resp, respLen, 0, 0, NULL, FALSE);
} }
} }
@ -604,6 +601,10 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq)
} \ } \
} }
//note: couldn't we just use MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2) from common.h - marshmellow
#define CHECK_FOR_SUBCARRIER_duo() { \
v = MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2); \
}
switch(Demod.state) { switch(Demod.state) {
case DEMOD_UNSYNCD: case DEMOD_UNSYNCD:
@ -758,10 +759,11 @@ static void GetSamplesFor14443bDemod(int n, bool quiet)
// Allocate memory from BigBuf for some buffers // Allocate memory from BigBuf for some buffers
// free all previous allocations first // free all previous allocations first
BigBuf_free(); ///BigBuf_free();
// The response (tag -> reader) that we're receiving. // The response (tag -> reader) that we're receiving.
// Set up the demodulator for tag -> reader responses. // Set up the demodulator for tag -> reader responses.
// this init, can take some time to execute, memset
DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
// The DMA buffer, used to stream samples from the FPGA // The DMA buffer, used to stream samples from the FPGA
@ -798,15 +800,15 @@ static void GetSamplesFor14443bDemod(int n, bool quiet)
samples += 2; samples += 2;
// // is this | 0x01 the error? & 0xfe in https://github.com/Proxmark/proxmark3/issues/103
gotFrame = Handle14443bSamplesDemod(ci , cq ); // can we double this?
gotFrame = Handle14443bSamplesDemod(ci<<2 , cq<<2);
if ( gotFrame ) if ( gotFrame )
break; break;
} }
if(samples > n || gotFrame) { if(samples > n || gotFrame)
break; break;
}
} }
//disable //disable
@ -824,9 +826,8 @@ static void GetSamplesFor14443bDemod(int n, bool quiet)
); );
} }
//Tracing if (tracing > 0)
if (Demod.len > 0) LogTrace(Demod.output, Demod.len, samples, samples, NULL, FALSE);
LogTrace(Demod.output, Demod.len, 0, 0, NULL, FALSE);
} }
@ -890,14 +891,14 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len)
ToSendReset(); ToSendReset();
// Establish initial reference level // Establish initial reference level
for(i = 0; i < 40; i++) for(i = 0; i < 40; ++i)
ToSendStuffBit(1); ToSendStuffBit(1);
// Send SOF // Send SOF
for(i = 0; i < 10; i++) for(i = 0; i < 10; ++i)
ToSendStuffBit(0); ToSendStuffBit(0);
for(i = 0; i < len; i++) { for(i = 0; i < len; ++i) {
// Stop bits/EGT // Stop bits/EGT
ToSendStuffBit(1); ToSendStuffBit(1);
ToSendStuffBit(1); ToSendStuffBit(1);
@ -905,7 +906,7 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len)
ToSendStuffBit(0); ToSendStuffBit(0);
// Data bits // Data bits
b = cmd[i]; b = cmd[i];
for(j = 0; j < 8; j++) { for(j = 0; j < 8; ++j) {
if(b & 1) if(b & 1)
ToSendStuffBit(1); ToSendStuffBit(1);
else else
@ -916,16 +917,16 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len)
} }
// Send EOF // Send EOF
ToSendStuffBit(1); ToSendStuffBit(1);
for(i = 0; i < 10; i++) for(i = 0; i < 10; ++i)
ToSendStuffBit(0); ToSendStuffBit(0);
for(i = 0; i < 8; i++) for(i = 0; i < 8; ++i)
ToSendStuffBit(1); ToSendStuffBit(1);
// And then a little more, to make sure that the last character makes // And then a little more, to make sure that the last character makes
// it out before we switch to rx mode. // it out before we switch to rx mode.
for(i = 0; i < 24; i++) for(i = 0; i < 24; ++i)
ToSendStuffBit(1); ToSendStuffBit(1);
// Convert from last character reference to length // Convert from last character reference to length
@ -940,18 +941,18 @@ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len)
{ {
CodeIso14443bAsReader(cmd, len); CodeIso14443bAsReader(cmd, len);
TransmitFor14443b(); TransmitFor14443b();
if (tracing) {
//uint8_t parity[MAX_PARITY_SIZE]; if(trigger) LED_A_ON();
//LogTrace(cmd,len, 0, 0, parity, TRUE);
LogTrace(cmd,len, 0, 0, NULL, TRUE); if (tracing) LogTrace(cmd, len, 0, 0, NULL, TRUE);
}
} }
/* Sends an APDU to the tag /* Sends an APDU to the tag
* TODO: check CRC and preamble * TODO: check CRC and preamble
*/ */
int iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response) uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response)
{ {
uint8_t crc[2] = {0x00, 0x00};
uint8_t message_frame[message_length + 4]; uint8_t message_frame[message_length + 4];
// PCB // PCB
message_frame[0] = 0x0A | pcb_blocknum; message_frame[0] = 0x0A | pcb_blocknum;
@ -969,7 +970,11 @@ int iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *respo
if(Demod.len < 3) if(Demod.len < 3)
return 0; return 0;
// TODO: Check CRC // VALIDATE CRC
ComputeCrc14443(CRC_14443_B, Demod.output, Demod.len-2, &crc[0], &crc[1]);
if ( crc[0] != Demod.output[Demod.len-2] || crc[1] != Demod.output[Demod.len-1] )
return 0;
// copy response contents // copy response contents
if(response != NULL) if(response != NULL)
memcpy(response, Demod.output, Demod.len); memcpy(response, Demod.output, Demod.len);
@ -977,43 +982,120 @@ int iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *respo
return Demod.len; return Demod.len;
} }
/**
* SRx Initialise.
*/
uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card )
{
// INITIATE command: wake up the tag using the INITIATE
static const uint8_t init_srx[] = { ISO14443B_INITIATE, 0x00, 0x97, 0x5b };
// SELECT command (with space for CRC)
uint8_t select_srx[] = { ISO14443B_SELECT, 0x00, 0x00, 0x00};
// temp to calc crc.
uint8_t crc[2] = {0x00, 0x00};
CodeAndTransmit14443bAsReader(init_srx, sizeof(init_srx));
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
if (Demod.len == 0) return 2;
// Randomly generated Chip ID
if (card) card->chipid = Demod.output[0];
select_srx[1] = Demod.output[0];
ComputeCrc14443(CRC_14443_B, select_srx, 2, &select_srx[2], &select_srx[3]);
CodeAndTransmit14443bAsReader(select_srx, sizeof(select_srx));
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
if (Demod.len != 3) return 2;
// Check the CRC of the answer:
ComputeCrc14443(CRC_14443_B, Demod.output, Demod.len-2 , &crc[0], &crc[1]);
if(crc[0] != Demod.output[1] || crc[1] != Demod.output[2]) return 3;
// Check response from the tag: should be the same UID as the command we just sent:
if (select_srx[1] != Demod.output[0]) return 1;
// First get the tag's UID:
select_srx[0] = ISO14443B_GET_UID;
ComputeCrc14443(CRC_14443_B, select_srx, 1 , &select_srx[1], &select_srx[2]);
CodeAndTransmit14443bAsReader(select_srx, 3); // Only first three bytes for this one
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
if (Demod.len != 10) return 2;
// The check the CRC of the answer
ComputeCrc14443(CRC_14443_B, Demod.output, Demod.len-2, &crc[0], &crc[1]);
if(crc[0] != Demod.output[8] || crc[1] != Demod.output[9]) return 3;
if (card) {
card->uidlen = 8;
memcpy(card->uid, Demod.output, 8);
}
return 0;
}
/* Perform the ISO 14443 B Card Selection procedure /* Perform the ISO 14443 B Card Selection procedure
* Currently does NOT do any collision handling. * Currently does NOT do any collision handling.
* It expects 0-1 cards in the device's range. * It expects 0-1 cards in the device's range.
* TODO: Support multiple cards (perform anticollision) * TODO: Support multiple cards (perform anticollision)
* TODO: Verify CRC checksums * TODO: Verify CRC checksums
*/ */
int iso14443b_select_card() uint8_t iso14443b_select_card(iso14b_card_select_t *card )
{ {
// WUPB command (including CRC) // WUPB command (including CRC)
// Note: WUPB wakes up all tags, REQB doesn't wake up tags in HALT state // Note: WUPB wakes up all tags, REQB doesn't wake up tags in HALT state
static const uint8_t wupb[] = { 0x05, 0x00, 0x08, 0x39, 0x73 }; static const uint8_t wupb[] = { ISO14443B_REQB, 0x00, 0x08, 0x39, 0x73 };
// ATTRIB command (with space for CRC) // ATTRIB command (with space for CRC)
uint8_t attrib[] = { 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00}; uint8_t attrib[] = { ISO14443B_ATTRIB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00};
// temp to calc crc.
uint8_t crc[2] = {0x00, 0x00};
// first, wake up the tag // first, wake up the tag
CodeAndTransmit14443bAsReader(wupb, sizeof(wupb)); CodeAndTransmit14443bAsReader(wupb, sizeof(wupb));
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
// ATQB too short?
if (Demod.len < 14)
return 2;
// select the tag // ATQB too short?
if (Demod.len < 14) return 2;
// VALIDATE CRC
ComputeCrc14443(CRC_14443_B, Demod.output, Demod.len-2, &crc[0], &crc[1]);
if ( crc[0] != Demod.output[12] || crc[1] != Demod.output[13] )
return 3;
if (card) {
card->uidlen = 4;
memcpy(card->uid, Demod.output+1, 4);
memcpy(card->atqb, Demod.output+5, 7);
}
// copy the PUPI to ATTRIB // copy the PUPI to ATTRIB
memcpy(attrib + 1, Demod.output + 1, 4); memcpy(attrib + 1, Demod.output + 1, 4);
/* copy the protocol info from ATQB (Protocol Info -> Protocol_Type) into
ATTRIB (Param 3) */ // copy the protocol info from ATQB (Protocol Info -> Protocol_Type) into ATTRIB (Param 3)
attrib[7] = Demod.output[10] & 0x0F; attrib[7] = Demod.output[10] & 0x0F;
ComputeCrc14443(CRC_14443_B, attrib, 9, attrib + 9, attrib + 10); ComputeCrc14443(CRC_14443_B, attrib, 9, attrib + 9, attrib + 10);
CodeAndTransmit14443bAsReader(attrib, sizeof(attrib)); CodeAndTransmit14443bAsReader(attrib, sizeof(attrib));
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
// Answer to ATTRIB too short? // Answer to ATTRIB too short?
if(Demod.len < 3) if(Demod.len < 3) return 2;
return 2;
// VALIDATE CRC
ComputeCrc14443(CRC_14443_B, Demod.output, Demod.len-2, &crc[0], &crc[1]);
if ( crc[0] != Demod.output[1] || crc[1] != Demod.output[2] )
return 3;
// CID
if (card) card->cid = Demod.output[0];
// reset PCB block number // reset PCB block number
pcb_blocknum = 0; pcb_blocknum = 0;
return 1; return 0;
} }
// Set up ISO 14443 Type B communication (similar to iso14443a_setup) // Set up ISO 14443 Type B communication (similar to iso14443a_setup)
@ -1034,7 +1116,7 @@ void iso14443b_setup() {
// Signal field is on with the appropriate LED // Signal field is on with the appropriate LED
LED_D_ON(); LED_D_ON();
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);
SpinDelay(200); SpinDelay(400);
// Start the timer // Start the timer
StartCountSspClk(); StartCountSspClk();
@ -1049,7 +1131,7 @@ void iso14443b_setup() {
// //
// I tried to be systematic and check every answer of the tag, every CRC, etc... // I tried to be systematic and check every answer of the tag, every CRC, etc...
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void ReadSTMemoryIso14443b(uint32_t dwLast) void ReadSTMemoryIso14443b(uint8_t numofblocks)
{ {
FpgaDownloadAndGo(FPGA_BITSTREAM_HF); FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
clear_trace(); clear_trace();
@ -1070,10 +1152,10 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
// Signal field is on with the appropriate LED // Signal field is on with the appropriate LED
LED_D_ON(); LED_D_ON();
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);
SpinDelay(200); SpinDelay(300);
// First command: wake up the tag using the INITIATE command // First command: wake up the tag using the INITIATE command
uint8_t cmd1[] = {0x06, 0x00, 0x97, 0x5b}; uint8_t cmd1[] = {ISO14443B_INITIATE, 0x00, 0x97, 0x5b};
CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1)); CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
@ -1088,7 +1170,7 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
// There is a response, SELECT the uid // There is a response, SELECT the uid
DbpString("Now SELECT tag:"); DbpString("Now SELECT tag:");
cmd1[0] = 0x0E; // 0x0E is SELECT cmd1[0] = ISO14443B_SELECT; // 0x0E is SELECT
cmd1[1] = Demod.output[0]; cmd1[1] = Demod.output[0];
ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]); ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);
CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1)); CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
@ -1114,7 +1196,7 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
// Tag is now selected, // Tag is now selected,
// First get the tag's UID: // First get the tag's UID:
cmd1[0] = 0x0B; cmd1[0] = ISO14443B_GET_UID;
ComputeCrc14443(CRC_14443_B, cmd1, 1 , &cmd1[1], &cmd1[2]); ComputeCrc14443(CRC_14443_B, cmd1, 1 , &cmd1[1], &cmd1[2]);
CodeAndTransmit14443bAsReader(cmd1, 3); // Only first three bytes for this one CodeAndTransmit14443bAsReader(cmd1, 3); // Only first three bytes for this one
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
@ -1135,12 +1217,13 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
(Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0]); (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0]);
// Now loop to read all 16 blocks, address from 0 to last block // Now loop to read all 16 blocks, address from 0 to last block
Dbprintf("Tag memory dump, block 0 to %d", dwLast); Dbprintf("Tag memory dump, block 0 to %d", numofblocks);
cmd1[0] = 0x08; cmd1[0] = 0x08;
i = 0x00; i = 0x00;
dwLast++; ++numofblocks;
for (;;) { for (;;) {
if (i == dwLast) { if (i == numofblocks) {
DbpString("System area block (0xff):"); DbpString("System area block (0xff):");
i = 0xff; i = 0xff;
} }
@ -1148,9 +1231,10 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]); ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);
CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1)); CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
if (Demod.len != 6) { // Check if we got an answer from the tag if (Demod.len != 6) { // Check if we got an answer from the tag
DbpString("Expected 6 bytes from tag, got less..."); DbpString("Expected 6 bytes from tag, got less...");
return; return;
} }
// The check the CRC of the answer (use cmd1 as temporary variable): // The check the CRC of the answer (use cmd1 as temporary variable):
ComputeCrc14443(CRC_14443_B, Demod.output, 4, &cmd1[2], &cmd1[3]); ComputeCrc14443(CRC_14443_B, Demod.output, 4, &cmd1[2], &cmd1[3]);
@ -1163,16 +1247,14 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
Dbprintf("Address=%02x, Contents=%08x, CRC=%04x", i, Dbprintf("Address=%02x, Contents=%08x, CRC=%04x", i,
(Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0], (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0],
(Demod.output[4]<<8)+Demod.output[5]); (Demod.output[4]<<8)+Demod.output[5]);
if (i == 0xff) {
break; if (i == 0xff) break;
} ++i;
i++;
} }
set_tracing(FALSE); set_tracing(FALSE);
} }
//============================================================================= //=============================================================================
// 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.
@ -1236,7 +1318,6 @@ void RAMFUNC SnoopIso14443b(void)
upTo = dmaBuf; upTo = dmaBuf;
lastRxCounter = ISO14443B_DMA_BUFFER_SIZE; lastRxCounter = ISO14443B_DMA_BUFFER_SIZE;
FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE); FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE);
//uint8_t parity[MAX_PARITY_SIZE] = {0x00};
bool TagIsActive = FALSE; bool TagIsActive = FALSE;
bool ReaderIsActive = FALSE; bool ReaderIsActive = FALSE;
@ -1245,10 +1326,8 @@ void RAMFUNC SnoopIso14443b(void)
for(;;) { for(;;) {
int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) & int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) &
(ISO14443B_DMA_BUFFER_SIZE-1); (ISO14443B_DMA_BUFFER_SIZE-1);
if(behindBy > maxBehindBy) {
maxBehindBy = behindBy;
}
if(behindBy > maxBehindBy) maxBehindBy = behindBy;
if(behindBy < 2) continue; if(behindBy < 2) continue;
ci = upTo[0]; ci = upTo[0];
@ -1281,27 +1360,27 @@ void RAMFUNC SnoopIso14443b(void)
if (!TagIsActive) { // no need to try decoding reader data if the tag is sending if (!TagIsActive) { // no need to try decoding reader data if the tag is sending
if (Handle14443bUartBit(ci & 0x01)) { if (Handle14443bUartBit(ci & 0x01)) {
if(triggered && tracing) {
//LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, TRUE); if(triggered && tracing)
LogTrace(Uart.output, Uart.byteCnt, samples, samples, NULL, TRUE); LogTrace(Uart.output, Uart.byteCnt, samples, samples, NULL, TRUE);
}
/* And ready to receive another command. */ /* And ready to receive another command. */
UartReset(); UartReset();
/* And also reset the demod code, which might have been */ /* And also reset the demod code, which might have been */
/* false-triggered by the commands from the reader. */ /* false-triggered by the commands from the reader. */
DemodReset(); DemodReset();
} }
if (Handle14443bUartBit(cq & 0x01)) { if (Handle14443bUartBit(cq & 0x01)) {
if(triggered && tracing) { if(triggered && tracing)
//LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, TRUE);
LogTrace(Uart.output, Uart.byteCnt, samples, samples, NULL, TRUE); LogTrace(Uart.output, Uart.byteCnt, samples, samples, NULL, TRUE);
}
/* And ready to receive another command. */ /* And ready to receive another command. */
UartReset(); UartReset();
/* And also reset the demod code, which might have been */ /* And also reset the demod code, which might have been */
/* false-triggered by the commands from the reader. */ /* false-triggered by the commands from the reader. */
DemodReset(); DemodReset();
} }
ReaderIsActive = (Uart.state > STATE_GOT_FALLING_EDGE_OF_SOF); ReaderIsActive = (Uart.state > STATE_GOT_FALLING_EDGE_OF_SOF);
} }
@ -1311,7 +1390,6 @@ void RAMFUNC SnoopIso14443b(void)
//Use samples as a time measurement //Use samples as a time measurement
if(tracing) if(tracing)
//LogTrace(Demod.output, Demod.len, samples, samples, parity, FALSE);
LogTrace(Demod.output, Demod.len, samples, samples, NULL, FALSE); LogTrace(Demod.output, Demod.len, samples, samples, NULL, FALSE);
triggered = TRUE; triggered = TRUE;
@ -1336,47 +1414,94 @@ void RAMFUNC SnoopIso14443b(void)
set_tracing(FALSE); set_tracing(FALSE);
} }
void iso14b_set_trigger(bool enable) {
trigger = enable;
}
/* /*
* Send raw command to tag ISO14443B * Send raw command to tag ISO14443B
* @Input * @Input
* datalen len of buffer data * param flags enum ISO14B_COMMAND. (mifare.h)
* recv bool when true wait for data from tag and send to client * len len of buffer data
* powerfield bool leave the field on when true * data buffer with bytes to send
* data buffer with byte to send
* *
* @Output * @Output
* none * none
* *
*/ */
void SendRawCommand14443B(uint32_t datalen, uint32_t recv, uint8_t powerfield, uint8_t data[]) void SendRawCommand14443B_Ex(UsbCommand *c)
{ {
// param ISO_ iso14b_command_t param = c->arg[0];
// param ISO_CONNECT size_t len = c->arg[1] & 0xffff;
// param ISO14A_NO_DISCONNECT uint8_t *cmd = c->d.asBytes;
//if (param & ISO14A_NO_DISCONNECT) uint8_t status = 0;
// return; uint32_t sendlen = sizeof(iso14b_card_select_t);
iso14443b_setup(); uint8_t buf[USB_CMD_DATA_SIZE] = {0x00};
if ( datalen == 0 && recv == 0 && powerfield == 0){ if (MF_DBGLEVEL > 3) Dbprintf("param, %04x", param );
} else { // turn on trigger (LED_A)
if (param & ISO14B_REQUEST_TRIGGER)
iso14b_set_trigger(TRUE);
if (param & ISO14B_CONNECT) {
// 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);
clear_trace(); clear_trace();
set_tracing(TRUE); iso14443b_setup();
CodeAndTransmit14443bAsReader(data, datalen);
} }
if (recv) { set_tracing(TRUE);
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, FALSE);
uint16_t len = MIN(Demod.len, USB_CMD_DATA_SIZE); if ( param & ISO14B_SELECT_STD) {
cmd_send(CMD_ACK, len, 0, 0, Demod.output, len); iso14b_card_select_t *card = (iso14b_card_select_t*)buf;
status = iso14443b_select_card(card);
cmd_send(CMD_ACK, status, sendlen, 0, buf, sendlen);
// 0: OK 2: attrib fail, 3:crc fail,
if ( status > 0 ) return;
} }
if (!powerfield) { if ( param & ISO14B_SELECT_SR) {
iso14b_card_select_t *card = (iso14b_card_select_t*)buf;
status = iso14443b_select_srx_card(card);
cmd_send(CMD_ACK, status, sendlen, 0, buf, sendlen);
// 0: OK 2: attrib fail, 3:crc fail,
if ( status > 0 ) return;
}
if (param & ISO14B_APDU) {
status = iso14443b_apdu(cmd, len, buf);
cmd_send(CMD_ACK, status, status, 0, buf, status);
}
if (param & ISO14B_RAW) {
if(param & ISO14B_APPEND_CRC) {
AppendCrc14443b(cmd, len);
len += 2;
}
CodeAndTransmit14443bAsReader(cmd, len);
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
sendlen = MIN(Demod.len, USB_CMD_DATA_SIZE);
status = (Demod.len > 0) ? 0 : 1;
cmd_send(CMD_ACK, status, sendlen, 0, Demod.output, sendlen);
}
// turn off trigger (LED_A)
if (param & ISO14B_REQUEST_TRIGGER)
iso14a_set_trigger(FALSE);
// turn off antenna et al
// we don't send a HALT command.
if ( param & ISO14B_DISCONNECT) {
if (MF_DBGLEVEL > 3) Dbprintf("disconnect");
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
FpgaDisableSscDma(); FpgaDisableSscDma();
set_tracing(FALSE); set_tracing(FALSE);
LED_D_OFF(); LEDsoff();
} }
} }

View file

@ -7,15 +7,29 @@
// at your option, any later version. See the LICENSE.txt file for the text of // at your option, any later version. See the LICENSE.txt file for the text of
// the license. // the license.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Routines to support ISO 14443 type A. // Routines to support ISO 14443 type B.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#ifndef __ISO14443B_H #ifndef __ISO14443B_H
#define __ISO14443B_H #define __ISO14443B_H
#include "common.h"
int iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response); #include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
#include "iso14443crc.h"
#include "common.h"
#include "mifare.h"
#include "protocols.h"
#include "mifareutil.h" // access to global variable: MF_DBGLEVEL
extern void AppendCrc14443b(uint8_t *data, int len);
uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response);
void iso14443b_setup(); void iso14443b_setup();
int iso14443b_select_card(); uint8_t iso14443b_select_card(iso14b_card_select_t* card);
uint8_t iso14443b_select_card_srx(iso14b_card_select_t* card);
void SendRawCommand14443B_Ex(UsbCommand *c);
#endif /* __ISO14443B_H */ #endif /* __ISO14443B_H */

View file

@ -317,21 +317,7 @@ static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *
// every other is Q. We just want power, so abs(I) + abs(Q) is // every other is Q. We just want power, so abs(I) + abs(Q) is
// close to what we want. // close to what we want.
if(getNext) { if(getNext) {
int8_t r; int8_t r = ABS(b) + ABS(prev);
r = ABS(b);
// if(b < 0) {
// r = -b;
// } else {
// r = b;
// }
// ABS(prev)
if(prev < 0) {
r -= prev;
} else {
r += prev;
}
dest[c++] = (uint8_t)r; dest[c++] = (uint8_t)r;
@ -466,19 +452,7 @@ static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int
// every other is Q. We just want power, so abs(I) + abs(Q) is // every other is Q. We just want power, so abs(I) + abs(Q) is
// close to what we want. // close to what we want.
if(getNext) { if(getNext) {
int8_t r; int8_t r = ABS(b) + ABS(prev);
r = ABS(b);
// if(b < 0) {
// r = -b;
// } else {
// r = b;
// }
if(prev < 0) {
r -= prev;
} else {
r += prev;
}
dest[c++] = (uint8_t)r; dest[c++] = (uint8_t)r;
@ -647,18 +621,7 @@ void AcquireRawAdcSamplesIso15693(void)
// every other is Q. We just want power, so abs(I) + abs(Q) is // every other is Q. We just want power, so abs(I) + abs(Q) is
// close to what we want. // close to what we want.
if(getNext) { if(getNext) {
int8_t r; int8_t r = ABS(b) + ABS(prev);
if(b < 0) {
r = -b;
} else {
r = b;
}
if(prev < 0) {
r -= prev;
} else {
r += prev;
}
dest[c++] = (uint8_t)r; dest[c++] = (uint8_t)r;
@ -712,18 +675,7 @@ void RecordRawAdcSamplesIso15693(void)
// every other is Q. We just want power, so abs(I) + abs(Q) is // every other is Q. We just want power, so abs(I) + abs(Q) is
// close to what we want. // close to what we want.
if(getNext) { if(getNext) {
int8_t r; int8_t r = ABS(b) + ABS(prev);
if(b < 0) {
r = -b;
} else {
r = b;
}
if(prev < 0) {
r -= prev;
} else {
r += prev;
}
dest[c++] = (uint8_t)r; dest[c++] = (uint8_t)r;

View file

@ -734,7 +734,7 @@ int CmdHF14ACmdRaw(const char *cmd) {
datalen = (datalen > USB_CMD_DATA_SIZE) ? USB_CMD_DATA_SIZE : datalen; datalen = (datalen > USB_CMD_DATA_SIZE) ? USB_CMD_DATA_SIZE : datalen;
c.arg[1] = (datalen & 0xFFFF) | (uint32_t)(numbits << 16); c.arg[1] = (datalen & 0xFFFF) | (uint32_t)(numbits << 16);
memcpy(c.d.asBytes,data,datalen); memcpy(c.d.asBytes, data, datalen);
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
@ -749,26 +749,15 @@ int CmdHF14ACmdRaw(const char *cmd) {
} }
static void waitCmd(uint8_t iSelect) { static void waitCmd(uint8_t iSelect) {
uint8_t *recv;
UsbCommand resp; UsbCommand resp;
char *hexout; uint16_t len = 0;
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
recv = resp.d.asBytes; len = iSelect ? (resp.arg[1] & 0xffff) : (resp.arg[0] & 0xffff);
uint8_t iLen = iSelect ? resp.arg[1] : resp.arg[0]; PrintAndLog("received %i octets", len);
PrintAndLog("received %i octets",iLen); if(!len)
if(!iLen)
return; return;
hexout = (char *)malloc(iLen * 3 + 1); PrintAndLog("%s", sprint_hex(resp.d.asBytes, len) );
if (hexout != NULL) {
for (int i = 0; i < iLen; i++) { // data in hex
sprintf(&hexout[i * 3], "%02X ", recv[i]);
}
PrintAndLog("%s", hexout);
free(hexout);
} else {
PrintAndLog("malloc failed your client has low memory?");
}
} else { } else {
PrintAndLog("timeout while waiting for reply."); PrintAndLog("timeout while waiting for reply.");
} }

File diff suppressed because it is too large Load diff

View file

@ -11,14 +11,46 @@
#ifndef CMDHF14B_H__ #ifndef CMDHF14B_H__
#define CMDHF14B_H__ #define CMDHF14B_H__
#include "iso14443crc.h"
#include "proxmark3.h"
#include "data.h"
#include "graph.h"
#include "util.h"
#include "ui.h"
#include "cmdparser.h"
#include "cmdmain.h"
#include "cmdhf14a.h"
#include "tea.h"
#include "cmdhf.h"
#include "prng.h"
#include "sha1.h"
#include "mifare.h" // structs/enum for ISO14B
#include "protocols.h" // definitions of ISO14B protocol
int usage_hf_14b_info(void);
int usage_hf_14b_reader(void);
int usage_hf_14b_raw(void);
int usage_hf_14b_snoop(void);
int usage_hf_14b_sim(void);
int usage_hf_14b_read_srx(void);
int usage_hf_14b_write_srx(void);
int CmdHF14B(const char *Cmd); int CmdHF14B(const char *Cmd);
int CmdHF14BList(const char *Cmd); int CmdHF14BList(const char *Cmd);
int CmdHF14BInfo(const char *Cmd); int CmdHF14BInfo(const char *Cmd);
int CmdHF14BSim(const char *Cmd); int CmdHF14BSim(const char *Cmd);
int CmdHF14BSnoop(const char *Cmd); int CmdHF14BSnoop(const char *Cmd);
int CmdSri512Read(const char *Cmd);
int CmdSrix4kRead(const char *Cmd);
int CmdHF14BWrite( const char *cmd); int CmdHF14BWrite( const char *cmd);
int HF14BInfo(bool verbose); int CmdHF14BReader(const char *Cmd);
bool HF14BInfo(bool verbose);
bool HF14BReader(bool verbose);
int CmdHF14BCmdRaw (const char *Cmd);
// SRi ST Microelectronics read/write
int CmdHF14BReadSri(const char *Cmd);
int CmdHF14BWriteSri(const char *Cmd);
bool waitCmd(bool verbose);
#endif #endif

View file

@ -101,8 +101,7 @@ typedef struct {
// For the 13.56 MHz tags // For the 13.56 MHz tags
#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300 #define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300
#define CMD_READ_SRI512_TAG 0x0303 #define CMD_READ_SRI_TAG 0x0303
#define CMD_READ_SRIX4K_TAG 0x0304
#define CMD_ISO_14443B_COMMAND 0x0305 #define CMD_ISO_14443B_COMMAND 0x0305
#define CMD_READER_ISO_15693 0x0310 #define CMD_READER_ISO_15693 0x0310
#define CMD_SIMTAG_ISO_15693 0x0311 #define CMD_SIMTAG_ISO_15693 0x0311

View file

@ -67,8 +67,7 @@ local _commands = {
--// For the 13.56 MHz tags --// For the 13.56 MHz tags
CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 = 0x0300, CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 = 0x0300,
CMD_READ_SRI512_TAG = 0x0303, CMD_READ_SRI_TAG = 0x0303,
CMD_READ_SRIX4K_TAG = 0x0304,
CMD_ISO_14443B_COMMAND = 0x0305, CMD_ISO_14443B_COMMAND = 0x0305,
CMD_READER_ISO_15693 = 0x0310, CMD_READER_ISO_15693 = 0x0310,
CMD_SIMTAG_ISO_15693 = 0x0311, CMD_SIMTAG_ISO_15693 = 0x0311,
@ -238,6 +237,6 @@ function Command:getBytes()
local data = self.data local data = self.data
local cmd = self.cmd local cmd = self.cmd
local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3 local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3
return bin.pack("LLLLH",cmd, arg1, arg2, arg3, data); return bin.pack("LLLLH", cmd, arg1, arg2, arg3, data);
end end
return _commands return _commands

View file

@ -1,4 +1,3 @@
--[[ --[[
This is a library to read 14443b tags. It can be used something like this This is a library to read 14443b tags. It can be used something like this
@ -14,45 +13,57 @@
-- Loads the commands-library -- Loads the commands-library
local cmds = require('commands') local cmds = require('commands')
local utils = require('utils') local utils = require('utils')
local TIMEOUT = 10000 -- Shouldn't take longer than 2 seconds local TIMEOUT = 4000
local ISO14B_COMMAND = {
ISO14B_CONNECT = 1,
ISO14B_DISCONNECT = 2,
ISO14B_APDU = 4,
ISO14B_RAW = 8,
ISO14B_REQUEST_TRIGGER = 0x10,
ISO14B_APPEND_CRC = 0x20,
ISO14B_SELECT_STD = 0x40,
ISO14B_SELECT_SR = 0x80,
}
local function parse1443b_reqb(data) local function parse1443b(data)
--[[ --[[
--]]
local pcb = data:sub(1,2)
local uid = data:sub(3,10)
local pps = data:sub(11,18)
local ats = data:sub(19,24)
local crc = data:sub(25,29)
return { pcb = pcb, uid = uid, pps = pps, ats = ats, crc = crc, cid = '' }
end
local function parse1443b_attrib(data) Based on this struct :
--[[
--]]
local attrib = data:sub(1,2)
local crc = data:sub(3,7)
return { attrib = attrib, crc = crc }
end
typedef struct {
byte_t uid[10];
byte_t uidlen;
byte_t atqb[7];
byte_t chipid;
byte_t cid;
} __attribute__((__packed__)) iso14b_card_select_t;
--]]
local count, uid, uidlen, atqb, chipid, cid = bin.unpack('H10CH7CC',data)
uid = uid:sub(1,2*uidlen)
return { uid = uid, uidlen = uidlen, atqb = atqb, chipid = chipid, cid = cid }
end
--- Sends a USBpacket to the device --- Sends a USBpacket to the device
-- @param command - the usb packet to send -- @param command - the usb packet to send
-- @param readresponse - if set to true, we read the device answer packet -- @param ignoreresponse - if set to true, we don't read the device answer packet
-- which is usually recipe for fail. If not sent, the host will wait 2s for a -- which is usually recipe for fail. If not sent, the host will wait 2s for a
-- response of type CMD_ACK -- response of type CMD_ACK
-- @return packet,nil if successfull -- @return packet,nil if successfull
-- nil, errormessage if unsuccessfull -- nil, errormessage if unsuccessfull
local function sendToDevice(cmd, readresponse) local function sendToDevice(cmd, ignoreresponse)
core.clearCommandBuffer() --core.clearCommandBuffer()
local bytes = cmd:getBytes()
local count,c,arg0,arg1,arg2 = bin.unpack('LLLL',bytes)
local err = core.SendCommand(cmd:getBytes()) local err = core.SendCommand(cmd:getBytes())
if err then if err then
print(err) print('ERROR',err)
return nil, err return nil, err
end end
if readresponse == 0 then return '',nil end if ignoreresponse then return nil,nil end
local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT) local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT)
if response == nil then return nil, nil end
return response,nil return response,nil
end end
--- Picks out and displays the data read from a tag --- Picks out and displays the data read from a tag
@ -63,133 +74,63 @@ end
-- @param usbpacket the data received from the device -- @param usbpacket the data received from the device
local function showData(usbpacket) local function showData(usbpacket)
local response = Command.parse(usbpacket) local response = Command.parse(usbpacket)
local len = tonumber(response.arg1) * 2 local len = response.arg2 * 2
local data = string.sub(response.data, 0, len); local data = string.sub(response.data, 0, len);
print("<< ",data) print("<< ",data)
end end
---
-- Sends a usbpackage , "hf 14b raw" and the 14bCrc is added to the rawdata before sending
local function sendRaw(rawdata, readresponse, addcrc)
-- add crc first
local rawdata_crc = rawdata
if ( addcrc == 1) then
rawdata_crc = utils.Crc14b(rawdata)
end
print(">> ", rawdata_crc)
local command = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND,
arg1 = #rawdata_crc/2, -- LEN of data, which is half the length of the ASCII-string rawdata
arg2 = readresponse, -- read response
arg3 = 1, -- leave power on
data = rawdata_crc} -- raw data bytes
return sendToDevice(command, readresponse)
end
-- This function does a connect and retrieves some info -- This function does a connect and retrieves some info
-- @return if successfull: an table containing card info -- @return if successfull: an table containing card info
-- @return if unsuccessfull : nil, error -- @return if unsuccessfull : nil, error
local function read14443b(disconnect)
-- void SendRawCommand14443B(uint32_t datalen, uint32_t recv, uint8_t powerfield, uint8_t data[]) local command, result, info, err, data
local function select1443b()
local result, infoReqb, infoAttrib, infoPong, err, resp, len, data local flags = ISO14B_COMMAND.ISO14B_CONNECT +
local goodReqbResponse = false ISO14B_COMMAND.ISO14B_SELECT_STD
--REQB
local p = 20
while p > 0 do
-- 05 00 08
-- 05
-- command (REQB/WUPB)
-- 00
-- AFI application family identifier ( 00 == all sorts)
-- 08 (ie WUPB)
-- bit 0-1-2 | N slots ( 0 = 1, 1 = 2, 2 = 4, 3 = 8, 4 == 16)
-- bit 3 | (1== WUPB, 0 == REQB)
-- bit 4-5-6-7 | AFI application family identifier
local result, err = sendRaw('050008', 1, 1)
if result then
resp = Command.parse( result )
len = tonumber(resp.arg1) * 2
local data = string.sub(resp.data, 0, len)
if ( resp.arg1 == 14 ) then
--print ('DATA ::', data)
infoReqb, err = parse1443b_reqb(data)
--print(infoReqb.pcb, infoReqb.uid, infoReqb.pps, infoReqb.ats, infoReqb.crc)
goodReqbResponse = true
break -- break while loop. REQB got a good response
end
end
-- send some strange 0A/0C if disconnect then
-- if ( p < 3) then print('DISCONNECT')
-- sendRaw('0A', 0, 0) flags = flags + ISO14B_COMMAND.ISO14B_DISCONNECT
-- sendRaw('0C', 0, 0)
-- end
p = p - 1
print('retrying')
end end
if goodReqbResponse == false then command = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = flags}
err = "No response from card" local result,err = sendToDevice(command, false)
print(err)
return nil, err
end
--SLOT MARKER
-- result, err = sendRaw('05', 1, 1)
-- if result then
-- showData(result)
-- resp = Command.parse( result )
-- if arg1 == 0 then
-- return nil, "iso14443b card - SLOT MARKER failed"
-- end
-- len = tonumber(resp.arg1) * 2
-- data = string.sub(resp.data, 0, len)
-- infoAttrib, err = parse1443b_attrib(data)
-- print( infoAttrib.attrib, infoAttrib.crc)
-- else
-- err ="No response from card"
-- print(err)
-- return nil, err
-- end
--ATTRIB
local cid = '00'
result, err = sendRaw('1D'..infoReqb.uid..'000801'..cid, 1, 1)
if result then if result then
showData(result) local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result)
resp = Command.parse( result ) if arg0 == 0 then
if resp.arg1 == 0 then data = string.sub(result, count)
return nil, "iso14443b card - ATTRIB failed" info, err = parse1443b(data)
else
err = "iso14443b card select failed"
end end
len = tonumber(resp.arg1) * 2
data = string.sub(resp.data, 0, len)
infoAttrib, err = parse1443b_attrib(data)
infoReqb.cid = infoAttrib.attrib:sub(2,2)
else
err ="No response from card"
print(err)
return nil, err
end
--PING / PONG - Custom Anticollison for Navigo.
local ping = ('BA00')
result, err = sendRaw(ping, 1, 1)
if result then
resp = Command.parse( result )
if arg1 == 0 then
return nil, "iso14443b card - PING/PONG failed"
end
showData(result)
else else
err = "No response from card" err = "No response from card"
end
if err then
print(err) print(err)
return nil, err return nil, err
end end
return info
return infoReqb
end end
--PING / PONG - Custom Anticollison for Navigo.
-- AA / BB ?!?
-- local ping = ('BA00')
-- result, err = sendRaw(ping, 1, 1)
-- if result then
-- resp = Command.parse( result )
-- if arg1 == 0 then
-- return nil, "iso14443b card - PING/PONG failed"
-- end
-- showData(result)
-- else
-- err = "No response from card"
-- print(err)
-- return nil, err
-- end
--- ---
-- Waits for a mifare card to be placed within the vicinity of the reader. -- Waits for a mifare card to be placed within the vicinity of the reader.
@ -198,42 +139,20 @@ end
local function waitFor14443b() local function waitFor14443b()
print("Waiting for card... press any key to quit") print("Waiting for card... press any key to quit")
while not core.ukbhit() do while not core.ukbhit() do
res, err = select1443b() res, err = read14443b(false)
if res then return res end if res then return res end
if res == nil then return nil, err end
-- err means that there was no response from card -- err means that there was no response from card
end end
return nil, "Aborted by user" return nil, "Aborted by user"
end end
local function disconnect(uid)
local halt = ('50'..uid) -- 50 UID0 UID1 UID2 UID3 CRC1 CRC2
result, err = sendRaw(halt, 1, 1)
if result then
resp = Command.parse( result )
showData(result) -- expected answer is 00 CRC1 CRC2
else
err = "No response from card"
print(err)
return nil, err
end
-- shutdown raw command / pm3 device.
local command = Command:new{ cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = 0, arg2 = 0, arg3 = 0 }
-- We can ignore the response here, no ACK is returned for this command
-- Check /armsrc/iso14443b.c, SendRawCommand14443B() for details
return sendToDevice(command, 0)
end
local library = { local library = {
select1443b = select1443b, parse1443b = parse1443b,
select = select1443b, read1443b = read14443b,
waitFor14443b = waitFor14443b, waitFor14443b = waitFor14443b,
sendToDevice = sendToDevice, sendToDevice = sendToDevice,
disconnect = disconnect,
sendRaw = sendRaw,
showData = showData, showData = showData,
ISO14B_COMMAND = ISO14B_COMMAND,
} }
return library return library

View file

@ -31,5 +31,4 @@ typedef unsigned char byte_t;
#endif #endif
#define RAMFUNC __attribute((long_call, section(".ramfunc"))) #define RAMFUNC __attribute((long_call, section(".ramfunc")))
#endif #endif

View file

@ -37,4 +37,29 @@ typedef enum ISO14A_COMMAND {
ISO14A_TOPAZMODE = (1 << 8) ISO14A_TOPAZMODE = (1 << 8)
} iso14a_command_t; } iso14a_command_t;
//-----------------------------------------------------------------------------
// ISO 14443B
//-----------------------------------------------------------------------------
typedef struct {
byte_t uid[10];
byte_t uidlen;
byte_t atqb[7];
byte_t chipid;
byte_t cid;
} __attribute__((__packed__)) iso14b_card_select_t;
typedef enum ISO14B_COMMAND {
ISO14B_CONNECT = (1 << 0),
ISO14B_DISCONNECT = (1 << 1),
ISO14B_APDU = (1 << 2),
ISO14B_RAW = (1 << 3),
ISO14B_REQUEST_TRIGGER = (1 << 4),
ISO14B_APPEND_CRC = (1 << 5),
ISO14B_SELECT_STD = (1 << 6),
ISO14B_SELECT_SR = (1 << 7)
} iso14b_command_t;
#endif // _MIFARE_H_ #endif // _MIFARE_H_

View file

@ -109,8 +109,7 @@ typedef struct{
// For the 13.56 MHz tags // For the 13.56 MHz tags
#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300 #define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300
#define CMD_READ_SRI512_TAG 0x0303 #define CMD_READ_SRI_TAG 0x0303
#define CMD_READ_SRIX4K_TAG 0x0304
#define CMD_ISO_14443B_COMMAND 0x0305 #define CMD_ISO_14443B_COMMAND 0x0305
#define CMD_READER_ISO_15693 0x0310 #define CMD_READER_ISO_15693 0x0310
#define CMD_SIMTAG_ISO_15693 0x0311 #define CMD_SIMTAG_ISO_15693 0x0311