first beta - patch sent to librfid list
[rfid/librfid.git] / gemtag / gemtag.c
1 /*
2  *  (C) 2006 by Harald Welte <laforge@gnumonks.org>
3  *              Frank Zirkelbach <hackbard@hackdaworld.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 <stdlib.h>
21 #include <unistd.h>
22 #include <string.h>
23 #include <errno.h>
24
25 #include <usb.h>
26 #include "gemtag.h"
27
28 int asciidump(unsigned char *data,int len) {
29
30         int i;
31
32         for(i=0;i<len;i++)
33                 printf("%c",(data[i]>0x19)&&(data[i]<0x7f)?data[i]:'.');
34
35         return 0;
36 }
37
38 int hexdump(unsigned char *data,int len) {
39
40         int i;
41
42         for(i=0;i<len;i++) printf("%02x ",data[i]);
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
185         struct usb_device *gemtag;
186         unsigned int i;
187         struct gemtag_handle *gh;
188         char info[64];
189
190         usb_init();
191         usb_find_busses();
192         usb_find_devices();
193
194         gemtag=find_device(USB_VENDOR_GEMTAG,USB_DEVICE_X501);
195         if(!gemtag) return NULL;
196
197         gh=malloc(sizeof(struct gemtag_handle));
198         if(!gh) return NULL;
199
200         memset(gh,0,sizeof(struct gemtag_handle));
201
202         gh->handle=usb_open(gemtag);
203         if(!gh->handle)
204                 goto out_free;
205
206         for(i=1;i<4;i++) {
207                 memset(info,0,sizeof(info));
208                 usb_get_string_simple(gh->handle,i,info,sizeof(info));
209                 printf("%s ",info);
210         }
211         printf("opened successfully\n");
212
213         if(usb_set_configuration(gh->handle,1)) {
214                 perror("set config");
215                 goto out_free;
216         }
217         printf("set configuration 1, ");
218
219         if(usb_claim_interface(gh->handle,0)) {
220                 perror("claim interface");
221                 goto out_free;
222         }
223         printf("claimed interface 0\n");
224
225         /*
226         if(usb_set_altinterface(gh->handle,0))
227                 perror("set alt interface");
228         printf("activated alt setting 0\n");
229         */
230
231         return gh;
232
233 out_free:
234         free(gh);
235         return NULL;
236 }
237
238 int gemtag_close(struct gemtag_handle *gh) {
239
240         if(gh->handle) usb_close(gh->handle);
241         if(gh) free(gh);
242
243         return 0;
244 }
245
246 int gemtag_transform_mifare_key(struct gemtag_handle *gh,
247                          unsigned char *key6,unsigned char *key12) {
248
249         unsigned int len;
250
251         gemtag_transceive(gh,GEMTAG_CMD_HOST_CODE_KEY,key6,6,key12,&len);
252
253         return 0;
254 }
255
256 int gemtag_auth_e2(struct gemtag_handle *gh,unsigned char authmode,
257                    int sector,unsigned char *key6) {
258
259         unsigned char buf[32];
260         unsigned int len,ret;
261
262         /* memory layout (sector/block) ? */
263
264         buf[0]=authmode;
265         buf[1]=0;
266         memcpy(buf+2,key6,6);
267         ret=gemtag_transceive(gh,GEMTAG_CMD_PCD_LOAD_KEY_E2,buf,8,buf,&len);
268         if(ret) return -LOAD_E2_FAILED;
269
270         buf[0]=authmode;
271         memcpy(buf+1,gh->serial,4);
272         buf[5]=0;
273         buf[6]=sector;
274         ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_AUTH_E2,buf,7,buf,&len);
275         if(ret) return -AUTH_E2_FAILED;
276
277         return 0;
278
279 }
280
281 int gemtag_auth_mifare_key(struct gemtag_handle *gh,
282                            unsigned char *key6,int sector) {
283
284         unsigned char key12[12];        
285         unsigned char buf[32];
286         unsigned int len,ret;
287
288         gemtag_transform_mifare_key(gh,key6,key12);
289                              
290         buf[0]=GEMTAG_PICC_AUTHENT1A;   /* auth mode */
291         memcpy(buf+1,gh->serial,4);     /* sreial */
292         memcpy(buf+5,key12,12);         /* transformed key */
293         buf[17]=sector;                 /* sector */
294         ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_AUTH_KEY,buf,18,
295                               buf,&len);
296         if(ret) return -AUTH_FAILED;
297
298         return 0;
299 }
300
301 int gemtag_read16(struct gemtag_handle *gh,int sector,unsigned char *data) {
302
303         unsigned char buf[32];
304         int len,ret;
305
306         buf[0]=sector;
307         ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_READ,buf,1,data,&len);
308         if(ret) return -READ_FAILED;
309
310         return 0;
311 }
312
313 int gemtag_write16(struct gemtag_handle *gh,int sector,unsigned char *data) {
314
315         unsigned char buf[32];
316         int ret,len;
317
318         buf[0]=sector;
319         memcpy(buf+1,data,16);
320         ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_WRITE,buf,17,buf,&len);
321         if(ret) return -WRITE_FAILED;
322
323         return 0;
324 }
325
326 int gemtag_select_picc(struct gemtag_handle *gh) {
327
328         unsigned char buf[16];
329         unsigned int len;
330         int ret;
331
332         buf[0]=GEMTAG_PICC_REQIDL;
333         ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_REQUEST,buf,1,buf,&len);
334         if(ret) return -NO_PICC;
335
336         buf[0]=GEMTAG_PICC_STD_SELECT_CODE;
337         memset(buf+1,0,5);
338         ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_CASC_ANTICOLL,buf,6,buf,&len);
339         if(ret) return -NO_PICC;
340         memcpy(gh->serial,buf,4);
341
342         buf[0]=GEMTAG_PICC_STD_SELECT_CODE;
343         memcpy(buf+1,gh->serial,4);
344         ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_CASC_SELECT,buf,5,buf,&len);
345         if(ret) return -PICC_SELECT_ERROR;
346
347         return 0;
348 }
349
350 int main(int argc, char **argv) {
351
352         struct gemtag_handle *gh;
353         unsigned char buf[256];
354         unsigned char key6[6];
355         int i,ret;
356
357         gh=gemtag_open();
358
359         gh->caps|=GEMTAG_CAP_CRC;
360         //gh->caps|=GEMTAG_CAP_VERB_TRANSMIT;
361
362         if(gemtag_select_picc(gh)) {
363                 printf("no card found!\n");
364                 return -NO_PICC;
365         }
366
367         memset(key6,0xff,6);
368         printf("\nreading sectors ... (serial: %02x %02x %02x %02x)\n\n",
369                gh->serial[3],gh->serial[2],gh->serial[1],gh->serial[0]);
370         i=0;
371         while(!gemtag_auth_mifare_key(gh,key6,i)) {
372                 ret=gemtag_read16(gh,i,buf);
373                 printf("%02x: ",i);
374                 hexdump(buf,16);
375                 printf(" | ");
376                 asciidump(buf,16);
377                 printf("\n");
378                 i+=1;
379         }
380         printf("\n");
381
382         gemtag_close(gh);
383
384         return 0;
385 }
386