I just merged @marshmellow's branch "iclass" and that was a lot of new functionality. *great work*
Things like the ICLASS, tryDecryptWord, -- My other stuff like default keys, some new Mifare EV1 commands 0x40, 0x43 for the logging annotation, start of the T55x7 configblock helper functionality (ripped from Adam Lauries RFIdler code) Changes to the PCF7931 functions written, which has a lousy input check..
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
// LCD code
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "../include/proxmark3.h"
|
||||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "LCD.h"
|
||||
#include "fonts.h"
|
||||
|
||||
@@ -992,6 +992,9 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
||||
ReadPCF7931();
|
||||
cmd_send(CMD_ACK,0,0,0,0,0);
|
||||
break;
|
||||
case CMD_PCF7931_WRITE:
|
||||
WritePCF7931(c->d.asDwords[0],c->d.asDwords[1],c->d.asDwords[2],c->d.asDwords[3],c->d.asDwords[4],c->d.asDwords[5],c->d.asDwords[6], c->d.asDwords[9], c->d.asDwords[7]-128,c->d.asDwords[8]-128, c->arg[0], c->arg[1], c->arg[2]);
|
||||
break;
|
||||
case CMD_EM4X_READ_WORD:
|
||||
EM4xReadWord(c->arg[1], c->arg[2],c->d.asBytes[0]);
|
||||
break;
|
||||
@@ -1212,6 +1215,24 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
||||
case CMD_ICLASS_EML_MEMSET:
|
||||
emlSet(c->d.asBytes,c->arg[0], c->arg[1]);
|
||||
break;
|
||||
case CMD_ICLASS_WRITEBLOCK:
|
||||
iClass_WriteBlock(c->arg[0], c->d.asBytes);
|
||||
break;
|
||||
case CMD_ICLASS_READCHECK: // auth step 1
|
||||
iClass_ReadCheck(c->arg[0], c->arg[1]);
|
||||
break;
|
||||
case CMD_ICLASS_READBLOCK:
|
||||
iClass_ReadBlk(c->arg[0]);
|
||||
break;
|
||||
case CMD_ICLASS_AUTHENTICATION: //check
|
||||
iClass_Authentication(c->d.asBytes);
|
||||
break;
|
||||
case CMD_ICLASS_DUMP:
|
||||
iClass_Dump(c->arg[0], c->arg[1]);
|
||||
break;
|
||||
case CMD_ICLASS_CLONE:
|
||||
iClass_Clone(c->arg[0], c->arg[1], c->d.asBytes);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case CMD_BUFF_CLEAR:
|
||||
|
||||
@@ -94,6 +94,11 @@ int DemodPCF7931(uint8_t **outBlocks);
|
||||
int IsBlock0PCF7931(uint8_t *Block);
|
||||
int IsBlock1PCF7931(uint8_t *Block);
|
||||
void ReadPCF7931();
|
||||
void SendCmdPCF7931(uint32_t * tab);
|
||||
bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p);
|
||||
bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p);
|
||||
bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab);
|
||||
void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data);
|
||||
void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode);
|
||||
void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode);
|
||||
|
||||
@@ -190,6 +195,13 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
|
||||
void ReaderIClass(uint8_t arg0);
|
||||
void ReaderIClass_Replay(uint8_t arg0,uint8_t *MAC);
|
||||
void IClass_iso14443A_GetPublic(uint8_t arg0);
|
||||
void iClass_Authentication(uint8_t *MAC);
|
||||
void iClass_WriteBlock(uint8_t blockNo, uint8_t *data);
|
||||
void iClass_ReadBlk(uint8_t blockNo);
|
||||
bool iClass_ReadBlock(uint8_t blockNo, uint8_t *readdata);
|
||||
void iClass_Dump(uint8_t blockno, uint8_t numblks);
|
||||
void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data);
|
||||
void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType);
|
||||
|
||||
void CopyViKingtoT55x7(uint32_t block1,uint32_t block2);
|
||||
// hitag2.h
|
||||
|
||||
276
armsrc/iclass.c
276
armsrc/iclass.c
@@ -1601,16 +1601,16 @@ void setupIclassReader()
|
||||
|
||||
}
|
||||
|
||||
size_t sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t* resp, uint8_t expected_size, uint8_t retries)
|
||||
bool sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t* resp, uint8_t expected_size, uint8_t retries)
|
||||
{
|
||||
while(retries-- > 0)
|
||||
{
|
||||
ReaderTransmitIClass(command, cmdsize);
|
||||
if(expected_size == ReaderReceiveIClass(resp)){
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return 1;//Error
|
||||
return false;//Error
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1620,14 +1620,17 @@ size_t sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t*
|
||||
* 1 = Got CSN
|
||||
* 2 = Got CSN and CC
|
||||
*/
|
||||
uint8_t handshakeIclassTag(uint8_t *card_data)
|
||||
uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key)
|
||||
{
|
||||
static uint8_t act_all[] = { 0x0a };
|
||||
static uint8_t identify[] = { 0x0c };
|
||||
//static uint8_t identify[] = { 0x0c };
|
||||
static uint8_t identify[] = { 0x0c, 0x00, 0x73, 0x33 };
|
||||
static uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
|
||||
static uint8_t readcheck_cc[]= { 0x88, 0x02,};
|
||||
static uint8_t readcheck_cc[]= { 0x88, 0x02 };
|
||||
if (use_credit_key)
|
||||
readcheck_cc[0] = 0x18;
|
||||
else
|
||||
readcheck_cc[0] = 0x88;
|
||||
|
||||
uint8_t resp[ICLASS_BUFFER_SIZE];
|
||||
|
||||
@@ -1668,6 +1671,9 @@ uint8_t handshakeIclassTag(uint8_t *card_data)
|
||||
|
||||
return read_status;
|
||||
}
|
||||
uint8_t handshakeIclassTag(uint8_t *card_data){
|
||||
return handshakeIclassTag_ext(card_data, false);
|
||||
}
|
||||
|
||||
|
||||
// Reader iClass Anticollission
|
||||
@@ -1687,6 +1693,9 @@ void ReaderIClass(uint8_t arg0) {
|
||||
uint8_t result_status = 0;
|
||||
bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE;
|
||||
bool try_once = arg0 & FLAG_ICLASS_READER_ONE_TRY;
|
||||
bool use_credit_key = false;
|
||||
if (arg0 & FLAG_ICLASS_READER_CEDITKEY)
|
||||
use_credit_key = true;
|
||||
set_tracing(TRUE);
|
||||
setupIclassReader();
|
||||
|
||||
@@ -1701,7 +1710,7 @@ void ReaderIClass(uint8_t arg0) {
|
||||
}
|
||||
WDT_HIT();
|
||||
|
||||
read_status = handshakeIclassTag(card_data);
|
||||
read_status = handshakeIclassTag_ext(card_data, use_credit_key);
|
||||
|
||||
if(read_status == 0) continue;
|
||||
if(read_status == 1) result_status = FLAG_ICLASS_READER_CSN;
|
||||
@@ -1715,11 +1724,10 @@ void ReaderIClass(uint8_t arg0) {
|
||||
if(arg0 & FLAG_ICLASS_READER_CONF)
|
||||
{
|
||||
if(sendCmdGetResponseWithRetries(readConf, sizeof(readConf),card_data+8, 10, 10))
|
||||
{
|
||||
Dbprintf("Failed to dump config block");
|
||||
}else
|
||||
{
|
||||
result_status |= FLAG_ICLASS_READER_CONF;
|
||||
} else {
|
||||
Dbprintf("Failed to dump config block");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1727,10 +1735,9 @@ void ReaderIClass(uint8_t arg0) {
|
||||
if(arg0 & FLAG_ICLASS_READER_AA){
|
||||
if(sendCmdGetResponseWithRetries(readAA, sizeof(readAA),card_data+(8*4), 10, 10))
|
||||
{
|
||||
// Dbprintf("Failed to dump AA block");
|
||||
}else
|
||||
{
|
||||
result_status |= FLAG_ICLASS_READER_AA;
|
||||
} else {
|
||||
//Dbprintf("Failed to dump AA block");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1814,7 +1821,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
|
||||
//for now replay captured auth (as cc not updated)
|
||||
memcpy(check+5,MAC,4);
|
||||
|
||||
if(sendCmdGetResponseWithRetries(check, sizeof(check),resp, 4, 5))
|
||||
if(!sendCmdGetResponseWithRetries(check, sizeof(check),resp, 4, 5))
|
||||
{
|
||||
Dbprintf("Error: Authentication Fail!");
|
||||
continue;
|
||||
@@ -1826,7 +1833,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
|
||||
read[2] = crc >> 8;
|
||||
read[3] = crc & 0xff;
|
||||
|
||||
if(sendCmdGetResponseWithRetries(read, sizeof(read),resp, 10, 10))
|
||||
if(!sendCmdGetResponseWithRetries(read, sizeof(read),resp, 10, 10))
|
||||
{
|
||||
Dbprintf("Dump config (block 1) failed");
|
||||
continue;
|
||||
@@ -1853,7 +1860,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
|
||||
read[2] = crc >> 8;
|
||||
read[3] = crc & 0xff;
|
||||
|
||||
if(!sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 10))
|
||||
if(sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 10))
|
||||
{
|
||||
Dbprintf(" %02x: %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
block, resp[0], resp[1], resp[2],
|
||||
@@ -1904,130 +1911,129 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
|
||||
LED_A_OFF();
|
||||
}
|
||||
|
||||
//2. Create Read method (cut-down from above) based off responses from 1.
|
||||
// Since we have the MAC could continue to use replay function.
|
||||
//3. Create Write method
|
||||
/*
|
||||
void IClass_iso14443A_write(uint8_t arg0, uint8_t blockNo, uint8_t *data, uint8_t *MAC) {
|
||||
uint8_t act_all[] = { 0x0a };
|
||||
uint8_t identify[] = { 0x0c };
|
||||
uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t readcheck_cc[]= { 0x88, 0x02 };
|
||||
uint8_t check[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t read[] = { 0x0c, 0x00, 0x00, 0x00 };
|
||||
uint8_t write[] = { 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
uint16_t crc = 0;
|
||||
|
||||
uint8_t* resp = (((uint8_t *)BigBuf) + 3560);
|
||||
void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType) {
|
||||
uint8_t readcheck[] = { keyType, blockNo };
|
||||
uint8_t resp[] = {0,0,0,0,0,0,0,0};
|
||||
size_t isOK = 0;
|
||||
isOK = sendCmdGetResponseWithRetries(readcheck, sizeof(readcheck), resp, sizeof(resp), 6);
|
||||
cmd_send(CMD_ACK,isOK,0,0,0,0);
|
||||
}
|
||||
|
||||
// Reset trace buffer
|
||||
memset(trace, 0x44, RECV_CMD_OFFSET);
|
||||
traceLen = 0;
|
||||
void iClass_Authentication(uint8_t *MAC) {
|
||||
uint8_t check[] = { ICLASS_CMD_CHECK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t resp[ICLASS_BUFFER_SIZE];
|
||||
memcpy(check+5,MAC,4);
|
||||
bool isOK;
|
||||
isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 6);
|
||||
cmd_send(CMD_ACK,isOK,0,0,0,0);
|
||||
}
|
||||
bool iClass_ReadBlock(uint8_t blockNo, uint8_t *readdata) {
|
||||
uint8_t readcmd[] = {ICLASS_CMD_READ_OR_IDENTIFY, blockNo, 0x00, 0x00}; //0x88, 0x00 // can i use 0C?
|
||||
char bl = blockNo;
|
||||
uint16_t rdCrc = iclass_crc16(&bl, 1);
|
||||
readcmd[2] = rdCrc >> 8;
|
||||
readcmd[3] = rdCrc & 0xff;
|
||||
uint8_t resp[] = {0,0,0,0,0,0,0,0,0,0};
|
||||
bool isOK = false;
|
||||
|
||||
// Setup SSC
|
||||
FpgaSetupSsc();
|
||||
// Start from off (no field generated)
|
||||
// Signal field is off with the appropriate LED
|
||||
LED_D_OFF();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
SpinDelay(200);
|
||||
//readcmd[1] = blockNo;
|
||||
isOK = sendCmdGetResponseWithRetries(readcmd, sizeof(readcmd), resp, 10, 10);
|
||||
memcpy(readdata, resp, sizeof(resp));
|
||||
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
return isOK;
|
||||
}
|
||||
|
||||
// Now give it time to spin up.
|
||||
// Signal field is on with the appropriate LED
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
|
||||
SpinDelay(200);
|
||||
void iClass_ReadBlk(uint8_t blockno) {
|
||||
uint8_t readblockdata[] = {0,0,0,0,0,0,0,0,0,0};
|
||||
bool isOK = false;
|
||||
isOK = iClass_ReadBlock(blockno, readblockdata);
|
||||
cmd_send(CMD_ACK, isOK, 0, 0, readblockdata, 8);
|
||||
}
|
||||
|
||||
LED_A_ON();
|
||||
void iClass_Dump(uint8_t blockno, uint8_t numblks) {
|
||||
uint8_t readblockdata[] = {0,0,0,0,0,0,0,0,0,0};
|
||||
bool isOK = false;
|
||||
uint8_t blkCnt = 0;
|
||||
|
||||
for(int i=0;i<1;i++) {
|
||||
|
||||
if(traceLen > TRACE_SIZE) {
|
||||
DbpString("Trace full");
|
||||
BigBuf_free();
|
||||
uint8_t *dataout = BigBuf_malloc(255*8);
|
||||
if (dataout == NULL){
|
||||
Dbprintf("out of memory");
|
||||
OnError(1);
|
||||
return;
|
||||
}
|
||||
memset(dataout,0xFF,255*8);
|
||||
|
||||
for (;blkCnt < numblks; blkCnt++) {
|
||||
isOK = iClass_ReadBlock(blockno+blkCnt, readblockdata);
|
||||
if (!isOK || (readblockdata[0] == 0xBB || readblockdata[7] == 0xBB || readblockdata[2] == 0xBB)) { //try again
|
||||
isOK = iClass_ReadBlock(blockno+blkCnt, readblockdata);
|
||||
if (!isOK) {
|
||||
Dbprintf("Block %02X failed to read", blkCnt+blockno);
|
||||
break;
|
||||
}
|
||||
|
||||
if (BUTTON_PRESS()) break;
|
||||
|
||||
// Send act_all
|
||||
ReaderTransmitIClass(act_all, 1);
|
||||
// Card present?
|
||||
if(ReaderReceiveIClass(resp)) {
|
||||
ReaderTransmitIClass(identify, 1);
|
||||
if(ReaderReceiveIClass(resp) == 10) {
|
||||
// Select card
|
||||
memcpy(&select[1],resp,8);
|
||||
ReaderTransmitIClass(select, sizeof(select));
|
||||
|
||||
if(ReaderReceiveIClass(resp) == 10) {
|
||||
Dbprintf(" Selected CSN: %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
resp[0], resp[1], resp[2],
|
||||
resp[3], resp[4], resp[5],
|
||||
resp[6], resp[7]);
|
||||
}
|
||||
// Card selected
|
||||
Dbprintf("Readcheck on Sector 2");
|
||||
ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc));
|
||||
if(ReaderReceiveIClass(resp) == 8) {
|
||||
Dbprintf(" CC: %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
resp[0], resp[1], resp[2],
|
||||
resp[3], resp[4], resp[5],
|
||||
resp[6], resp[7]);
|
||||
}else return;
|
||||
Dbprintf("Authenticate");
|
||||
//for now replay captured auth (as cc not updated)
|
||||
memcpy(check+5,MAC,4);
|
||||
Dbprintf(" AA: %02x %02x %02x %02x",
|
||||
check[5], check[6], check[7],check[8]);
|
||||
ReaderTransmitIClass(check, sizeof(check));
|
||||
if(ReaderReceiveIClass(resp) == 4) {
|
||||
Dbprintf(" AR: %02x %02x %02x %02x",
|
||||
resp[0], resp[1], resp[2],resp[3]);
|
||||
}else {
|
||||
Dbprintf("Error: Authentication Fail!");
|
||||
return;
|
||||
}
|
||||
Dbprintf("Write Block");
|
||||
|
||||
//read configuration for max block number
|
||||
read_success=false;
|
||||
read[1]=1;
|
||||
uint8_t *blockno=&read[1];
|
||||
crc = iclass_crc16((char *)blockno,1);
|
||||
read[2] = crc >> 8;
|
||||
read[3] = crc & 0xff;
|
||||
while(!read_success){
|
||||
ReaderTransmitIClass(read, sizeof(read));
|
||||
if(ReaderReceiveIClass(resp) == 10) {
|
||||
read_success=true;
|
||||
mem=resp[5];
|
||||
memory.k16= (mem & 0x80);
|
||||
memory.book= (mem & 0x20);
|
||||
memory.k2= (mem & 0x8);
|
||||
memory.lockauth= (mem & 0x2);
|
||||
memory.keyaccess= (mem & 0x1);
|
||||
|
||||
}
|
||||
}
|
||||
if (memory.k16){
|
||||
cardsize=255;
|
||||
}else cardsize=32;
|
||||
//check card_size
|
||||
|
||||
memcpy(write+1,blockNo,1);
|
||||
memcpy(write+2,data,8);
|
||||
memcpy(write+10,mac,4);
|
||||
while(!send_success){
|
||||
ReaderTransmitIClass(write, sizeof(write));
|
||||
if(ReaderReceiveIClass(resp) == 10) {
|
||||
write_success=true;
|
||||
}
|
||||
}//
|
||||
}
|
||||
WDT_HIT();
|
||||
memcpy(dataout+(blkCnt*8),readblockdata,8);
|
||||
}
|
||||
|
||||
LED_A_OFF();
|
||||
}*/
|
||||
//return pointer to dump memory in arg3
|
||||
cmd_send(CMD_ACK,isOK,blkCnt,BigBuf_max_traceLen(),0,0);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
BigBuf_free();
|
||||
}
|
||||
|
||||
bool iClass_WriteBlock_ext(uint8_t blockNo, uint8_t *data) {
|
||||
uint8_t write[] = { ICLASS_CMD_UPDATE, blockNo, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
//uint8_t readblockdata[10];
|
||||
//write[1] = blockNo;
|
||||
memcpy(write+2, data, 12); // data + mac
|
||||
uint8_t resp[] = {0,0,0,0,0,0,0,0,0,0};
|
||||
bool isOK;
|
||||
isOK = sendCmdGetResponseWithRetries(write,sizeof(write),resp,sizeof(resp),10);
|
||||
if (isOK) {
|
||||
//Dbprintf("WriteResp: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",resp[0],resp[1],resp[2],resp[3],resp[4],resp[5],resp[6],resp[7],resp[8],resp[9]);
|
||||
if (memcmp(write+2,resp,8)) {
|
||||
//error try again
|
||||
isOK = sendCmdGetResponseWithRetries(write,sizeof(write),resp,sizeof(resp),10);
|
||||
}
|
||||
}
|
||||
return isOK;
|
||||
}
|
||||
|
||||
void iClass_WriteBlock(uint8_t blockNo, uint8_t *data) {
|
||||
bool isOK = iClass_WriteBlock_ext(blockNo, data);
|
||||
if (isOK){
|
||||
Dbprintf("Write block [%02x] successful",blockNo);
|
||||
}else {
|
||||
Dbprintf("Write block [%02x] failed",blockNo);
|
||||
}
|
||||
cmd_send(CMD_ACK,isOK,0,0,0,0);
|
||||
}
|
||||
|
||||
void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) {
|
||||
int i;
|
||||
int written = 0;
|
||||
int total_block = (endblock - startblock) + 1;
|
||||
for (i = 0; i < total_block;i++){
|
||||
// block number
|
||||
if (iClass_WriteBlock_ext(i+startblock, data+(i*12))){
|
||||
Dbprintf("Write block [%02x] successful",i + startblock);
|
||||
written++;
|
||||
} else {
|
||||
if (iClass_WriteBlock_ext(i+startblock, data+(i*12))){
|
||||
Dbprintf("Write block [%02x] successful",i + startblock);
|
||||
written++;
|
||||
} else {
|
||||
Dbprintf("Write block [%02x] failed",i + startblock);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (written == total_block)
|
||||
Dbprintf("Clone complete");
|
||||
else
|
||||
Dbprintf("Clone incomplete");
|
||||
|
||||
cmd_send(CMD_ACK,1,0,0,0,0);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
}
|
||||
|
||||
@@ -947,10 +947,10 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data)
|
||||
uint8_t sak;
|
||||
|
||||
// PACK response to PWD AUTH for EV1/NTAG
|
||||
uint8_t response8[4];
|
||||
uint8_t response8[4] = {0,0,0,0};
|
||||
|
||||
// The first response contains the ATQA (note: bytes are transmitted in reverse order).
|
||||
uint8_t response1[2];
|
||||
uint8_t response1[2] = {0,0};
|
||||
|
||||
switch (tagType) {
|
||||
case 1: { // MIFARE Classic
|
||||
@@ -1299,7 +1299,8 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data)
|
||||
if ( tagType == 7 ) {
|
||||
p_response = &responses[8]; // PACK response
|
||||
uint32_t pwd = bytes_to_num(receivedCmd+1,4);
|
||||
Dbprintf("Auth attempt: %08x", pwd);
|
||||
|
||||
if ( MF_DBGLEVEL >= 3) Dbprintf("Auth attempt: %08x", pwd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -2206,28 +2207,6 @@ int32_t dist_nt(uint32_t nt1, uint32_t nt2) {
|
||||
return(-99999); // either nt1 or nt2 are invalid nonces
|
||||
}
|
||||
|
||||
int32_t dist_nt_ex32(uint32_t nt1, uint32_t nt2, bool *result) {
|
||||
|
||||
uint16_t i;
|
||||
uint32_t nttmp1, nttmp2;
|
||||
|
||||
if (nt1 == nt2) return 0;
|
||||
|
||||
nttmp1 = nt1;
|
||||
nttmp2 = nt2;
|
||||
|
||||
*result = true;
|
||||
for (i = 1; i < 0xFFFFFFFF; i++) {
|
||||
nttmp1 = prng_successor(nttmp1, 1);
|
||||
if (nttmp1 == nt2) return i;
|
||||
|
||||
nttmp2 = prng_successor(nttmp2, 1);
|
||||
if (nttmp2 == nt1) return -i;
|
||||
}
|
||||
|
||||
*result = false;
|
||||
return(-99999); // either nt1 or nt2 are invalid nonces
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Recover several bits of the cypher stream. This implements (first stages of)
|
||||
|
||||
257
armsrc/lfops.c
257
armsrc/lfops.c
@@ -2125,3 +2125,260 @@ void CopyViKingtoT55x7(uint32_t block1,uint32_t block2)
|
||||
DbpString("DONE!");
|
||||
}
|
||||
|
||||
|
||||
#define T0_PCF 8 //period for the pcf7931 in us
|
||||
|
||||
/* Write on a byte of a PCF7931 tag
|
||||
* @param address : address of the block to write
|
||||
@param byte : address of the byte to write
|
||||
@param data : data to write
|
||||
*/
|
||||
void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data)
|
||||
{
|
||||
|
||||
uint32_t tab[1024]={0}; // data times frame
|
||||
uint32_t u = 0;
|
||||
uint8_t parity = 0;
|
||||
bool comp = 0;
|
||||
|
||||
|
||||
//BUILD OF THE DATA FRAME
|
||||
|
||||
//alimentation of the tag (time for initializing)
|
||||
AddPatternPCF7931(init_delay, 0, 8192/2*T0_PCF, tab);
|
||||
|
||||
//PMC
|
||||
Dbprintf("Initialization delay : %d us", init_delay);
|
||||
AddPatternPCF7931(8192/2*T0_PCF + 319*T0_PCF+70, 3*T0_PCF, 29*T0_PCF, tab);
|
||||
|
||||
Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p);
|
||||
|
||||
//password indication bit
|
||||
AddBitPCF7931(1, tab, l, p);
|
||||
|
||||
|
||||
//password (on 56 bits)
|
||||
Dbprintf("Password (LSB first on each byte) : %02x %02x %02x %02x %02x %02x %02x", pass1,pass2,pass3,pass4,pass5,pass6,pass7);
|
||||
AddBytePCF7931(pass1, tab, l, p);
|
||||
AddBytePCF7931(pass2, tab, l, p);
|
||||
AddBytePCF7931(pass3, tab, l, p);
|
||||
AddBytePCF7931(pass4, tab, l, p);
|
||||
AddBytePCF7931(pass5, tab, l, p);
|
||||
AddBytePCF7931(pass6, tab, l, p);
|
||||
AddBytePCF7931(pass7, tab, l, p);
|
||||
|
||||
|
||||
//programming mode (0 or 1)
|
||||
AddBitPCF7931(0, tab, l, p);
|
||||
|
||||
//block adress on 6 bits
|
||||
Dbprintf("Block address : %02x", address);
|
||||
for (u=0; u<6; u++)
|
||||
{
|
||||
if (address&(1<<u)) { // bit 1
|
||||
parity++;
|
||||
AddBitPCF7931(1, tab, l, p);
|
||||
} else{ // bit 0
|
||||
AddBitPCF7931(0, tab, l, p);
|
||||
}
|
||||
}
|
||||
|
||||
//byte address on 4 bits
|
||||
Dbprintf("Byte address : %02x", byte);
|
||||
for (u=0; u<4; u++)
|
||||
{
|
||||
if (byte&(1<<u)) { // bit 1
|
||||
parity++;
|
||||
AddBitPCF7931(1, tab, l, p);
|
||||
} else{ // bit 0
|
||||
AddBitPCF7931(0, tab, l, p);
|
||||
}
|
||||
}
|
||||
|
||||
//data on 8 bits
|
||||
Dbprintf("Data : %02x", data);
|
||||
for (u=0; u<8; u++)
|
||||
{
|
||||
if (data&(1<<u)) { // bit 1
|
||||
parity++;
|
||||
AddBitPCF7931(1, tab, l, p);
|
||||
} else{ //bit 0
|
||||
AddBitPCF7931(0, tab, l, p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//parity bit
|
||||
if((parity%2)==0){
|
||||
AddBitPCF7931(0, tab, l, p); //even parity
|
||||
}else{
|
||||
AddBitPCF7931(1, tab, l, p);//odd parity
|
||||
}
|
||||
|
||||
//time access memory
|
||||
AddPatternPCF7931(5120+2680, 0, 0, tab);
|
||||
|
||||
//conversion of the scale time
|
||||
for(u=0;u<500;u++){
|
||||
tab[u]=(tab[u] * 3)/2;
|
||||
}
|
||||
|
||||
|
||||
//compennsation of the counter reload
|
||||
while (!comp){
|
||||
comp = 1;
|
||||
for(u=0;tab[u]!=0;u++){
|
||||
if(tab[u] > 0xFFFF){
|
||||
tab[u] -= 0xFFFF;
|
||||
comp = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SendCmdPCF7931(tab);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Send a trame to a PCF7931 tags
|
||||
* @param tab : array of the data frame
|
||||
*/
|
||||
|
||||
void SendCmdPCF7931(uint32_t * tab){
|
||||
uint16_t u=0;
|
||||
uint16_t tempo=0;
|
||||
|
||||
Dbprintf("SENDING DATA FRAME...");
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU );
|
||||
|
||||
LED_A_ON();
|
||||
|
||||
// steal this pin from the SSP and use it to control the modulation
|
||||
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
|
||||
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
|
||||
|
||||
//initialization of the timer
|
||||
AT91C_BASE_PMC->PMC_PCER |= (0x1 << 12) | (0x1 << 13) | (0x1 << 14);
|
||||
AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
|
||||
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK; //clock at 48/32 MHz
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN;
|
||||
AT91C_BASE_TCB->TCB_BCR = 1;
|
||||
|
||||
|
||||
tempo = AT91C_BASE_TC0->TC_CV;
|
||||
for(u=0;tab[u]!= 0;u+=3){
|
||||
|
||||
|
||||
// modulate antenna
|
||||
HIGH(GPIO_SSC_DOUT);
|
||||
while(tempo != tab[u]){
|
||||
tempo = AT91C_BASE_TC0->TC_CV;
|
||||
}
|
||||
|
||||
// stop modulating antenna
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
while(tempo != tab[u+1]){
|
||||
tempo = AT91C_BASE_TC0->TC_CV;
|
||||
}
|
||||
|
||||
|
||||
// modulate antenna
|
||||
HIGH(GPIO_SSC_DOUT);
|
||||
while(tempo != tab[u+2]){
|
||||
tempo = AT91C_BASE_TC0->TC_CV;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
LED_A_OFF();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
SpinDelay(200);
|
||||
|
||||
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
|
||||
DbpString("FINISH !");
|
||||
DbpString("(Could be usefull to send the same trame many times)");
|
||||
LED(0xFFFF, 1000);
|
||||
}
|
||||
|
||||
|
||||
/* Add a byte for building the data frame of PCF7931 tags
|
||||
* @param b : byte to add
|
||||
* @param tab : array of the data frame
|
||||
* @param l : offset on low pulse width
|
||||
* @param p : offset on low pulse positioning
|
||||
*/
|
||||
|
||||
bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p){
|
||||
|
||||
uint32_t u;
|
||||
for (u=0; u<8; u++)
|
||||
{
|
||||
if (byte&(1<<u)) { //bit à 1
|
||||
if(AddBitPCF7931(1, tab, l, p)==1)return 1;
|
||||
} else { //bit à 0
|
||||
if(AddBitPCF7931(0, tab, l, p)==1)return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add a bits for building the data frame of PCF7931 tags
|
||||
* @param b : bit to add
|
||||
* @param tab : array of the data frame
|
||||
* @param l : offset on low pulse width
|
||||
* @param p : offset on low pulse positioning
|
||||
*/
|
||||
bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p){
|
||||
uint8_t u = 0;
|
||||
|
||||
for(u=0;tab[u]!=0;u+=3){} //we put the cursor at the last value of the array
|
||||
|
||||
|
||||
if(b==1){ //add a bit 1
|
||||
if(u==0) tab[u] = 34*T0_PCF+p;
|
||||
else tab[u] = 34*T0_PCF+tab[u-1]+p;
|
||||
|
||||
tab[u+1] = 6*T0_PCF+tab[u]+l;
|
||||
tab[u+2] = 88*T0_PCF+tab[u+1]-l-p;
|
||||
return 0;
|
||||
}else{ //add a bit 0
|
||||
|
||||
if(u==0) tab[u] = 98*T0_PCF+p;
|
||||
else tab[u] = 98*T0_PCF+tab[u-1]+p;
|
||||
|
||||
tab[u+1] = 6*T0_PCF+tab[u]+l;
|
||||
tab[u+2] = 24*T0_PCF+tab[u+1]-l-p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Add a custom pattern in the data frame
|
||||
* @param a : delay of the first high pulse
|
||||
* @param b : delay of the low pulse
|
||||
* @param c : delay of the last high pulse
|
||||
* @param tab : array of the data frame
|
||||
*/
|
||||
bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab){
|
||||
uint32_t u = 0;
|
||||
for(u=0;tab[u]!=0;u+=3){} //we put the cursor at the last value of the array
|
||||
|
||||
if(u==0) tab[u] = a;
|
||||
else tab[u] = a + tab[u-1];
|
||||
|
||||
tab[u+1] = b+tab[u];
|
||||
tab[u+2] = c+tab[u+1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user