]>
Commit | Line | Data |
---|---|---|
a553f267 | 1 | //----------------------------------------------------------------------------- |
2 | // Copyright (C) 2010 iZsh <izsh at fail0verflow.com> | |
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 | // High frequency ISO14443B commands | |
9 | //----------------------------------------------------------------------------- | |
10 | ||
7fe9b0b7 | 11 | #include <stdio.h> |
12 | #include <stdlib.h> | |
13 | #include <stdbool.h> | |
14 | #include <string.h> | |
15 | #include <stdint.h> | |
16 | #include "iso14443crc.h" | |
902cb3c0 | 17 | #include "proxmark3.h" |
7fe9b0b7 | 18 | #include "data.h" |
19 | #include "graph.h" | |
3fe4ff4f | 20 | #include "util.h" |
7fe9b0b7 | 21 | #include "ui.h" |
22 | #include "cmdparser.h" | |
23 | #include "cmdhf14b.h" | |
7cf3ef20 | 24 | #include "cmdmain.h" |
7fe9b0b7 | 25 | |
26 | static int CmdHelp(const char *Cmd); | |
27 | ||
7fe9b0b7 | 28 | int CmdHF14BList(const char *Cmd) |
29 | { | |
388c92bd | 30 | PrintAndLog("Deprecated command, use 'hf list 14b' instead"); |
7fe9b0b7 | 31 | |
388c92bd | 32 | return 0; |
7fe9b0b7 | 33 | } |
7fe9b0b7 | 34 | |
132a0217 | 35 | int CmdHF14BSim(const char *Cmd) |
7fe9b0b7 | 36 | { |
132a0217 | 37 | UsbCommand c={CMD_SIMULATE_TAG_ISO_14443B}; |
7fe9b0b7 | 38 | SendCommand(&c); |
39 | return 0; | |
40 | } | |
41 | ||
42 | int CmdHF14BSnoop(const char *Cmd) | |
43 | { | |
132a0217 | 44 | UsbCommand c = {CMD_SNOOP_ISO_14443B}; |
7fe9b0b7 | 45 | SendCommand(&c); |
46 | return 0; | |
47 | } | |
48 | ||
49 | /* New command to read the contents of a SRI512 tag | |
50 | * SRI512 tags are ISO14443-B modulated memory tags, | |
51 | * this command just dumps the contents of the memory | |
52 | */ | |
53 | int CmdSri512Read(const char *Cmd) | |
54 | { | |
55 | UsbCommand c = {CMD_READ_SRI512_TAG, {strtol(Cmd, NULL, 0), 0, 0}}; | |
56 | SendCommand(&c); | |
57 | return 0; | |
58 | } | |
59 | ||
60 | /* New command to read the contents of a SRIX4K tag | |
61 | * SRIX4K tags are ISO14443-B modulated memory tags, | |
62 | * this command just dumps the contents of the memory/ | |
63 | */ | |
64 | int CmdSrix4kRead(const char *Cmd) | |
65 | { | |
66 | UsbCommand c = {CMD_READ_SRIX4K_TAG, {strtol(Cmd, NULL, 0), 0, 0}}; | |
67 | SendCommand(&c); | |
68 | return 0; | |
69 | } | |
70 | ||
7cf3ef20 | 71 | int CmdHF14BCmdRaw (const char *cmd) { |
72 | UsbCommand resp; | |
73 | uint8_t *recv; | |
74 | UsbCommand c = {CMD_ISO_14443B_COMMAND, {0, 0, 0}}; // len,recv? | |
75 | uint8_t reply=1; | |
76 | uint8_t crc=0; | |
77 | uint8_t power=0; | |
78 | char buf[5]=""; | |
79 | int i=0; | |
5ee70129 | 80 | uint8_t data[100] = {0x00}; |
7cf3ef20 | 81 | unsigned int datalen=0, temp; |
82 | char *hexout; | |
83 | ||
84 | if (strlen(cmd)<3) { | |
85 | PrintAndLog("Usage: hf 14b raw [-r] [-c] [-p] <0A 0B 0C ... hex>"); | |
86 | PrintAndLog(" -r do not read response"); | |
87 | PrintAndLog(" -c calculate and append CRC"); | |
88 | PrintAndLog(" -p leave the field on after receive"); | |
89 | return 0; | |
90 | } | |
91 | ||
92 | // strip | |
93 | while (*cmd==' ' || *cmd=='\t') cmd++; | |
94 | ||
95 | while (cmd[i]!='\0') { | |
96 | if (cmd[i]==' ' || cmd[i]=='\t') { i++; continue; } | |
97 | if (cmd[i]=='-') { | |
98 | switch (cmd[i+1]) { | |
99 | case 'r': | |
100 | case 'R': | |
101 | reply=0; | |
102 | break; | |
103 | case 'c': | |
104 | case 'C': | |
105 | crc=1; | |
106 | break; | |
107 | case 'p': | |
108 | case 'P': | |
109 | power=1; | |
110 | break; | |
111 | default: | |
112 | PrintAndLog("Invalid option"); | |
113 | return 0; | |
114 | } | |
115 | i+=2; | |
116 | continue; | |
117 | } | |
118 | if ((cmd[i]>='0' && cmd[i]<='9') || | |
119 | (cmd[i]>='a' && cmd[i]<='f') || | |
120 | (cmd[i]>='A' && cmd[i]<='F') ) { | |
121 | buf[strlen(buf)+1]=0; | |
122 | buf[strlen(buf)]=cmd[i]; | |
123 | i++; | |
124 | ||
125 | if (strlen(buf)>=2) { | |
126 | sscanf(buf,"%x",&temp); | |
127 | data[datalen]=(uint8_t)(temp & 0xff); | |
128 | datalen++; | |
129 | *buf=0; | |
130 | } | |
131 | continue; | |
132 | } | |
133 | PrintAndLog("Invalid char on input"); | |
5ee70129 | 134 | return 1; |
7cf3ef20 | 135 | } |
06b82e6a | 136 | if (datalen == 0) |
137 | { | |
138 | PrintAndLog("Missing data input"); | |
139 | return 0; | |
140 | } | |
7cf3ef20 | 141 | if(crc) |
142 | { | |
143 | uint8_t first, second; | |
144 | ComputeCrc14443(CRC_14443_B, data, datalen, &first, &second); | |
145 | data[datalen++] = first; | |
146 | data[datalen++] = second; | |
147 | } | |
148 | ||
149 | c.arg[0] = datalen; | |
150 | c.arg[1] = reply; | |
151 | c.arg[2] = power; | |
152 | memcpy(c.d.asBytes,data,datalen); | |
153 | ||
154 | SendCommand(&c); | |
155 | ||
156 | if (reply) { | |
157 | if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) { | |
158 | recv = resp.d.asBytes; | |
159 | PrintAndLog("received %i octets",resp.arg[0]); | |
51d4f6f1 | 160 | if(resp.arg[0] == 0) |
7cf3ef20 | 161 | return 0; |
162 | hexout = (char *)malloc(resp.arg[0] * 3 + 1); | |
163 | if (hexout != NULL) { | |
164 | uint8_t first, second; | |
165 | for (int i = 0; i < resp.arg[0]; i++) { // data in hex | |
7bb9d33e | 166 | sprintf(&hexout[i * 3], "%02X ", recv[i]); |
7cf3ef20 | 167 | } |
168 | PrintAndLog("%s", hexout); | |
169 | free(hexout); | |
51d4f6f1 | 170 | if (resp.arg[0] > 2) { |
171 | ComputeCrc14443(CRC_14443_B, recv, resp.arg[0]-2, &first, &second); | |
172 | if(recv[resp.arg[0]-2]==first && recv[resp.arg[0]-1]==second) { | |
173 | PrintAndLog("CRC OK"); | |
174 | } else { | |
175 | PrintAndLog("CRC failed"); | |
176 | } | |
7cf3ef20 | 177 | } |
178 | } else { | |
179 | PrintAndLog("malloc failed your client has low memory?"); | |
180 | } | |
181 | } else { | |
182 | PrintAndLog("timeout while waiting for reply."); | |
183 | } | |
184 | } // if reply | |
185 | return 0; | |
186 | } | |
187 | ||
3fe4ff4f | 188 | int CmdHF14BWrite( const char *Cmd){ |
189 | ||
190 | /* | |
191 | * For SRIX4K blocks 00 - 7F | |
192 | * hf 14b raw -c -p 09 $srix4kwblock $srix4kwdata | |
193 | * | |
194 | * For SR512 blocks 00 - 0F | |
195 | * hf 14b raw -c -p 09 $sr512wblock $sr512wdata | |
196 | * | |
197 | * Special block FF = otp_lock_reg block. | |
198 | * Data len 4 bytes- | |
199 | */ | |
200 | char cmdp = param_getchar(Cmd, 0); | |
201 | uint8_t blockno = -1; | |
202 | uint8_t data[4] = {0x00}; | |
203 | bool isSrix4k = true; | |
204 | char str[20]; | |
205 | ||
b5be31f9 | 206 | if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') { |
3fe4ff4f | 207 | PrintAndLog("Usage: hf 14b write <1|2> <BLOCK> <DATA>"); |
b5be31f9 | 208 | PrintAndLog(" [1 = SRIX4K]"); |
209 | PrintAndLog(" [2 = SRI512]"); | |
210 | PrintAndLog(" [BLOCK number depends on tag, special block == FF]"); | |
211 | PrintAndLog(" sample: hf 14b write 1 7F 11223344"); | |
212 | PrintAndLog(" : hf 14b write 1 FF 11223344"); | |
213 | PrintAndLog(" : hf 14b write 2 15 11223344"); | |
214 | PrintAndLog(" : hf 14b write 2 FF 11223344"); | |
3fe4ff4f | 215 | return 0; |
216 | } | |
217 | ||
b5be31f9 | 218 | if ( cmdp == '2' ) |
3fe4ff4f | 219 | isSrix4k = false; |
220 | ||
b5be31f9 | 221 | //blockno = param_get8(Cmd, 1); |
222 | ||
223 | if ( param_gethex(Cmd,1, &blockno, 2) ) { | |
224 | PrintAndLog("Block number must include 2 HEX symbols"); | |
225 | return 0; | |
226 | } | |
3fe4ff4f | 227 | |
228 | if ( isSrix4k ){ | |
229 | if ( blockno > 0x7f && blockno != 0xff ){ | |
230 | PrintAndLog("Block number out of range"); | |
231 | return 0; | |
232 | } | |
233 | } else { | |
234 | if ( blockno > 0x0f && blockno != 0xff ){ | |
235 | PrintAndLog("Block number out of range"); | |
236 | return 0; | |
237 | } | |
238 | } | |
239 | ||
240 | if (param_gethex(Cmd, 2, data, 8)) { | |
241 | PrintAndLog("Data must include 8 HEX symbols"); | |
242 | return 0; | |
243 | } | |
244 | ||
245 | if ( blockno == 0xff) | |
b5be31f9 | 246 | PrintAndLog("[%s] Write special block %02X [ %s ]", (isSrix4k)?"SRIX4K":"SRI512" , blockno, sprint_hex(data,4) ); |
3fe4ff4f | 247 | else |
b5be31f9 | 248 | PrintAndLog("[%s] Write block %02X [ %s ]", (isSrix4k)?"SRIX4K":"SRI512", blockno, sprint_hex(data,4) ); |
3fe4ff4f | 249 | |
fe5b3a44 | 250 | sprintf(str, "-c 09 %02x %02x%02x%02x%02x", blockno, data[0], data[1], data[2], data[3]); |
b5be31f9 | 251 | |
3fe4ff4f | 252 | CmdHF14BCmdRaw(str); |
253 | return 0; | |
254 | } | |
255 | ||
7fe9b0b7 | 256 | static command_t CommandTable[] = |
257 | { | |
258 | {"help", CmdHelp, 1, "This help"}, | |
388c92bd | 259 | {"list", CmdHF14BList, 0, "[Deprecated] List ISO 14443b history"}, |
132a0217 | 260 | {"sim", CmdHF14BSim, 0, "Fake ISO 14443B tag"}, |
261 | {"snoop", CmdHF14BSnoop, 0, "Eavesdrop ISO 14443B"}, | |
7cf3ef20 | 262 | {"sri512read", CmdSri512Read, 0, "Read contents of a SRI512 tag"}, |
263 | {"srix4kread", CmdSrix4kRead, 0, "Read contents of a SRIX4K tag"}, | |
264 | {"raw", CmdHF14BCmdRaw, 0, "Send raw hex data to tag"}, | |
3fe4ff4f | 265 | {"write", CmdHF14BWrite, 0, "Write data to a SRI512 | SRIX4K tag"}, |
7fe9b0b7 | 266 | {NULL, NULL, 0, NULL} |
267 | }; | |
268 | ||
269 | int CmdHF14B(const char *Cmd) | |
270 | { | |
271 | CmdsParse(CommandTable, Cmd); | |
272 | return 0; | |
273 | } | |
274 | ||
275 | int CmdHelp(const char *Cmd) | |
276 | { | |
277 | CmdsHelp(CommandTable); | |
278 | return 0; | |
279 | } |