- fix mifare write support
[librfid] / utils / librfid-tool.c
1 /* librfid-tool - a small command-line tool for librfid testing
2  *
3  * (C) 2005-2006 by Harald Welte <laforge@gnumonks.org>
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License version 2 
7  *  as published by the Free Software Foundation
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #include <stdio.h>
20 #include <unistd.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <libgen.h>
25
26 #define _GNU_SOURCE
27 #include <getopt.h>
28
29 #include <librfid/rfid.h>
30 #include <librfid/rfid_scan.h>
31 #include <librfid/rfid_reader.h>
32 #include <librfid/rfid_layer2.h>
33 #include <librfid/rfid_protocol.h>
34
35 #include <librfid/rfid_protocol_mifare_classic.h>
36 #include <librfid/rfid_protocol_mifare_ul.h>
37
38 #include "librfid-tool.h"
39
40
41 static int select_mf(void)
42 {
43         unsigned char cmd[] = { 0x00, 0xa4, 0x00, 0x00, 0x02, 0x3f, 0x00, 0x00 };
44         unsigned char ret[256];
45         unsigned int rlen = sizeof(ret);
46
47         int rv;
48
49         rv = rfid_protocol_transceive(ph, cmd, sizeof(cmd), ret, &rlen, 0, 0);
50         if (rv < 0)
51                 return rv;
52
53         printf("%d: [%s]\n", rlen, hexdump(ret, rlen));
54
55         return 0;
56 }
57
58
59 static int iso7816_get_challenge(unsigned char len)
60 {
61         unsigned char cmd[] = { 0x00, 0x84, 0x00, 0x00, 0x08 };
62         unsigned char ret[256];
63         unsigned int rlen = sizeof(ret);
64
65         cmd[4] = len;
66
67         int rv;
68
69         rv = rfid_protocol_transceive(ph, cmd, sizeof(cmd), ret, &rlen, 0, 0);
70         if (rv < 0)
71                 return rv;
72
73         printf("%d: [%s]\n", rlen, hexdump(ret, rlen));
74
75         return 0;
76 }
77
78 int
79 iso7816_select_application(void)
80 {
81         unsigned char cmd[] = { 0x00, 0xa4, 0x04, 0x0c, 0x07,
82                        0xa0, 0x00, 0x00, 0x02, 0x47, 0x10, 0x01 };
83         unsigned char resp[7];
84         unsigned int rlen = sizeof(resp);
85
86         int rv;
87
88         rv = rfid_protocol_transceive(ph, cmd, sizeof(cmd), resp, &rlen, 0, 0);
89         if (rv < 0)
90                 return rv;
91
92         /* FIXME: parse response */
93         printf("%s\n", hexdump(resp, rlen));
94
95         return 0;
96 }
97
98 int
99 iso7816_select_ef(u_int16_t fid)
100 {
101         unsigned char cmd[7] = { 0x00, 0xa4, 0x02, 0x0c, 0x02, 0x00, 0x00 };
102         unsigned char resp[7];
103         unsigned int rlen = sizeof(resp);
104
105         int rv;
106
107         cmd[5] = (fid >> 8) & 0xff;
108         cmd[6] = fid & 0xff;
109
110         rv = rfid_protocol_transceive(ph, cmd, sizeof(cmd), resp, &rlen, 0, 0);
111         if (rv < 0)
112                 return rv;
113
114         /* FIXME: parse response */
115         printf("%s\n", hexdump(resp, rlen));
116
117         return 0;
118 }
119
120 int
121 iso7816_read_binary(unsigned char *buf, unsigned int *len)
122 {
123         unsigned char cmd[] = { 0x00, 0xb0, 0x00, 0x00, 0x00 };
124         unsigned char resp[256];
125         unsigned int rlen = sizeof(resp);
126         
127         int rv;
128
129         rv = rfid_protocol_transceive(ph, cmd, sizeof(cmd), resp, &rlen, 0, 0);
130         if (rv < 0)
131                 return rv;
132
133         printf("%s\n", hexdump(resp, rlen));
134
135         /* FIXME: parse response, determine whether we need additional reads */
136
137         /* FIXME: copy 'len' number of response bytes to 'buf' */
138         return 0;
139 }
140
141 /* wrapper function around SELECT EF and READ BINARY */
142 int
143 iso7816_read_ef(u_int16_t fid, unsigned char *buf, unsigned int *len)
144 {
145         int rv;
146
147         rv = iso7816_select_ef(fid);
148         if (rv < 0)
149                 return rv;
150
151         return iso7816_read_binary(buf, len);
152 }
153
154 /* mifare ultralight helpers */
155 int
156 mifare_ulight_write(struct rfid_protocol_handle *ph)
157 {
158         unsigned char buf[4] = { 0xa1, 0xa2, 0xa3, 0xa4 };
159
160         return rfid_protocol_write(ph, 10, buf, 4);
161 }
162
163 int
164 mifare_ulight_blank(struct rfid_protocol_handle *ph)
165 {
166         unsigned char buf[4] = { 0x00, 0x00, 0x00, 0x00 };
167         int i, ret;
168
169         for (i = 4; i <= MIFARE_UL_PAGE_MAX; i++) {
170                 ret = rfid_protocol_write(ph, i, buf, 4);
171                 if (ret < 0)
172                         return ret;
173         }
174         return 0;
175 }
176
177 static int
178 mifare_ulight_read(struct rfid_protocol_handle *ph)
179 {
180         unsigned char buf[20];
181         unsigned int len = sizeof(buf);
182         int ret;
183         int i;
184
185         for (i = 0; i <= MIFARE_UL_PAGE_MAX; i++) {
186                 ret = rfid_protocol_read(ph, i, buf, &len);
187                 if (ret < 0)
188                         return ret;
189
190                 printf("Page 0x%x: %s\n", i, hexdump(buf, 4));
191         }
192         return 0;
193 }
194
195 /* mifare classic helpers */
196 static int
197 mifare_classic_read_sector(struct rfid_protocol_handle *ph, int sector)
198 {
199         unsigned char buf[20];
200         unsigned int len = sizeof(buf);
201         int ret;
202         int block;
203
204         /* FIXME: make this work for sectors > 31 */
205         printf("Reading sector %u\n", sector);
206
207         for (block = sector*4; block < sector*4+4; block++) {
208                 printf("Reading block %u: ", block);
209                 ret = rfid_protocol_read(ph, block, buf, &len);
210                 if(ret == -ETIMEDOUT)
211                         fprintf(stderr, "TIMEOUT\n");
212                 if (ret < 0) {
213                         printf("Error %d reading\n", ret);
214                         return ret;
215                 }
216
217                 printf("Page 0x%x: %s\n", block, hexdump(buf, len));
218         }
219         return 0;
220 }
221
222 static char *proto_names[] = {
223         [RFID_PROTOCOL_TCL] = "tcl",
224         [RFID_PROTOCOL_MIFARE_UL] = "mifare-ultralight",
225         [RFID_PROTOCOL_MIFARE_CLASSIC] = "mifare-classic",
226 };
227
228 static int proto_by_name(const char *name)
229 {
230         int i;
231
232         for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
233                 if (proto_names[i] == NULL)
234                         continue;
235                 if (!strcasecmp(name, proto_names[i]))
236                         return i;
237         }
238         return -1;
239 }
240
241 static char *l2_names[] = {
242         [RFID_LAYER2_ISO14443A] = "iso14443a",
243         [RFID_LAYER2_ISO14443B] = "iso14443b",
244         [RFID_LAYER2_ISO15693] = "iso15693",
245 };
246
247 static int l2_by_name(const char *name)
248 {
249         int i;
250
251         for (i = 0; i < ARRAY_SIZE(l2_names); i++) {
252                 if (l2_names[i] == NULL)
253                         continue;
254                 if (!strcasecmp(name, l2_names[i]))
255                         return i;
256         }
257         return -1;
258 }
259
260 static void do_scan(void)
261 {
262         int rc;
263         printf("scanning for RFID token...\n");
264         rc = rfid_scan(rh, &l2h, &ph);
265         if (rc >= 2) {
266                 unsigned char uid_buf[16];
267                 unsigned int uid_len = sizeof(uid_buf);
268                 rfid_layer2_getopt(l2h, RFID_OPT_LAYER2_UID, &uid_buf,
269                                    &uid_len);
270                 printf("Layer 2 success (%s): %s\n", rfid_layer2_name(l2h),
271                         hexdump(uid_buf, uid_len));
272         }
273         if (rc >= 3) {
274                 printf("Protocol success (%s)\n", rfid_protocol_name(ph));
275         }
276 }
277
278 #define OPTION_OFFSET 256
279
280 static struct option original_opts[] = {
281         { "help", 0, 0, 'h' },
282         { "layer2", 1, 0, 'l' },
283         { "protocol", 1, 0, 'p' },
284         { "scan", 0, 0, 's' },
285         { "scan-loop", 0, 0, 'S' },
286         {0, 0, 0, 0}
287 };
288
289 /* module / option merging code */
290 static struct option *opts = original_opts;
291 static unsigned int global_option_offset = 0;
292
293 static char *program_name;
294 static char *program_version = LIBRFID_TOOL_VERSION;
295
296 static void free_opts(int reset_offset)
297 {
298         if (opts != original_opts) {
299                 free(opts);
300                 opts = original_opts;
301                 if (reset_offset)
302                         global_option_offset = 0;
303         }
304 }
305
306 static struct option *
307 merge_options(struct option *oldopts, const struct option *newopts,
308               unsigned int *option_offset)
309 {
310         unsigned int num_old, num_new, i;
311         struct option *merge;
312
313         for (num_old = 0; oldopts[num_old].name; num_old++);
314         for (num_new = 0; oldopts[num_new].name; num_new++);
315
316         global_option_offset += OPTION_OFFSET;
317         *option_offset = global_option_offset;
318
319         merge = malloc(sizeof(struct option) * (num_new + num_old + 1));
320         memcpy(merge, oldopts, num_old * sizeof(struct option));
321         free_opts(0); /* Release previous options merged if any */
322         for (i = 0; i < num_new; i++) {
323                 merge[num_old + i] = newopts[i];
324                 merge[num_old + i].val += *option_offset;
325         }
326         memset(merge + num_old + num_new, 0, sizeof(struct option));
327
328         return merge;
329 }
330
331 struct rfidtool_module *find_module(const char *name)
332 {
333         return NULL;
334 }
335
336 void register_module(struct rfidtool_module *me)
337 {
338         struct rfidtool_module *old;
339
340         if (strcmp(me->version, program_version) != 0) {
341                 fprintf(stderr, "%s: target `%s' v%s (I'm v%s).\n",
342                         program_name, me->name, me->version, program_version);
343                 exit(1);
344         }
345
346         old = find_module(me->name);
347         if (old) {
348                 fprintf(stderr, "%s: target `%s' already registere.\n",
349                         program_name, me->name);
350                 exit(1);
351         }
352 }
353
354 static void help(void)
355 {
356         printf( " -s    --scan          scan until first RFID tag is found\n"
357                 " -S    --scan-loop     endless scanning loop\n" 
358                 " -p    --protocol      {tcl,mifare-ultralight,mifare-classic}\n"
359                 " -l    --layer2        {iso14443a,iso14443b,iso15693}\n"
360                 " -h    --help\n");
361 }
362
363 int main(int argc, char **argv)
364 {
365         int rc;
366         char buf[0x40];
367         int i, protocol = -1, layer2 = -1;
368
369         program_name = basename(argv[0]);
370         
371         printf("%s - (C) 2006 by Harald Welte\n"
372                "This program is Free Software and has "
373                "ABSOLUTELY NO WARRANTY\n\n", program_name);
374
375         printf("initializing librfid\n");
376         rfid_init();
377
378         while (1) {
379                 int c, option_index = 0;
380                 c = getopt_long(argc, argv, "hp:l:sS", opts, &option_index);
381                 if (c == -1)
382                         break;
383
384                 switch (c) {
385                 case 's':
386                         if (reader_init() < 0)
387                                 exit(1);
388                         do_scan();
389                         exit(0);
390                         break;
391                 case 'S':
392                         if (reader_init() < 0)
393                                 exit(1);
394                         while (1) 
395                                 do_scan();
396                         exit(0);
397                         break;
398                 case 'p':
399                         protocol = proto_by_name(optarg);
400                         if (protocol < 0) {
401                                 fprintf(stderr, "unknown protocol `%s'\n", 
402                                         optarg);
403                                 exit(2);
404                         }
405                         break;
406                 case 'l':
407                         layer2 = l2_by_name(optarg);
408                         if (layer2 < 0) {
409                                 fprintf(stderr, "unknown layer2 `%s'\n",
410                                         optarg);
411                                 exit(2);
412                         }
413                         break;
414                 case 'h':
415                         help();
416                         exit(0);
417                         break;
418                 }
419         }
420
421         switch (protocol) {
422         case RFID_PROTOCOL_MIFARE_UL:
423         case RFID_PROTOCOL_MIFARE_CLASSIC:
424                 layer2 = RFID_LAYER2_ISO14443A;
425                 break;
426         case -1:
427                 fprintf(stderr, "you have to specify --protocol\n");
428                 exit(2);
429         }
430
431         if (layer2 < 0) {
432                 fprintf(stderr, "you have to specify --layer2\n");
433                 exit(2);
434         }
435         
436         if (reader_init() < 0)
437                 exit(1);
438
439         if (l2_init(layer2) < 0)
440                 exit(1);
441
442         if (l3_init(protocol) < 0)
443                 exit(1);
444
445         switch (protocol) {
446                 char buf[32000];
447                 int len = 200;
448
449         case RFID_PROTOCOL_TCL:
450                 printf("Protocol T=CL\n");
451                 /* we've established T=CL at this point */
452                 printf("selecting Master File\n");
453                 rc = select_mf();
454                 if (rc < 0) {
455                         printf("error selecting MF\n");
456                         break;
457                 }
458
459                 printf("Getting random challenge, length 255\n");
460                 rc = iso7816_get_challenge(0xff);
461                 if (rc < 0) {
462                         printf("error getting random challenge\n");
463                         break;
464                 }
465
466                 printf("selecting Passport application\n");
467                 rc = iso7816_select_application();
468                 if (rc < 0) {
469                         printf("error selecting passport application\n");
470                         break;
471                 }
472
473                 printf("selecting EF 0x1e\n");
474                 rc = iso7816_select_ef(0x011e);
475                 if (rc < 0) {
476                         printf("error selecting EF 0x1e\n");
477                         break;
478                 }
479
480                 printf("selecting EF 0x01\n");
481                 rc = iso7816_select_ef(0x0101);
482                 if (rc < 0) {
483                         printf("error selecting EF 0x01\n");
484                         break;
485                 }
486
487                 while (1) {
488                         printf("reading EF1\n");
489                         len = 200;
490                         printf("reading ef\n");
491                         rc = iso7816_read_binary(buf, &len);
492                         if (rc < 0) {
493                                 printf("error reading EF\n");
494                                 break;
495                         }
496                 }
497 #if 0
498                 for (i = 0; i < 4; i++)
499                         iso7816_get_challenge(0xff);
500 #endif
501                 break;
502         case RFID_PROTOCOL_MIFARE_UL:
503                 printf("Protocol Mifare Ultralight\n");
504                 mifare_ulight_read(ph);
505 #if 0
506                 mifare_ulight_blank(ph);
507                 mifare_ulight_write(ph);
508                 mifare_ulight_read(ph);
509 #endif
510                 break;
511         case RFID_PROTOCOL_MIFARE_CLASSIC:
512                 printf("Protocol Mifare Classic\n");
513                 {
514                         int sector;
515                         for (sector = 0; sector < 31; sector++) {
516                                 printf("Authenticating sector %u: ", sector);
517                                 fflush(stdout);
518                                 rc = mfcl_set_key(ph, MIFARE_CL_KEYA_DEFAULT_INFINEON);
519                                 if (rc < 0) {
520                                         printf("key format error\n");
521                                         exit(1);
522                                 }
523                                 rc = mfcl_auth(ph, RFID_CMD_MIFARE_AUTH1A, sector*4);
524                                 if (rc < 0) {
525                                         printf("mifare auth error\n");
526                                         exit(1);
527                                 } else 
528                                         printf("mifare auth succeeded!\n");
529
530                                 mifare_classic_read_sector(ph, sector);
531                         }
532                 }
533                 break;
534         default:
535                 printf("unknown protocol\n");
536                 exit(1);
537                 break;
538         }
539
540         rfid_reader_close(rh);
541         
542         exit(0);
543 }