Merge pull request #140 from marshmellow42/iclass

iClass major updates
This commit is contained in:
Martin Holst Swende 2015-10-13 09:39:04 +02:00
commit be6250d31b
21 changed files with 1603 additions and 483 deletions

View file

@ -5,6 +5,12 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
## [unreleased][unreleased]
### Added
- `hf iclass managekeys` to save, load and manage iclass keys. (adjusted most commands to accept a loaded key in memory) (marshmellow)
- `hf iclass readblk` to select, authenticate, and read 1 block from an iclass card (marshmellow)
- `hf iclass writeblk` to select, authenticate, and write 1 block to an iclass card (or picopass) (marshmellow + others)
- `hf iclass clone` to take a saved dump file and clone selected blocks to a new tag (marshmellow + others)
- `hf iclass calcnewkey` - to calculate the div_key change to change a key - (experimental) (marshmellow + others)
- `hf iclass encryptblk` - to encrypt a data block hex to prep for writing that block (marshmellow)
- ISO14443a stand-alone operation with ARM CFLAG="WITH_ISO14443a_StandAlone". This code can read & emulate two banks of 14a tag UIDs and write to "magic" cards (Craig Young)
- AWID26 command context added as 'lf awid' containing realtime demodulation as well as cloning/simulation based on tag numbers (Craig Young)
- Added 'hw status'. This command makes the ARM print out some runtime information. (holiman)
@ -12,6 +18,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Added `data hex2bin` and `data bin2hex` for command line conversion between binary and hexadecimal (holiman)
### Changed
- changed `lf config t <threshold>` to be 0 - 128 and will trigger on + or - threshold value (marshmellow)
- `hf iclass dump` cli options - can now dump AA1 and AA2 with different keys in one run (does not go to muliple pages for the larger tags yet)
- Revised workflow for StandAloneMode14a (Craig Young)
- EPA functions (`hf epa`) now support both ISO 14443-A and 14443-B cards (frederikmoellers)
- 'hw version' only talks to ARM at startup, after that the info is cached. (pwpiwi)

View file

@ -1178,11 +1178,29 @@ void UsbPacketReceived(uint8_t *packet, int len)
ReaderIClass(c->arg[0]);
break;
case CMD_READER_ICLASS_REPLAY:
ReaderIClass_Replay(c->arg[0], c->d.asBytes);
ReaderIClass_Replay(c->arg[0], c->d.asBytes);
break;
case CMD_ICLASS_EML_MEMSET:
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:

View file

@ -156,9 +156,6 @@ void OnSuccess();
void OnError(uint8_t reason);
/// iso15693.h
void RecordRawAdcSamplesIso15693(void);
void AcquireRawAdcSamplesIso15693(void);
@ -174,6 +171,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);
// hitag2.h
void SnoopHitag(uint32_t type);

View file

@ -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");
}
}
@ -1762,8 +1769,8 @@ void ReaderIClass(uint8_t arg0) {
}
LED_B_OFF();
}
cmd_send(CMD_ACK,0,0,0,card_data, 0);
LED_A_OFF();
cmd_send(CMD_ACK,0,0,0,card_data, 0);
LED_A_OFF();
}
void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
@ -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");
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();
BigBuf_free();
uint8_t *dataout = BigBuf_malloc(255*8);
if (dataout == NULL){
Dbprintf("out of memory");
OnError(1);
return;
}
LED_A_OFF();
}*/
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;
}
}
memcpy(dataout+(blkCnt*8),readblockdata,8);
}
//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();
}

View file

@ -557,16 +557,16 @@ int CmdHFSearch(const char *Cmd){
PrintAndLog("\nValid ISO14443A Tag Found - Quiting Search\n");
return ans;
}
ans = HF14BInfo(false);
if (ans) {
PrintAndLog("\nValid ISO14443B Tag Found - Quiting Search\n");
return ans;
}
ans = HFiClassReader("", false, false);
if (ans) {
PrintAndLog("\nValid iClass Tag (or PicoPass Tag) Found - Quiting Search\n");
return ans;
}
ans = HF14BInfo(false);
if (ans) {
PrintAndLog("\nValid ISO14443B Tag Found - Quiting Search\n");
return ans;
}
ans = HF15Reader("", false);
if (ans) {
PrintAndLog("\nValid ISO15693 Tag Found - Quiting Search\n");

File diff suppressed because it is too large Load diff

View file

@ -14,11 +14,26 @@
int CmdHFiClass(const char *Cmd);
int CmdHFiClassSnoop(const char *Cmd);
int CmdHFiClassSim(const char *Cmd);
int CmdHFiClassCalcNewKey(const char *Cmd);
int CmdHFiClassCloneTag(const char *Cmd);
int CmdHFiClassDecrypt(const char *Cmd);
int CmdHFiClassEncryptBlk(const char *Cmd);
int CmdHFiClassELoad(const char *Cmd);
int CmdHFiClassList(const char *Cmd);
int HFiClassReader(const char *Cmd, bool loop, bool verbose);
int CmdHFiClassReader(const char *Cmd);
int CmdHFiClassReader_Dump(const char *Cmd);
int CmdHFiClassReader_Replay(const char *Cmd);
int CmdHFiClassReadKeyFile(const char *filename);
int CmdHFiClassReadTagFile(const char *Cmd);
int CmdHFiClass_ReadBlock(const char *Cmd);
int CmdHFiClass_TestMac(const char *Cmd);
int CmdHFiClassManageKeys(const char *Cmd);
int CmdHFiClass_loclass(const char *Cmd);
int CmdHFiClassSnoop(const char *Cmd);
int CmdHFiClassSim(const char *Cmd);
int CmdHFiClassWriteKeyFile(const char *Cmd);
int CmdHFiClass_WriteBlock(const char *Cmd);
void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize);
void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite);
#endif

View file

@ -1951,6 +1951,13 @@ int CmdHF14AMfSniff(const char *Cmd){
return 0;
}
//needs nt, ar, at, Data to decrypt
int CmdDecryptTraceCmds(const char *Cmd){
uint8_t data[50];
int len = 0;
param_gethex_ex(Cmd,3,data,&len);
return tryDecryptWord(param_get32ex(Cmd,0,0,16),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16),data,len/2);
}
static command_t CommandTable[] =
{
@ -1979,6 +1986,7 @@ static command_t CommandTable[] =
{"cgetsc", CmdHF14AMfCGetSc, 0, "Read sector - Magic Chinese card"},
{"cload", CmdHF14AMfCLoad, 0, "Load dump into magic Chinese card"},
{"csave", CmdHF14AMfCSave, 0, "Save dump from magic Chinese card into file or emulator"},
{"decrypt", CmdDecryptTraceCmds,1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"},
{NULL, NULL, 0, NULL}
};

View file

@ -1138,7 +1138,7 @@ static command_t CommandTable[] =
{"read", CmdLFRead, 0, "['s' silent] Read 125/134 kHz LF ID-only tag. Do 'lf read h' for help"},
{"search", CmdLFfind, 1, "[offline] ['u'] Read and Search for valid known tag (in offline mode it you can load first then search) - 'u' to search for unknown tags"},
{"sim", CmdLFSim, 0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"},
{"simask", CmdLFaskSim, 0, "[clock] [invert <1|0>] [manchester/raw <'m'|'r'>] [msg separator 's'] [d <hexdata>] -- Simulate LF ASK tag from demodbuffer or input"},
{"simask", CmdLFaskSim, 0, "[clock] [invert <1|0>] [biphase/manchester/raw <'b'|'m'|'r'>] [msg separator 's'] [d <hexdata>] -- Simulate LF ASK tag from demodbuffer or input"},
{"simfsk", CmdLFfskSim, 0, "[c <clock>] [i] [H <fcHigh>] [L <fcLow>] [d <hexdata>] -- Simulate LF FSK tag from demodbuffer or input"},
{"simpsk", CmdLFpskSim, 0, "[1|2|3] [c <clock>] [i] [r <carrier>] [d <raw hex to sim>] -- Simulate LF PSK tag from demodbuffer or input"},
{"simbidir", CmdLFSimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},

View file

@ -37,7 +37,7 @@ int usage_t55xx_config(){
PrintAndLog("Options: ");
PrintAndLog(" h This help");
PrintAndLog(" b <8|16|32|40|50|64|100|128> Set bitrate");
PrintAndLog(" d <FSK|FSK1|FSK1a|FSK2|FSK2a|ASK|PSK1|PSK2|NZ|BI|BIa> Set demodulation FSK / ASK / PSK / NZ / Biphase / Biphase A");
PrintAndLog(" d <FSK|FSK1|FSK1a|FSK2|FSK2a|ASK|PSK1|PSK2|NRZ|BI|BIa> Set demodulation FSK / ASK / PSK / NRZ / Biphase / Biphase A");
PrintAndLog(" i [1] Invert data signal, defaults to normal");
PrintAndLog(" o [offset] Set offset, where data should start decode in bitstream");
PrintAndLog("");

View file

@ -115,9 +115,17 @@ typedef struct {
#define CMD_WRITER_LEGIC_RF 0x0389
#define CMD_EPA_PACE_COLLECT_NONCE 0x038A
#define CMD_ICLASS_READCHECK 0x038F
#define CMD_ICLASS_CLONE 0x0390
#define CMD_ICLASS_DUMP 0x0391
#define CMD_SNOOP_ICLASS 0x0392
#define CMD_SIMULATE_TAG_ICLASS 0x0393
#define CMD_READER_ICLASS 0x0394
#define CMD_READER_ICLASS_REPLAY 0x0395
#define CMD_ICLASS_READBLOCK 0x0396
#define CMD_ICLASS_WRITEBLOCK 0x0397
#define CMD_ICLASS_EML_MEMSET 0x0398
#define CMD_ICLASS_AUTHENTICATION 0x0399
// For measurements of the antenna tuning
#define CMD_MEASURE_ANTENNA_TUNING 0x0400

View file

@ -224,23 +224,44 @@ void MAC(uint8_t* k, BitstreamIn input, BitstreamOut out)
void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4])
{
uint8_t cc_nr[13] = { 0 };
uint8_t div_key[8];
uint8_t div_key[8];
//cc_nr=(uint8_t*)malloc(length+1);
memcpy(cc_nr,cc_nr_p,12);
memcpy(div_key,div_key_p,8);
memcpy(cc_nr, cc_nr_p, 12);
memcpy(div_key, div_key_p, 8);
reverse_arraybytes(cc_nr,12);
BitstreamIn bitstream = {cc_nr,12 * 8,0};
uint8_t dest []= {0,0,0,0,0,0,0,0};
BitstreamOut out = { dest, sizeof(dest)*8, 0 };
MAC(div_key,bitstream, out);
//The output MAC must also be reversed
reverse_arraybytes(dest, sizeof(dest));
memcpy(mac, dest, 4);
BitstreamIn bitstream = {cc_nr, 12 * 8, 0};
uint8_t dest []= {0,0,0,0,0,0,0,0};
BitstreamOut out = { dest, sizeof(dest)*8, 0 };
MAC(div_key,bitstream, out);
//The output MAC must also be reversed
reverse_arraybytes(dest, sizeof(dest));
memcpy(mac, dest, 4);
//free(cc_nr);
return;
return;
}
void doMAC_N(uint8_t *address_data_p, uint8_t address_data_size, uint8_t *div_key_p, uint8_t mac[4])
{
uint8_t *address_data;
uint8_t div_key[8];
address_data = (uint8_t*) malloc(address_data_size);
memcpy(address_data, address_data_p, address_data_size);
memcpy(div_key, div_key_p, 8);
reverse_arraybytes(address_data, address_data_size);
BitstreamIn bitstream = {address_data, address_data_size * 8, 0};
uint8_t dest []= {0,0,0,0,0,0,0,0};
BitstreamOut out = { dest, sizeof(dest)*8, 0 };
MAC(div_key, bitstream, out);
//The output MAC must also be reversed
reverse_arraybytes(dest, sizeof(dest));
memcpy(mac, dest, 4);
free(address_data);
return;
}
#ifndef ON_DEVICE
int testMAC()
{

View file

@ -42,6 +42,8 @@
#include <stdint.h>
void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]);
void doMAC_N(uint8_t *address_data_p,uint8_t address_data_size, uint8_t *div_key_p, uint8_t mac[4]);
#ifndef ON_DEVICE
int testMAC();
#endif

View file

@ -88,11 +88,17 @@ local _commands = {
CMD_EPA_PACE_COLLECT_NONCE = 0x038A,
--//CMD_EPA_ = 0x038B,
CMD_ICLASS_READCHECK = 0x038F,
CMD_ICLASS_CLONE = 0x0390,
CMD_ICLASS_DUMP = 0x0391,
CMD_SNOOP_ICLASS = 0x0392,
CMD_SIMULATE_TAG_ICLASS = 0x0393,
CMD_READER_ICLASS = 0x0394,
CMD_READER_ICLASS_REPLAY = 0x0395,
CMD_ICLASS_ISO14443A_WRITE = 0x0397,
CMD_READER_ICLASS_REPLAY = 0x0395,
CMD_ICLASS_READBLOCK = 0x0396,
CMD_ICLASS_WRITEBLOCK = 0x0397,
CMD_ICLASS_EML_MEMSET = 0x0398,
CMD_ICLASS_AUTHENTICATION = 0x0399,
--// For measurements of the antenna tuning
CMD_MEASURE_ANTENNA_TUNING = 0x0400,

View file

@ -619,3 +619,23 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
return 0;
}
int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len){
/*
uint32_t nt; // tag challenge
uint32_t ar_enc; // encrypted reader response
uint32_t at_enc; // encrypted tag response
*/
if (traceCrypto1) {
crypto1_destroy(traceCrypto1);
}
ks2 = ar_enc ^ prng_successor(nt, 64);
ks3 = at_enc ^ prng_successor(nt, 96);
traceCrypto1 = lfsr_recovery64(ks2, ks3);
mf_crypto1_decrypt(traceCrypto1, data, len, 0);
PrintAndLog("Decrypted data: [%s]", sprint_hex(data,len) );
crypto1_destroy(traceCrypto1);
return 0;
}

View file

@ -67,3 +67,4 @@ int isBlockEmpty(int blockN);
int isBlockTrailer(int blockN);
int loadTraceCard(uint8_t *tuid);
int saveTraceCard(void);
int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len);

View file

@ -333,7 +333,28 @@ int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt)
return 0;
}
int param_gethex_ex(const char *line, int paramnum, uint8_t * data, int *hexcnt)
{
int bg, en, temp, i;
//if (hexcnt % 2)
// return 1;
if (param_getptr(line, &bg, &en, paramnum)) return 1;
*hexcnt = en - bg + 1;
if (*hexcnt % 2) //error if not complete hex bytes
return 1;
for(i = 0; i < *hexcnt; i += 2) {
if (!(isxdigit(line[bg + i]) && isxdigit(line[bg + i + 1])) ) return 1;
sscanf((char[]){line[bg + i], line[bg + i + 1], 0}, "%X", &temp);
data[i / 2] = temp & 0xff;
}
return 0;
}
int param_getstr(const char *line, int paramnum, char * str)
{
int bg, en;

View file

@ -55,6 +55,7 @@ uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base);
uint8_t param_getdec(const char *line, int paramnum, uint8_t *destination);
uint8_t param_isdec(const char *line, int paramnum);
int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt);
int param_gethex_ex(const char *line, int paramnum, uint8_t * data, int *hexcnt);
int param_getstr(const char *line, int paramnum, char * str);
int hextobinarray( char *target, char *source);

View file

@ -11,13 +11,13 @@
typedef struct {
uint8_t app_limit;
uint8_t otp[2];
uint8_t block_writelock;
uint8_t chip_config;
uint8_t mem_config;
uint8_t eas;
uint8_t fuses;
uint8_t app_limit; //[8]
uint8_t otp[2]; //[9-10]
uint8_t block_writelock;//[11]
uint8_t chip_config; //[12]
uint8_t mem_config; //[13]
uint8_t eas; //[14]
uint8_t fuses; //[15]
}picopass_conf_block;
@ -74,24 +74,54 @@ void fuse_config(const picopass_hdr *hdr)
if( isset( fuses, FUSE_RA)) prnt(" RA: Read access enabled");
else prnt(" RA: Read access not enabled");
}
void mem_config(const picopass_hdr *hdr)
void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t *app_areas, uint8_t *kb) {
// mem-bit 5, mem-bit 7, chip-bit 4: defines chip type
if(isset(chip_cfg, 0x10) && notset(mem_cfg, 0x80) && notset(mem_cfg, 0x20)) {
*kb = 2;
*app_areas = 2;
*max_blk = 31;
} else if(isset(chip_cfg, 0x10) && isset(mem_cfg, 0x80) && notset(mem_cfg, 0x20)) {
*kb = 16;
*app_areas = 2;
*max_blk = 255; //16kb
} else if(notset(chip_cfg, 0x10) && notset(mem_cfg, 0x80) && notset(mem_cfg, 0x20)) {
*kb = 16;
*app_areas = 16;
*max_blk = 255; //16kb
} else if(isset(chip_cfg, 0x10) && isset(mem_cfg, 0x80) && isset(mem_cfg, 0x20)) {
*kb = 32;
*app_areas = 3;
*max_blk = 255; //16kb
} else if(notset(chip_cfg, 0x10) && notset(mem_cfg, 0x80) && isset(mem_cfg, 0x20)) {
*kb = 32;
*app_areas = 17;
*max_blk = 255; //16kb
} else {
*kb = 32;
*app_areas = 2;
*max_blk = 255;
}
}
void mem_app_config(const picopass_hdr *hdr)
{
uint8_t mem = hdr->conf.mem_config;
if( isset (mem, 0x80)) prnt(" Mem: 16KBits (255 * 8 bytes)");
else prnt(" Mem: 2 KBits ( 32 * 8 bytes)");
}
void applimit_config(const picopass_hdr *hdr)
{
uint8_t chip = hdr->conf.chip_config;
uint8_t applimit = hdr->conf.app_limit;
prnt(" AA1: blocks 6-%d", applimit);
prnt(" AA2: blocks %d-", (applimit+1));
if (applimit < 6) applimit = 26;
uint8_t kb = 2;
uint8_t app_areas = 2;
uint8_t max_blk = 31;
getMemConfig(mem, chip, &max_blk, &app_areas, &kb);
prnt(" Mem: %u KBits/%u App Areas (%u * 8 bytes) [%02X]", kb, app_areas, max_blk, mem);
prnt(" AA1: blocks 06-%02X", applimit);
prnt(" AA2: blocks %02X-%02X", applimit+1, max_blk);
}
void print_picopass_info(const picopass_hdr *hdr)
{
fuse_config(hdr);
mem_config(hdr);
applimit_config(hdr);
mem_app_config(hdr);
}
void printIclassDumpInfo(uint8_t* iclass_dump)
{

View file

@ -99,7 +99,7 @@ NXP/Philips CUSTOM COMMANDS
#define ICLASS_CMD_CHECK 0x05
#define ICLASS_CMD_DETECT 0x0F
#define ICLASS_CMD_HALT 0x00
#define ICLASS_CMD_UPDATE 0x87
#define ICLASS_CMD_UPDATE 0x87
#define ICLASS_CMD_ACT 0x8E
#define ICLASS_CMD_READ4 0x06
@ -196,5 +196,6 @@ NXP/Philips CUSTOM COMMANDS
void printIclassDumpInfo(uint8_t* iclass_dump);
void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t *app_areas, uint8_t *kb);
#endif // PROTOCOLS_H

View file

@ -133,12 +133,17 @@ typedef struct{
#define CMD_EPA_PACE_COLLECT_NONCE 0x038A
#define CMD_EPA_PACE_REPLAY 0x038B
#define CMD_ICLASS_READCHECK 0x038F
#define CMD_ICLASS_CLONE 0x0390
#define CMD_ICLASS_DUMP 0x0391
#define CMD_SNOOP_ICLASS 0x0392
#define CMD_SIMULATE_TAG_ICLASS 0x0393
#define CMD_READER_ICLASS 0x0394
#define CMD_READER_ICLASS_REPLAY 0x0395
#define CMD_ICLASS_ISO14443A_WRITE 0x0397
#define CMD_ICLASS_READBLOCK 0x0396
#define CMD_ICLASS_WRITEBLOCK 0x0397
#define CMD_ICLASS_EML_MEMSET 0x0398
#define CMD_ICLASS_AUTHENTICATION 0x0399
// For measurements of the antenna tuning
#define CMD_MEASURE_ANTENNA_TUNING 0x0400
@ -209,6 +214,7 @@ typedef struct{
#define FLAG_ICLASS_READER_CONF 0x08
#define FLAG_ICLASS_READER_AA 0x10
#define FLAG_ICLASS_READER_ONE_TRY 0x20
#define FLAG_ICLASS_READER_CEDITKEY 0x40