]> git.zerfleddert.de Git - proxmark3-svn/blob - client/cmdhf14a.c
iso14a reader patches [Hagen Fritsch]
[proxmark3-svn] / client / cmdhf14a.c
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch
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
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include "iso14443crc.h"
15 #include "data.h"
16 #include "proxusb.h"
17 #include "ui.h"
18 #include "cmdparser.h"
19 #include "cmdhf14a.h"
20 #include "common.h"
21
22 static int CmdHelp(const char *Cmd);
23
24 int CmdHF14AList(const char *Cmd)
25 {
26 uint8_t got[1920];
27 GetFromBigBuf(got, sizeof(got));
28
29 PrintAndLog("recorded activity:");
30 PrintAndLog(" ETU :rssi: who bytes");
31 PrintAndLog("---------+----+----+-----------");
32
33 int i = 0;
34 int prev = -1;
35
36 for (;;) {
37 if(i >= 1900) {
38 break;
39 }
40
41 bool isResponse;
42 int timestamp = *((uint32_t *)(got+i));
43 if (timestamp & 0x80000000) {
44 timestamp &= 0x7fffffff;
45 isResponse = 1;
46 } else {
47 isResponse = 0;
48 }
49
50 int metric = 0;
51 int parityBits = *((uint32_t *)(got+i+4));
52 // 4 bytes of additional information...
53 // maximum of 32 additional parity bit information
54 //
55 // TODO:
56 // at each quarter bit period we can send power level (16 levels)
57 // or each half bit period in 256 levels.
58
59
60 int len = got[i+8];
61
62 if (len > 100) {
63 break;
64 }
65 if (i + len >= 1900) {
66 break;
67 }
68
69 uint8_t *frame = (got+i+9);
70
71 // Break and stick with current result if buffer was not completely full
72 if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }
73
74 char line[1000] = "";
75 int j;
76 for (j = 0; j < len; j++) {
77 int oddparity = 0x01;
78 int k;
79
80 for (k=0;k<8;k++) {
81 oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
82 }
83
84 //if((parityBits >> (len - j - 1)) & 0x01) {
85 if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
86 sprintf(line+(j*4), "%02x! ", frame[j]);
87 }
88 else {
89 sprintf(line+(j*4), "%02x ", frame[j]);
90 }
91 }
92
93 char *crc;
94 crc = "";
95 if (len > 2) {
96 uint8_t b1, b2;
97 for (j = 0; j < (len - 1); j++) {
98 // gives problems... search for the reason..
99 /*if(frame[j] == 0xAA) {
100 switch(frame[j+1]) {
101 case 0x01:
102 crc = "[1] Two drops close after each other";
103 break;
104 case 0x02:
105 crc = "[2] Potential SOC with a drop in second half of bitperiod";
106 break;
107 case 0x03:
108 crc = "[3] Segment Z after segment X is not possible";
109 break;
110 case 0x04:
111 crc = "[4] Parity bit of a fully received byte was wrong";
112 break;
113 default:
114 crc = "[?] Unknown error";
115 break;
116 }
117 break;
118 }*/
119 }
120
121 if (strlen(crc)==0) {
122 ComputeCrc14443(CRC_14443_A, frame, len-2, &b1, &b2);
123 if (b1 != frame[len-2] || b2 != frame[len-1]) {
124 crc = (isResponse & (len < 6)) ? "" : " !crc";
125 } else {
126 crc = "";
127 }
128 }
129 } else {
130 crc = ""; // SHORT
131 }
132
133 char metricString[100];
134 if (isResponse) {
135 sprintf(metricString, "%3d", metric);
136 } else {
137 strcpy(metricString, " ");
138 }
139
140 PrintAndLog(" +%7d: %s: %s %s %s",
141 (prev < 0 ? 0 : (timestamp - prev)),
142 metricString,
143 (isResponse ? "TAG" : " "), line, crc);
144
145 prev = timestamp;
146 i += (len + 9);
147 }
148 return 0;
149 }
150
151 void iso14a_set_timeout(uint32_t timeout) {
152 UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_SET_TIMEOUT, 0, timeout}};
153 SendCommand(&c);
154 }
155
156 int CmdHF14AMifare(const char *Cmd)
157 {
158 UsbCommand c = {CMD_READER_MIFARE, {strtol(Cmd, NULL, 0), 0, 0}};
159 SendCommand(&c);
160 return 0;
161 }
162
163 int CmdHF14AReader(const char *Cmd)
164 {
165 UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}};
166 SendCommand(&c);
167 UsbCommand * resp = WaitForResponse(CMD_ACK);
168 uint8_t * uid = resp->d.asBytes;
169 iso14a_card_select_t * card = uid + 12;
170
171 if(resp->arg[0] == 0) {
172 PrintAndLog("iso14443a card select failed");
173 return 0;
174 }
175
176 PrintAndLog("ATQA : %02x %02x", card->atqa[0], card->atqa[1]);
177 PrintAndLog(" UID : %s", sprint_hex(uid, 12));
178 PrintAndLog(" SAK : %02x [%d]", card->sak, resp->arg[0]);
179 if(resp->arg[0] == 1)
180 PrintAndLog(" ATS : %s", sprint_hex(card->ats, card->ats_len));
181 else
182 PrintAndLog("proprietary non-iso14443a card found, RATS not supported");
183
184 return resp->arg[0];
185 }
186
187 // ## simulate iso14443a tag
188 // ## greg - added ability to specify tag UID
189 int CmdHF14ASim(const char *Cmd)
190 {
191
192 unsigned int hi = 0, lo = 0;
193 int n = 0, i = 0;
194 while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
195 hi= (hi << 4) | (lo >> 28);
196 lo= (lo << 4) | (n & 0xf);
197 }
198
199 // c.arg should be set to *Cmd or convert *Cmd to the correct format for a uid
200 UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a, {hi, lo, 0}};
201 PrintAndLog("Emulating 14443A TAG with UID %x%16x", hi, lo);
202 SendCommand(&c);
203 return 0;
204 }
205
206 int CmdHF14ASnoop(const char *Cmd)
207 {
208 UsbCommand c = {CMD_SNOOP_ISO_14443a};
209 SendCommand(&c);
210 return 0;
211 }
212
213 static command_t CommandTable[] =
214 {
215 {"help", CmdHelp, 1, "This help"},
216 {"list", CmdHF14AList, 0, "List ISO 14443a history"},
217 {"mifare", CmdHF14AMifare, 0, "Read out sector 0 parity error messages"},
218 {"reader", CmdHF14AReader, 0, "Act like an ISO14443 Type A reader"},
219 {"sim", CmdHF14ASim, 0, "<UID> -- Fake ISO 14443a tag"},
220 {"snoop", CmdHF14ASnoop, 0, "Eavesdrop ISO 14443 Type A"},
221 {NULL, NULL, 0, NULL}
222 };
223
224 int CmdHF14A(const char *Cmd)
225 {
226 CmdsParse(CommandTable, Cmd);
227 return 0;
228 }
229
230 int CmdHelp(const char *Cmd)
231 {
232 CmdsHelp(CommandTable);
233 return 0;
234 }
Impressum, Datenschutz