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