121170f9c0dafa9da84f03faac256af59fc0adde
[rfid/librfid.git] / gemtag / gemtag.c
1 /*
2  *  (C) 2006 by Frank Zirkelbach <hackbard@hackdaworld.org>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License version 2 
6  *  as published by the Free Software Foundation
7  *
8  *  This program is distributed in the hope that it will be useful,
9  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  *  GNU General Public License for more details.
12  *
13  *  You should have received a copy of the GNU General Public License
14  *  along with this program; if not, write to the Free Software
15  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16  */
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <string.h>
22 #include <errno.h>
23
24 #include <usb.h>
25 #include "gemtag.h"
26
27 int asciidump(unsigned char *data,int len) {
28         int i;
29
30         for(i=0;i<len;i++)
31                 if((data[i]>0x19)&&(data[i]<0x7f)) printf("%c",data[i]);
32                 else printf(".");
33         //printf("\n");
34
35         return 0;
36 }
37
38 int hexdump(unsigned char *data,int len) {
39         int i;
40
41         for(i=0;i<len;i++) printf("%02x ",data[i]);
42         //printf("\n");
43
44         return 0;
45 }
46
47 struct usb_device *find_device(unsigned short vendor,unsigned short device) {
48         
49         struct usb_bus *bus;
50         struct usb_device *dev;
51
52         bus=usb_get_busses();
53         while(bus) {
54                 dev=bus->devices;
55                 while(dev) {
56                         if(dev->descriptor.idVendor==vendor &&
57                            dev->descriptor.idProduct==device)
58                                 return dev;
59                         dev=dev->next;
60                 }
61                 bus=bus->next;
62         }
63         return NULL;
64 }
65
66 u_int16_t gemtag_calc_crc(unsigned char *data,u_int16_t len) {
67
68         u_int16_t crc_polynom;
69         u_int16_t crc_preset;
70         u_int16_t crc;
71         int i,j;
72                 
73         crc_polynom=0x8408;
74         crc_preset=0xffff;
75         crc=0xffff;
76
77         for(i=0;i<len;i++) {
78                 crc^=data[i];
79                 for(j=0;j<8;j++) {
80                         if(crc&0x0001)
81                                 crc=(crc>>1)^crc_polynom;
82                         else
83                                 crc=(crc>>1);
84                 }
85         }
86         return crc;
87 }
88
89 int gemtag_transceive(struct gemtag_handle *gh,unsigned char cmd,
90                       unsigned char *tx,unsigned int tx_len,
91                       unsigned char *rx,unsigned int *rx_len) {
92
93         unsigned char txbuf[256];
94         unsigned char rxbuf[256];
95         struct gemtag_cmd_hdr *txhdr;
96         struct gemtag_cmd_hdr *rxhdr;
97         u_int16_t crc,*crcptr;
98         int i,ret,size,rest;
99
100         txhdr=(struct gemtag_cmd_hdr *)txbuf;
101         rxhdr=(struct gemtag_cmd_hdr *)rxbuf;
102
103         txhdr->start=0xa5;
104         txhdr->seq=++(gh->seq);
105         txhdr->cmd=cmd;
106         txhdr->len=tx_len;
107         size=sizeof(struct gemtag_cmd_hdr);
108         memcpy(txbuf+size,tx,tx_len);
109         size+=tx_len;
110
111         /* crc check */
112         if(gh->caps&GEMTAG_CAP_CRC) {
113                 crcptr=(u_int16_t *)(txbuf+size);
114                 crc=gemtag_calc_crc(txbuf,size);
115                 //*crcptr=(crc>>8)|(crc<<8);
116                 *crcptr=crc;
117                 size+=2;
118         }
119
120         /* usb write */
121         if(gh->caps&GEMTAG_CAP_VERB_TRANSMIT) {
122                 printf("(%02d) -> ",size);
123                 hexdump(txbuf,size);
124         }
125         ret=usb_interrupt_write(gh->handle,0x02,txbuf,size,0);
126         if(ret<=0) {
127                 perror("usb interrupt write");
128                 return ret;
129         }
130
131         /* usb read */
132         ret=usb_interrupt_read(gh->handle,0x81,rxbuf,32,0);
133         if(ret<=0) {
134                 perror("usb interrupt read");
135                 return ret;
136         }
137         if(ret<5) {
138                 if(gh->caps&GEMTAG_CAP_VERB_TRANSMIT)
139                         return -SHORT_ANSWER;
140         }
141
142         *rx_len=rxbuf[3]|(rxbuf[4]<<8);
143         size=*rx_len+sizeof(struct gemtag_cmd_hdr); 
144         if(gh->caps&GEMTAG_CAP_CRC) size+=2;
145
146         i=1;
147         rest=size-ret;
148         while(rest>=0) {
149                 ret=usb_interrupt_read(gh->handle,0x81,rxbuf+i*32,32,0);
150                 if(ret<=0) {
151                         perror("usb interrupt read (missing bytes)");
152                         return ret;
153                 }
154                 i++;
155                 rest-=ret;
156         }
157
158         if(gh->caps&GEMTAG_CAP_VERB_TRANSMIT) {
159                 printf("(%02d) <- ",size);
160                 hexdump(rxbuf,size);
161         }
162
163         /* crc check */
164         if(gh->caps&GEMTAG_CAP_CRC) {
165                 size-=2;
166                 crcptr=(u_int16_t *)(rxbuf+size);
167                 crc=gemtag_calc_crc(rxbuf,size);
168                 if(((crc>>8)!=rxbuf[size+1])||((crc&0xff)!=rxbuf[size]))
169                         return -BAD_CRC;
170         }
171
172         /* check sequence number */     
173         if(rxhdr->seq!=txhdr->seq) return -SEQ_MISMATCH;
174
175         /* check return code */
176         if(rxbuf[2]) return -CMD_FAILED;
177
178         memcpy(rx,rxbuf+sizeof(struct gemtag_cmd_hdr),*rx_len);
179
180         return 0;
181 }
182
183 struct gemtag_handle *gemtag_open(void) {
184         struct usb_device *gemtag;
185         unsigned int i;
186         struct gemtag_handle *gh;
187         char info[64];
188
189         usb_init();
190         usb_find_busses();
191         usb_find_devices();
192
193         gemtag=find_device(USB_VENDOR_GEMTAG,USB_DEVICE_X501);
194         if(!gemtag) return NULL;
195
196         gh=malloc(sizeof(struct gemtag_handle));
197         if(!gh) return NULL;
198
199         memset(gh,0,sizeof(struct gemtag_handle));
200
201         gh->handle=usb_open(gemtag);
202         if(!gh->handle)
203                 goto out_free;
204
205         for(i=1;i<4;i++) {
206                 memset(info,0,sizeof(info));
207                 usb_get_string_simple(gh->handle,i,info,sizeof(info));
208                 printf("%s ",info);
209         }
210         printf("opened successfully\n");
211
212         if(usb_set_configuration(gh->handle,1)) {
213                 perror("set config");
214                 goto out_free;
215         }
216         printf("set configuration 1, ");
217
218         if(usb_claim_interface(gh->handle,0)) {
219                 perror("claim interface");
220                 goto out_free;
221         }
222         printf("claimed interface 0\n");
223
224         /*
225         if(usb_set_altinterface(gh->handle,0))
226                 perror("set alt interface");
227         printf("activated alt setting 0\n");
228         */
229
230         return gh;
231
232 out_free:
233         free(gh);
234         return NULL;
235 }
236
237 int gemtag_close(struct gemtag_handle *gh) {
238
239         if(gh->handle) usb_close(gh->handle);
240         if(gh) free(gh);
241
242         return 0;
243 }
244
245 int gemtag_transform_mifare_key(struct gemtag_handle *gh,
246                          unsigned char *key6,unsigned char *key12) {
247
248         unsigned int len;
249
250         gemtag_transceive(gh,GEMTAG_CMD_HOST_CODE_KEY,key6,6,key12,&len);
251
252         return 0;
253 }
254
255 int gemtag_auth_key(struct gemtag_handle *gh,unsigned char authmode,
256                     int sector,unsigned char *key6) {
257
258         unsigned char buf[32];
259         unsigned int len,ret;
260
261         /* to be continued */
262
263 }
264
265 int gemtag_auth_mifare_key(struct gemtag_handle *gh,
266                            unsigned char *key6,int sector) {
267
268         unsigned char key12[12];        
269         unsigned char buf[32];
270         unsigned int len,ret;
271
272         gemtag_transform_mifare_key(gh,key6,key12);
273                              
274         buf[0]=GEMTAG_PICC_AUTHENT1A;   /* auth mode */
275         memcpy(buf+1,gh->serial,4);     /* sreial */
276         memcpy(buf+5,key12,12);         /* transformed key */
277         buf[17]=sector;                 /* sector */
278         ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_AUTH_KEY,buf,18,
279                               buf,&len);
280         if(ret) return -AUTH_FAILED;
281
282         return 0;
283 }
284
285 int gemtag_read16(struct gemtag_handle *gh,int sector,unsigned char *data) {
286
287         unsigned char buf[32];
288         int len,ret;
289
290         buf[0]=sector;
291         ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_READ,buf,1,data,&len);
292         if(ret) return -READ_FAILED;
293
294         return 0;
295 }
296
297 int gemtag_write16(struct gemtag_handle *gh,int sector,unsigned char *data) {
298
299         unsigned char buf[32];
300         int ret,len;
301
302         buf[0]=sector;
303         memcpy(buf+1,data,16);
304         ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_WRITE,buf,17,buf,&len);
305
306         return ret;
307 }
308
309 int gemtag_select_picc(struct gemtag_handle *gh) {
310
311         unsigned char buf[16];
312         unsigned int len;
313         int ret;
314
315         buf[0]=GEMTAG_PICC_REQIDL;
316         ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_REQUEST,buf,1,buf,&len);
317         if(ret) return -NO_PICC;
318
319         buf[0]=GEMTAG_PICC_STD_SELECT_CODE;
320         memset(buf+1,0,5);
321         ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_CASC_ANTICOLL,buf,6,buf,&len);
322         if(ret) return -NO_PICC;
323         memcpy(gh->serial,buf,4);
324
325         buf[0]=GEMTAG_PICC_STD_SELECT_CODE;
326         memcpy(buf+1,gh->serial,4);
327         ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_CASC_SELECT,buf,5,buf,&len);
328         if(ret) return -PICC_SELECT_ERROR;
329
330         return 0;
331 }
332
333 int main(int argc, char **argv) {
334
335         struct gemtag_handle *gh;
336         unsigned char buf[256];
337         unsigned char key6[6];
338         int i,ret;
339
340         gh=gemtag_open();
341
342         gh->caps|=GEMTAG_CAP_CRC;
343         //gh->caps|=GEMTAG_CAP_VERB_TRANSMIT;
344
345         /*
346         printf("Device:\n");
347         gemtag_transceive(gh,GEMTAG_CMD_GET_FW_VERSION,
348                           NULL,0,buf,&buflen);
349         asciidump(buf,buflen);
350         printf("\n");
351         */
352
353         if(gemtag_select_picc(gh)) {
354                 printf("no card found!\n");
355                 return -NO_PICC;
356         }
357
358         memset(key6,0xff,6);
359         printf("\nreading sectors ... (serial: %02x %02x %02x %02x)\n\n",
360                gh->serial[3],gh->serial[2],gh->serial[1],gh->serial[0]);
361         i=0;
362         while(!gemtag_auth_mifare_key(gh,key6,i)) {
363                 gemtag_read16(gh,i,buf);
364                 printf("%02x: ",i);
365                 hexdump(buf,16);
366                 printf(" | ");
367                 asciidump(buf,16);
368                 printf("\n");
369                 i+=1;
370         }
371         printf("\n");
372
373         /* try to write some data */
374         printf("write some data to the sector 04:\n");
375         for(i=0;i<16;i++) buf[i]=i;
376         i=4;
377         ret=gemtag_auth_mifare_key(gh,key6,i);
378         printf("return = %d\n",ret);
379         if(ret) printf("auth failed!\n");
380         ret=gemtag_write16(gh,i,buf);
381         if(ret) printf("write failed!\n");
382         printf("return = %d\n",ret);
383         ret=gemtag_read16(gh,i,buf);
384         if(ret) printf("read failed!\n");
385         printf("return = %d\n",ret);
386         printf("%02x: ",i);
387         hexdump(buf,16);
388         printf("\n");
389
390         gemtag_close(gh);
391
392         return 0;
393 }
394