]> cvs.zerfleddert.de Git - proxmark3-svn/blame - client/cmdhf14a.c
1. Mifare read block command
[proxmark3-svn] / client / cmdhf14a.c
CommitLineData
a553f267 1//-----------------------------------------------------------------------------
534983d7 2// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch
a553f267 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 ISO14443A commands
9//-----------------------------------------------------------------------------
10
7fe9b0b7 11#include <stdio.h>
590f8ff9 12#include <stdlib.h>
7fe9b0b7 13#include <string.h>
20f9a2a1 14#include "util.h"
7fe9b0b7 15#include "iso14443crc.h"
16#include "data.h"
17#include "proxusb.h"
18#include "ui.h"
19#include "cmdparser.h"
20#include "cmdhf14a.h"
534983d7 21#include "common.h"
20f9a2a1 22#include "cmdmain.h"
7fe9b0b7 23
24static int CmdHelp(const char *Cmd);
25
26int CmdHF14AList(const char *Cmd)
27{
28 uint8_t got[1920];
29 GetFromBigBuf(got, sizeof(got));
30
31 PrintAndLog("recorded activity:");
32 PrintAndLog(" ETU :rssi: who bytes");
33 PrintAndLog("---------+----+----+-----------");
34
35 int i = 0;
36 int prev = -1;
37
38 for (;;) {
39 if(i >= 1900) {
40 break;
41 }
42
43 bool isResponse;
44 int timestamp = *((uint32_t *)(got+i));
45 if (timestamp & 0x80000000) {
46 timestamp &= 0x7fffffff;
47 isResponse = 1;
48 } else {
49 isResponse = 0;
50 }
51
52 int metric = 0;
53 int parityBits = *((uint32_t *)(got+i+4));
54 // 4 bytes of additional information...
55 // maximum of 32 additional parity bit information
56 //
57 // TODO:
58 // at each quarter bit period we can send power level (16 levels)
59 // or each half bit period in 256 levels.
60
61
62 int len = got[i+8];
63
64 if (len > 100) {
65 break;
66 }
67 if (i + len >= 1900) {
68 break;
69 }
70
71 uint8_t *frame = (got+i+9);
72
73 // Break and stick with current result if buffer was not completely full
74 if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }
75
76 char line[1000] = "";
77 int j;
78 for (j = 0; j < len; j++) {
79 int oddparity = 0x01;
80 int k;
81
82 for (k=0;k<8;k++) {
83 oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
84 }
85
86 //if((parityBits >> (len - j - 1)) & 0x01) {
87 if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
88 sprintf(line+(j*4), "%02x! ", frame[j]);
89 }
90 else {
91 sprintf(line+(j*4), "%02x ", frame[j]);
92 }
93 }
94
95 char *crc;
96 crc = "";
97 if (len > 2) {
98 uint8_t b1, b2;
99 for (j = 0; j < (len - 1); j++) {
100 // gives problems... search for the reason..
101 /*if(frame[j] == 0xAA) {
102 switch(frame[j+1]) {
103 case 0x01:
104 crc = "[1] Two drops close after each other";
105 break;
106 case 0x02:
107 crc = "[2] Potential SOC with a drop in second half of bitperiod";
108 break;
109 case 0x03:
110 crc = "[3] Segment Z after segment X is not possible";
111 break;
112 case 0x04:
113 crc = "[4] Parity bit of a fully received byte was wrong";
114 break;
115 default:
116 crc = "[?] Unknown error";
117 break;
118 }
119 break;
120 }*/
121 }
122
123 if (strlen(crc)==0) {
124 ComputeCrc14443(CRC_14443_A, frame, len-2, &b1, &b2);
125 if (b1 != frame[len-2] || b2 != frame[len-1]) {
126 crc = (isResponse & (len < 6)) ? "" : " !crc";
127 } else {
128 crc = "";
129 }
130 }
131 } else {
132 crc = ""; // SHORT
133 }
134
135 char metricString[100];
136 if (isResponse) {
137 sprintf(metricString, "%3d", metric);
138 } else {
139 strcpy(metricString, " ");
140 }
141
142 PrintAndLog(" +%7d: %s: %s %s %s",
143 (prev < 0 ? 0 : (timestamp - prev)),
144 metricString,
145 (isResponse ? "TAG" : " "), line, crc);
146
147 prev = timestamp;
148 i += (len + 9);
149 }
150 return 0;
151}
152
534983d7 153void iso14a_set_timeout(uint32_t timeout) {
154 UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_SET_TIMEOUT, 0, timeout}};
155 SendCommand(&c);
156}
157
7fe9b0b7 158int CmdHF14AMifare(const char *Cmd)
159{
160 UsbCommand c = {CMD_READER_MIFARE, {strtol(Cmd, NULL, 0), 0, 0}};
161 SendCommand(&c);
162 return 0;
163}
164
20f9a2a1
M
165int CmdHF14AMfWrBl(const char *Cmd)
166{
167 int i, temp;
168 uint8_t blockNo = 0;
169 uint8_t keyType = 0;
170 uint8_t key[6] = {0, 0, 0, 0, 0, 0};
171 uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
172
173 const char *cmdp = Cmd;
174 const char *cmdpe = Cmd;
175
176 if (strlen(Cmd)<3) {
177 PrintAndLog("Usage: hf 14 mfwrbl <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)>");
178 PrintAndLog(" sample: hf 14a mfwrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F");
179 return 0;
180 }
181 PrintAndLog("l: %s", Cmd);
182
183 // skip spaces
184 while (*cmdp==' ' || *cmdp=='\t') cmdp++;
185 blockNo = strtol(cmdp, NULL, 0) & 0xff;
186
187 // next value
188 while (*cmdp!=' ' && *cmdp!='\t') cmdp++;
189 while (*cmdp==' ' || *cmdp=='\t') cmdp++;
190 if (*cmdp != 'A' && *cmdp != 'a') {
191 keyType = 1;
192 }
193
194 // next value
195 while (*cmdp!=' ' && *cmdp!='\t') cmdp++;
196 while (*cmdp==' ' || *cmdp=='\t') cmdp++;
197
198 // next value here:cmdpe
199 cmdpe = cmdp;
200 while (*cmdpe!=' ' && *cmdpe!='\t') cmdpe++;
201 while (*cmdpe==' ' || *cmdpe=='\t') cmdpe++;
202
203 if ((int)cmdpe - (int)cmdp != 13) {
204 PrintAndLog("Length of key must be 12 hex symbols");
205 return 0;
206 }
207
208 for(i = 0; i < 6; i++) {
209 sscanf((char[]){cmdp[0],cmdp[1],0},"%X",&temp);
210 key[i] = temp & 0xff;
211 cmdp++;
212 cmdp++;
213 }
214
215 // next value
216 while (*cmdp!=' ' && *cmdp!='\t') cmdp++;
217 while (*cmdp==' ' || *cmdp=='\t') cmdp++;
218
219 if (strlen(cmdp) != 32) {
220 PrintAndLog("Length of block data must be 32 hex symbols");
221 return 0;
222 }
223
224 for(i = 0; i < 16; i++) {
225 sscanf((char[]){cmdp[0],cmdp[1],0},"%X",&temp);
226 bldata[i] = temp & 0xff;
227 cmdp++;
228 cmdp++;
229 }
230 PrintAndLog(" block no:%02x key type:%02x key:%s", blockNo, keyType, sprint_hex(key, 6));
231 PrintAndLog(" data: %s", sprint_hex(bldata, 16));
232
233 UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};
234 memcpy(c.d.asBytes, key, 6);
235 memcpy(c.d.asBytes + 10, bldata, 16);
236 SendCommand(&c);
237 UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500);
238
239 if (resp != NULL) {
240 uint8_t isOK = resp->arg[0] & 0xff;
241
242 PrintAndLog("isOk:%02x", isOK);
243 } else {
244 PrintAndLog("Command execute timeout");
245 }
246
247 return 0;
248}
249
250int CmdHF14AMfRdBl(const char *Cmd)
251{
252 int i, temp;
253 uint8_t blockNo = 0;
254 uint8_t keyType = 0;
255 uint8_t key[6] = {0, 0, 0, 0, 0, 0};
256
257 const char *cmdp = Cmd;
258
259
260 if (strlen(Cmd)<3) {
261 PrintAndLog("Usage: hf 14 mfrdbl <block number> <key A/B> <key (12 hex symbols)>");
262 PrintAndLog(" sample: hf 14a mfrdbl 0 A FFFFFFFFFFFF ");
263 return 0;
264 }
265
266 // skip spaces
267 while (*cmdp==' ' || *cmdp=='\t') cmdp++;
268 blockNo = strtol(cmdp, NULL, 0) & 0xff;
269
270 // next value
271 while (*cmdp!=' ' && *cmdp!='\t') cmdp++;
272 while (*cmdp==' ' || *cmdp=='\t') cmdp++;
273 if (*cmdp != 'A' && *cmdp != 'a') {
274 keyType = 1;
275 }
276
277 // next value
278 while (*cmdp!=' ' && *cmdp!='\t') cmdp++;
279 while (*cmdp==' ' || *cmdp=='\t') cmdp++;
280
281 if (strlen(cmdp) != 12) {
282 PrintAndLog("Length of key must be 12 hex symbols");
283 return 0;
284 }
285
286 for(i = 0; i < 6; i++) {
287 sscanf((char[]){cmdp[0],cmdp[1],0},"%X",&temp);
288 key[i] = temp & 0xff;
289 cmdp++;
290 cmdp++;
291 }
292 PrintAndLog(" block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6));
293
294 UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};
295 memcpy(c.d.asBytes, key, 6);
296 SendCommand(&c);
297 UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500);
298
299 if (resp != NULL) {
300 uint8_t isOK = resp->arg[0] & 0xff;
301 uint8_t * data = resp->d.asBytes;
302
303 PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 16));
304 } else {
305 PrintAndLog("Command execute timeout");
306 }
307
308 return 0;
309}
310
311int CmdHF14AMfRdSc(const char *Cmd)
312{
313 int i, temp;
314 uint8_t sectorNo = 0;
315 uint8_t keyType = 0;
316 uint8_t key[6] = {0, 0, 0, 0, 0, 0};
317
318 const char *cmdp = Cmd;
319
320
321 if (strlen(Cmd)<3) {
322 PrintAndLog("Usage: hf 14 mfrdsc <sector number> <key A/B> <key (12 hex symbols)>");
323 PrintAndLog(" sample: hf 14a mfrdsc 0 A FFFFFFFFFFFF ");
324 return 0;
325 }
326
327 // skip spaces
328 while (*cmdp==' ' || *cmdp=='\t') cmdp++;
329 sectorNo = strtol(cmdp, NULL, 0) & 0xff;
330
331 // next value
332 while (*cmdp!=' ' && *cmdp!='\t') cmdp++;
333 while (*cmdp==' ' || *cmdp=='\t') cmdp++;
334 if (*cmdp != 'A' && *cmdp != 'a') {
335 keyType = 1;
336 }
337
338 // next value
339 while (*cmdp!=' ' && *cmdp!='\t') cmdp++;
340 while (*cmdp==' ' || *cmdp=='\t') cmdp++;
341
342 if (strlen(cmdp) != 12) {
343 PrintAndLog("Length of key must be 12 hex symbols");
344 return 0;
345 }
346
347 for(i = 0; i < 6; i++) {
348 sscanf((char[]){cmdp[0],cmdp[1],0},"%X",&temp);
349 key[i] = temp & 0xff;
350 cmdp++;
351 cmdp++;
352 }
353 PrintAndLog(" sector no:%02x key type:%02x key:%s ", sectorNo, keyType, sprint_hex(key, 6));
354
355 UsbCommand c = {CMD_MIFARE_READSC, {sectorNo, keyType, 0}};
356 memcpy(c.d.asBytes, key, 6);
357 SendCommand(&c);
358 UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500);
359 PrintAndLog(" ");
360
361 if (resp != NULL) {
362 uint8_t isOK = resp->arg[0] & 0xff;
363 uint8_t * data = resp->d.asBytes;
364
365 PrintAndLog("isOk:%02x", isOK);
366 for (i = 0; i < 2; i++) {
367 PrintAndLog("data:%s", sprint_hex(data + i * 16, 16));
368 }
369 } else {
370 PrintAndLog("Command1 execute timeout");
371 }
372
373 // response2
374 resp = WaitForResponseTimeout(CMD_ACK, 500);
375 PrintAndLog(" ");
376
377 if (resp != NULL) {
378 uint8_t * data = resp->d.asBytes;
379
380 for (i = 0; i < 2; i++) {
381 PrintAndLog("data:%s", sprint_hex(data + i * 16, 16));
382 }
383 } else {
384 PrintAndLog("Command2 execute timeout");
385 }
386
387 return 0;
388}
389
7fe9b0b7 390int CmdHF14AReader(const char *Cmd)
391{
534983d7 392 UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}};
393 SendCommand(&c);
394 UsbCommand * resp = WaitForResponse(CMD_ACK);
395 uint8_t * uid = resp->d.asBytes;
396 iso14a_card_select_t * card = uid + 12;
397
398 if(resp->arg[0] == 0) {
399 PrintAndLog("iso14443a card select failed");
400 return 0;
401 }
402
403 PrintAndLog("ATQA : %02x %02x", card->atqa[0], card->atqa[1]);
404 PrintAndLog(" UID : %s", sprint_hex(uid, 12));
405 PrintAndLog(" SAK : %02x [%d]", card->sak, resp->arg[0]);
406 if(resp->arg[0] == 1)
407 PrintAndLog(" ATS : %s", sprint_hex(card->ats, card->ats_len));
408 else
409 PrintAndLog("proprietary non-iso14443a card found, RATS not supported");
410
411 return resp->arg[0];
7fe9b0b7 412}
413
414// ## simulate iso14443a tag
415// ## greg - added ability to specify tag UID
416int CmdHF14ASim(const char *Cmd)
417{
418
419 unsigned int hi = 0, lo = 0;
420 int n = 0, i = 0;
421 while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
422 hi= (hi << 4) | (lo >> 28);
423 lo= (lo << 4) | (n & 0xf);
424 }
425
426 // c.arg should be set to *Cmd or convert *Cmd to the correct format for a uid
427 UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a, {hi, lo, 0}};
428 PrintAndLog("Emulating 14443A TAG with UID %x%16x", hi, lo);
429 SendCommand(&c);
430 return 0;
431}
432
433int CmdHF14ASnoop(const char *Cmd)
434{
435 UsbCommand c = {CMD_SNOOP_ISO_14443a};
436 SendCommand(&c);
437 return 0;
438}
439
440static command_t CommandTable[] =
441{
442 {"help", CmdHelp, 1, "This help"},
443 {"list", CmdHF14AList, 0, "List ISO 14443a history"},
444 {"mifare", CmdHF14AMifare, 0, "Read out sector 0 parity error messages"},
20f9a2a1
M
445 {"mfrdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"},
446 {"mfrdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"},
447 {"mfwrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"},
7fe9b0b7 448 {"reader", CmdHF14AReader, 0, "Act like an ISO14443 Type A reader"},
449 {"sim", CmdHF14ASim, 0, "<UID> -- Fake ISO 14443a tag"},
450 {"snoop", CmdHF14ASnoop, 0, "Eavesdrop ISO 14443 Type A"},
451 {NULL, NULL, 0, NULL}
452};
453
454int CmdHF14A(const char *Cmd)
455{
456 CmdsParse(CommandTable, Cmd);
457 return 0;
458}
459
460int CmdHelp(const char *Cmd)
461{
462 CmdsHelp(CommandTable);
463 return 0;
464}
Impressum, Datenschutz