1 //-----------------------------------------------------------------------------
3 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
4 // at your option, any later version. See the LICENSE.txt file for the text of
6 //-----------------------------------------------------------------------------
7 // Low frequency NEDAP tag commands
8 //-----------------------------------------------------------------------------
10 #include "cmdlfnedap.h"
16 #include "cmdparser.h" // command_t
19 #include "cmdlft55xx.h" // verify write
24 #include "protocols.h"
25 #include "cliparser.h"
26 #include "cmdlfem4x05.h" // EM defines
27 #include "commonutil.h"
31 #define UNKNOWN_A 0x00
32 #define UNKNOWN_B 0x00
34 static int CmdHelp(const char *Cmd
);
36 const uint8_t translateTable
[10] = {8, 2, 1, 12, 4, 5, 10, 13, 0, 9};
37 const uint8_t invTranslateTable
[16] = {8, 2, 1, 0xff, 4, 5, 0xff, 0xff, 0, 9, 6, 0xff, 3, 7, 0xff, 0xff};
38 const uint8_t preamble
[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}; // zero inside
40 static uint8_t isEven_64_63(const uint8_t *data
) { // 8
43 return (bitcount32(tmp
[0]) + (bitcount32(tmp
[1] & 0xfeffffff))) & 1;
46 //NEDAP demod - ASK/Biphase (or Diphase), RF/64 with preamble of 1111111110 (always a 128 bit data stream)
47 int demodNedap(bool verbose
) {
48 (void) verbose
; // unused so far
49 uint8_t data
[16], buffer
[7], r0
, r1
, r2
, r3
, r4
, r5
, idxC1
, idxC2
, idxC3
, idxC4
, idxC5
, fixed0
, fixed1
, unk1
, unk2
, subtype
; // 4 bits
50 size_t size
, offset
= 0;
51 uint16_t checksum
, customerCode
; // 12 bits
52 uint32_t badgeId
; // max 99999
54 if (ASKbiphaseDemod(0, 64, 1, 0, false) != PM3_SUCCESS
) {
55 if (g_debugMode
) PrintAndLogEx(DEBUG
, "DEBUG: Error - NEDAP: ASK/Biphase Demod failed");
59 size
= DemodBufferLen
;
60 if (!preambleSearch(DemodBuffer
, (uint8_t *) preamble
, sizeof(preamble
), &size
, &offset
)) {
61 PrintAndLogEx(DEBUG
, "DEBUG: Error - NEDAP: preamble not found");
66 setDemodBuff(DemodBuffer
, size
, offset
);
67 setClockGrid(g_DemodClock
, g_DemodStartIdx
+ (g_DemodClock
* offset
));
70 if ((size
!= 128) && (size
!= 64)) {
71 PrintAndLogEx(DEBUG
, "DEBUG: Error - NEDAP: Size not correct: %zu", size
);
75 if (bits_to_array(DemodBuffer
, size
, data
) != PM3_SUCCESS
) {
76 PrintAndLogEx(DEBUG
, "DEBUG: Error - NEDAP: bits_to_array error\n");
81 int ret
= PM3_SUCCESS
;
86 if (isEven_64_63(data
) != (data
[7] & 0x01)) {
87 PrintAndLogEx(ERR
, "Bad parity (%1u)", data
[7] & 0x01);
92 // (1111111110 0 -- zero inside)
93 if ((data
[0] != 0xFF) && ((data
[1] & 0xE0) != 0x80)) {
94 PrintAndLogEx(ERR
, "Bad header");
98 buffer
[0] = (data
[0] << 7) | (data
[1] >> 1);
99 buffer
[1] = (data
[1] << 7) | (data
[2] >> 1);
100 buffer
[2] = (data
[2] << 7) | (data
[3] >> 1);
101 buffer
[3] = ((data
[4] & 0x1e) << 3) | ((data
[5] & 0x1e) >> 1);
102 buffer
[4] = ((data
[6] & 0x1e) << 3) | ((data
[7] & 0x1e) >> 1);
105 init_table(CRC_XMODEM
);
106 checksum
= crc16_xmodem(buffer
, 5);
108 buffer
[6] = (data
[3] << 7) | ((data
[4] & 0xe0) >> 1) | ((data
[4] & 0x01) << 3) | ((data
[5] & 0xe0) >> 5);
109 buffer
[5] = (data
[5] << 7) | ((data
[6] & 0xe0) >> 1) | ((data
[6] & 0x01) << 3) | ((data
[7] & 0xe0) >> 5);
110 uint16_t checksum2
= (buffer
[6] << 8) + buffer
[5];
111 bool isValid
= (checksum
== checksum2
);
113 subtype
= (data
[1] & 0x1e) >> 1;
114 customerCode
= ((data
[1] & 0x01) << 11) | (data
[2] << 3) | ((data
[3] & 0xe0) >> 5);
116 if (isValid
== false) {
117 PrintAndLogEx(ERR
, "Checksum : %s (calc 0x%04X != 0x%04X)", _RED_("fail"), checksum
, checksum2
);
121 idxC1
= invTranslateTable
[(data
[3] & 0x1e) >> 1];
122 idxC2
= invTranslateTable
[(data
[4] & 0x1e) >> 1];
123 idxC3
= invTranslateTable
[(data
[5] & 0x1e) >> 1];
124 idxC4
= invTranslateTable
[(data
[6] & 0x1e) >> 1];
125 idxC5
= invTranslateTable
[(data
[7] & 0x1e) >> 1];
128 if ((idxC1
!= 0xFF) && (idxC2
!= 0xFF) && (idxC3
!= 0xFF) && (idxC4
!= 0xFF) && (idxC5
!= 0xFF)) {
130 r2
= ((10 + idxC2
) - (idxC1
+ 1)) % 10;
131 r3
= ((10 + idxC3
) - (idxC2
+ 1)) % 10;
132 r4
= ((10 + idxC4
) - (idxC3
+ 1)) % 10;
133 r5
= ((10 + idxC5
) - (idxC4
+ 1)) % 10;
135 badgeId
= r1
* 10000 + r2
* 1000 + r3
* 100 + r4
* 10 + r5
;
137 PrintAndLogEx(SUCCESS
, "NEDAP (%s) - ID: " _YELLOW_("%05u") " subtype: " _YELLOW_("%1u")" customer code: " _YELLOW_("%u / 0x%03X") " Raw: " _YELLOW_("%s")
138 , (size
== 128) ? "128b" : "64b"
143 , sprint_hex_inrow(data
, size
/ 8)
145 PrintAndLogEx(DEBUG
, "Checksum (%s) 0x%04X", _GREEN_("ok"), checksum
);
148 PrintAndLogEx(ERR
, "Invalid idx (1:%02x - 2:%02x - 3:%02x - 4:%02x - 5:%02x)", idxC1
, idxC2
, idxC3
, idxC4
, idxC5
);
154 PrintAndLogEx(DEBUG
, "NEDAP Tag, second part found");
156 if (isEven_64_63(data
+ 8) != (data
[15] & 0x01)) {
157 PrintAndLogEx(ERR
, "Bad parity (%1u)", data
[15] & 0x01);
168 && (data
[14] & 0x02)) {
169 PrintAndLogEx(ERR
, "Bad zeros");
174 r4
= (data
[8] >> 3) & 0x0F;
175 r5
= ((data
[8] << 1) & 0x0F) | (data
[9] >> 7);
176 r2
= (data
[9] >> 2) & 0x0F;
177 r3
= ((data
[9] << 2) & 0x0F) | (data
[10] >> 6);
178 r0
= ((data
[10] >> 1) & 0x0F);
179 r1
= ((data
[10] << 3) & 0x0F) | (data
[11] >> 5);
181 fixed0
= ((data
[11] << 4) & 0xF0) | (data
[12] >> 4);
182 fixed1
= ((data
[12] << 5) & 0xE0) | (data
[13] >> 3);
184 unk1
= ((data
[13] << 6) & 0xC0) | (data
[14] >> 2);
185 unk2
= ((data
[14] << 7) & 0xC0) | (data
[15] >> 1);
188 if (!r0
&& (r1
< 10) && (r2
< 10) && (r3
< 10) && (r4
< 10) && (r5
< 10)) {
190 badgeId
= r1
* 10000 + r2
* 1000 + r3
* 100 + r4
* 10 + r5
;
191 PrintAndLogEx(SUCCESS
, "Second Card: " _YELLOW_("%05u"), badgeId
);
193 if ((fixed0
== FIXED_71
) && (fixed1
== FIXED_40
))
194 PrintAndLogEx(DEBUG
, "Fixed part {0 = 0x%02x, 1 = 0x%02x}", fixed0
, fixed1
);
196 PrintAndLogEx(DEBUG
, "Bad fixed: {0 = 0x%02x (%0x02x), 1 = 0x%02x (%0x02x)}", fixed0
, FIXED_71
, fixed1
, FIXED_40
);
198 PrintAndLogEx(DEBUG
, "Unknown part {1 = 0x%02x, 2 = 0x%02x}", unk1
, unk2
);
200 PrintAndLogEx(ERR
, "Bad digits (0:%1x - 1:%1x - 2:%1x - 3:%1x - 4:%1x - 5:%1x)", r0
, r1
, r2
, r3
, r4
, r5
);
208 static int CmdLFNedapDemod(const char *Cmd
) {
209 CLIParserContext
*ctx
;
210 CLIParserInit(&ctx
, "lf nedap demod",
211 "Try to find Nedap preamble, if found decode / descramble data",
219 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
221 return demodNedap(true);
224 preamble enc tag type encrypted uid P d 33 d 90 d 04 d 71 d 40 d 45 d E7 P
225 1111111110 00101101000001011010001100100100001011010100110101100 1 0 00110011 0 10010000 0 00000100 0 01110001 0 01000000 0 01000101 0 11100111 1
226 uid2 uid1 uid0 I I R R
227 1111111110 00101101000001011010001100100100001011010100110101100 1
239 I = Identical on all tags
241 UID2, UID1, UID0 == card number
245 lf t55xx wr -b 0 -d 00170082
248 lf t55xx wr -b 1 -d FF8B4168
249 lf t55xx wr -b 2 -d C90B5359
250 lf t55xx wr -b 3 -d 19A40087
251 lf t55xx wr -b 4 -d 120115CF
254 lf t55xx wr -b 1 -d FF8B6B20
255 lf t55xx wr -b 2 -d F19B84A3
256 lf t55xx wr -b 3 -d 18058007
257 lf t55xx wr -b 4 -d 1200857C
260 lf t55xx wr -b 1 -d ffbfa73e
261 lf t55xx wr -b 2 -d 4c0003ff
262 lf t55xx wr -b 3 -d ffbfa73e
263 lf t55xx wr -b 4 -d 4c0003ff
267 static int CmdLFNedapReader(const char *Cmd
) {
268 CLIParserContext
*ctx
;
269 CLIParserInit(&ctx
, "lf nedap reader",
271 "lf nedap reader -@ -> continuous reader mode"
276 arg_lit0("@", NULL
, "optional - continuous reader mode"),
279 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
280 bool cm
= arg_get_lit(ctx
, 1);
284 PrintAndLogEx(INFO
, "Press " _GREEN_("<Enter>") " to exit");
288 lf_read(false, 16000);
290 } while (cm
&& !kbd_enter_pressed());
295 static void NedapGen(uint8_t subType
, uint16_t customerCode
, uint32_t id
, bool isLong
, uint8_t *data
) { // 8 or 16
296 uint8_t buffer
[7], r1
, r2
, r3
, r4
, r5
, idxC1
, idxC2
, idxC3
, idxC4
, idxC5
, i
, tmp
, carry
, id2
, id1
, id0
;
299 r1
= (uint8_t)(id
/ 10000);
300 r2
= (uint8_t)((id
% 10000) / 1000);
301 r3
= (uint8_t)((id
% 1000) / 100);
302 r4
= (uint8_t)((id
% 100) / 10);
303 r5
= (uint8_t)(id
% 10);
307 idxC2
= (idxC1
+ 1 + r2
) % 10;
308 idxC3
= (idxC2
+ 1 + r3
) % 10;
309 idxC4
= (idxC3
+ 1 + r4
) % 10;
310 idxC5
= (idxC4
+ 1 + r5
) % 10;
312 buffer
[0] = 0xc0 | (subType
& 0x0F);
313 buffer
[1] = (customerCode
& 0x0FF0) >> 4;
314 buffer
[2] = ((customerCode
& 0x000F) << 4) | translateTable
[idxC1
];
315 buffer
[3] = (translateTable
[idxC2
] << 4) | translateTable
[idxC3
];
316 buffer
[4] = (translateTable
[idxC4
] << 4) | translateTable
[idxC5
];
319 init_table(CRC_XMODEM
);
320 checksum
= crc16_xmodem(buffer
, 5);
322 buffer
[6] = ((checksum
& 0x000F) << 4) | (buffer
[4] & 0x0F);
323 buffer
[5] = (checksum
& 0x00F0) | ((buffer
[4] & 0xF0) >> 4);
324 buffer
[4] = ((checksum
& 0x0F00) >> 4) | (buffer
[3] & 0x0F);
325 buffer
[3] = ((checksum
& 0xF000) >> 8) | ((buffer
[3] & 0xF0) >> 4);
328 for (i
= 0, carry
= 0; i
< sizeof(buffer
); i
++) {
329 tmp
= buffer
[sizeof(buffer
) - 1 - i
];
330 data
[7 - i
] = ((tmp
& 0x7F) << 1) | carry
;
331 carry
= (tmp
& 0x80) >> 7;
333 data
[0] = 0xFE | carry
;
334 data
[7] |= isEven_64_63(data
);
339 id1
= (r2
<< 4) | r3
;
340 id2
= (r4
<< 4) | r5
;
342 data
[8] = (id2
>> 1);
343 data
[9] = ((id2
& 0x01) << 7) | (id1
>> 2);
344 data
[10] = ((id1
& 0x03) << 6) | (id0
>> 3);
345 data
[11] = ((id0
& 0x07) << 5) | (FIXED_71
>> 4);
346 data
[12] = ((FIXED_71
& 0x0F) << 4) | (FIXED_40
>> 5);
347 data
[13] = ((FIXED_40
& 0x1F) << 3) | (UNKNOWN_A
>> 6);
348 data
[14] = ((UNKNOWN_A
& 0x3F) << 2) | (UNKNOWN_B
>> 7);
349 data
[15] = ((UNKNOWN_B
& 0x7F) << 1);
350 data
[15] |= isEven_64_63(data
+ 8);
354 static int CmdLFNedapClone(const char *Cmd
) {
355 CLIParserContext
*ctx
;
356 CLIParserInit(&ctx
, "lf nedap clone",
357 "clone a Nedap tag to a T55x7, Q5/T5555 or EM4305/4469 tag.",
358 "lf nedap clone --st 1 --cc 101 --id 1337"
363 arg_u64_0(NULL
, "st", "<dec>", "optional - sub type (default 5)"),
364 arg_u64_1(NULL
, "cc", "<dec>", "customer code (0-4095)"),
365 arg_u64_1(NULL
, "id", "<dec>", "ID (0-99999)"),
366 arg_lit0("l", "long", "optional - long (128), default to short (64)"),
367 arg_lit0(NULL
, "q5", "optional - specify writing to Q5/T5555 tag"),
368 arg_lit0(NULL
, "em", "optional - specify writing to EM4305/4469 tag"),
371 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
373 uint8_t sub_type
= arg_get_u32_def(ctx
, 1, 5);
374 uint16_t customer_code
= arg_get_u32_def(ctx
, 2, 0);
375 uint32_t id
= arg_get_u32_def(ctx
, 3, 0);
376 bool is_long
= arg_get_lit(ctx
, 4);
377 bool q5
= arg_get_lit(ctx
, 5);
378 bool em
= arg_get_lit(ctx
, 6);
383 PrintAndLogEx(FAILED
, "Can't specify both Q5 and EM4305 at the same time");
386 if (sub_type
> 0xF) {
387 PrintAndLogEx(FAILED
, "out-of-range, valid subtype is between 0-15");
391 if (customer_code
> 0xFFF) {
392 PrintAndLogEx(FAILED
, "out-of-range, valid customer code is between 0-4095");
397 PrintAndLogEx(FAILED
, "out-of-range, id max value is 99999");
401 PrintAndLogEx(SUCCESS
, "NEDAP (%s) - ID: " _GREEN_("%05u") " subtype: " _GREEN_("%1u") " customer code: " _GREEN_("%u / 0x%03X")
402 , is_long
? "128b" : "64b"
410 //NEDAP - compat mode, ASK/DIphase, data rate 64, 4 data blocks
411 // DI-phase (CDP) T55x7_MODULATION_DIPHASE
413 uint32_t blocks
[5] = {0};
416 blocks
[0] = T55X7_NEDAP_128_CONFIG_BLOCK
;
419 blocks
[0] = T55X7_NEDAP_64_CONFIG_BLOCK
;
421 char cardtype
[16] = {"T55x7"};
426 blocks
[0] = T5555_FIXED
| T5555_MODULATION_BIPHASE
| T5555_INVERT_OUTPUT
| T5555_SET_BITRATE(64) | 4 << T5555_MAXBLOCK_SHIFT
;
428 blocks
[0] = T5555_FIXED
| T5555_MODULATION_BIPHASE
| T5555_INVERT_OUTPUT
| T5555_SET_BITRATE(64) | 2 << T5555_MAXBLOCK_SHIFT
;
435 blocks
[0] = EM4305_NEDAP_128_CONFIG_BLOCK
;
437 blocks
[0] = EM4305_NEDAP_64_CONFIG_BLOCK
;
439 snprintf(cardtype
, sizeof(cardtype
), "EM4305/4469");
442 // generate nedap bitstream
444 NedapGen(sub_type
, customer_code
, id
, is_long
, data
);
446 for (uint8_t i
= 1; i
< max
; i
++) {
447 blocks
[i
] = bytes_to_num(data
+ ((i
- 1) * 4), 4);
450 PrintAndLogEx(SUCCESS
, "Preparing to clone NEDAP to " _YELLOW_("%s") " tag", cardtype
);
451 print_blocks(blocks
, max
);
455 res
= em4x05_clone_tag(blocks
, ARRAYLEN(blocks
), 0, false);
457 res
= clone_t55xx_tag(blocks
, ARRAYLEN(blocks
));
460 if (res
== PM3_SUCCESS
) {
461 PrintAndLogEx(INFO
, "The block 0 was changed (eXtended) which can be hard to detect.");
462 PrintAndLogEx(INFO
, "Configure it manually " _YELLOW_("`lf t55xx config -b 64 --BI -i -o 32`"));
464 PrintAndLogEx(NORMAL
, "");
466 PrintAndLogEx(SUCCESS
, "Done");
467 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`lf nedap reader`") " to verify");
471 static int CmdLFNedapSim(const char *Cmd
) {
473 CLIParserContext
*ctx
;
474 CLIParserInit(&ctx
, "lf nedap sim",
475 "Enables simulation of NEDAP card with specified card number.\n"
476 "Simulation runs until the button is pressed or another USB command is issued.",
477 "lf nedap sim --st 1 --cc 101 --id 1337"
482 arg_u64_0(NULL
, "st", "<dec>", "optional - sub type (default 5)"),
483 arg_u64_1(NULL
, "cc", "<dec>", "customer code (0-4095)"),
484 arg_u64_1(NULL
, "id", "<dec>", "ID (0-99999)"),
485 arg_lit0("l", "long", "optional - long (128), default to short (64)"),
488 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
490 uint8_t sub_type
= arg_get_u32_def(ctx
, 1, 5);
491 uint16_t customer_code
= arg_get_u32_def(ctx
, 2, 0);
492 uint32_t id
= arg_get_u32_def(ctx
, 3, 0);
493 bool is_long
= arg_get_lit(ctx
, 4);
496 if (sub_type
> 0xF) {
497 PrintAndLogEx(FAILED
, "out-of-range, valid subtype is between 0-15");
501 if (customer_code
> 0xFFF) {
502 PrintAndLogEx(FAILED
, "out-of-range, valid customer code is between 0-4095");
507 PrintAndLogEx(FAILED
, "out-of-range, id max value is 99999");
511 PrintAndLogEx(SUCCESS
, "NEDAP (%s) - ID: " _GREEN_("%05u") " subtype: " _GREEN_("%1u") " customer code: " _GREEN_("%u / 0x%03X")
512 , is_long
? "128b" : "64b"
519 // generate nedap bitstream
520 uint8_t max
= (is_long
) ? 16 : 8;
522 NedapGen(sub_type
, customer_code
, id
, is_long
, data
);
525 for (uint8_t i
= 0; i
< max
; i
++) {
526 num_to_bytebits(data
[i
], 8, bs
+ i
* 8);
529 PrintAndLogEx(SUCCESS
, "Simulating NEDAP - Raw: " _YELLOW_("%s"), sprint_hex_inrow(data
, max
));
531 // NEDAP, Biphase = 2, clock 64, inverted, (DIPhase == inverted BIphase)
532 lf_asksim_t
*payload
= calloc(1, sizeof(lf_asksim_t
) + DemodBufferLen
);
533 payload
->encoding
= 2;
535 payload
->separator
= 0;
537 memcpy(payload
->data
, bs
, (max
* 8));
539 clearCommandBuffer();
540 SendCommandNG(CMD_LF_ASK_SIMULATE
, (uint8_t *)payload
, sizeof(lf_asksim_t
) + DemodBufferLen
);
543 PacketResponseNG resp
;
544 WaitForResponse(CMD_LF_ASK_SIMULATE
, &resp
);
546 PrintAndLogEx(INFO
, "Done");
547 if (resp
.status
!= PM3_EOPABORTED
)
553 static command_t CommandTable
[] = {
554 {"help", CmdHelp
, AlwaysAvailable
, "This help"},
555 {"demod", CmdLFNedapDemod
, AlwaysAvailable
, "demodulate Nedap tag from the GraphBuffer"},
556 {"reader", CmdLFNedapReader
, IfPm3Lf
, "attempt to read and extract tag data"},
557 {"clone", CmdLFNedapClone
, IfPm3Lf
, "clone Nedap tag to T55x7 or Q5/T5555"},
558 {"sim", CmdLFNedapSim
, IfPm3Lf
, "simulate Nedap tag"},
559 {NULL
, NULL
, NULL
, NULL
}
562 static int CmdHelp(const char *Cmd
) {
563 (void)Cmd
; // Cmd is not used so far
564 CmdsHelp(CommandTable
);
568 int CmdLFNedap(const char *Cmd
) {
569 clearCommandBuffer();
570 return CmdsParse(CommandTable
, Cmd
);