cmdlfpyramid.c \
cmdlfguard.c \
cmdlfnedap.c \
+ cmdlfjablotron.c \
pm3_binlib.c \
scripting.c \
cmdscript.c \
sum += CRUMB(bytes[i], 4);
sum += CRUMB(bytes[i], 6);
}
- sum ^= mask;
+ sum &= mask;
return sum;
}
static uint8_t calcSumCrumbAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask) {
sum += NIBBLE_LOW(bytes[i]);
sum += NIBBLE_HIGH(bytes[i]);
}
- sum ^= mask;
+ sum &= mask;
return sum;
}
static uint8_t calcSumNibbleAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask){
uint8_t sum = 0;
for (uint8_t i = 0; i < len; i++)
sum += bytes[i];
- sum ^= mask;
+ sum &= mask;
return sum;
}
// Ones complement
uint8_t sum = 0;
for (uint8_t i = 0; i < len; i++)
sum -= bytes[i];
- sum ^= mask;
+ sum &= mask;
return sum;
}
static uint8_t calcSumByteSubOnes( uint8_t* bytes, uint8_t len, uint32_t mask){
sum -= NIBBLE_LOW(bytes[i]);
sum -= NIBBLE_HIGH(bytes[i]);
}
- sum ^= mask;
+ sum &= mask;
return sum;
}
static uint8_t calcSumNibbleSubOnes( uint8_t* bytes, uint8_t len, uint32_t mask) {
}
len >>= 1;
- PrintAndLog("\nTests with '%s' hex bytes", sprint_hex(data, len));
- PrintAndLog(" JA: CRC8: %X (0x6C expected)", CRC8ja(data, len) );
+ //PrintAndLog("\nTests with '%s' hex bytes", sprint_hex(data, len));
PrintAndLog("\nTests of reflection. Two current methods in source code");
PrintAndLog(" reflect(0x3e23L,3) is %04X == 0x3e26", reflect(0x3e23L,3) );
uint8_t dataStr[] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39 };
uint8_t legic8 = CRC8Legic(dataStr, sizeof(dataStr));
- PrintAndLog("JA: CRC8 : %X (0x28 expected)", CRC8ja(dataStr, sizeof(dataStr)) );
PrintAndLog("LEGIC: CRC16: %X", CRC16Legic(dataStr, sizeof(dataStr), legic8));
//these below has been tested OK.
sscanf(Cmd, "%i %i %i %i", &offset, &clk, &invert, &maxErr);
uint8_t BitStream[MAX_DEMOD_BUF_LEN];
- size_t size = getFromGraphBuf(BitStream);
+ size_t size = getFromGraphBuf(BitStream);
+ if (size == 0 ) {
+ if (g_debugMode) PrintAndLog("DEBUG: no data in graphbuf");
+ return 0;
+ }
//invert here inverts the ask raw demoded bits which has no effect on the demod, but we need the pointer
int errCnt = askdemod(BitStream, &size, &clk, &invert, maxErr, 0, 0);
if ( errCnt < 0 || errCnt > maxErr ) {
return 0;
}
-// by marshmellow - sim ask data given clock, fcHigh, fcLow, invert
+// by marshmellow - sim fsk data given clock, fcHigh, fcLow, invert
// - allow pull data from DemodBuffer
int CmdLFfskSim(const char *Cmd)
{
//might be able to autodetect FCs and clock from Graphbuffer if using demod buffer
// otherwise will need FChigh, FClow, Clock, and bitstream
- uint8_t fcHigh=0, fcLow=0, clk=0;
- uint8_t invert=0;
- bool errors = FALSE;
- char hexData[32] = {0x00}; // store entered hex data
- uint8_t data[255] = {0x00};
- int dataLen = 0;
- uint8_t cmdp = 0;
- while(param_getchar(Cmd, cmdp) != 0x00)
- {
- switch(param_getchar(Cmd, cmdp))
- {
- case 'h':
- return usage_lf_simfsk();
- case 'i':
- invert = 1;
- cmdp++;
- break;
- case 'c':
- errors |= param_getdec(Cmd,cmdp+1,&clk);
- cmdp+=2;
- break;
- case 'H':
- errors |= param_getdec(Cmd,cmdp+1,&fcHigh);
- cmdp+=2;
- break;
- case 'L':
- errors |= param_getdec(Cmd,cmdp+1,&fcLow);
- cmdp+=2;
- break;
- //case 's':
- // separator=1;
- // cmdp++;
- // break;
- case 'd':
- dataLen = param_getstr(Cmd, cmdp+1, hexData);
- if (dataLen==0) {
- errors=TRUE;
- } else {
- dataLen = hextobinarray((char *)data, hexData);
- }
- if (dataLen==0) errors=TRUE;
- if (errors) PrintAndLog ("Error getting hex data");
- cmdp+=2;
- break;
- default:
- PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
- errors = TRUE;
- break;
- }
- if(errors) break;
- }
- if(cmdp == 0 && DemodBufferLen == 0)
- {
- errors = TRUE;// No args
- }
-
- //Validations
- if(errors)
- {
- return usage_lf_simfsk();
- }
+ uint8_t fcHigh = 0, fcLow = 0, clk = 0;
+ uint8_t invert = 0;
+ bool errors = FALSE;
+ char hexData[32] = {0x00}; // store entered hex data
+ uint8_t data[255] = {0x00};
+ int dataLen = 0;
+ uint8_t cmdp = 0;
+
+ while(param_getchar(Cmd, cmdp) != 0x00)
+ {
+ switch(param_getchar(Cmd, cmdp))
+ {
+ case 'h':
+ return usage_lf_simfsk();
+ case 'i':
+ invert = 1;
+ cmdp++;
+ break;
+ case 'c':
+ errors |= param_getdec(Cmd, cmdp+1, &clk);
+ cmdp += 2;
+ break;
+ case 'H':
+ errors |= param_getdec(Cmd, cmdp+1, &fcHigh);
+ cmdp += 2;
+ break;
+ case 'L':
+ errors |= param_getdec(Cmd, cmdp+1, &fcLow);
+ cmdp += 2;
+ break;
+ //case 's':
+ // separator = 1;
+ // cmdp++;
+ // break;
+ case 'd':
+ dataLen = param_getstr(Cmd, cmdp+1, hexData);
+ if (dataLen == 0)
+ errors = TRUE;
+ else
+ dataLen = hextobinarray((char *)data, hexData);
+
+ if (dataLen == 0) errors = TRUE;
+ if (errors) PrintAndLog ("Error getting hex data");
+ cmdp+=2;
+ break;
+ default:
+ PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+ errors = TRUE;
+ break;
+ }
+ if(errors) break;
+ }
+
+ // No args
+ if(cmdp == 0 && DemodBufferLen == 0)
+ errors = TRUE;
- if (dataLen == 0){ //using DemodBuffer
- if (clk==0 || fcHigh==0 || fcLow==0){ //manual settings must set them all
- uint8_t ans = fskClocks(&fcHigh, &fcLow, &clk, 0);
- if (ans==0){
- if (!fcHigh) fcHigh=10;
- if (!fcLow) fcLow=8;
- if (!clk) clk=50;
- }
- }
- } else {
- setDemodBuf(data, dataLen, 0);
- }
+ //Validations
+ if(errors) return usage_lf_simfsk();
+
+ if (dataLen == 0){ //using DemodBuffer
+ if (clk == 0 || fcHigh == 0 || fcLow == 0){ //manual settings must set them all
+ uint8_t ans = fskClocks(&fcHigh, &fcLow, &clk, 0);
+ if (ans==0){
+ if (!fcHigh) fcHigh = 10;
+ if (!fcLow) fcLow = 8;
+ if (!clk) clk = 50;
+ }
+ }
+ } else {
+ setDemodBuf(data, dataLen, 0);
+ }
//default if not found
- if (clk == 0) clk = 50;
- if (fcHigh == 0) fcHigh = 10;
- if (fcLow == 0) fcLow = 8;
+ if (clk == 0) clk = 50;
+ if (fcHigh == 0) fcHigh = 10;
+ if (fcLow == 0) fcLow = 8;
- uint16_t arg1, arg2;
- arg1 = fcHigh << 8 | fcLow;
- arg2 = invert << 8 | clk;
- size_t size = DemodBufferLen;
- if (size > USB_CMD_DATA_SIZE) {
- PrintAndLog("DemodBuffer too long for current implementation - length: %d - max: %d", size, USB_CMD_DATA_SIZE);
- size = USB_CMD_DATA_SIZE;
- }
- UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}};
+ uint16_t arg1, arg2;
+ arg1 = fcHigh << 8 | fcLow;
+ arg2 = invert << 8 | clk;
+ size_t size = DemodBufferLen;
+ if (size > USB_CMD_DATA_SIZE) {
+ PrintAndLog("DemodBuffer too long for current implementation - length: %d - max: %d", size, USB_CMD_DATA_SIZE);
+ size = USB_CMD_DATA_SIZE;
+ }
+ UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}};
- memcpy(c.d.asBytes, DemodBuffer, size);
+ memcpy(c.d.asBytes, DemodBuffer, size);
clearCommandBuffer();
- SendCommand(&c);
- return 0;
+ SendCommand(&c);
+ return 0;
}
// by marshmellow - sim ask data given clock, invert, manchester or raw, separator
// - allow pull data from DemodBuffer
int CmdLFaskSim(const char *Cmd)
{
- //autodetect clock from Graphbuffer if using demod buffer
+ // autodetect clock from Graphbuffer if using demod buffer
// needs clock, invert, manchester/raw as m or r, separator as s, and bitstream
- uint8_t encoding = 1, separator = 0, clk=0, invert=0;
+ uint8_t encoding = 1, separator = 0, clk = 0, invert = 0;
bool errors = FALSE;
char hexData[32] = {0x00};
uint8_t data[255]= {0x00}; // store entered hex data
cmdp++;
break;
case 'c':
- errors |= param_getdec(Cmd,cmdp+1,&clk);
- cmdp+=2;
+ errors |= param_getdec(Cmd, cmdp+1, &clk);
+ cmdp += 2;
break;
case 'b':
- encoding=2; //biphase
+ encoding = 2; //biphase
cmdp++;
break;
case 'm':
- encoding=1;
+ encoding = 1; //manchester
cmdp++;
break;
case 'r':
- encoding=0;
+ encoding = 0; //raw
cmdp++;
break;
case 's':
- separator=1;
+ separator = 1;
cmdp++;
break;
case 'd':
dataLen = param_getstr(Cmd, cmdp+1, hexData);
- if (dataLen==0)
+ if (dataLen == 0)
errors = TRUE;
else
dataLen = hextobinarray((char *)data, hexData);
- if (dataLen==0) errors = TRUE;
+ if (dataLen == 0) errors = TRUE;
if (errors) PrintAndLog ("Error getting hex data, datalen: %d", dataLen);
- cmdp+=2;
+ cmdp += 2;
break;
default:
PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
}
if(errors) break;
}
-
+
+ // No args
if(cmdp == 0 && DemodBufferLen == 0)
- errors = TRUE;// No args
+ errors = TRUE;
//Validations
if(errors) return usage_lf_simask();
ans=CmdFSKdemodIO("");
if (ans>0) {
- PrintAndLog("\nValid IO Prox ID Found!");
- return 1;
+ PrintAndLog("\nValid IO Prox ID Found!");
+ return 1;
}
-
ans=CmdFSKdemodPyramid("");
if (ans>0) {
- PrintAndLog("\nValid Pyramid ID Found!");
- return 1;
+ PrintAndLog("\nValid Pyramid ID Found!");
+ return 1;
}
-
ans=CmdFSKdemodParadox("");
if (ans>0) {
- PrintAndLog("\nValid Paradox ID Found!");
- return 1;
+ PrintAndLog("\nValid Paradox ID Found!");
+ return 1;
}
-
ans=CmdFSKdemodAWID("");
if (ans>0) {
- PrintAndLog("\nValid AWID ID Found!");
- return 1;
+ PrintAndLog("\nValid AWID ID Found!");
+ return 1;
}
-
ans=CmdFSKdemodHID("");
if (ans>0) {
- PrintAndLog("\nValid HID Prox ID Found!");
- return 1;
+ PrintAndLog("\nValid HID Prox ID Found!");
+ return 1;
}
-
ans=CmdAskEM410xDemod("");
if (ans>0) {
- PrintAndLog("\nValid EM410x ID Found!");
- return 1;
+ PrintAndLog("\nValid EM410x ID Found!");
+ return 1;
}
-
ans=CmdG_Prox_II_Demod("");
if (ans>0) {
- PrintAndLog("\nValid Guardall G-Prox II ID Found!");
- return 1;
+ PrintAndLog("\nValid Guardall G-Prox II ID Found!");
+ return 1;
}
-
ans=CmdFDXBdemodBI("");
if (ans>0) {
PrintAndLog("\nValid FDX-B ID Found!");
return 1;
}
-
ans=EM4x50Read("", false);
if (ans>0) {
PrintAndLog("\nValid EM4x50 ID Found!");
return 1;
}
-
ans=CmdVikingDemod("");
if (ans>0) {
PrintAndLog("\nValid Viking ID Found!");
return 1;
}
-
ans=CmdIndalaDecode("");
if (ans>0) {
PrintAndLog("\nValid Indala ID Found!");
return 1;
}
-
ans=CmdPSKNexWatch("");
if (ans>0) {
PrintAndLog("\nValid NexWatch ID Found!");
return 1;
}
+ ans=CmdJablotronDemod("");
+ if (ans>0) {
+ PrintAndLog("\nValid Jablotron ID Found!");
+ return 1;
+ }
ans=CmdLFNedapDemod("");
if (ans>0) {
PrintAndLog("\nValid NEDAP ID Found!");
{"hid", CmdLFHID, 1, "{ HID RFIDs... }"},
{"hitag", CmdLFHitag, 1, "{ HITAG RFIDs... }"},
{"io", CmdLFIO, 1, "{ IOPROX RFIDs... }"},
+ {"jablotron", CmdLFJablotron, 1, "{ JABLOTRON RFIDs... }"},
{"nedap", CmdLFNedap, 1, "{ NEDAP RFIDs... }"},
{"pcf7931", CmdLFPCF7931, 1, "{ PCF7931 RFIDs... }"},
{"presco", CmdLFPresco, 1, "{ Presco RFIDs... }"},
#include "proxmark3.h"
#include "lfdemod.h"
-#include "util.h" // for parsing cli command utils
-#include "ui.h" // for show graph controls
-#include "graph.h" // for graph data
-#include "cmdparser.h" // for getting cli commands included in cmdmain.h
-#include "cmdmain.h" // for sending cmds to device
-#include "data.h" // for GetFromBigBuf
-#include "cmddata.h" // for `lf search`
-#include "cmdlfawid.h" // for awid menu
-#include "cmdlfem4x.h" // for em4x menu
-#include "cmdlfhid.h" // for hid menu
-#include "cmdlfhitag.h" // for hitag menu
-#include "cmdlfio.h" // for ioprox menu
-#include "cmdlft55xx.h" // for t55xx menu
-#include "cmdlfti.h" // for ti menu
-#include "cmdlfpresco.h" // for presco menu
-#include "cmdlfpcf7931.h"// for pcf7931 menu
-#include "cmdlfpyramid.h"// for pyramid menu
-#include "cmdlfviking.h" // for viking menu
-#include "cmdlfguard.h" // for GuardAll menu
-#include "cmdlfnedap.h" // for NEDAP menu
+#include "util.h" // for parsing cli command utils
+#include "ui.h" // for show graph controls
+#include "graph.h" // for graph data
+#include "cmdparser.h" // for getting cli commands included in cmdmain.h
+#include "cmdmain.h" // for sending cmds to device
+#include "data.h" // for GetFromBigBuf
+#include "cmddata.h" // for `lf search`
+#include "cmdlfawid.h" // for awid menu
+#include "cmdlfem4x.h" // for em4x menu
+#include "cmdlfhid.h" // for hid menu
+#include "cmdlfhitag.h" // for hitag menu
+#include "cmdlfio.h" // for ioprox menu
+#include "cmdlft55xx.h" // for t55xx menu
+#include "cmdlfti.h" // for ti menu
+#include "cmdlfpresco.h" // for presco menu
+#include "cmdlfpcf7931.h" // for pcf7931 menu
+#include "cmdlfpyramid.h" // for pyramid menu
+#include "cmdlfviking.h" // for viking menu
+#include "cmdlfguard.h" // for GuardAll menu
+#include "cmdlfnedap.h" // for NEDAP menu
+#include "cmdlfjablotron.h" // for JABLOTRON menu
int CmdLF(const char *Cmd);
--- /dev/null
+//-----------------------------------------------------------------------------
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// Low frequency Presco tag commands
+//-----------------------------------------------------------------------------
+#include "cmdlfjablotron.h"
+
+static int CmdHelp(const char *Cmd);
+
+int usage_lf_jablotron_clone(void){
+ PrintAndLog("clone a Jablotron tag to a T55x7 tag.");
+ PrintAndLog("Usage: lf jablotron clone d <Card-ID> <Q5>");
+ PrintAndLog("Options :");
+ PrintAndLog(" d <Card-ID> : jablotron card ID");
+ PrintAndLog(" <Q5> : specify write to Q5 (t5555 instead of t55x7)");
+ PrintAndLog("");
+ PrintAndLog("Sample : lf jablotron clone d 123456789");
+ return 0;
+}
+
+int usage_lf_jablotron_sim(void) {
+ PrintAndLog("Enables simulation of jablotron card with specified card number.");
+ PrintAndLog("Simulation runs until the button is pressed or another USB command is issued.");
+ PrintAndLog("Per jablotron format, the card number is 9 digit number and can contain *# chars. Larger values are truncated.");
+ PrintAndLog("");
+ PrintAndLog("Usage: lf jablotron sim d <Card-ID> or H <hex-ID>");
+ PrintAndLog("Options :");
+ PrintAndLog(" d <Card-ID> : jablotron card number");
+// PrintAndLog(" H <hex-ID> : 8 digit hex card number");
+ PrintAndLog("");
+ PrintAndLog("Sample : lf jablotron sim d 123456789");
+ return 0;
+}
+
+int getJablotronBits(uint64_t fullcode, uint8_t *bits) {
+ //preamp
+ num_to_bytebits(0xFFFF, 16, bits);
+
+ //fullcode
+ num_to_bytebits(fullcode, 40, bits+16);
+
+ //chksum byte
+ uint8_t crc = 0;
+ for (int i=16; i < 56; i += 8) {
+ crc += bytebits_to_byte(bits+i,8);
+ }
+ crc ^= 0x3A;
+ num_to_bytebits(crc, 8, bits+56);
+
+ return 1;
+}
+
+//see ASKDemod for what args are accepted
+int CmdJablotronDemod(const char *Cmd) {
+
+ //Differential Biphase / di-phase (inverted biphase)
+ //get binary from ask wave
+ if (!ASKbiphaseDemod("0 64 1 0", FALSE)) {
+ if (g_debugMode) PrintAndLog("Error Jablotron: ASKbiphaseDemod failed");
+ return 0;
+ }
+ size_t size = DemodBufferLen;
+ int ans = JablotronDemod(DemodBuffer, &size);
+ if (ans < 0){
+ if (g_debugMode){
+ // if (ans == -5)
+ // PrintAndLog("DEBUG: Error - not enough samples");
+ // else if (ans == -1)
+ // PrintAndLog("DEBUG: Error - only noise found");
+ // else if (ans == -2)
+ // PrintAndLog("DEBUG: Error - problem during ASK/Biphase demod");
+ if (ans == -3)
+ PrintAndLog("DEBUG: Error - Size not correct: %d", size);
+ else if (ans == -4)
+ PrintAndLog("DEBUG: Error - Jablotron preamble not found");
+ else
+ PrintAndLog("DEBUG: Error - ans: %d", ans);
+ }
+ return 0;
+ }
+ //got a good demod
+ uint32_t raw1 = bytebits_to_byte(DemodBuffer+ans, 32);
+ uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32);
+ uint64_t cardid = (raw1 & 0x0000FFFF);
+ cardid <<= 32;
+ cardid |= (raw2 >> 8);
+
+ PrintAndLog("Jablotron Tag Found: Card ID %12X", cardid);
+ PrintAndLog("Raw: %08X%08X", raw1 ,raw2);
+
+ setDemodBuf(DemodBuffer+ans, 64, 0);
+
+ //PrintAndLog("1410-%u-%u-%08X-%02X", fullcode);
+ return 1;
+}
+
+int CmdJablotronRead(const char *Cmd) {
+ // read lf silently
+ CmdLFRead("s");
+ // get samples silently
+ getSamples("30000",false);
+ // demod and output Presco ID
+ return CmdJablotronDemod(Cmd);
+}
+
+int CmdJablotronClone(const char *Cmd) {
+
+ uint64_t fullcode = 0;
+ uint32_t blocks[3] = {T55x7_MODULATION_DIPHASE | T55x7_BITRATE_RF_64 | 2<<T55x7_MAXBLOCK_SHIFT, 0, 0};
+
+ uint8_t bits[64];
+ uint8_t *bs = bits;
+ memset(bs, 0, sizeof(bits));
+
+ char cmdp = param_getchar(Cmd, 0);
+ if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_jablotron_clone();
+
+ fullcode = param_get64ex(Cmd, 1, 0, 16);
+
+ //Q5
+ if (param_getchar(Cmd, 2) == 'Q' || param_getchar(Cmd, 2) == 'q') {
+ //t5555 (Q5) BITRATE = (RF-2)/2 (iceman)
+ blocks[0] = T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | 64<<T5555_BITRATE_SHIFT | 2<<T5555_MAXBLOCK_SHIFT;
+ }
+
+ if ((fullcode & 0xFFFFFFFFFFFF) != fullcode) {
+ fullcode &= 0xFFFFFFFFFFFF;
+ PrintAndLog("Card Number Truncated to 40-bits: %u", fullcode);
+ }
+
+ if ( !getJablotronBits(fullcode, bs)) {
+ PrintAndLog("Error with tag bitstream generation.");
+ return 1;
+ }
+
+ //
+ blocks[1] = bytebits_to_byte(bs,32);
+ blocks[2] = bytebits_to_byte(bs+32,32);
+
+ PrintAndLog("Preparing to clone Jablotron to T55x7 with FullCode: %12X", fullcode);
+ PrintAndLog("Blk | Data ");
+ PrintAndLog("----+------------");
+ PrintAndLog(" 00 | 0x%08x", blocks[0]);
+ PrintAndLog(" 01 | 0x%08x", blocks[1]);
+ PrintAndLog(" 02 | 0x%08x", blocks[2]);
+
+ UsbCommand resp;
+ UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}};
+
+ for (int i=4; i>=0; i--) {
+ c.arg[0] = blocks[i];
+ c.arg[1] = i;
+ clearCommandBuffer();
+ SendCommand(&c);
+ if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){
+ PrintAndLog("Error occurred, device did not respond during write operation.");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int CmdJablotronSim(const char *Cmd) {
+ uint64_t fullcode = 0;
+
+ char cmdp = param_getchar(Cmd, 0);
+ if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_jablotron_sim();
+
+ fullcode = param_get64ex(Cmd, 1, 0, 16);
+
+ uint8_t clk = 64, encoding = 2, separator = 0, invert = 1;
+ uint16_t arg1, arg2;
+ size_t size = 64;
+ arg1 = clk << 8 | encoding;
+ arg2 = invert << 8 | separator;
+
+ PrintAndLog("Simulating Jablotron - FullCode: %12X", fullcode);
+
+ UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}};
+ getJablotronBits(fullcode, c.d.asBytes);
+ clearCommandBuffer();
+ SendCommand(&c);
+ return 0;
+}
+
+static command_t CommandTable[] = {
+ {"help", CmdHelp, 1, "This help"},
+ {"read", CmdJablotronRead, 0, "Attempt to read and Extract tag data"},
+ {"clone", CmdJablotronClone, 0, "h <hex> [Q5] clone jablotron tag"},
+ {"sim", CmdJablotronSim, 0, "h <hex> simulate jablotron tag"},
+ {NULL, NULL, 0, NULL}
+};
+
+int CmdLFJablotron(const char *Cmd) {
+ clearCommandBuffer();
+ CmdsParse(CommandTable, Cmd);
+ return 0;
+}
+
+int CmdHelp(const char *Cmd) {
+ CmdsHelp(CommandTable);
+ return 0;
+}
--- /dev/null
+//-----------------------------------------------------------------------------
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// Low frequency T55xx commands
+//-----------------------------------------------------------------------------
+#ifndef CMDLFJABLOTRON_H__
+#define CMDLFJABLOTRON_H__
+#include <string.h>
+#include <inttypes.h>
+#include "proxmark3.h"
+#include "ui.h"
+#include "util.h"
+#include "graph.h"
+#include "cmdparser.h"
+#include "cmddata.h"
+#include "cmdmain.h"
+#include "cmdlf.h"
+#include "protocols.h" // for T55xx config register definitions
+#include "lfdemod.h" // parityTest
+int CmdLFJablotron(const char *Cmd);
+int CmdJablotronClone(const char *Cmd);
+int CmdJablotronSim(const char *Cmd);
+int CmdJablotronRead(const char *Cmd);
+int CmdJablotronDemod(const char *Cmd);
+
+int getJablotronBits(uint64_t fullcode, uint8_t *bits);
+
+int usage_lf_jablotron_clone(void);
+int usage_lf_jablotron_sim(void);
+int usage_lf_jablotron_read(void);
+int usage_lf_jablotron_demod(void);
+#endif
+
int CmdLFNedapDemod(const char *Cmd) {
//raw ask demod no start bit finding just get binary from wave
- uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
- size_t size = getFromGraphBuf(BitStream);
- if (size==0) return 0;
-
- //get binary from ask wave
if (!ASKbiphaseDemod("0 64 0 0", FALSE)) {
if (g_debugMode) PrintAndLog("Error NEDAP: ASKbiphaseDemod failed");
return 0;
}
- size = DemodBufferLen;
+ size_t size = DemodBufferLen;
int idx = NedapDemod(DemodBuffer, &size);
if (idx < 0){
if (g_debugMode){
uint8_t firstParity = GetParity( DemodBuffer, EVEN, 63);
if ( firstParity != DemodBuffer[63] ) {
PrintAndLog("1st 64bit parity check failed: %d|%d ", DemodBuffer[63], firstParity);
- //return 0;
+ return 0;
}
uint8_t secondParity = GetParity( DemodBuffer+64, EVEN, 63);
if ( secondParity != DemodBuffer[127] ) {
PrintAndLog("2st 64bit parity check failed: %d|%d ", DemodBuffer[127], secondParity);
- //return 0;
+ return 0;
}
// ok valid card found!
return reflect(crc_finish(&crc), 8);
}
-// credits to marshmellow
-// width=8 poly=0xA3, reversed poly=0x8B, init=0xB0 refin=true refout=true xorout=0x00 check=0x28 name="CRC-8/JA"
-uint32_t CRC8ja(uint8_t *buff, size_t size) {
- crc_t crc;
- crc_init_ref(&crc, 8, 0xA3, 0x42, 0x00, TRUE, TRUE);
- for ( int i=0; i < size; ++i)
- crc_update(&crc, buff[i], 8);
- return crc_finish(&crc);
- //return reflect(crc_finish(&crc), 8);
-}
-
// This CRC-16 is used in Legic Advant systems.
// width=8 poly=0xB400, reversed poly=0x init=depends refin=true refout=true xorout=0x0000 check= name="CRC-16/LEGIC"
uint32_t CRC16Legic(uint8_t *buff, size_t size, uint8_t uidcrc) {
// ie: uidcrc = 0x78 then initial_value == 0x7878
uint32_t CRC16Legic(uint8_t *buff, size_t size, uint8_t uidcrc);
-// Calculate CRC-8/ja checksum
-uint32_t CRC8ja(uint8_t *buff, size_t size);
-
// test crc 16.
uint32_t CRC16_DNP(uint8_t *buff, size_t size);
uint32_t CRC16_CCITT(uint8_t *buff, size_t size);
return (int)startIdx;
}
+// ASK/Diphase fc/64 (inverted Biphase)
+// Note: this i s not a demod, this is only a detection
+// the parameter *dest needs to be demoded before call
+int JablotronDemod(uint8_t *dest, size_t *size){
+ //make sure buffer has enough data
+ if (*size < 64) return -1;
+
+ size_t startIdx = 0;
+ // 0xFFFF preamble, 64bits
+ uint8_t preamble[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+
+ uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx);
+ if (errChk == 0) return -4; //preamble not found
+
+ uint8_t checkCalc = 0;
+ for (int i=16; i < 56; i += 8) {
+ checkCalc += bytebits_to_byte(dest+startIdx+i,8);
+ }
+ checkCalc ^= 0x3A;
+
+ uint8_t crc = bytebits_to_byte(dest+startIdx+56,8);
+
+ if ( checkCalc != crc ) return -5;
+ if (*size != 64) return -6;
+ return (int)startIdx;
+}
+
// by marshmellow
// FSK Demod then try to locate an AWID ID
int AWIDdemodFSK(uint8_t *dest, size_t *size)
int VikingDemod_AM(uint8_t *dest, size_t *size);
int PrescoDemod(uint8_t *dest, size_t *size);
int NedapDemod(uint8_t *dest, size_t *size);
+int JablotronDemod(uint8_t *dest, size_t *size);
#endif