* fills the uid pointer unless NULL
* fills resp_data unless NULL */
int iso14443a_select_card(byte_t* uid_ptr, iso14a_card_select_t* p_hi14a_card, uint32_t* cuid_ptr) {
+
+ iso14a_set_timeout(10500); // 10ms default 10*105 =
+
+ //uint8_t deselect[] = {0xc2}; //DESELECT
//uint8_t halt[] = { 0x50, 0x00, 0x57, 0xCD }; // HALT
uint8_t wupa[] = { 0x52 }; // WAKE-UP
//uint8_t reqa[] = { 0x26 }; // REQUEST A
int len;
// test for the SKYLANDERS TOY.
- //ReaderTransmit(halt,sizeof(halt), NULL);
- //len = ReaderReceive(resp, resp_par);
+ // ReaderTransmit(deselect,sizeof(deselect), NULL);
+ // len = ReaderReceive(resp, resp_par);
// Broadcast for a card, WUPA (0x52) will force response from all cards in the field
ReaderTransmitBitsPar(wupa,7,0, NULL);
p_hi14a_card->sak = sak;
p_hi14a_card->ats_len = 0;
}
-
+
if( (sak & 0x20) == 0) {
return 2; // non iso14443a compliant tag
}
AppendCrc14443a(rats, 2);
ReaderTransmit(rats, sizeof(rats), NULL);
+
len = ReaderReceive(resp, resp_par);
- if(!len) return 0;
+ Dbprintf("RATS Reponse: %d", len);
+ if(!len) {
+ Dbprintf("RATS: %02x %02x %02x", resp[0], resp[1], resp[2]);
+ return 0;
+ }
if(p_hi14a_card) {
memcpy(p_hi14a_card->ats, resp, sizeof(p_hi14a_card->ats));
if(select_status == 0) {
PrintAndLog("iso14443a card select failed");
+ // disconnect
+ c.arg[0] = 0;
+ c.arg[1] = 0;
+ c.arg[2] = 0;
+ SendCommand(&c);
return 0;
}
int CmdHFiClassList(const char *Cmd)
{
-
bool ShowWaitCycles = false;
char param = param_getchar(Cmd, 0);
return 0;
}
- uint8_t got[TRACE_BUFFER_SIZE];
- GetFromBigBuf(got,sizeof(got),0);
+// for the time being. Need better Bigbuf handling.
+#define TRACE_SIZE 3000
+
+ uint8_t trace[TRACE_SIZE];
+ GetFromBigBuf(trace, TRACE_SIZE, 0);
WaitForResponse(CMD_ACK,NULL);
PrintAndLog("Recorded Activity");
PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer");
PrintAndLog("All times are in carrier periods (1/13.56Mhz)");
PrintAndLog("");
- PrintAndLog(" Start | End | Src | Data");
- PrintAndLog("-----------|-----------|-----|--------");
-
- int i;
- uint32_t first_timestamp = 0;
+ PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC ");
+ PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------------");
+
+ uint16_t tracepos = 0;
+ uint16_t duration;
+ uint16_t data_len;
+ uint16_t parity_len;
+ bool isResponse;
uint32_t timestamp;
- bool tagToReader;
- uint32_t parityBits;
- uint8_t len;
- uint8_t *frame;
- uint32_t EndOfTransmissionTimestamp = 0;
+ uint32_t first_timestamp;
+ uint32_t EndOfTransmissionTimestamp;
+
+ for (;;) {
+ if(tracepos >= TRACE_SIZE) {
+ break;
+ }
- for( i=0; i < TRACE_BUFFER_SIZE;)
- {
- //First 32 bits contain
- // isResponse (1 bit)
- // timestamp (remaining)
- //Then paritybits
- //Then length
- timestamp = *((uint32_t *)(got+i));
- parityBits = *((uint32_t *)(got+i+4));
- len = got[i+8];
- frame = (got+i+9);
- uint32_t next_timestamp = (*((uint32_t *)(got+i+9))) & 0x7fffffff;
-
- tagToReader = timestamp & 0x80000000;
- timestamp &= 0x7fffffff;
-
- if(i==0) {
+ timestamp = *((uint32_t *)(trace + tracepos));
+ if(tracepos == 0) {
first_timestamp = timestamp;
}
- // Break and stick with current result idf buffer was not completely full
- if (frame[0] == 0x44 && frame[1] == 0x44 && frame[2] == 0x44 && frame[3] == 0x44) break;
-
- char line[1000] = "";
-
- if(len)//We have some data to display
- {
- int j,oddparity;
-
- for(j = 0; j < len ; j++)
- {
- oddparity = 0x01 ^ xorbits_8(frame[j] & 0xFF);
-
- if (tagToReader && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
- sprintf(line+(j*4), "%02x! ", frame[j]);
- } else {
- sprintf(line+(j*4), "%02x ", frame[j]);
- }
- }
- }else
- {
- if (ShowWaitCycles) {
- sprintf(line, "fdt (Frame Delay Time): %d", (next_timestamp - timestamp));
- }
+ // Break and stick with current result if buffer was not completely full
+ if (timestamp == 0x44444444) break;
+
+ tracepos += 4;
+ duration = *((uint16_t *)(trace + tracepos));
+ tracepos += 2;
+ data_len = *((uint16_t *)(trace + tracepos));
+ tracepos += 2;
+
+ if (data_len & 0x8000) {
+ data_len &= 0x7fff;
+ isResponse = true;
+ } else {
+ isResponse = false;
}
- char *crc = "";
-
- if(len > 2)
- {
- uint8_t b1, b2;
- if(!tagToReader && len == 4) {
- // Rough guess that this is a command from the reader
- // For iClass the command byte is not part of the CRC
- ComputeCrc14443(CRC_ICLASS, &frame[1], len-3, &b1, &b2);
- }
- else {
- // For other data.. CRC might not be applicable (UPDATE commands etc.)
- ComputeCrc14443(CRC_ICLASS, frame, len-2, &b1, &b2);
- }
+ parity_len = (data_len-1)/8 + 1;
- if (b1 != frame[len-2] || b2 != frame[len-1]) {
- crc = (tagToReader & (len < 8)) ? "" : " !crc";
- }
+ if (tracepos + data_len + parity_len >= TRACE_SIZE) {
+ break;
}
-
- i += (len + 9);
- EndOfTransmissionTimestamp = (*((uint32_t *)(got+i))) & 0x7fffffff;
-
- // Not implemented for iclass on the ARM-side
- //if (!ShowWaitCycles) i += 9;
-
- PrintAndLog(" %9d | %9d | %s | %s %s",
- (timestamp - first_timestamp),
- (EndOfTransmissionTimestamp - first_timestamp),
- (len?(tagToReader ? "Tag" : "Rdr"):" "),
- line, crc);
- }
- return 0;
-}
-
-int CmdHFiClassListOld(const char *Cmd)
-{
- uint8_t got[1920];
- GetFromBigBuf(got,sizeof(got),0);
-
- PrintAndLog("recorded activity:");
- PrintAndLog(" ETU :rssi: who bytes");
- PrintAndLog("---------+----+----+-----------");
-
- int i = 0;
- int prev = -1;
-
- for (;;) {
- if(i >= 1900) {
- break;
- }
-
- bool isResponse;
- int timestamp = *((uint32_t *)(got+i));
- if (timestamp & 0x80000000) {
- timestamp &= 0x7fffffff;
- isResponse = 1;
- } else {
- isResponse = 0;
- }
-
-
- int metric = 0;
-
- int parityBits = *((uint32_t *)(got+i+4));
- // 4 bytes of additional information...
- // maximum of 32 additional parity bit information
- //
- // TODO:
- // at each quarter bit period we can send power level (16 levels)
- // or each half bit period in 256 levels.
-
-
- int len = got[i+8];
-
- if (len > 100) {
- break;
- }
- if (i + len >= 1900) {
- break;
- }
-
- uint8_t *frame = (got+i+9);
-
- // Break and stick with current result if buffer was not completely full
- if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }
-
- char line[1000] = "";
- int j;
- for (j = 0; j < len; j++) {
+
+ uint8_t *frame = trace + tracepos;
+ tracepos += data_len;
+ uint8_t *parityBytes = trace + tracepos;
+ tracepos += parity_len;
+
+ char line[16][110];
+ for (int j = 0; j < data_len; j++) {
int oddparity = 0x01;
int k;
oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
}
- //if((parityBits >> (len - j - 1)) & 0x01) {
- if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
- sprintf(line+(j*4), "%02x! ", frame[j]);
- }
- else {
- sprintf(line+(j*4), "%02x ", frame[j]);
- }
- }
+ uint8_t parityBits = parityBytes[j>>3];
+ if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
+ sprintf(line[j/16]+((j%16)*4), "%02x! ", frame[j]);
+ } else {
+ sprintf(line[j/16]+((j%16)*4), "%02x ", frame[j]);
+ }
- char *crc;
- crc = "";
- if (len > 2) {
- uint8_t b1, b2;
- for (j = 0; j < (len - 1); j++) {
- // gives problems... search for the reason..
- /*if(frame[j] == 0xAA) {
- switch(frame[j+1]) {
- case 0x01:
- crc = "[1] Two drops close after each other";
- break;
- case 0x02:
- crc = "[2] Potential SOC with a drop in second half of bitperiod";
- break;
- case 0x03:
- crc = "[3] Segment Z after segment X is not possible";
- break;
- case 0x04:
- crc = "[4] Parity bit of a fully received byte was wrong";
- break;
- default:
- crc = "[?] Unknown error";
- break;
- }
- break;
- }*/
- }
+ }
- if (strlen(crc)==0) {
- if(!isResponse && len == 4) {
+ char *crc = "";
+ if (data_len > 2) {
+ uint8_t b1, b2;
+ if(!isResponse && data_len == 4 ) {
// Rough guess that this is a command from the reader
// For iClass the command byte is not part of the CRC
- ComputeCrc14443(CRC_ICLASS, &frame[1], len-3, &b1, &b2);
+ ComputeCrc14443(CRC_ICLASS, &frame[1], data_len-3, &b1, &b2);
+ if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) {
+ crc = "!crc";
+ }
}
else {
// For other data.. CRC might not be applicable (UPDATE commands etc.)
- ComputeCrc14443(CRC_ICLASS, frame, len-2, &b1, &b2);
- }
- //printf("%1x %1x",(unsigned)b1,(unsigned)b2);
- if (b1 != frame[len-2] || b2 != frame[len-1]) {
- crc = (isResponse & (len < 8)) ? "" : " !crc";
- } else {
- crc = "";
- }
- }
- } else {
- crc = ""; // SHORT
- }
-
- char metricString[100];
- if (isResponse) {
- sprintf(metricString, "%3d", metric);
- } else {
- strcpy(metricString, " ");
- }
-
- PrintAndLog(" +%7d: %s: %s %s %s",
- (prev < 0 ? 0 : (timestamp - prev)),
- metricString,
- (isResponse ? "TAG" : " "), line, crc);
+ ComputeCrc14443(CRC_ICLASS, frame, data_len-2, &b1, &b2);
+ if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) {
+ crc = "!crc";
+ }
+ }
+ }
- prev = timestamp;
- i += (len + 9);
- }
+ EndOfTransmissionTimestamp = timestamp + duration;
+
+ int num_lines = (data_len - 1)/16 + 1;
+ for (int j = 0; j < num_lines; j++) {
+ if (j == 0) {
+ PrintAndLog(" %9d | %9d | %s | %-64s| %s",
+ (timestamp - first_timestamp),
+ (EndOfTransmissionTimestamp - first_timestamp),
+ (isResponse ? "Tag" : "Rdr"),
+ line[j],
+ (j == num_lines-1)?crc:"");
+ } else {
+ PrintAndLog(" | | | %-64s| %s",
+ line[j],
+ (j == num_lines-1)?crc:"");
+ }
+ }
+
+ bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000;
+
+ if (ShowWaitCycles && !isResponse && next_isResponse) {
+ uint32_t next_timestamp = *((uint32_t *)(trace + tracepos));
+ if (next_timestamp != 0x44444444) {
+ PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d",
+ (EndOfTransmissionTimestamp - first_timestamp),
+ (next_timestamp - first_timestamp),
+ " ",
+ (next_timestamp - EndOfTransmissionTimestamp));
+ }
+ }
+
+ }
+
return 0;
}
{"simman", CmdLFSimManchester, 0, "<Clock> <Bitstream> [GAP] Simulate arbitrary Manchester LF tag"},
{"snoop", CmdLFSnoop, 0, "['l'|'h'|<divisor>] [trigger threshold]-- Snoop LF (l:125khz, h:134khz)"},
- {"avid", CmdLFAWID26, 1, "{ AWID26 tags }"},
+ {"awid26", CmdLFAWID26, 1, "{ AWID26 tags }"},
{"em4x", CmdLFEM4X, 1, "{ EM4X tags }"},
{"hid", CmdLFHID, 1, "{ HID tags }"},
{"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders }"},
#include <inttypes.h>
#include "proxmark3.h"
#include "ui.h"
-#include "graph.h"
+//#include "graph.h"
#include "cmdmain.h"
#include "cmdparser.h"
-#include "cmddata.h"
+//#include "cmddata.h"
#include "cmdlf.h"
#include "cmdlfawid26.h"
#include "util.h"
-#include "data.h"
+//#include "data.h"
static int CmdHelp(const char *Cmd);
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') {
- PrintAndLog("Usage: lf awid26 write []");
+ PrintAndLog("Usage: lf awid26 clone <facility> <id>");
PrintAndLog(" [], ");
PrintAndLog("");
- PrintAndLog(" sample: lf awid26 write 26 2233");
- PrintAndLog(" : lf awid26 write 26 15 2233");
+ PrintAndLog(" sample: lf awid26 clone 15 2233");
return 0;
}
return 0;
}
+
+// convert 96 bit AWID FSK data to 8 digit BCD UID
+bool awid26_hex_to_uid(unsigned char *response, unsigned char *awid26)
+{
+ // uint8_t i, tmp[96], tmp1[7];
+ // int site;
+ // int id;
+
+ // if(!hextobinarray(tmp, awid26))
+ // return false;
+
+ // // data is in blocks of 4 bits - every 4th bit is parity, except the first
+ // // block which is all zeros
+ // for(i= 0 ; i < 4 ; ++i)
+ // if(tmp[i] != 0x00)
+ // return false;
+
+ // // discard 1st block
+ // memcpy(tmp, tmp + 4, 92);
+
+ // // check and strip parity on the rest
+ // for(i= 1 ; i < 23 ; ++i)
+ // if(tmp[(i * 4) - 1] != parity(tmp + (i - 1) * 4, ODD, 3))
+ // return false;
+ // else
+ // memcpy((tmp + (i - 1) * 3), tmp + (i - 1) * 4, 3);
+
+ // // discard the rest of the header - 1 more 3 bit block
+ // memcpy(tmp, tmp + 3, 66);
+
+ // // next 8 bits is data length - should be 26: 0x1A
+ // binarraytohex(tmp1, tmp, 8);
+ // if(strcmp(tmp1, "1A") != 0)
+ // return false;
+ // memcpy(tmp, tmp +8, 58);
+
+ // // standard wiegand parity check - even for 1st 12 bits, odd for 2nd 12
+ // if(tmp[0] != parity(tmp + 1, EVEN, 12))
+ // return false;
+ // if(tmp[25] != parity(tmp + 13, ODD, 12))
+ // return false;
+
+ // // convert to hex, ignoring parity bits
+ // if(!binarraytohex(tmp1, tmp + 1, 24))
+ // return false;
+
+ // // convert hex to site/id
+ // sscanf(tmp1,"%2X%4X", &site, &id);
+
+ // // final output 8 byte BCD
+ // sprintf(response,"%03d%05d", site, id);
+
+ return true;
+}
+
+// convert null-terminated BCD UID (8 digits) to 96 bit awid26 encoded binary array
+bool bcd_to_awid26_bin(unsigned char *awid26, unsigned char *bcd)
+{
+ // char i, p, tmp1[8], tmp2[26];
+ // int tmpint;
+
+ // if(strlen(bcd) != 8)
+ // return false;
+
+ // // convert BCD site code to HEX
+ // sscanf(bcd, "%03d", &tmpint);
+ // sprintf(tmp2, "%02x", tmpint);
+ // memcpy(tmp1, tmp2, 2);
+
+ // // convert BCD ID to HEX
+ // sscanf(bcd + 3, "%05d", &tmpint);;
+ // sprintf(tmp2, "%04x", tmpint);
+
+ // // copy with trailing NULL
+ // memcpy(tmp1 + 2, tmp2, 5);
+
+ // // convert full HEX to binary, leaving room for parity prefix
+ // hextobinarray(tmp2 + 1, tmp1);
+
+ // wiegand_add_parity(tmp2, tmp2 + 1, 24);
+
+ // memset(awid26, '\x0', 96);
+
+ // // magic 18 bit awid26 header (we will overwrite the last two bits)
+ // hextobinarray(awid26, "011D8");
+
+ // // copy to target leaving space for parity bits
+ // for(i= 0, p= 18 ; i < 26 ; ++i, ++p)
+ // {
+ // // skip target bit if this is a parity location
+ // if(!((p + 1) % 4))
+ // p += 1;
+ // awid26[p]= tmp2[i];
+ // }
+
+ // // add parity bits
+ // for(i= 1 ; i < 24 ; ++i)
+ // awid26[((i + 1) * 4) - 1]= parity(&awid26[i * 4], ODD, 3);
+
+ return false;
+}
+
// int CmdReadTrace(const char *Cmd)
// {
static command_t CommandTable[] =
{
- {"help", CmdHelp, 1, "This help"},
- {"clone", CmdClone, 0, "<facility> <id> -- clone to a t55xx tag"},
+ {"help", CmdHelp, 1, "This help"},
+ {"clone", CmdClone, 1, "<facility> <id> -- clone AWID26 to t55xx tag"},
{NULL, NULL, 0, NULL}
};
int CmdLFAWID26(const char *Cmd);
int CmdClone(const char *Cmd);
+bool awid26_hex_to_uid(unsigned char *response, unsigned char *awid26);
+bool bcd_to_awid26_bin(unsigned char *awid26, unsigned char *bcd);
#endif
\r
int i = start;\r
int j = len-1;\r
+ if (len > 32) {\r
+ return 0;\r
+ }\r
uint32_t tmp = 0;\r
for (; j >= 0; --j, ++i){\r
tmp |= bits[i] << j;\r
return en - bg + 1;
}
+
+/*
+The following methods comes from Rfidler sourcecode.
+https://github.com/ApertureLabsLtd/RFIDler/blob/master/firmware/Pic32/RFIDler.X/src/
+*/
+
+// convert hex to sequence of 0/1 bit values
+// returns number of bits converted
+int hextobinarray(char *target, char *source)
+{
+ int length, i, count= 0;
+ char x;
+
+ length = strlen(source);
+ // process 4 bits (1 hex digit) at a time
+ while(length--)
+ {
+ x= *(source++);
+ // capitalize
+ if (x >= 'a' && x <= 'f')
+ x -= 32;
+ // convert to numeric value
+ if (x >= '0' && x <= '9')
+ x -= '0';
+ else if (x >= 'A' && x <= 'F')
+ x -= 'A' - 10;
+ else
+ return 0;
+ // output
+ for(i= 0 ; i < 4 ; ++i, ++count)
+ *(target++)= (x >> (3 - i)) & 1;
+ }
+
+ return count;
+}
+
+// convert hex to human readable binary string
+int hextobinstring(char *target, char *source)
+{
+ int length;
+
+ if(!(length= hextobinarray(target, source)))
+ return 0;
+ binarraytobinstring(target, target, length);
+ return length;
+}
+
+// convert binary array of 0x00/0x01 values to hex (safe to do in place as target will always be shorter than source)
+// return number of bits converted
+int binarraytohex(char *target, char *source, int length)
+{
+ unsigned char i, x;
+ int j = length;
+
+ if(j % 4)
+ return 0;
+
+ while(j)
+ {
+ for(i= x= 0 ; i < 4 ; ++i)
+ x += ( source[i] << (3 - i));
+ sprintf(target,"%X", x);
+ ++target;
+ source += 4;
+ j -= 4;
+ }
+ return length;
+}
+
+// convert binary array to human readable binary
+void binarraytobinstring(char *target, char *source, int length)
+{
+ int i;
+
+ for(i= 0 ; i < length ; ++i)
+ *(target++)= *(source++) + '0';
+ *target= '\0';
+}
+
+// return parity bit required to match type
+uint8_t parity( char *bits, uint8_t type, int length)
+{
+ int x;
+
+ for(x= 0 ; length > 0 ; --length)
+ x += bits[length - 1];
+ x %= 2;
+
+ return x ^ type;
+}
+
+// add HID parity to binary array: EVEN prefix for 1st half of ID, ODD suffix for 2nd half
+void wiegand_add_parity(char *target, char *source, char length)
+{
+ *(target++)= parity(source, EVEN, length / 2);
+ memcpy(target, source, length);
+ target += length;
+ *(target)= parity(source + length / 2, ODD, length / 2);
+}
#ifndef MAX
# define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
+#define TRUE 1
+#define FALSE 0
+#define EVEN 0
+#define ODD 1
int ukbhit(void);
int param_gethex(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);
+ int hextobinstring( char *target, char *source);
+ int binarraytohex( char *target, char *source, int length);
+void binarraytobinstring(char *target, char *source, int length);
+uint8_t parity( char *string, uint8_t type, int length);
+void wiegand_add_parity(char *target, char *source, char length);