fix little endian vs big endian in the macros... again... but this time correct
[RRG-proxmark3.git] / client / src / cmdlfguard.c
blob11ebbb8958fcec03bcecad06f3d13cec01b82cef
1 //-----------------------------------------------------------------------------
2 // Marshmellow
3 //
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
6 // the license.
7 //-----------------------------------------------------------------------------
8 // Low frequency Farpoint G Prox II / Pyramid tag commands
9 // Biphase, rf/ , 96 bits (unknown key calc + some bits)
10 //-----------------------------------------------------------------------------
11 #include "cmdlfguard.h"
12 #include <string.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <ctype.h>
16 #include "commonutil.h" // ARRAYLEN
17 #include "cmdparser.h" // command_t
18 #include "comms.h"
19 #include "ui.h"
20 #include "cmddata.h"
21 #include "cmdlf.h"
22 #include "protocols.h" // for T55xx config register definitions
23 #include "lfdemod.h" // parityTest
24 #include "cmdlft55xx.h" // verifywrite
25 #include "cliparser.h"
26 #include "cmdlfem4x05.h" // EM defines
28 static int CmdHelp(const char *Cmd);
30 // attempts to demodulate and identify a G_Prox_II verex/chubb card
31 // WARNING: if it fails during some points it will destroy the DemodBuffer data
32 // but will leave the GraphBuffer intact.
33 // if successful it will push askraw data back to demod buffer ready for emulation
34 int demodGuard(bool verbose) {
35 (void) verbose; // unused so far
36 //Differential Biphase
37 //get binary from ask wave
38 if (ASKbiphaseDemod(0, 64, 0, 0, false) != PM3_SUCCESS) {
39 PrintAndLogEx(DEBUG, "DEBUG: Error - gProxII ASKbiphaseDemod failed");
40 return PM3_ESOFT;
43 size_t size = DemodBufferLen;
45 int preambleIndex = detectGProxII(DemodBuffer, &size);
46 if (preambleIndex < 0) {
48 if (preambleIndex == -1)
49 PrintAndLogEx(DEBUG, "DEBUG: Error - gProxII too few bits found");
50 else if (preambleIndex == -2)
51 PrintAndLogEx(DEBUG, "DEBUG: Error - gProxII preamble not found");
52 else if (preambleIndex == -3)
53 PrintAndLogEx(DEBUG, "DEBUG: Error - gProxII size not correct: %zu", size);
54 else if (preambleIndex == -5)
55 PrintAndLogEx(DEBUG, "DEBUG: Error - gProxII wrong spacerbits");
56 else
57 PrintAndLogEx(DEBUG, "DEBUG: Error - gProxII ans: %d", preambleIndex);
58 return PM3_ESOFT;
61 // got a good demod of 96 bits
63 uint8_t plain[8] = {0x00};
64 uint8_t xorKey = 0;
65 size_t startIdx = preambleIndex + 6; //start after 6 bit preamble
66 uint8_t bits_no_spacer[90];
68 // not mess with raw DemodBuffer copy to a new sample array
69 memcpy(bits_no_spacer, DemodBuffer + startIdx, 90);
71 // remove the 18 (90/5=18) parity bits (down to 72 bits (96-6-18=72))
72 size_t len = removeParity(bits_no_spacer, 0, 5, 3, 90); //source, startloc, paritylen, ptype, length_to_run
73 if (len != 72) {
74 PrintAndLogEx(DEBUG, "DEBUG: Error - gProxII spacer removal did not produce 72 bits: %zu, start: %zu", len, startIdx);
75 return PM3_ESOFT;
78 // get key and then get all 8 bytes of payload decoded
79 xorKey = (uint8_t)bytebits_to_byteLSBF(bits_no_spacer, 8);
80 for (size_t idx = 0; idx < 8; idx++) {
81 plain[idx] = ((uint8_t)bytebits_to_byteLSBF(bits_no_spacer + 8 + (idx * 8), 8)) ^ xorKey;
82 PrintAndLogEx(DEBUG, "DEBUG: gProxII byte %zu after xor: %02x", idx, plain[idx]);
85 setDemodBuff(DemodBuffer, 96, preambleIndex);
86 setClockGrid(g_DemodClock, g_DemodStartIdx + (preambleIndex * g_DemodClock));
88 //plain contains 8 Bytes (64 bits) of decrypted raw tag data
89 uint8_t fmtLen = plain[0] >> 2;
90 uint32_t FC = 0;
91 uint32_t Card = 0;
92 //get raw 96 bits to print
93 uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32);
94 uint32_t raw2 = bytebits_to_byte(DemodBuffer + 32, 32);
95 uint32_t raw3 = bytebits_to_byte(DemodBuffer + 64, 32);
96 bool unknown = false;
97 switch (fmtLen) {
98 case 36:
99 FC = ((plain[3] & 0x7F) << 7) | (plain[4] >> 1);
100 Card = ((plain[4] & 1) << 19) | (plain[5] << 11) | (plain[6] << 3) | ((plain[7] & 0xE0) >> 5);
101 break;
102 case 26:
103 FC = ((plain[3] & 0x7F) << 1) | (plain[4] >> 7);
104 Card = ((plain[4] & 0x7F) << 9) | (plain[5] << 1) | (plain[6] >> 7);
105 break;
106 default :
107 unknown = true;
108 break;
110 if (!unknown)
111 PrintAndLogEx(SUCCESS, "G-Prox-II - len: " _GREEN_("%u")" FC: " _GREEN_("%u") " Card: " _GREEN_("%u") ", Raw: %08x%08x%08x", fmtLen, FC, Card, raw1, raw2, raw3);
112 else
113 PrintAndLogEx(SUCCESS, "G-Prox-II - Unknown len: " _GREEN_("%u") ", Raw: %08x%08x%08x", fmtLen, raw1, raw2, raw3);
115 return PM3_SUCCESS;
118 static int CmdGuardDemod(const char *Cmd) {
119 CLIParserContext *ctx;
120 CLIParserInit(&ctx, "lf gproxii demod",
121 "Try to find Guardall Prox-II preamble, if found decode / descramble data",
122 "lf gproxii demod"
125 void *argtable[] = {
126 arg_param_begin,
127 arg_param_end
129 CLIExecWithReturn(ctx, Cmd, argtable, true);
130 CLIParserFree(ctx);
131 return demodGuard(true);
134 static int CmdGuardReader(const char *Cmd) {
135 CLIParserContext *ctx;
136 CLIParserInit(&ctx, "lf gproxii reader",
137 "read a Guardall tag",
138 "lf gproxii reader -@ -> continuous reader mode"
141 void *argtable[] = {
142 arg_param_begin,
143 arg_lit0("@", NULL, "optional - continuous reader mode"),
144 arg_param_end
146 CLIExecWithReturn(ctx, Cmd, argtable, true);
147 bool cm = arg_get_lit(ctx, 1);
148 CLIParserFree(ctx);
150 if (cm) {
151 PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
154 do {
155 lf_read(false, 10000);
156 demodGuard(!cm);
157 } while (cm && !kbd_enter_pressed());
159 return PM3_SUCCESS;
162 static int CmdGuardClone(const char *Cmd) {
163 CLIParserContext *ctx;
164 CLIParserInit(&ctx, "lf gproxii clone",
165 "clone a Guardall tag to a T55x7, Q5/T5555 or EM4305/4469 tag.\n"
166 "The facility-code is 8-bit and the card number is 16-bit. Larger values are truncated.\n"
167 "Currently work only on 26bit",
168 "lf gproxii clone --fmt 26 --fc 123 --cn 1337\n"
169 "lf gproxii clone --q5 --fmt 26 --fc 123 --cn 1337 -> encode for Q5/T5555 tag\n"
170 "lf gproxii clone --em --fmt 26 --fc 123 --cn 1337 -> encode for EM4305/4469"
173 void *argtable[] = {
174 arg_param_begin,
175 arg_u64_1(NULL, "fmt", "<dec>", "format length 26|32|36|40"),
176 arg_u64_1(NULL, "fc", "<dec>", "8-bit value facility code"),
177 arg_u64_1(NULL, "cn", "<dec>", "16-bit value card number"),
178 arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
179 arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
180 arg_param_end
182 CLIExecWithReturn(ctx, Cmd, argtable, false);
184 uint32_t fmtlen = arg_get_u32_def(ctx, 1, 0);
185 uint32_t fc = arg_get_u32_def(ctx, 2, 0);
186 uint32_t cn = arg_get_u32_def(ctx, 3, 0);
187 bool q5 = arg_get_lit(ctx, 4);
188 bool em = arg_get_lit(ctx, 5);
189 CLIParserFree(ctx);
191 if (q5 && em) {
192 PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
193 return PM3_EINVARG;
196 fmtlen &= 0x7f;
197 uint32_t facilitycode = (fc & 0x000000FF);
198 uint32_t cardnumber = (cn & 0x0000FFFF);
200 //GuardProxII - compat mode, ASK/Biphase, data rate 64, 3 data blocks
201 uint8_t *bs = calloc(96, sizeof(uint8_t));
202 if (getGuardBits(fmtlen, facilitycode, cardnumber, bs) != PM3_SUCCESS) {
203 PrintAndLogEx(ERR, "Error with tag bitstream generation.");
204 free(bs);
205 return PM3_ESOFT;
208 uint32_t blocks[4] = {T55x7_MODULATION_BIPHASE | T55x7_BITRATE_RF_64 | 3 << T55x7_MAXBLOCK_SHIFT, 0, 0, 0};
209 char cardtype[16] = {"T55x7"};
210 // Q5
211 if (q5) {
212 blocks[0] = T5555_FIXED | T5555_MODULATION_BIPHASE | T5555_SET_BITRATE(64) | 3 << T5555_MAXBLOCK_SHIFT;
213 snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
216 // EM4305
217 if (em) {
218 blocks[0] = EM4305_GUARDPROXII_CONFIG_BLOCK;
219 snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
222 blocks[1] = bytebits_to_byte(bs, 32);
223 blocks[2] = bytebits_to_byte(bs + 32, 32);
224 blocks[3] = bytebits_to_byte(bs + 64, 32);
226 free(bs);
228 PrintAndLogEx(INFO, "Preparing to clone Guardall to " _YELLOW_("%s") " with Facility Code: " _GREEN_("%u") " Card Number: " _GREEN_("%u")
229 , cardtype
230 , facilitycode
231 , cardnumber
233 print_blocks(blocks, ARRAYLEN(blocks));
235 int res;
236 if (em) {
237 res = em4x05_clone_tag(blocks, ARRAYLEN(blocks), 0, false);
238 } else {
239 res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
241 PrintAndLogEx(SUCCESS, "Done");
242 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf gproxii reader`") " to verify");
243 return res;
246 static int CmdGuardSim(const char *Cmd) {
248 CLIParserContext *ctx;
249 CLIParserInit(&ctx, "lf gproxii sim",
250 "Enables simulation of Guardall card with specified card number.\n"
251 "Simulation runs until the button is pressed or another USB command is issued.\n"
252 "The facility-code is 8-bit and the card number is 16-bit. Larger values are truncated.\n"
253 "Currently work only on 26bit",
254 "lf gproxii sim --fmt 26 --fc 123 --cn 1337\n"
257 void *argtable[] = {
258 arg_param_begin,
259 arg_u64_1(NULL, "fmt", "<dec>", "format length 26|32|36|40"),
260 arg_u64_1(NULL, "fc", "<dec>", "8-bit value facility code"),
261 arg_u64_1(NULL, "cn", "<dec>", "16-bit value card number"),
262 arg_param_end
264 CLIExecWithReturn(ctx, Cmd, argtable, false);
266 uint32_t fmtlen = arg_get_u32_def(ctx, 1, 0);
267 uint32_t fc = arg_get_u32_def(ctx, 2, 0);
268 uint32_t cn = arg_get_u32_def(ctx, 3, 0);
269 CLIParserFree(ctx);
271 fmtlen &= 0x7F;
272 uint32_t facilitycode = (fc & 0x000000FF);
273 uint32_t cardnumber = (cn & 0x0000FFFF);
275 uint8_t bs[96];
276 memset(bs, 0x00, sizeof(bs));
278 if (getGuardBits(fmtlen, facilitycode, cardnumber, bs) != PM3_SUCCESS) {
279 PrintAndLogEx(ERR, "Error with tag bitstream generation.");
280 return PM3_ESOFT;
283 PrintAndLogEx(SUCCESS, "Simulating Guardall Prox - Facility Code: " _YELLOW_("%u") " CardNumber: " _YELLOW_("%u")
284 , facilitycode
285 , cardnumber
288 // Guard uses: clk: 64, invert: 0, encoding: 2 (ASK Biphase)
289 lf_asksim_t *payload = calloc(1, sizeof(lf_asksim_t) + sizeof(bs));
290 payload->encoding = 2;
291 payload->invert = 0;
292 payload->separator = 0;
293 payload->clock = 64;
294 memcpy(payload->data, bs, sizeof(bs));
296 clearCommandBuffer();
297 SendCommandNG(CMD_LF_ASK_SIMULATE, (uint8_t *)payload, sizeof(lf_asksim_t) + sizeof(bs));
298 free(payload);
300 PacketResponseNG resp;
301 WaitForResponse(CMD_LF_ASK_SIMULATE, &resp);
303 PrintAndLogEx(INFO, "Done");
304 if (resp.status != PM3_EOPABORTED)
305 return resp.status;
306 return PM3_SUCCESS;
309 static command_t CommandTable[] = {
310 {"help", CmdHelp, AlwaysAvailable, "this help"},
311 {"demod", CmdGuardDemod, AlwaysAvailable, "demodulate a G Prox II tag from the GraphBuffer"},
312 {"reader", CmdGuardReader, IfPm3Lf, "attempt to read and extract tag data"},
313 {"clone", CmdGuardClone, IfPm3Lf, "clone Guardall tag to T55x7 or Q5/T5555"},
314 {"sim", CmdGuardSim, IfPm3Lf, "simulate Guardall 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 CmdLFGuard(const char *Cmd) {
325 clearCommandBuffer();
326 return CmdsParse(CommandTable, Cmd);
329 // demod gProxIIDemod
330 // error returns as -x
331 // success returns start position in bitstream
332 // Bitstream must contain previously askrawdemod and biphasedemoded data
333 int detectGProxII(uint8_t *bits, size_t *size) {
335 size_t startIdx = 0;
336 uint8_t preamble[] = {1, 1, 1, 1, 1, 0};
338 // sanity check
339 if (*size < sizeof(preamble)) return -1;
341 if (!preambleSearch(bits, preamble, sizeof(preamble), size, &startIdx))
342 return -2; //preamble not found
344 //gProxII should be 96 bits
345 if (*size != 96) return -3;
347 //check first 6 spacer bits to verify format
348 if (!bits[startIdx + 5] && !bits[startIdx + 10] && !bits[startIdx + 15] && !bits[startIdx + 20] && !bits[startIdx + 25] && !bits[startIdx + 30]) {
349 //confirmed proper separator bits found
350 //return start position
351 return (int) startIdx;
353 return -5; //spacer bits not found - not a valid gproxII
356 // Works for 26bits.
357 int getGuardBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits) {
359 uint8_t xorKey = 0x66;
360 uint8_t i;
361 uint8_t pre[96];
362 uint8_t rawbytes[12];
363 memset(pre, 0x00, sizeof(pre));
364 memset(rawbytes, 0x00, sizeof(rawbytes));
366 // add format length (decimal)
367 switch (fmtlen) {
368 case 32: {
369 rawbytes[1] = (32 << 2);
371 break;
373 case 36: {
374 rawbytes[1] = (36 << 2);
375 // Get wiegand from FacilityCode 14bits, CardNumber 20bits
376 uint8_t wiegand[36];
377 memset(wiegand, 0x00, sizeof(wiegand));
378 num_to_bytebits(fc, 14, wiegand);
379 num_to_bytebits(cn, 20, wiegand + 14);
381 // add wiegand parity bits (dest, source, len)
382 wiegand_add_parity(pre, wiegand, 34);
383 break;
385 case 40: {
386 rawbytes[1] = (40 << 2);
387 break;
389 case 26:
390 default: {
391 rawbytes[1] = (26 << 2);
392 // Get 26 wiegand from FacilityCode, CardNumber
393 uint8_t wiegand[24];
394 memset(wiegand, 0x00, sizeof(wiegand));
395 num_to_bytebits(fc, 8, wiegand);
396 num_to_bytebits(cn, 16, wiegand + 8);
398 // add wiegand parity bits (dest, source, len)
399 wiegand_add_parity(pre, wiegand, 24);
400 break;
403 // 2bit checksum, unknown today,
404 // these two bits are the last ones of rawbyte[1], hence the LSHIFT above.
407 // xor key
408 rawbytes[0] = xorKey;
410 rawbytes[2] = 1;
411 rawbytes[3] = 0;
413 // add wiegand to rawbytes
414 for (i = 0; i < 5; ++i)
415 rawbytes[i + 4] = bytebits_to_byte(pre + (i * 8), 8);
417 PrintAndLogEx(DEBUG, " WIE | %s", sprint_hex(rawbytes, sizeof(rawbytes)));
419 // XOR (only works on wiegand stuff)
420 for (i = 1; i < sizeof(rawbytes); ++i)
421 rawbytes[i] ^= xorKey ;
423 PrintAndLogEx(DEBUG, " XOR | %s", sprint_hex(rawbytes, sizeof(rawbytes)));
425 // convert rawbytes to bits in pre
426 for (i = 0; i < sizeof(rawbytes); ++i)
427 num_to_bytebitsLSBF(rawbytes[i], 8, pre + (i * 8));
429 PrintAndLogEx(DEBUG, " Raw | %s", sprint_hex(rawbytes, sizeof(rawbytes)));
430 PrintAndLogEx(DEBUG, " Raw | %s", sprint_bin(pre, 96));
432 // add spacer bit 0 every 4 bits, starting with index 0,
433 // 12 bytes, 24 nibbles. 24+1 extra bites. 3bytes. ie 9bytes | 1byte xorkey, 8bytes rawdata (72bits, should be enough for a 40bit wiegand)
434 addParity(pre, guardBits + 6, 72, 5, 3);
436 // preamble
437 guardBits[0] = 1;
438 guardBits[1] = 1;
439 guardBits[2] = 1;
440 guardBits[3] = 1;
441 guardBits[4] = 1;
442 guardBits[5] = 0;
444 PrintAndLogEx(DEBUG, " FIN | %s\n", sprint_bin(guardBits, 96));
445 return PM3_SUCCESS;