fix one too small
[RRG-proxmark3.git] / client / src / cmdlfjablotron.c
blob2651ebe514b1235ba47622637325c4c84c13a2be
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
16 // Low frequency Jablotron tag commands
17 // Differential Biphase, RF/64, 64 bits long (complete)
18 //-----------------------------------------------------------------------------
20 #include "cmdlfjablotron.h"
21 #include <string.h>
22 #include <inttypes.h>
23 #include <stdlib.h>
24 #include <ctype.h>
25 #include "cmdparser.h" // command_t
26 #include "comms.h"
27 #include "commonutil.h" // ARRAYLEN
28 #include "ui.h"
29 #include "cmddata.h"
30 #include "cmdlf.h"
31 #include "protocols.h" // for T55xx config register definitions
32 #include "lfdemod.h" // parityTest
33 #include "cmdlft55xx.h" // verifywrite
34 #include "cliparser.h"
35 #include "cmdlfem4x05.h" // EM defines
37 #define JABLOTRON_ARR_LEN 64
39 static int CmdHelp(const char *Cmd);
41 static uint8_t jablontron_chksum(uint8_t *bits) {
42 uint8_t chksum = 0;
43 for (int i = 16; i < 56; i += 8) {
44 chksum += bytebits_to_byte(bits + i, 8);
46 chksum ^= 0x3A;
47 return chksum;
50 static uint64_t getJablontronCardId(uint64_t rawcode) {
51 uint64_t id = 0;
52 uint8_t bytes[] = {0, 0, 0, 0, 0};
53 num_to_bytes(rawcode, 5, bytes);
54 for (int i = 0; i < 5; i++) {
55 id *= 100;
56 id += NIBBLE_HIGH(bytes[i]) * 10 + NIBBLE_LOW(bytes[i]);
58 return id;
61 int demodJablotron(bool verbose) {
62 (void) verbose; // unused so far
63 //Differential Biphase / di-phase (inverted biphase)
64 //get binary from ask wave
65 if (ASKbiphaseDemod(0, 64, 1, 0, false) != PM3_SUCCESS) {
66 if (g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: Error - Jablotron ASKbiphaseDemod failed");
67 return PM3_ESOFT;
69 size_t size = g_DemodBufferLen;
70 int ans = detectJablotron(g_DemodBuffer, &size);
71 if (ans < 0) {
72 if (g_debugMode) {
73 if (ans == -1)
74 PrintAndLogEx(DEBUG, "DEBUG: Error - Jablotron too few bits found");
75 else if (ans == -2)
76 PrintAndLogEx(DEBUG, "DEBUG: Error - Jablotron preamble not found");
77 else if (ans == -3)
78 PrintAndLogEx(DEBUG, "DEBUG: Error - Jablotron size not correct: %zu", size);
79 else if (ans == -5)
80 PrintAndLogEx(DEBUG, "DEBUG: Error - Jablotron checksum failed");
81 else
82 PrintAndLogEx(DEBUG, "DEBUG: Error - Jablotron ans: %d", ans);
84 return PM3_ESOFT;
87 setDemodBuff(g_DemodBuffer, JABLOTRON_ARR_LEN, ans);
88 setClockGrid(g_DemodClock, g_DemodStartIdx + (ans * g_DemodClock));
90 //got a good demod
91 uint32_t raw1 = bytebits_to_byte(g_DemodBuffer, 32);
92 uint32_t raw2 = bytebits_to_byte(g_DemodBuffer + 32, 32);
94 // bytebits_to_byte - uint32_t
95 uint64_t rawid = ((uint64_t)(bytebits_to_byte(g_DemodBuffer + 16, 8) & 0xff) << 32) | bytebits_to_byte(g_DemodBuffer + 24, 32);
96 uint64_t id = getJablontronCardId(rawid);
98 PrintAndLogEx(SUCCESS, "Jablotron - Card: " _GREEN_("%"PRIx64) ", Raw: %08X%08X", id, raw1, raw2);
100 uint8_t chksum = raw2 & 0xFF;
101 bool isok = (chksum == jablontron_chksum(g_DemodBuffer));
103 PrintAndLogEx(DEBUG, "Checksum: %02X ( %s )", chksum, isok ? _GREEN_("ok") : _RED_("Fail"));
105 id = DEC2BCD(id);
106 // Printed format: 1410-nn-nnnn-nnnn
107 PrintAndLogEx(SUCCESS, "Printed: " _GREEN_("1410-%02X-%04X-%04X"),
108 (uint8_t)(id >> 32) & 0xFF,
109 (uint16_t)(id >> 16) & 0xFFFF,
110 (uint16_t)id & 0xFFFF
112 return PM3_SUCCESS;
115 //see ASKDemod for what args are accepted
116 static int CmdJablotronDemod(const char *Cmd) {
117 CLIParserContext *ctx;
118 CLIParserInit(&ctx, "lf jablotron demod",
119 "Try to find Jablotron preamble, if found decode / descramble data",
120 "lf jablotron demod\n"
123 void *argtable[] = {
124 arg_param_begin,
125 arg_param_end
127 CLIExecWithReturn(ctx, Cmd, argtable, true);
128 CLIParserFree(ctx);
129 return demodJablotron(true);
132 static int CmdJablotronReader(const char *Cmd) {
133 CLIParserContext *ctx;
134 CLIParserInit(&ctx, "lf jablotron reader",
135 "read a jablotron tag",
136 "lf jablotron reader -@ -> continuous reader mode"
139 void *argtable[] = {
140 arg_param_begin,
141 arg_lit0("@", NULL, "optional - continuous reader mode"),
142 arg_param_end
144 CLIExecWithReturn(ctx, Cmd, argtable, true);
145 bool cm = arg_get_lit(ctx, 1);
146 CLIParserFree(ctx);
148 if (cm) {
149 PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
152 do {
153 lf_read(false, 16000);
154 demodJablotron(!cm);
155 } while (cm && !kbd_enter_pressed());
157 return PM3_SUCCESS;
160 static int CmdJablotronClone(const char *Cmd) {
162 CLIParserContext *ctx;
163 CLIParserInit(&ctx, "lf jablotron clone",
164 "clone a Jablotron tag to a T55x7, Q5/T5555 or EM4305/4469 tag.\n"
165 "Tag must be on the antenna when issuing this command.",
166 "lf jablotron clone --cn 01b669 -> encode for T55x7 tag\n"
167 "lf jablotron clone --cn 01b669 --q5 -> encode for Q5/T5555 tag\n"
168 "lf jablotron clone --cn 01b669 --em -> encode for EM4305/4469"
171 void *argtable[] = {
172 arg_param_begin,
173 arg_str1(NULL, "cn", "<hex>", "Jablotron card ID - 5 bytes max"),
174 arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
175 arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
176 arg_param_end
178 CLIExecWithReturn(ctx, Cmd, argtable, false);
180 int raw_len = 0;
181 uint8_t raw[5] = {0};
182 CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
184 bool q5 = arg_get_lit(ctx, 2);
185 bool em = arg_get_lit(ctx, 3);
186 CLIParserFree(ctx);
188 if (q5 && em) {
189 PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
190 return PM3_EINVARG;
193 uint32_t blocks[3] = {T55x7_MODULATION_DIPHASE | T55x7_BITRATE_RF_64 | 2 << T55x7_MAXBLOCK_SHIFT, 0, 0};
194 char cardtype[16] = {"T55x7"};
195 // Q5
196 if (q5) {
197 blocks[0] = T5555_FIXED | T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 2 << T5555_MAXBLOCK_SHIFT;
198 snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
201 // EM4305
202 if (em) {
203 blocks[0] = EM4305_JABLOTRON_CONFIG_BLOCK;
204 snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
208 uint64_t fullcode = bytes_to_num(raw, raw_len);
210 // clearing the topbit needed for the preambl detection.
211 if ((fullcode & 0x7FFFFFFFFF) != fullcode) {
212 fullcode &= 0x7FFFFFFFFF;
213 PrintAndLogEx(INFO, "Card Number Truncated to 39bits: %"PRIx64, fullcode);
216 uint8_t *bits = calloc(JABLOTRON_ARR_LEN, sizeof(uint8_t));
217 if (bits == NULL) {
218 PrintAndLogEx(WARNING, "Failed to allocate memory");
219 return PM3_EMALLOC;
222 if (getJablotronBits(fullcode, bits) != PM3_SUCCESS) {
223 PrintAndLogEx(ERR, "Error with tag bitstream generation.");
224 return PM3_ESOFT;
227 blocks[1] = bytebits_to_byte(bits, 32);
228 blocks[2] = bytebits_to_byte(bits + 32, 32);
230 free(bits);
232 uint64_t id = getJablontronCardId(fullcode);
234 PrintAndLogEx(INFO, "Preparing to clone Jablotron to " _YELLOW_("%s") " with FullCode: " _GREEN_("%"PRIx64)" id: " _GREEN_("%"PRIx64), cardtype, fullcode, id);
235 print_blocks(blocks, ARRAYLEN(blocks));
237 int res;
238 if (em) {
239 res = em4x05_clone_tag(blocks, ARRAYLEN(blocks), 0, false);
240 } else {
241 res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
243 PrintAndLogEx(SUCCESS, "Done");
244 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf jablotron reader`") " to verify");
245 return res;
248 static int CmdJablotronSim(const char *Cmd) {
249 CLIParserContext *ctx;
250 CLIParserInit(&ctx, "lf jablotron sim",
251 "Enables simulation of jablotron card with specified card number.\n"
252 "Simulation runs until the button is pressed or another USB command is issued.",
253 "lf jablotron sim --cn 01b669"
256 void *argtable[] = {
257 arg_param_begin,
258 arg_str1(NULL, "cn", "<hex>", "Jablotron card ID - 5 bytes max"),
259 arg_param_end
261 CLIExecWithReturn(ctx, Cmd, argtable, false);
263 int raw_len = 0;
264 uint8_t raw[5] = {0};
265 CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
266 CLIParserFree(ctx);
268 uint64_t fullcode = bytes_to_num(raw, raw_len);
270 // clearing the topbit needed for the preambl detection.
271 if ((fullcode & 0x7FFFFFFFFF) != fullcode) {
272 fullcode &= 0x7FFFFFFFFF;
273 PrintAndLogEx(INFO, "Card Number Truncated to 39bits: %"PRIx64, fullcode);
276 PrintAndLogEx(SUCCESS, "Simulating Jablotron - FullCode: " _YELLOW_("%"PRIx64), fullcode);
278 uint8_t *bs = calloc(JABLOTRON_ARR_LEN, sizeof(uint8_t));
279 if (bs == NULL) {
280 PrintAndLogEx(WARNING, "Failed to allocate memory");
281 return PM3_EMALLOC;
284 getJablotronBits(fullcode, bs);
286 lf_asksim_t *payload = calloc(1, sizeof(lf_asksim_t) + JABLOTRON_ARR_LEN);
287 payload->encoding = 2;
288 payload->invert = 1;
289 payload->separator = 0;
290 payload->clock = 64;
291 memcpy(payload->data, bs, JABLOTRON_ARR_LEN);
293 free(bs);
295 clearCommandBuffer();
296 SendCommandNG(CMD_LF_ASK_SIMULATE, (uint8_t *)payload, sizeof(lf_asksim_t) + JABLOTRON_ARR_LEN);
297 free(payload);
299 PacketResponseNG resp;
300 WaitForResponse(CMD_LF_ASK_SIMULATE, &resp);
302 PrintAndLogEx(INFO, "Done!");
303 if (resp.status != PM3_EOPABORTED) {
304 return resp.status;
306 return PM3_SUCCESS;
309 static command_t CommandTable[] = {
310 {"help", CmdHelp, AlwaysAvailable, "This help"},
311 {"demod", CmdJablotronDemod, AlwaysAvailable, "demodulate an Jablotron tag from the GraphBuffer"},
312 {"reader", CmdJablotronReader, IfPm3Lf, "attempt to read and extract tag data"},
313 {"clone", CmdJablotronClone, IfPm3Lf, "clone jablotron tag to T55x7, Q5/T5555 or EM4305/4469"},
314 {"sim", CmdJablotronSim, IfPm3Lf, "simulate jablotron tag"},
315 {NULL, NULL, NULL, NULL}
318 static int CmdHelp(const char *Cmd) {
319 (void)Cmd; // Cmd is not used so far
320 CmdsHelp(CommandTable);
321 return PM3_SUCCESS;
324 int CmdLFJablotron(const char *Cmd) {
325 clearCommandBuffer();
326 return CmdsParse(CommandTable, Cmd);
329 int getJablotronBits(uint64_t fullcode, uint8_t *bits) {
330 //preamp
331 num_to_bytebits(0xFFFF, 16, bits);
333 //fullcode
334 num_to_bytebits(fullcode, 40, bits + 16);
336 //chksum byte
337 uint8_t chksum = jablontron_chksum(bits);
338 num_to_bytebits(chksum, 8, bits + 56);
339 return PM3_SUCCESS;
342 // ASK/Diphase fc/64 (inverted Biphase)
343 // Note: this is not a demod, this is only a detection
344 // the parameter *bits needs to be demoded before call
345 // 0xFFFF preamble, 64bits
346 int detectJablotron(uint8_t *bits, size_t *size) {
347 if (*size < JABLOTRON_ARR_LEN * 2) return -1; //make sure buffer has enough data
348 size_t startIdx = 0;
349 uint8_t preamble[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0};
350 if (preambleSearch(bits, preamble, sizeof(preamble), size, &startIdx) == 0)
351 return -2; //preamble not found
352 if (*size != JABLOTRON_ARR_LEN) return -3; // wrong demoded size
354 uint8_t checkchksum = jablontron_chksum(bits + startIdx);
355 uint8_t crc = bytebits_to_byte(bits + startIdx + 56, 8);
356 if (checkchksum != crc) return -5;
357 return (int)startIdx;