X-Git-Url: https://hackdaworld.org/gitweb/?p=rfid%2Flibrfid.git;a=blobdiff_plain;f=gemtag%2Fgemtag.c;h=48dc427f47d7fd46da21be1c96a540505584c091;hp=28538c77098921f5a93d911ccb95852cb76159b8;hb=d72a365a0f044de71ae7c13dd7782895f531a944;hpb=c8c92a9a0bb6354e1740a838b3f51000b59f4e97 diff --git a/gemtag/gemtag.c b/gemtag/gemtag.c index 28538c7..48dc427 100644 --- a/gemtag/gemtag.c +++ b/gemtag/gemtag.c @@ -1,5 +1,5 @@ /* - * (C) 2006 by Frank Zirkelbach + * (C) 2006 by Frank Zirkelbach * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -24,15 +24,27 @@ #include #include "gemtag.h" -/* variables */ +int asciidump(unsigned char *data,int len) { + int i; -struct gemtag_handle { - struct usb_dev_handle *handle; -}; + for(i=0;i0x19)&&(data[i]<0x7f)) printf("%c",data[i]); + else printf("_"); + //printf("\n"); -/* functions */ + return 0; +} + +int hexdump(unsigned char *data,int len) { + int i; + + for(i=0;i>1)^crc_polynom; + else + crc=(crc>>1); + } + } + return crc; +} + +int gemtag_transceive(struct gemtag_handle *gh,unsigned char cmd, + unsigned char *tx,unsigned int tx_len, + unsigned char *rx,unsigned int *rx_len) { + + unsigned char txbuf[256]; + unsigned char rxbuf[256]; + struct gemtag_cmd_hdr *txhdr; + struct gemtag_cmd_hdr *rxhdr; + u_int16_t crc,*crcptr; + int i,ret,size,rest; + + txhdr=(struct gemtag_cmd_hdr *)txbuf; + rxhdr=(struct gemtag_cmd_hdr *)rxbuf; + + txhdr->start=0xa5; + txhdr->seq=++(gh->seq); + txhdr->cmd=cmd; + txhdr->len=tx_len; + size=sizeof(struct gemtag_cmd_hdr); + memcpy(txbuf+size,tx,tx_len); + size+=tx_len; + + /* crc check */ + if(gh->caps&GEMTAG_CAP_CRC) { + crcptr=(u_int16_t *)(txbuf+size); + crc=gemtag_calc_crc(txbuf,size); + //*crcptr=(crc>>8)|(crc<<8); + *crcptr=crc; + size+=2; + } + + /* usb write */ + if(gh->caps&GEMTAG_CAP_VERB_TRANSMIT) { + printf("(%02d) -> ",size); + hexdump(txbuf,size); + } + ret=usb_interrupt_write(gh->handle,0x02,txbuf,size,0); + if(ret<=0) { + perror("usb interrupt write"); + return ret; + } + + /* usb read */ + ret=usb_interrupt_read(gh->handle,0x81,rxbuf,32,0); + if(ret<=0) { + perror("usb interrupt read"); + return ret; + } + if(ret<5) { + if(gh->caps&GEMTAG_CAP_VERB_TRANSMIT) + return -SHORT_ANSWER; + } + + *rx_len=rxbuf[3]|(rxbuf[4]<<8); + size=*rx_len+sizeof(struct gemtag_cmd_hdr); + if(gh->caps&GEMTAG_CAP_CRC) size+=2; + + i=1; + rest=size-ret; + while(rest>=0) { + ret=usb_interrupt_read(gh->handle,0x81,rxbuf+i*32,32,0); + if(ret<=0) { + perror("usb interrupt read (missing bytes)"); + return ret; + } + i++; + rest-=ret; + } + + if(gh->caps&GEMTAG_CAP_VERB_TRANSMIT) { + printf("(%02d) <- ",size); + hexdump(rxbuf,size); + } + + /* crc check */ + if(gh->caps&GEMTAG_CAP_CRC) { + size-=2; + crcptr=(u_int16_t *)(rxbuf+size); + crc=gemtag_calc_crc(rxbuf,size); + if(((crc>>8)!=rxbuf[size+1])||((crc&0xff)!=rxbuf[size])) + return -BAD_CRC; + } + + /* check sequence number */ + if(rxhdr->seq!=txhdr->seq) return -SEQ_MISMATCH; + + /* check return code */ + if(rxbuf[2]) return -CMD_FAILED; + + memcpy(rx,rxbuf+sizeof(struct gemtag_cmd_hdr),*rx_len); + + return 0; +} + struct gemtag_handle *gemtag_open(void) { struct usb_device *gemtag; - unsigned char rbuf[16]; - unsigned int rlen; - unsigned int i,numconf; - unsigned int j,numint; + unsigned int i; struct gemtag_handle *gh; - - rlen=sizeof(rbuf); + char info[64]; usb_init(); usb_find_busses(); usb_find_devices(); - gemtag=find_device(USB_VENDOR_GEMTAG, USB_DEVICE_X501); + gemtag=find_device(USB_VENDOR_GEMTAG,USB_DEVICE_X501); if(!gemtag) return NULL; gh=malloc(sizeof(struct gemtag_handle)); @@ -73,34 +198,160 @@ struct gemtag_handle *gemtag_open(void) { memset(gh,0,sizeof(struct gemtag_handle)); - numconf=gemtag->descriptor.bNumConfigurations; - printf("found gemtag, %u configurations\n",numconf); - for(i=0;iconfig[i].bNumInterfaces; - printf("config %u [nr %u] has %u interfaces\n", - i,gemtag->config[i].bConfigurationValue, - numint); - for(j=0;jconfig[i].interface[j].num_altsetting); - } - } - gh->handle=usb_open(gemtag); if(!gh->handle) goto out_free; + for(i=1;i<4;i++) { + memset(info,0,sizeof(info)); + usb_get_string_simple(gh->handle,i,info,sizeof(info)); + printf("%s ",info); + } + printf("opened successfully\n"); + + if(usb_set_configuration(gh->handle,1)) { + perror("set config"); + goto out_free; + } + printf("set configuration 1, "); + + if(usb_claim_interface(gh->handle,0)) { + perror("claim interface"); + goto out_free; + } + printf("claimed interface 0\n"); + + /* + if(usb_set_altinterface(gh->handle,0)) + perror("set alt interface"); + printf("activated alt setting 0\n"); + */ + + return gh; + out_free: free(gh); return NULL; } + +int gemtag_close(struct gemtag_handle *gh) { + + if(gh->handle) usb_close(gh->handle); + if(gh) free(gh); + + return 0; +} + +int gemtag_transform_mifare_key(struct gemtag_handle *gh, + unsigned char *key6,unsigned char *key12) { + + unsigned int len; + + gemtag_transceive(gh,GEMTAG_CMD_HOST_CODE_KEY,key6,6,key12,&len); + + return 0; +} + +int gemtag_auth_mifare_key(struct gemtag_handle *gh, + unsigned char *key6,int sector) { + + unsigned char key12[12]; + unsigned char buf[32]; + unsigned int len,ret; + + gemtag_transform_mifare_key(gh,key6,key12); + + buf[0]=0x60; /* auth mode */ + memcpy(buf+1,gh->serial,4); /* sreial */ + memcpy(buf+5,key12,12); /* transformed key */ + buf[17]=sector; /* sector */ + ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_AUTH_KEY,buf,18, + buf,&len); + if(ret) return -AUTH_FAILED; + + return 0; +} + +int gemtag_read16(struct gemtag_handle *gh,int sector, + unsigned char *data) { + + unsigned char buf[32]; + int len,ret; + + buf[0]=sector; + ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_READ, + buf,1,data,&len); + if(ret) return -READ_FAILED; + + return 0; +} + +int gemtag_pick_picc(struct gemtag_handle *gh) { + + unsigned char buf[16]; + unsigned int len; + int ret; + + buf[0]=GEMTAG_PICC_REQIDL; + ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_REQUEST,buf,1,buf,&len); + if(ret) return -NO_PICC; + + buf[0]=GEMTAG_PICC_STD_SELECT_CODE; + memset(buf+1,0,5); + ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_CASC_ANTICOLL,buf,6,buf,&len); + if(ret) return -NO_PICC; + memcpy(gh->serial,buf,4); + + buf[0]=GEMTAG_PICC_STD_SELECT_CODE; + memcpy(buf+1,gh->serial,4); + ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_CASC_SELECT,buf,5,buf,&len); + if(ret) return -PICC_SELECT_ERROR; + + return 0; +} int main(int argc, char **argv) { struct gemtag_handle *gh; + unsigned char buf[256]; + unsigned char key6[6]; + int i; gh=gemtag_open(); - return 1; + gh->caps|=GEMTAG_CAP_CRC; + //gh->caps|=GEMTAG_CAP_VERB_TRANSMIT; + + /* + printf("Device:\n"); + gemtag_transceive(gh,GEMTAG_CMD_GET_FW_VERSION, + NULL,0,buf,&buflen); + asciidump(buf,buflen); + printf("\n"); + */ + + if(gemtag_pick_picc(gh)) { + printf("no card found!\n"); + return -NO_PICC; + } + + memset(key6,0xff,6); + printf("\nreading sectors ... (serial: %02x %02x %02x %02x)\n\n", + gh->serial[3],gh->serial[2],gh->serial[1],gh->serial[0]); + for(i=0;i<256;i++) { + gemtag_auth_mifare_key(gh,key6,i); + if(!gemtag_read16(gh,i,buf)) { + printf("%02x: ",i++); + hexdump(buf,16); + printf(" | "); + asciidump(buf,16); + printf("\n"); + } + else return 0; + } + + gemtag_close(gh); + + return 0; }