patch introduces -ETIMEDOUT as an error return code in case of
[librfid] / utils / librfid-tool.c
1 /*                                                 -*- linux-c -*-
2  *  This program is free software; you can redistribute it and/or modify
3  *  it under the terms of the GNU General Public License version 2 
4  *  as published by the Free Software Foundation
5  *
6  *  This program is distributed in the hope that it will be useful,
7  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
8  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9  *  GNU General Public License for more details.
10  *
11  *  You should have received a copy of the GNU General Public License
12  *  along with this program; if not, write to the Free Software
13  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
14  */
15
16 #include <stdio.h>
17 #include <unistd.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <errno.h>
21
22 #define _GNU_SOURCE
23 #include <getopt.h>
24
25 #include <librfid/rfid.h>
26 #include <librfid/rfid_reader.h>
27 #include <librfid/rfid_layer2.h>
28 #include <librfid/rfid_protocol.h>
29
30 #include <librfid/rfid_protocol_mifare_classic.h>
31 #include <librfid/rfid_protocol_mifare_ul.h>
32
33 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
34
35 static const char *
36 hexdump(const void *data, unsigned int len)
37 {
38         static char string[1024];
39         unsigned char *d = (unsigned char *) data;
40         unsigned int i, left;
41
42         string[0] = '\0';
43         left = sizeof(string);
44         for (i = 0; len--; i += 3) {
45                 if (i >= sizeof(string) -4)
46                         break;
47                 snprintf(string+i, 4, " %02x", *d++);
48         }
49         return string;
50 }
51
52 static struct rfid_reader_handle *rh;
53 static struct rfid_layer2_handle *l2h;
54 static struct rfid_protocol_handle *ph;
55
56 static int init()
57 {
58         unsigned char buf[0x3f];
59         int rc;
60
61         printf("initializing librfid\n");
62         rfid_init();
63
64         printf("opening reader handle\n");
65         rh = rfid_reader_open(NULL, RFID_READER_CM5121);
66         if (!rh) {
67                 fprintf(stderr, "error, no cm5121 handle\n");
68                 return -1;
69         }
70
71         printf("opening layer2 handle\n");
72         l2h = rfid_layer2_init(rh, RFID_LAYER2_ISO14443A);
73         //l2h = rfid_layer2_init(rh, RFID_LAYER2_ISO14443B);
74         if (!l2h) {
75                 fprintf(stderr, "error during iso14443a_init\n");
76                 return -1;
77         }
78
79         //rc632_register_dump(rh->ah, buf);
80
81         printf("running layer2 anticol\n");
82         rc = rfid_layer2_open(l2h);
83         if (rc < 0) {
84                 fprintf(stderr, "error during layer2_open\n");
85                 return rc;
86         }
87
88         return 0;
89 }
90
91 static int l3(int protocol)
92 {
93         printf("running layer3 (ats)\n");
94         ph = rfid_protocol_init(l2h, protocol);
95         if (!ph) {
96                 fprintf(stderr, "error during protocol_init\n");
97                 return -1;
98         }
99         if (rfid_protocol_open(ph) < 0) {
100                 fprintf(stderr, "error during protocol_open\n");
101                 return -1;
102         }
103
104         printf("we now have layer3 up and running\n");
105
106         return 0;
107 }
108
109 static int select_mf(void)
110 {
111         unsigned char cmd[] = { 0x00, 0xa4, 0x00, 0x00, 0x02, 0x3f, 0x00, 0x00 };
112         unsigned char ret[256];
113         unsigned int rlen = sizeof(ret);
114
115         int rv;
116
117         rv = rfid_protocol_transcieve(ph, cmd, sizeof(cmd), ret, &rlen, 0, 0);
118         if (rv < 0)
119                 return rv;
120
121         printf("%d: [%s]\n", rlen, hexdump(ret, rlen));
122
123         return 0;
124 }
125
126
127 static int iso7816_get_challenge(unsigned char len)
128 {
129         unsigned char cmd[] = { 0x00, 0x84, 0x00, 0x00, 0x08 };
130         unsigned char ret[256];
131         unsigned int rlen = sizeof(ret);
132
133         cmd[4] = len;
134
135         int rv;
136
137         rv = rfid_protocol_transcieve(ph, cmd, sizeof(cmd), ret, &rlen, 0, 0);
138         if (rv < 0)
139                 return rv;
140
141         printf("%d: [%s]\n", rlen, hexdump(ret, rlen));
142
143         return 0;
144 }
145
146 int
147 iso7816_select_application(void)
148 {
149         unsigned char cmd[] = { 0x00, 0xa4, 0x04, 0x0c, 0x07,
150                        0xa0, 0x00, 0x00, 0x02, 0x47, 0x10, 0x01 };
151         unsigned char resp[7];
152         unsigned int rlen = sizeof(resp);
153
154         int rv;
155
156         rv = rfid_protocol_transcieve(ph, cmd, sizeof(cmd), resp, &rlen, 0, 0);
157         if (rv < 0)
158                 return rv;
159
160         /* FIXME: parse response */
161         printf("%s\n", hexdump(resp, rlen));
162
163         return 0;
164 }
165
166 int
167 iso7816_select_ef(u_int16_t fid)
168 {
169         unsigned char cmd[7] = { 0x00, 0xa4, 0x02, 0x0c, 0x02, 0x00, 0x00 };
170         unsigned char resp[7];
171         unsigned int rlen = sizeof(resp);
172
173         int rv;
174
175         cmd[5] = (fid >> 8) & 0xff;
176         cmd[6] = fid & 0xff;
177
178         rv = rfid_protocol_transcieve(ph, cmd, sizeof(cmd), resp, &rlen, 0, 0);
179         if (rv < 0)
180                 return rv;
181
182         /* FIXME: parse response */
183         printf("%s\n", hexdump(resp, rlen));
184
185         return 0;
186 }
187
188 int
189 iso7816_read_binary(unsigned char *buf, unsigned int *len)
190 {
191         unsigned char cmd[] = { 0x00, 0xb0, 0x00, 0x00, 0x00 };
192         unsigned char resp[256];
193         unsigned int rlen = sizeof(resp);
194         
195         int rv;
196
197         rv = rfid_protocol_transcieve(ph, cmd, sizeof(cmd), resp, &rlen, 0, 0);
198         if (rv < 0)
199                 return rv;
200
201         printf("%s\n", hexdump(resp, rlen));
202
203         /* FIXME: parse response, determine whether we need additional reads */
204
205         /* FIXME: copy 'len' number of response bytes to 'buf' */
206         return 0;
207 }
208
209 /* wrapper function around SELECT EF and READ BINARY */
210 int
211 iso7816_read_ef(u_int16_t fid, unsigned char *buf, unsigned int *len)
212 {
213         int rv;
214
215         rv = iso7816_select_ef(fid);
216         if (rv < 0)
217                 return rv;
218
219         return iso7816_read_binary(buf, len);
220 }
221
222 /* mifare ultralight helpers */
223 int
224 mifare_ulight_write(struct rfid_protocol_handle *ph)
225 {
226         unsigned char buf[4] = { 0xa1, 0xa2, 0xa3, 0xa4 };
227
228         return rfid_protocol_write(ph, 10, buf, 4);
229 }
230
231 int
232 mifare_ulight_blank(struct rfid_protocol_handle *ph)
233 {
234         unsigned char buf[4] = { 0x00, 0x00, 0x00, 0x00 };
235         int i, ret;
236
237         for (i = 4; i <= MIFARE_UL_PAGE_MAX; i++) {
238                 ret = rfid_protocol_write(ph, i, buf, 4);
239                 if (ret < 0)
240                         return ret;
241         }
242         return 0;
243 }
244
245 static int
246 mifare_ulight_read(struct rfid_protocol_handle *ph)
247 {
248         unsigned char buf[20];
249         unsigned int len = sizeof(buf);
250         int ret;
251         int i;
252
253         for (i = 0; i <= MIFARE_UL_PAGE_MAX; i++) {
254                 ret = rfid_protocol_read(ph, i, buf, &len);
255                 if (ret < 0)
256                         return ret;
257
258                 printf("Page 0x%x: %s\n", i, hexdump(buf, 4));
259         }
260         return 0;
261 }
262
263 /* mifare classic helpers */
264 static int
265 mifare_classic_read_sector(struct rfid_protocol_handle *ph, int sector)
266 {
267         unsigned char buf[20];
268         unsigned int len = sizeof(buf);
269         int ret;
270         int block;
271
272         /* FIXME: make this work for sectors > 31 */
273         printf("reading sector %u\n", sector);
274
275         for (block = sector*4; block < sector*4+4; block++) {
276                 printf("reading block %u\n", block);
277                 ret = rfid_protocol_read(ph, block, buf, &len);
278                 if(ret == -ETIMEDOUT)
279                         fprintf(stderr, "TIMEOUT\n");
280                 if (ret < 0)
281                         return ret;
282
283                 printf("Page 0x%x: %s\n", block, hexdump(buf, len));
284         }
285         return 0;
286 }
287
288 static char *proto_names[] = {
289         [RFID_PROTOCOL_TCL] = "tcl",
290         [RFID_PROTOCOL_MIFARE_UL] = "mifare-ultralight",
291         [RFID_PROTOCOL_MIFARE_CLASSIC] = "mifare-classic",
292 };
293
294 static int proto_by_name(const char *name)
295 {
296         int i;
297
298         for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
299                 if (proto_names[i] == NULL)
300                         continue;
301                 if (!strcasecmp(name, proto_names[i]))
302                         return i;
303         }
304         return -1;
305 }
306
307 static void help(void)
308 {
309         printf(" -p     --protocol {tcl,mifare-ultralight,mifare-classic}\n");
310 }
311
312 static struct option opts[] = {
313         { "help", 0, 0, 'h' },
314         { "protocol", 1, 0, 'p' },
315         {0, 0, 0, 0}
316 };
317
318 int main(int argc, char **argv)
319 {
320         int rc;
321         char buf[0x40];
322         int i, protocol = -1;
323         
324         printf("librfid_tool - (C) 2006 by Harald Welte\n"
325                "This program is Free Software and has ABSOLUTELY NO WARRANTY\n\n");
326
327         while (1) {
328                 int c, option_index = 0;
329                 c = getopt_long(argc, argv, "hp:", opts, &option_index);
330                 if (c == -1)
331                         break;
332
333                 switch (c) {
334                 case 'p':
335                         protocol = proto_by_name(optarg);
336                         if (protocol < 0) {
337                                 fprintf(stderr, "unknown protocol `%s'\n", optarg);
338                                 exit(2);
339                         }
340                         break;
341                 case 'h':
342                         help();
343                         exit(0);
344                         break;
345                 }
346         }
347
348         if (protocol < 0) {
349                 fprintf(stderr, "you have to specify --protocol\n");
350                 exit(2);
351         }
352
353         if (init() < 0)
354                 exit(1);
355
356         if (l3(protocol) < 0)
357                 exit(1);
358
359         switch (protocol) {
360                 char buf[32000];
361                 int len = 200;
362
363         case RFID_PROTOCOL_TCL:
364                 printf("Protocol T=CL\n");
365                 /* we've established T=CL at this point */
366                 printf("selecting Master File\n");
367                 rc = select_mf();
368                 if (rc < 0) {
369                         printf("error selecting MF\n");
370                         break;
371                 }
372
373                 printf("Getting random challenge, length 255\n");
374                 rc = iso7816_get_challenge(0xff);
375                 if (rc < 0) {
376                         printf("error getting random challenge\n");
377                         break;
378                 }
379
380                 printf("selecting Passport application\n");
381                 rc = iso7816_select_application();
382                 if (rc < 0) {
383                         printf("error selecting passport application\n");
384                         break;
385                 }
386
387                 printf("selecting EF 0x1e\n");
388                 rc = iso7816_select_ef(0x011e);
389                 if (rc < 0) {
390                         printf("error selecting EF 0x1e\n");
391                         break;
392                 }
393
394                 printf("selecting EF 0x01\n");
395                 rc = iso7816_select_ef(0x0101);
396                 if (rc < 0) {
397                         printf("error selecting EF 0x01\n");
398                         break;
399                 }
400
401                 while (1) {
402                         printf("reading EF1\n");
403                         len = 200;
404                         printf("reading ef\n");
405                         rc = iso7816_read_binary(buf, &len);
406                         if (rc < 0) {
407                                 printf("error reading EF\n");
408                                 break;
409                         }
410                 }
411 #if 0
412                 for (i = 0; i < 4; i++)
413                         iso7816_get_challenge(0xff);
414 #endif
415                 break;
416         case RFID_PROTOCOL_MIFARE_UL:
417                 printf("Protocol Mifare Ultralight\n");
418                 mifare_ulight_read(ph);
419 #if 0
420                 mifare_ulight_blank(ph);
421                 mifare_ulight_write(ph);
422                 mifare_ulight_read(ph);
423 #endif
424                 break;
425         case RFID_PROTOCOL_MIFARE_CLASSIC:
426                 printf("Protocol Mifare Classic\n");
427                 {
428                         int sector;
429                         for (sector = 1; sector < 31; sector++) {
430                                 rc = mfcl_set_key(ph, MIFARE_CL_KEYA_DEFAULT_INFINEON);
431                                 if (rc < 0) {
432                                         printf("key format error\n");
433                                         exit(1);
434                                 }
435                                 rc = mfcl_auth(ph, RFID_CMD_MIFARE_AUTH1A, sector*4);
436                                 if (rc < 0) {
437                                         printf("mifare auth error\n");
438                                         exit(1);
439                                 } else 
440                                         printf("mifare authe succeeded!\n");
441
442                                 mifare_classic_read_sector(ph, sector);
443                         }
444                 }
445                 break;
446         default:
447                 printf("unknown protocol\n");
448                 exit(1);
449                 break;
450         }
451
452         rfid_reader_close(rh);
453         
454         exit(0);
455 }