]> git.zerfleddert.de Git - proxmark3-svn/blame - client/cmdhf14a.c
nested authentication works ok (tested)
[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
4abe4f58
M
390int CmdHF14AMfNested(const char *Cmd)
391{
392 int i, temp;
393 uint8_t sectorNo = 0;
394 uint8_t keyType = 0;
395 uint8_t key[6] = {0, 0, 0, 0, 0, 0};
396
397 const char *cmdp = Cmd;
398
399
400 if (strlen(Cmd)<3) {
401 PrintAndLog("Usage: hf 14a nested <sector number> <key A/B> <key (12 hex symbols)>");
402 PrintAndLog(" sample: hf 14a nested 0 A FFFFFFFFFFFF ");
403 return 0;
404 }
405
406 // skip spaces
407 while (*cmdp==' ' || *cmdp=='\t') cmdp++;
408 sectorNo = strtol(cmdp, NULL, 0) & 0xff;
409
410 // next value
411 while (*cmdp!=' ' && *cmdp!='\t') cmdp++;
412 while (*cmdp==' ' || *cmdp=='\t') cmdp++;
413 if (*cmdp != 'A' && *cmdp != 'a') {
414 keyType = 1;
415 }
416
417 // next value
418 while (*cmdp!=' ' && *cmdp!='\t') cmdp++;
419 while (*cmdp==' ' || *cmdp=='\t') cmdp++;
420
421 if (strlen(cmdp) != 12) {
422 PrintAndLog("Length of key must be 12 hex symbols");
423 return 0;
424 }
425
426 for(i = 0; i < 6; i++) {
427 sscanf((char[]){cmdp[0],cmdp[1],0},"%X",&temp);
428 key[i] = temp & 0xff;
429 cmdp++;
430 cmdp++;
431 }
432 PrintAndLog(" sector no:%02x key type:%02x key:%s ", sectorNo, keyType, sprint_hex(key, 6));
433
434 UsbCommand c = {CMD_MIFARE_NESTED, {sectorNo, keyType, 0}};
435 memcpy(c.d.asBytes, key, 6);
436 SendCommand(&c);
437 UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500);
438 PrintAndLog(" ");
439
440 if (resp != NULL) {
441 uint8_t isOK = resp->arg[0] & 0xff;
442 uint8_t * data = resp->d.asBytes;
443
444 PrintAndLog("isOk:%02x", isOK);
445 for (i = 0; i < 2; i++) {
446 PrintAndLog("data:%s", sprint_hex(data + i * 16, 16));
447 }
448 } else {
449 PrintAndLog("Command execute timeout");
450 }
451
452 return 0;
453}
454
455int CmdHF14AMf1kSim(const char *Cmd)
456{
457 int i, temp;
458 uint8_t uid[4] = {0, 0, 0, 0};
459
460 const char *cmdp = Cmd;
461
462
463 if (strlen(Cmd)<3) {
464 PrintAndLog("Usage: hf 14a mfsim <uid (8 hex symbols)>");
465 PrintAndLog(" sample: hf 14a mfsim 0a0a0a0a ");
466 return 0;
467 }
468
469 // skip spaces
470 while (*cmdp==' ' || *cmdp=='\t') cmdp++;
471
472 if (strlen(cmdp) != 8) {
473 PrintAndLog("Length of UID must be 8 hex symbols");
474 return 0;
475 }
476
477 for(i = 0; i < 4; i++) {
478 sscanf((char[]){cmdp[0],cmdp[1],0},"%X",&temp);
479 uid[i] = temp & 0xff;
480 cmdp++;
481 cmdp++;
482 }
483 PrintAndLog(" uid:%s ", sprint_hex(uid, 4));
484
485 UsbCommand c = {CMD_SIMULATE_MIFARE_CARD, {0, 0, 0}};
486 memcpy(c.d.asBytes, uid, 6);
487 SendCommand(&c);
488
489 return 0;
490}
491
492
7fe9b0b7 493int CmdHF14AReader(const char *Cmd)
494{
534983d7 495 UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}};
496 SendCommand(&c);
497 UsbCommand * resp = WaitForResponse(CMD_ACK);
498 uint8_t * uid = resp->d.asBytes;
499 iso14a_card_select_t * card = uid + 12;
500
501 if(resp->arg[0] == 0) {
502 PrintAndLog("iso14443a card select failed");
503 return 0;
504 }
505
506 PrintAndLog("ATQA : %02x %02x", card->atqa[0], card->atqa[1]);
507 PrintAndLog(" UID : %s", sprint_hex(uid, 12));
508 PrintAndLog(" SAK : %02x [%d]", card->sak, resp->arg[0]);
509 if(resp->arg[0] == 1)
510 PrintAndLog(" ATS : %s", sprint_hex(card->ats, card->ats_len));
511 else
512 PrintAndLog("proprietary non-iso14443a card found, RATS not supported");
513
514 return resp->arg[0];
7fe9b0b7 515}
516
517// ## simulate iso14443a tag
518// ## greg - added ability to specify tag UID
519int CmdHF14ASim(const char *Cmd)
520{
521
522 unsigned int hi = 0, lo = 0;
523 int n = 0, i = 0;
524 while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
525 hi= (hi << 4) | (lo >> 28);
526 lo= (lo << 4) | (n & 0xf);
527 }
528
529 // c.arg should be set to *Cmd or convert *Cmd to the correct format for a uid
530 UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a, {hi, lo, 0}};
531 PrintAndLog("Emulating 14443A TAG with UID %x%16x", hi, lo);
532 SendCommand(&c);
533 return 0;
534}
535
536int CmdHF14ASnoop(const char *Cmd)
537{
538 UsbCommand c = {CMD_SNOOP_ISO_14443a};
539 SendCommand(&c);
540 return 0;
541}
542
543static command_t CommandTable[] =
544{
4abe4f58
M
545 {"help", CmdHelp, 1, "This help"},
546 {"list", CmdHF14AList, 0, "List ISO 14443a history"},
547 {"mifare", CmdHF14AMifare, 0, "Read out sector 0 parity error messages"},
548 {"mfrdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"},
549 {"mfrdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"},
550 {"mfwrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"},
551 {"nested", CmdHF14AMfNested, 0, "Test nested authentication"},
552 {"mfsim", CmdHF14AMf1kSim, 0, "Simulate MIFARE 1k card - NOT WORKING!!!"},
553 {"reader", CmdHF14AReader, 0, "Act like an ISO14443 Type A reader"},
554 {"sim", CmdHF14ASim, 0, "<UID> -- Fake ISO 14443a tag"},
555 {"snoop", CmdHF14ASnoop, 0, "Eavesdrop ISO 14443 Type A"},
7fe9b0b7 556 {NULL, NULL, 0, NULL}
557};
558
559int CmdHF14A(const char *Cmd)
560{
561 CmdsParse(CommandTable, Cmd);
562 return 0;
563}
564
565int CmdHelp(const char *Cmd)
566{
567 CmdsHelp(CommandTable);
568 return 0;
569}
Impressum, Datenschutz