}
CmdLFRead("s");
- getSamples("8201",true); //capture enough to get 2 complete preambles (4096*2+9)
+ //getSamples("8201",true); //capture enough to get 2 complete preambles (4096*2+9)
+ getSamples("6144",true);
} while (!CmdEM410xRead(""));
return 0;
{
// loops if the captured ID was in XL-format.
CmdEM410xWatch(Cmd);
- PrintAndLog("# Replaying captured ID: %llu", g_em410xid);
+ PrintAndLog("# Replaying captured ID: %" PRIu64 , g_em410xid);
CmdLFaskSim("");
return 0;
}
bool EM_EndParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType)
{
- if (rows*cols>size) return false;
+ if (rows*cols>size) return FALSE;
uint8_t colP=0;
//assume last col is a parity and do not test
for (uint8_t colNum = 0; colNum < cols-1; colNum++) {
for (uint8_t rowNum = 0; rowNum < rows; rowNum++) {
colP ^= BitStream[(rowNum*cols)+colNum];
}
- if (colP != pType) return false;
+ if (colP != pType) return FALSE;
}
- return true;
+ return TRUE;
}
bool EM_ByteParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType)
{
- if (rows*cols>size) return false;
+ if (rows*cols>size) return FALSE;
uint8_t rowP=0;
//assume last row is a parity row and do not test
for (uint8_t rowNum = 0; rowNum < rows-1; rowNum++) {
for (uint8_t colNum = 0; colNum < cols; colNum++) {
rowP ^= BitStream[(rowNum*cols)+colNum];
}
- if (rowP != pType) return false;
+ if (rowP != pType) return FALSE;
}
- return true;
+ return TRUE;
+}
+
+// EM word parity test.
+// 9*5 = 45 bits in total
+// 012345678|r1
+// 012345678|r2
+// 012345678|r3
+// 012345678|r4
+// ------------
+//c012345678| 0
+// |- must be zero
+
+bool EMwordparitytest(uint8_t *bits){
+
+ // last row/col parity must be 0
+ if (bits[44] != 0 ) return FALSE;
+
+ // col parity check
+ uint8_t c1 = bytebits_to_byte(bits, 8) ^ bytebits_to_byte(bits+9, 8) ^ bytebits_to_byte(bits+18, 8) ^ bytebits_to_byte(bits+27, 8);
+ uint8_t c2 = bytebits_to_byte(bits+36, 8);
+ if ( c1 != c2 ) return FALSE;
+
+ // row parity check
+ uint8_t rowP = 0;
+ for ( uint8_t i = 0; i < 36; ++i ) {
+
+ rowP ^= bits[i];
+ if ( i>0 && (i % 9) == 0) {
+
+ if ( rowP != EVEN )
+ return FALSE;
+
+ rowP = 0;
+ }
+ }
+ // all checks ok.
+ return TRUE;
}
if ( ctmp == 'H' || ctmp == 'h' ) return usage_lf_em4x50_read();
return EM4x50Read(Cmd, true);
}
-
int CmdEM4x50Write(const char *Cmd){
uint8_t ctmp = param_getchar(Cmd, 0);
if ( ctmp == 'H' || ctmp == 'h' ) return usage_lf_em4x50_write();
}
#define EM_PREAMBLE_LEN 6
-// download samples from device
-// and copy them to Graphbuffer
+// download samples from device and copy to Graphbuffer
bool downloadSamplesEM(){
// 8 bit preamble + 32 bit word response (max clock (128) * 40bits = 5120 samples)
setGraphBuf(got, sizeof(got));
return TRUE;
}
-//search for given preamble in given BitStream and return success=1 or fail=0 and startIndex
+
+// em_demod
bool doPreambleSearch(size_t *startIdx){
// sanity check
if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 demodbuffer too small");
return FALSE;
}
-
- // skip first two 0 bits as they might have been missed in the demod
- uint8_t preamble[EM_PREAMBLE_LEN] = {0,0,1,0,1,0};
-
- // set size to 15 to only test first 4 positions for the preamble
- size_t size = (15 > DemodBufferLen) ? DemodBufferLen : 15;
+
+ // set size to 20 to only test first 14 positions for the preamble
+ size_t size = (20 > DemodBufferLen) ? DemodBufferLen : 20;
*startIdx = 0;
- uint8_t found = 0;
-
- // em only sends preamble once, so look for it once in the first x bits
- for (int idx = 0; idx < size - EM_PREAMBLE_LEN; idx++){
- if (memcmp(DemodBuffer+idx, preamble, EM_PREAMBLE_LEN) == 0){
- //first index found
- *startIdx = idx;
- found = 1;
- break;
- }
- }
+ // skip first two 0 bits as they might have been missed in the demod
+ uint8_t preamble[EM_PREAMBLE_LEN] = {0,0,1,0,1,0};
- if ( !found) {
+ if ( !preambleSearchEx(DemodBuffer, preamble, EM_PREAMBLE_LEN, &size, startIdx, TRUE)) {
if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", *startIdx);
return FALSE;
}
bool setDemodBufferEM(uint32_t *word, size_t idx){
//test for even parity bits.
- size_t size = removeParity(DemodBuffer, idx + EM_PREAMBLE_LEN, 9, 0, 44);
- if (!size) {
- if (g_debugMode) PrintAndLog("DEBUG: Error -EM Parity not detected");
+ uint8_t parity[45] = {0};
+ memcpy( parity, DemodBuffer, 45);
+ if (!EMwordparitytest(parity) ){
+ PrintAndLog("DEBUG: Error - EM Parity tests failed");
+ return FALSE;
+ }
+
+ if (!removeParity(DemodBuffer, idx + EM_PREAMBLE_LEN, 9, 0, 44)) {
+ if (g_debugMode) PrintAndLog("DEBUG: Error - EM, failed removing parity");
return FALSE;
}
-
- //todo test last 8 bits for even parity || (xor)
setDemodBuf(DemodBuffer, 40, 0);
-
*word = bytebits_to_byteLSBF(DemodBuffer, 32);
-
- uint8_t lo = (uint8_t) bytebits_to_byteLSBF(DemodBuffer , 8);
- uint8_t lo2 = (uint8_t) bytebits_to_byteLSBF(DemodBuffer + 8, 8);
- uint8_t hi = (uint8_t) bytebits_to_byteLSBF(DemodBuffer + 16, 8);
- uint8_t hi2 = (uint8_t) bytebits_to_byteLSBF(DemodBuffer + 24, 8);
- uint8_t cs = (uint8_t) bytebits_to_byteLSBF(DemodBuffer + 32, 8);
- uint8_t cs2 = lo ^ lo2 ^ hi ^ hi2;
- if (g_debugMode) PrintAndLog("EM4x05/4x69 : %08X CS: %02X %s"
- , *word
- , cs
- , (cs2==cs) ? "Passed" : "Failed"
- );
-
- return (cs2==cs);
+ return TRUE;
}
// FSK, PSK, ASK/MANCHESTER, ASK/BIPHASE, ASK/DIPHASE
int CmdEM4x05Dump(const char *Cmd) {
uint8_t addr = 0;
- uint32_t pwd;
+ uint32_t pwd = 0;
bool usePwd = false;
uint8_t ctmp = param_getchar(Cmd, 0);
if ( ctmp == 'H' || ctmp == 'h' ) return usage_lf_em4x05_dump();
// for now use default input of 1 as invalid (unlikely 1 will be a valid password...)
pwd = param_get32ex(Cmd, 0, 1, 16);
- if ( pwd != 1 ) {
+ if ( pwd != 1 )
usePwd = true;
- }
+
int success = 1;
+ PrintAndLog("Addr | data | ascii");
+ PrintAndLog("-----+--------+------");
for (; addr < 16; addr++) {
if (addr == 2) {
if (usePwd) {
- PrintAndLog("PWD Address %02u | %08X",addr,pwd);
+ PrintAndLog(" %02u | %08X", addr, pwd);
} else {
- PrintAndLog("PWD Address 02 | cannot read");
+ PrintAndLog(" 02 | cannot read");
}
} else {
//success &= EM4x05Read(addr, pwd, usePwd);
return success;
}
-
+//ICEMAN; mentalnote to self: -1 is not doable for uint32_t..
int CmdEM4x05Read(const char *Cmd) {
int addr, pwd;
bool usePwd = false;
if (!downloadSamplesEM())
return -1;
- //todo: check response for 00001010 then write data for write confirmation!
-
+
//attempt demod:
//need 0 bits demoded (after preamble) to verify write cmd
uint32_t dummy = 0;