1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
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.
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 NEDAP tag commands
17 //-----------------------------------------------------------------------------
19 #include "cmdlfnedap.h"
25 #include "cmdparser.h" // command_t
28 #include "cmdlft55xx.h" // verify write
33 #include "protocols.h"
34 #include "cliparser.h"
35 #include "cmdlfem4x05.h" // EM defines
36 #include "commonutil.h"
40 #define UNKNOWN_A 0x00
41 #define UNKNOWN_B 0x00
43 static int CmdHelp(const char *Cmd
);
45 static const uint8_t translateTable
[10] = {8, 2, 1, 12, 4, 5, 10, 13, 0, 9};
46 static const uint8_t invTranslateTable
[16] = {8, 2, 1, 0xff, 4, 5, 0xff, 0xff, 0, 9, 6, 0xff, 3, 7, 0xff, 0xff};
47 static const uint8_t preamble
[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}; // zero inside
49 static uint8_t isEven_64_63(const uint8_t *data
) { // 8
52 return (bitcount32(tmp
[0]) + (bitcount32(tmp
[1] & 0xfeffffff))) & 1;
55 //NEDAP demod - ASK/Biphase (or Diphase), RF/64 with preamble of 1111111110 (always a 128 bit data stream)
56 int demodNedap(bool verbose
) {
57 (void) verbose
; // unused so far
58 uint8_t data
[16], buffer
[7], subtype
; // 4 bits
59 size_t size
, offset
= 0;
60 uint16_t checksum
, customerCode
; // 12 bits
61 uint32_t badgeId
; // max 99999
63 if (ASKbiphaseDemod(0, 64, 1, 0, false) != PM3_SUCCESS
) {
64 if (g_debugMode
) PrintAndLogEx(DEBUG
, "DEBUG: Error - NEDAP: ASK/Biphase Demod failed");
68 size
= g_DemodBufferLen
;
69 if (!preambleSearch(g_DemodBuffer
, (uint8_t *) preamble
, sizeof(preamble
), &size
, &offset
)) {
70 PrintAndLogEx(DEBUG
, "DEBUG: Error - NEDAP: preamble not found");
75 setDemodBuff(g_DemodBuffer
, size
, offset
);
76 setClockGrid(g_DemodClock
, g_DemodStartIdx
+ (g_DemodClock
* offset
));
79 if ((size
!= 128) && (size
!= 64)) {
80 PrintAndLogEx(DEBUG
, "DEBUG: Error - NEDAP: Size not correct: %zu", size
);
84 if (bits_to_array(g_DemodBuffer
, size
, data
) != PM3_SUCCESS
) {
85 PrintAndLogEx(DEBUG
, "DEBUG: Error - NEDAP: bits_to_array error\n");
90 int ret
= PM3_SUCCESS
;
95 if (isEven_64_63(data
) != (data
[7] & 0x01)) {
96 PrintAndLogEx(ERR
, "Bad parity (%1u)", data
[7] & 0x01);
101 // (1111111110 0 -- zero inside)
102 if ((data
[0] != 0xFF) && ((data
[1] & 0xE0) != 0x80)) {
103 PrintAndLogEx(ERR
, "Bad header");
107 buffer
[0] = (data
[0] << 7) | (data
[1] >> 1);
108 buffer
[1] = (data
[1] << 7) | (data
[2] >> 1);
109 buffer
[2] = (data
[2] << 7) | (data
[3] >> 1);
110 buffer
[3] = ((data
[4] & 0x1e) << 3) | ((data
[5] & 0x1e) >> 1);
111 buffer
[4] = ((data
[6] & 0x1e) << 3) | ((data
[7] & 0x1e) >> 1);
114 init_table(CRC_XMODEM
);
115 checksum
= crc16_xmodem(buffer
, 5);
117 buffer
[6] = (data
[3] << 7) | ((data
[4] & 0xe0) >> 1) | ((data
[4] & 0x01) << 3) | ((data
[5] & 0xe0) >> 5);
118 buffer
[5] = (data
[5] << 7) | ((data
[6] & 0xe0) >> 1) | ((data
[6] & 0x01) << 3) | ((data
[7] & 0xe0) >> 5);
119 uint16_t checksum2
= (buffer
[6] << 8) + buffer
[5];
120 bool isValid
= (checksum
== checksum2
);
122 subtype
= (data
[1] & 0x1e) >> 1;
123 customerCode
= ((data
[1] & 0x01) << 11) | (data
[2] << 3) | ((data
[3] & 0xe0) >> 5);
125 if (isValid
== false) {
126 PrintAndLogEx(ERR
, "Checksum : %s (calc 0x%04X != 0x%04X)", _RED_("fail"), checksum
, checksum2
);
130 uint8_t idxC1
= invTranslateTable
[(data
[3] & 0x1e) >> 1];
131 uint8_t idxC2
= invTranslateTable
[(data
[4] & 0x1e) >> 1];
132 uint8_t idxC3
= invTranslateTable
[(data
[5] & 0x1e) >> 1];
133 uint8_t idxC4
= invTranslateTable
[(data
[6] & 0x1e) >> 1];
134 uint8_t idxC5
= invTranslateTable
[(data
[7] & 0x1e) >> 1];
137 if ((idxC1
!= 0xFF) && (idxC2
!= 0xFF) && (idxC3
!= 0xFF) && (idxC4
!= 0xFF) && (idxC5
!= 0xFF)) {
139 uint8_t r2
= ((10 + idxC2
) - (idxC1
+ 1)) % 10;
140 uint8_t r3
= ((10 + idxC3
) - (idxC2
+ 1)) % 10;
141 uint8_t r4
= ((10 + idxC4
) - (idxC3
+ 1)) % 10;
142 uint8_t r5
= ((10 + idxC5
) - (idxC4
+ 1)) % 10;
144 badgeId
= r1
* 10000 + r2
* 1000 + r3
* 100 + r4
* 10 + r5
;
146 PrintAndLogEx(SUCCESS
, "NEDAP (%s) - ID: " _YELLOW_("%05u") " subtype: " _YELLOW_("%1u")" customer code: " _YELLOW_("%u / 0x%03X") " Raw: " _YELLOW_("%s")
147 , (size
== 128) ? "128b" : "64b"
152 , sprint_hex_inrow(data
, size
/ 8)
154 PrintAndLogEx(DEBUG
, "Checksum ( %s ) 0x%04X", _GREEN_("ok"), checksum
);
157 PrintAndLogEx(ERR
, "Invalid idx (1:%02x - 2:%02x - 3:%02x - 4:%02x - 5:%02x)", idxC1
, idxC2
, idxC3
, idxC4
, idxC5
);
163 PrintAndLogEx(DEBUG
, "NEDAP Tag, second part found");
165 if (isEven_64_63(data
+ 8) != (data
[15] & 0x01)) {
166 PrintAndLogEx(ERR
, "Bad parity (%1u)", data
[15] & 0x01);
177 && (data
[14] & 0x02)) {
178 PrintAndLogEx(ERR
, "Bad zeros");
183 uint8_t r4
= (data
[8] >> 3) & 0x0F;
184 uint8_t r5
= ((data
[8] << 1) & 0x0F) | (data
[9] >> 7);
185 uint8_t r2
= (data
[9] >> 2) & 0x0F;
186 uint8_t r3
= ((data
[9] << 2) & 0x0F) | (data
[10] >> 6);
187 uint8_t r0
= ((data
[10] >> 1) & 0x0F);
188 uint8_t r1
= ((data
[10] << 3) & 0x0F) | (data
[11] >> 5);
190 uint8_t fixed0
= ((data
[11] << 4) & 0xF0) | (data
[12] >> 4);
191 uint8_t fixed1
= ((data
[12] << 5) & 0xE0) | (data
[13] >> 3);
193 uint8_t unk1
= ((data
[13] << 6) & 0xC0) | (data
[14] >> 2);
194 uint8_t unk2
= ((data
[14] << 7) & 0xC0) | (data
[15] >> 1);
197 if (!r0
&& (r1
< 10) && (r2
< 10) && (r3
< 10) && (r4
< 10) && (r5
< 10)) {
199 badgeId
= r1
* 10000 + r2
* 1000 + r3
* 100 + r4
* 10 + r5
;
200 PrintAndLogEx(SUCCESS
, "Second Card: " _YELLOW_("%05u"), badgeId
);
202 if ((fixed0
== FIXED_71
) && (fixed1
== FIXED_40
))
203 PrintAndLogEx(DEBUG
, "Fixed part {0 = 0x%02x, 1 = 0x%02x}", fixed0
, fixed1
);
205 PrintAndLogEx(DEBUG
, "Bad fixed: {0 = 0x%02x (%0x02x), 1 = 0x%02x (%0x02x)}", fixed0
, FIXED_71
, fixed1
, FIXED_40
);
207 PrintAndLogEx(DEBUG
, "Unknown part {1 = 0x%02x, 2 = 0x%02x}", unk1
, unk2
);
209 PrintAndLogEx(ERR
, "Bad digits (0:%1x - 1:%1x - 2:%1x - 3:%1x - 4:%1x - 5:%1x)", r0
, r1
, r2
, r3
, r4
, r5
);
217 static int CmdLFNedapDemod(const char *Cmd
) {
218 CLIParserContext
*ctx
;
219 CLIParserInit(&ctx
, "lf nedap demod",
220 "Try to find Nedap preamble, if found decode / descramble data",
228 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
230 return demodNedap(true);
233 preamble enc tag type encrypted uid P d 33 d 90 d 04 d 71 d 40 d 45 d E7 P
234 1111111110 00101101000001011010001100100100001011010100110101100 1 0 00110011 0 10010000 0 00000100 0 01110001 0 01000000 0 01000101 0 11100111 1
235 uid2 uid1 uid0 I I R R
236 1111111110 00101101000001011010001100100100001011010100110101100 1
248 I = Identical on all tags
250 UID2, UID1, UID0 == card number
254 lf t55xx wr -b 0 -d 00170082
257 lf t55xx wr -b 1 -d FF8B4168
258 lf t55xx wr -b 2 -d C90B5359
259 lf t55xx wr -b 3 -d 19A40087
260 lf t55xx wr -b 4 -d 120115CF
263 lf t55xx wr -b 1 -d FF8B6B20
264 lf t55xx wr -b 2 -d F19B84A3
265 lf t55xx wr -b 3 -d 18058007
266 lf t55xx wr -b 4 -d 1200857C
269 lf t55xx wr -b 1 -d ffbfa73e
270 lf t55xx wr -b 2 -d 4c0003ff
271 lf t55xx wr -b 3 -d ffbfa73e
272 lf t55xx wr -b 4 -d 4c0003ff
276 static int CmdLFNedapReader(const char *Cmd
) {
277 CLIParserContext
*ctx
;
278 CLIParserInit(&ctx
, "lf nedap reader",
280 "lf nedap reader -@ -> continuous reader mode"
285 arg_lit0("@", NULL
, "optional - continuous reader mode"),
288 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
289 bool cm
= arg_get_lit(ctx
, 1);
293 PrintAndLogEx(INFO
, "Press " _GREEN_("<Enter>") " to exit");
297 lf_read(false, 16000);
299 } while (cm
&& !kbd_enter_pressed());
304 static void NedapGen(uint8_t subType
, uint16_t customerCode
, uint32_t id
, bool isLong
, uint8_t *data
) { // 8 or 16
307 uint8_t r1
= (uint8_t)(id
/ 10000);
308 uint8_t r2
= (uint8_t)((id
% 10000) / 1000);
309 uint8_t r3
= (uint8_t)((id
% 1000) / 100);
310 uint8_t r4
= (uint8_t)((id
% 100) / 10);
311 uint8_t r5
= (uint8_t)(id
% 10);
315 uint8_t idxC2
= (idxC1
+ 1 + r2
) % 10;
316 uint8_t idxC3
= (idxC2
+ 1 + r3
) % 10;
317 uint8_t idxC4
= (idxC3
+ 1 + r4
) % 10;
318 uint8_t idxC5
= (idxC4
+ 1 + r5
) % 10;
320 buffer
[0] = 0xc0 | (subType
& 0x0F);
321 buffer
[1] = (customerCode
& 0x0FF0) >> 4;
322 buffer
[2] = ((customerCode
& 0x000F) << 4) | translateTable
[idxC1
];
323 buffer
[3] = (translateTable
[idxC2
] << 4) | translateTable
[idxC3
];
324 buffer
[4] = (translateTable
[idxC4
] << 4) | translateTable
[idxC5
];
327 init_table(CRC_XMODEM
);
328 uint16_t checksum
= crc16_xmodem(buffer
, 5);
330 buffer
[6] = ((checksum
& 0x000F) << 4) | (buffer
[4] & 0x0F);
331 buffer
[5] = (checksum
& 0x00F0) | ((buffer
[4] & 0xF0) >> 4);
332 buffer
[4] = ((checksum
& 0x0F00) >> 4) | (buffer
[3] & 0x0F);
333 buffer
[3] = ((checksum
& 0xF000) >> 8) | ((buffer
[3] & 0xF0) >> 4);
337 for (uint8_t i
= 0; i
< sizeof(buffer
); i
++) {
338 uint8_t tmp
= buffer
[sizeof(buffer
) - 1 - i
];
339 data
[7 - i
] = ((tmp
& 0x7F) << 1) | carry
;
340 carry
= (tmp
& 0x80) >> 7;
342 data
[0] = 0xFE | carry
;
343 data
[7] |= isEven_64_63(data
);
348 uint8_t id1
= (r2
<< 4) | r3
;
349 uint8_t id2
= (r4
<< 4) | r5
;
351 data
[8] = (id2
>> 1);
352 data
[9] = ((id2
& 0x01) << 7) | (id1
>> 2);
353 data
[10] = ((id1
& 0x03) << 6) | (id0
>> 3);
354 data
[11] = ((id0
& 0x07) << 5) | (FIXED_71
>> 4);
355 data
[12] = ((FIXED_71
& 0x0F) << 4) | (FIXED_40
>> 5);
356 data
[13] = ((FIXED_40
& 0x1F) << 3) | (UNKNOWN_A
>> 6);
357 data
[14] = ((UNKNOWN_A
& 0x3F) << 2) | (UNKNOWN_B
>> 7);
358 data
[15] = ((UNKNOWN_B
& 0x7F) << 1);
359 data
[15] |= isEven_64_63(data
+ 8);
363 static int CmdLFNedapClone(const char *Cmd
) {
364 CLIParserContext
*ctx
;
365 CLIParserInit(&ctx
, "lf nedap clone",
366 "clone a Nedap tag to a T55x7, Q5/T5555 or EM4305/4469 tag.",
367 "lf nedap clone --st 1 --cc 101 --id 1337"
372 arg_u64_0(NULL
, "st", "<dec>", "optional - sub type (default 5)"),
373 arg_u64_1(NULL
, "cc", "<dec>", "customer code (0-4095)"),
374 arg_u64_1(NULL
, "id", "<dec>", "ID (0-99999)"),
375 arg_lit0("l", "long", "optional - long (128), default to short (64)"),
376 arg_lit0(NULL
, "q5", "optional - specify writing to Q5/T5555 tag"),
377 arg_lit0(NULL
, "em", "optional - specify writing to EM4305/4469 tag"),
380 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
382 uint8_t sub_type
= arg_get_u32_def(ctx
, 1, 5);
383 uint16_t customer_code
= arg_get_u32_def(ctx
, 2, 0);
384 uint32_t id
= arg_get_u32_def(ctx
, 3, 0);
385 bool is_long
= arg_get_lit(ctx
, 4);
386 bool q5
= arg_get_lit(ctx
, 5);
387 bool em
= arg_get_lit(ctx
, 6);
392 PrintAndLogEx(FAILED
, "Can't specify both Q5 and EM4305 at the same time");
395 if (sub_type
> 0xF) {
396 PrintAndLogEx(FAILED
, "out-of-range, valid subtype is between 0-15");
400 if (customer_code
> 0xFFF) {
401 PrintAndLogEx(FAILED
, "out-of-range, valid customer code is between 0-4095");
406 PrintAndLogEx(FAILED
, "out-of-range, id max value is 99999");
410 PrintAndLogEx(SUCCESS
, "NEDAP (%s) - ID: " _GREEN_("%05u") " subtype: " _GREEN_("%1u") " customer code: " _GREEN_("%u / 0x%03X")
411 , is_long
? "128b" : "64b"
419 //NEDAP - compat mode, ASK/DIphase, data rate 64, 4 data blocks
420 // DI-phase (CDP) T55x7_MODULATION_DIPHASE
422 uint32_t blocks
[5] = {0};
425 blocks
[0] = T55X7_NEDAP_128_CONFIG_BLOCK
;
428 blocks
[0] = T55X7_NEDAP_64_CONFIG_BLOCK
;
430 char cardtype
[16] = {"T55x7"};
435 blocks
[0] = T5555_FIXED
| T5555_MODULATION_BIPHASE
| T5555_INVERT_OUTPUT
| T5555_SET_BITRATE(64) | 4 << T5555_MAXBLOCK_SHIFT
;
437 blocks
[0] = T5555_FIXED
| T5555_MODULATION_BIPHASE
| T5555_INVERT_OUTPUT
| T5555_SET_BITRATE(64) | 2 << T5555_MAXBLOCK_SHIFT
;
444 blocks
[0] = EM4305_NEDAP_128_CONFIG_BLOCK
;
446 blocks
[0] = EM4305_NEDAP_64_CONFIG_BLOCK
;
448 snprintf(cardtype
, sizeof(cardtype
), "EM4305/4469");
451 // generate nedap bitstream
453 NedapGen(sub_type
, customer_code
, id
, is_long
, data
);
455 for (uint8_t i
= 1; i
< max
; i
++) {
456 blocks
[i
] = bytes_to_num(data
+ ((i
- 1) * 4), 4);
459 PrintAndLogEx(SUCCESS
, "Preparing to clone NEDAP to " _YELLOW_("%s") " tag", cardtype
);
460 print_blocks(blocks
, max
);
464 res
= em4x05_clone_tag(blocks
, ARRAYLEN(blocks
), 0, false);
466 res
= clone_t55xx_tag(blocks
, ARRAYLEN(blocks
));
469 if (res
== PM3_SUCCESS
) {
470 PrintAndLogEx(INFO
, "The block 0 was changed (eXtended) which can be hard to detect.");
471 PrintAndLogEx(INFO
, "Configure it manually " _YELLOW_("`lf t55xx config --rate 64 --BI -i -o 32`"));
473 PrintAndLogEx(NORMAL
, "");
475 PrintAndLogEx(SUCCESS
, "Done!");
476 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`lf nedap reader`") " to verify");
480 static int CmdLFNedapSim(const char *Cmd
) {
482 CLIParserContext
*ctx
;
483 CLIParserInit(&ctx
, "lf nedap sim",
484 "Enables simulation of NEDAP card with specified card number.\n"
485 "Simulation runs until the button is pressed or another USB command is issued.",
486 "lf nedap sim --st 1 --cc 101 --id 1337"
491 arg_u64_0(NULL
, "st", "<dec>", "optional - sub type (default 5)"),
492 arg_u64_1(NULL
, "cc", "<dec>", "customer code (0-4095)"),
493 arg_u64_1(NULL
, "id", "<dec>", "ID (0-99999)"),
494 arg_lit0("l", "long", "optional - long (128), default to short (64)"),
497 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
499 uint8_t sub_type
= arg_get_u32_def(ctx
, 1, 5);
500 uint16_t customer_code
= arg_get_u32_def(ctx
, 2, 0);
501 uint32_t id
= arg_get_u32_def(ctx
, 3, 0);
502 bool is_long
= arg_get_lit(ctx
, 4);
505 if (sub_type
> 0xF) {
506 PrintAndLogEx(FAILED
, "out-of-range, valid subtype is between 0-15");
510 if (customer_code
> 0xFFF) {
511 PrintAndLogEx(FAILED
, "out-of-range, valid customer code is between 0-4095");
516 PrintAndLogEx(FAILED
, "out-of-range, id max value is 99999");
520 PrintAndLogEx(SUCCESS
, "NEDAP (%s) - ID: " _GREEN_("%05u") " subtype: " _GREEN_("%1u") " customer code: " _GREEN_("%u / 0x%03X")
521 , is_long
? "128b" : "64b"
528 // generate nedap bitstream
529 uint8_t max
= (is_long
) ? 16 : 8;
531 NedapGen(sub_type
, customer_code
, id
, is_long
, data
);
533 uint8_t bs
[16 * 8] = {0};
534 for (uint8_t i
= 0; i
< max
; i
++) {
535 num_to_bytebits(data
[i
], 8, bs
+ i
* 8);
538 PrintAndLogEx(SUCCESS
, "Simulating NEDAP - Raw: " _YELLOW_("%s"), sprint_hex_inrow(data
, max
));
540 // NEDAP, Biphase = 2, clock 64, inverted, (DIPhase == inverted BIphase)
541 lf_asksim_t
*payload
= calloc(1, sizeof(lf_asksim_t
) + g_DemodBufferLen
);
542 payload
->encoding
= 2;
544 payload
->separator
= 0;
546 memcpy(payload
->data
, bs
, (max
* 8));
548 clearCommandBuffer();
549 SendCommandNG(CMD_LF_ASK_SIMULATE
, (uint8_t *)payload
, sizeof(lf_asksim_t
) + g_DemodBufferLen
);
552 PacketResponseNG resp
;
553 WaitForResponse(CMD_LF_ASK_SIMULATE
, &resp
);
555 PrintAndLogEx(INFO
, "Done!");
556 if (resp
.status
!= PM3_EOPABORTED
) {
562 static command_t CommandTable
[] = {
563 {"help", CmdHelp
, AlwaysAvailable
, "This help"},
564 {"demod", CmdLFNedapDemod
, AlwaysAvailable
, "demodulate Nedap tag from the GraphBuffer"},
565 {"reader", CmdLFNedapReader
, IfPm3Lf
, "attempt to read and extract tag data"},
566 {"clone", CmdLFNedapClone
, IfPm3Lf
, "clone Nedap tag to T55x7, Q5/T5555 or EM4305/4469"},
567 {"sim", CmdLFNedapSim
, IfPm3Lf
, "simulate Nedap tag"},
568 {NULL
, NULL
, NULL
, NULL
}
571 static int CmdHelp(const char *Cmd
) {
572 (void)Cmd
; // Cmd is not used so far
573 CmdsHelp(CommandTable
);
577 int CmdLFNedap(const char *Cmd
) {
578 clearCommandBuffer();
579 return CmdsParse(CommandTable
, Cmd
);