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 Verichip tag commands
8 //NRZ, RF/32, 128 bits long
9 //-----------------------------------------------------------------------------
10 #include "cmdlfverichip.h"
12 #include <ctype.h> //tolower
14 #include "commonutil.h" // ARRAYLEN
16 #include "cmdparser.h" // command_t
21 #include "lfdemod.h" // preamble test
22 #include "protocols.h" // t55xx defines
23 #include "cmdlft55xx.h" // clone..
25 static int CmdHelp(const char *Cmd
);
27 static int usage_lf_verichip_clone(void) {
28 PrintAndLogEx(NORMAL
, "clone a verichip tag to a T55x7 tag.");
29 PrintAndLogEx(NORMAL
, "");
30 PrintAndLogEx(NORMAL
, "Usage: lf verichip clone [h] [b <raw hex>]");
31 PrintAndLogEx(NORMAL
, "Options:");
32 PrintAndLogEx(NORMAL
, " h : this help");
33 PrintAndLogEx(NORMAL
, " b <raw hex> : raw hex data. 12 bytes max");
34 PrintAndLogEx(NORMAL
, "");
35 PrintAndLogEx(NORMAL
, "Examples:");
36 PrintAndLogEx(NORMAL
, _YELLOW_(" lf verichip clone b FF2049906D8511C593155B56D5B2649F "));
40 //see NRZDemod for what args are accepted
41 int demodVerichip(bool verbose
) {
42 (void) verbose
; // unused so far
44 if (NRZrawDemod(0, 0, 100, false) != PM3_SUCCESS
) {
45 PrintAndLogEx(DEBUG
, "DEBUG: Error - VERICHIP: NRZ Demod failed");
48 size_t size
= DemodBufferLen
;
49 int ans
= detectVerichip(DemodBuffer
, &size
);
52 PrintAndLogEx(DEBUG
, "DEBUG: Error - VERICHIP: too few bits found");
54 PrintAndLogEx(DEBUG
, "DEBUG: Error - VERICHIP: preamble not found");
56 PrintAndLogEx(DEBUG
, "DEBUG: Error - VERICHIP: Size not correct: %zu", size
);
58 PrintAndLogEx(DEBUG
, "DEBUG: Error - VERICHIP: ans: %d", ans
);
62 setDemodBuff(DemodBuffer
, 128, ans
);
63 setClockGrid(g_DemodClock
, g_DemodStartIdx
+ (ans
* g_DemodClock
));
66 uint32_t raw1
= bytebits_to_byte(DemodBuffer
, 32);
67 uint32_t raw2
= bytebits_to_byte(DemodBuffer
+ 32, 32);
68 uint32_t raw3
= bytebits_to_byte(DemodBuffer
+ 64, 32);
69 uint32_t raw4
= bytebits_to_byte(DemodBuffer
+ 96, 32);
71 // preamble then appears to have marker bits of "10" CS?
72 // 11111111001000000 10 01001100 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 10001100 10 100000001
73 // unknown checksum 9 bits at the end
75 PrintAndLogEx(SUCCESS
, "VERICHIP - Raw: %08X%08X%08X%08X", raw1
, raw2
, raw3
, raw4
);
76 PrintAndLogEx(INFO
, "How the Raw ID is translated by the reader is unknown. Share your trace file on forum");
80 static int CmdVerichipDemod(const char *Cmd
) {
82 return demodVerichip(true);
85 static int CmdVerichipRead(const char *Cmd
) {
87 lf_read(false, 4096 * 2 + 20);
88 return demodVerichip(true);
91 static int CmdVerichipClone(const char *Cmd
) {
98 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
99 switch (tolower(param_getchar(Cmd
, cmdp
))) {
101 return usage_lf_verichip_clone();
103 // skip first block, 4*4 = 16 bytes left
104 uint8_t rawhex
[16] = {0};
105 int res
= param_gethex_to_eol(Cmd
, cmdp
+ 1, rawhex
, sizeof(rawhex
), &datalen
);
109 for (uint8_t i
= 1; i
< ARRAYLEN(blocks
); i
++) {
110 blocks
[i
] = bytes_to_num(rawhex
+ ((i
- 1) * 4), sizeof(uint32_t));
116 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
122 if (errors
|| cmdp
== 0) return usage_lf_verichip_clone();
124 //Pac - compat mode, NRZ, data rate 40, 3 data blocks
125 blocks
[0] = T55x7_MODULATION_DIRECT
| T55x7_BITRATE_RF_40
| 4 << T55x7_MAXBLOCK_SHIFT
;
127 PrintAndLogEx(INFO
, "Preparing to clone Verichip to T55x7 with raw hex");
128 print_blocks(blocks
, ARRAYLEN(blocks
));
130 int res
= clone_t55xx_tag(blocks
, ARRAYLEN(blocks
));
131 PrintAndLogEx(SUCCESS
, "Done");
132 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`lf verichip read`") " to verify");
136 static int CmdVerichipSim(const char *Cmd
) {
139 PrintAndLogEx(INFO
, " To be implemented, feel free to contribute!");
143 static command_t CommandTable
[] = {
144 {"help", CmdHelp
, AlwaysAvailable
, "This help"},
145 {"demod", CmdVerichipDemod
, AlwaysAvailable
, "demodulate an VERICHIP tag from the GraphBuffer"},
146 {"read", CmdVerichipRead
, IfPm3Lf
, "attempt to read and extract tag data"},
147 {"clone", CmdVerichipClone
, IfPm3Lf
, "clone VERICHIP tag"},
148 {"sim", CmdVerichipSim
, IfPm3Lf
, "simulate VERICHIP tag"},
149 {NULL
, NULL
, NULL
, NULL
}
152 static int CmdHelp(const char *Cmd
) {
153 (void)Cmd
; // Cmd is not used so far
154 CmdsHelp(CommandTable
);
158 int CmdLFVerichip(const char *Cmd
) {
159 clearCommandBuffer();
160 return CmdsParse(CommandTable
, Cmd
);
163 // find VERICHIP preamble in already demoded data
164 int detectVerichip(uint8_t *dest
, size_t *size
) {
165 if (*size
< 128) return -1; //make sure buffer has data
167 uint8_t preamble
[] = {1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0};
168 if (!preambleSearch(dest
, preamble
, sizeof(preamble
), size
, &startIdx
))
169 return -2; //preamble not found
170 if (*size
< 128) return -3; //wrong demoded size
171 //return start position
172 return (int)startIdx
;