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 Verichip tag commands
17 //NRZ, RF/32, 128 bits long
18 //-----------------------------------------------------------------------------
19 #include "cmdlfverichip.h"
21 #include <ctype.h> //tolower
23 #include "commonutil.h" // ARRAYLEN
25 #include "cmdparser.h" // command_t
30 #include "lfdemod.h" // preamble test
31 #include "protocols.h" // t55xx defines
32 #include "cmdlft55xx.h" // clone..
34 static int CmdHelp(const char *Cmd
);
36 static int usage_lf_verichip_clone(void) {
37 PrintAndLogEx(NORMAL
, "clone a verichip tag to a T55x7 tag.");
38 PrintAndLogEx(NORMAL
, "");
39 PrintAndLogEx(NORMAL
, "Usage: lf verichip clone [h] [b <raw hex>]");
40 PrintAndLogEx(NORMAL
, "Options:");
41 PrintAndLogEx(NORMAL
, " h : this help");
42 PrintAndLogEx(NORMAL
, " b <raw hex> : raw hex data. 12 bytes max");
43 PrintAndLogEx(NORMAL
, "");
44 PrintAndLogEx(NORMAL
, "Examples:");
45 PrintAndLogEx(NORMAL
, _YELLOW_(" lf verichip clone b FF2049906D8511C593155B56D5B2649F "));
49 //see NRZDemod for what args are accepted
50 int demodVerichip(bool verbose
) {
51 (void) verbose
; // unused so far
53 if (NRZrawDemod(0, 0, 100, false) != PM3_SUCCESS
) {
54 PrintAndLogEx(DEBUG
, "DEBUG: Error - VERICHIP: NRZ Demod failed");
57 size_t size
= g_DemodBufferLen
;
58 int ans
= detectVerichip(g_DemodBuffer
, &size
);
61 PrintAndLogEx(DEBUG
, "DEBUG: Error - VERICHIP: too few bits found");
63 PrintAndLogEx(DEBUG
, "DEBUG: Error - VERICHIP: preamble not found");
65 PrintAndLogEx(DEBUG
, "DEBUG: Error - VERICHIP: Size not correct: %zu", size
);
67 PrintAndLogEx(DEBUG
, "DEBUG: Error - VERICHIP: ans: %d", ans
);
71 setDemodBuff(g_DemodBuffer
, 128, ans
);
72 setClockGrid(g_DemodClock
, g_DemodStartIdx
+ (ans
* g_DemodClock
));
75 uint32_t raw1
= bytebits_to_byte(g_DemodBuffer
, 32);
76 uint32_t raw2
= bytebits_to_byte(g_DemodBuffer
+ 32, 32);
77 uint32_t raw3
= bytebits_to_byte(g_DemodBuffer
+ 64, 32);
78 uint32_t raw4
= bytebits_to_byte(g_DemodBuffer
+ 96, 32);
80 // preamble then appears to have marker bits of "10" CS?
81 // 11111111001000000 10 01001100 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 10001100 10 100000001
82 // unknown checksum 9 bits at the end
84 PrintAndLogEx(SUCCESS
, "VERICHIP - Raw: %08X%08X%08X%08X", raw1
, raw2
, raw3
, raw4
);
85 PrintAndLogEx(INFO
, "How the Raw ID is translated by the reader is unknown. Share your trace file on forum");
89 static int CmdVerichipDemod(const char *Cmd
) {
91 return demodVerichip(true);
94 static int CmdVerichipRead(const char *Cmd
) {
96 lf_read(false, 4096 * 2 + 20);
97 return demodVerichip(true);
100 static int CmdVerichipClone(const char *Cmd
) {
107 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
108 switch (tolower(param_getchar(Cmd
, cmdp
))) {
110 return usage_lf_verichip_clone();
112 // skip first block, 4*4 = 16 bytes left
113 uint8_t rawhex
[16] = {0};
114 int res
= param_gethex_to_eol(Cmd
, cmdp
+ 1, rawhex
, sizeof(rawhex
), &datalen
);
118 for (uint8_t i
= 1; i
< ARRAYLEN(blocks
); i
++) {
119 blocks
[i
] = bytes_to_num(rawhex
+ ((i
- 1) * 4), sizeof(uint32_t));
125 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
131 if (errors
|| cmdp
== 0) return usage_lf_verichip_clone();
133 //Pac - compat mode, NRZ, data rate 40, 3 data blocks
134 blocks
[0] = T55x7_MODULATION_DIRECT
| T55x7_BITRATE_RF_40
| 4 << T55x7_MAXBLOCK_SHIFT
;
136 PrintAndLogEx(INFO
, "Preparing to clone Verichip to T55x7 with raw hex");
137 print_blocks(blocks
, ARRAYLEN(blocks
));
139 int res
= clone_t55xx_tag(blocks
, ARRAYLEN(blocks
));
140 PrintAndLogEx(SUCCESS
, "Done");
141 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`lf verichip read`") " to verify");
145 static int CmdVerichipSim(const char *Cmd
) {
148 PrintAndLogEx(INFO
, " To be implemented, feel free to contribute!");
152 static command_t CommandTable
[] = {
153 {"help", CmdHelp
, AlwaysAvailable
, "This help"},
154 {"demod", CmdVerichipDemod
, AlwaysAvailable
, "demodulate an VERICHIP tag from the GraphBuffer"},
155 {"read", CmdVerichipRead
, IfPm3Lf
, "attempt to read and extract tag data"},
156 {"clone", CmdVerichipClone
, IfPm3Lf
, "clone VERICHIP tag"},
157 {"sim", CmdVerichipSim
, IfPm3Lf
, "simulate VERICHIP tag"},
158 {NULL
, NULL
, NULL
, NULL
}
161 static int CmdHelp(const char *Cmd
) {
162 (void)Cmd
; // Cmd is not used so far
163 CmdsHelp(CommandTable
);
167 int CmdLFVerichip(const char *Cmd
) {
168 clearCommandBuffer();
169 return CmdsParse(CommandTable
, Cmd
);
172 // find VERICHIP preamble in already demoded data
173 int detectVerichip(uint8_t *dest
, size_t *size
) {
174 if (*size
< 128) return -1; //make sure buffer has data
176 uint8_t preamble
[] = {1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0};
177 if (!preambleSearch(dest
, preamble
, sizeof(preamble
), size
, &startIdx
))
178 return -2; //preamble not found
179 if (*size
< 128) return -3; //wrong demoded size
180 //return start position
181 return (int)startIdx
;