Changeset 1010 for trunk/src/ifd
- Timestamp:
- 12/17/07 13:29:24 (4 years ago)
- File:
-
- 1 edited
-
trunk/src/ifd/ifd-rutoken.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/ifd/ifd-rutoken.c
r1009 r1010 391 391 ifd_driver_register("rutoken", &rutoken_driver); 392 392 } 393 /*394 * driver for Rutoken devices395 *396 * Copyright (C) 2007, Pavel Mironchik <rutoken@rutoken.ru>397 * Copyright (C) 2007, Eugene Hermann <e_herman@tut.by>398 */399 400 #include "internal.h"401 #include "stdio.h"402 #include "unistd.h"403 #include "string.h"404 405 #define MAX_BUF_T0_LEN 256406 #define T0_HDR_LEN 5407 408 409 #define USB_ICC_POWER_ON 0x62410 #define USB_ICC_POWER_OFF 0x63411 #define USB_ICC_XFR_BLOCK 0x65412 #define USB_ICC_DATA_BLOCK 0x6F413 #define USB_ICC_GET_STATUS 0xA0414 415 #define ICC_STATUS_IDLE 0x00416 #define ICC_STATUS_READY_DATA 0x10417 #define ICC_STATUS_READY_SW 0x20418 #define ICC_STATUS_BUSY_COMMON 0x40419 #define ICC_STATUS_MUTE 0x80420 421 #define OUR_ATR_LEN 19422 423 static int rutoken_open(ifd_reader_t * reader, const char *device_name)424 {425 ifd_device_t *dev;426 ifd_debug(1, "rutoken_open - %s\n", device_name);427 ifd_debug(1, "%s:%d rutoken_open()", __FILE__, __LINE__);428 429 reader->name = "ruToken driver.\n";430 reader->nslots = 1;431 if (!(dev = ifd_device_open(device_name)))432 return -1;433 434 if (ifd_device_type(dev) != IFD_DEVICE_TYPE_USB) {435 ct_error("ruToken driver: device %s is not a USB device", device_name);436 ifd_device_close(dev);437 return -1;438 }439 440 reader->device = dev;441 dev->timeout = 1000;442 443 ifd_debug(1, "%s:%d Checkpoint", __FILE__, __LINE__);444 return 0;445 }446 447 static int rutoken_activate(ifd_reader_t * reader)448 {449 ifd_debug(1, "%s:%d rutoken_activate()", __FILE__, __LINE__);450 return 0;451 }452 453 static int rutoken_deactivate(ifd_reader_t * reader)454 {455 ifd_debug(1, "%s:%d rutoken_deactivate()", __FILE__, __LINE__);456 return -1;457 }458 459 // Get Status 0 - OK460 // - ERROR461 //462 int rutoken_getstatus(ifd_reader_t * reader, char *status)463 {464 // TODO Chech for timeout465 //ifd_debug(1, "");466 if(!ifd_usb_control(reader->device, 0xc1, USB_ICC_GET_STATUS, 0, 0, status, 1, 1000) < 0 )467 return -1;468 if((*status & 0xF0) == ICC_STATUS_BUSY_COMMON){469 int i;470 for(i = 0; i < 100000; i++) {471 if(!ifd_usb_control(reader->device, 0xc1, USB_ICC_GET_STATUS, 0, 0, status, 1, 1000) < 0 )472 return -1;473 if((*status & 0xF0) != ICC_STATUS_BUSY_COMMON)474 return 0;475 usleep(1000);476 }477 return -1;478 }479 return *status;480 }481 482 static int rutoken_card_reset(ifd_reader_t * reader, int slot, void *atr,483 size_t atr_len)484 {485 ifd_debug(1, "%s:%d rutoken_card_reset()", __FILE__, __LINE__);486 487 int nLen = 0, i;488 ifd_debug(1, "rutoken_card_reset, slot = %X\n", slot);489 if(ifd_usb_control(reader->device, 0x41, USB_ICC_POWER_OFF, 0, 0, 0, 0, -1) < 0)490 {491 ifd_debug(1, "error poweroff\n");492 return -1;493 }494 char status;495 if( rutoken_getstatus(reader, &status) < 0)496 {497 ifd_debug(1, "error get status\n");498 return -1;499 }500 if( status == ICC_STATUS_READY_DATA ) {501 char buf[OUR_ATR_LEN];502 memset(buf, 0, OUR_ATR_LEN);503 504 nLen = ifd_usb_control(reader->device, 0xc1, USB_ICC_POWER_ON, 0, 0, buf, OUR_ATR_LEN, 1000);505 if( nLen < 0 )506 {507 ifd_debug(1, "error poewron\n");508 return -1;509 }510 511 ifd_debug(1, "returned len = %d", nLen);512 for(i = 0; i < OUR_ATR_LEN; i++) ifd_debug(1, "%c", buf[i]);513 memcpy(atr, buf, nLen);514 return nLen;515 }516 517 ifd_debug(1, "error bad status\n");518 return -1;519 }520 521 static int rutoken_restart(ifd_reader_t * reader)522 {523 char atr[256];524 return rutoken_card_reset(reader, 0, atr, 256);525 }526 527 /*528 * Select a protocol.529 */530 static int rutoken_set_protocol(ifd_reader_t * reader, int nslot, int proto)531 {532 ifd_debug(1, "set protocol: {%d}", proto);533 534 ifd_slot_t *slot;535 ifd_protocol_t *p;536 537 ifd_debug(1, "proto=%d", proto);538 if (proto != IFD_PROTOCOL_T0 && proto != IFD_PROTOCOL_TRANSPARENT) {539 ct_error("%s: protocol %d not supported", reader->name, proto);540 return IFD_ERROR_NOT_SUPPORTED;541 }542 slot = &reader->slot[nslot];543 p = ifd_protocol_new(IFD_PROTOCOL_TRANSPARENT, reader, slot->dad);544 if (p == NULL) {545 ct_error("%s: internal error", reader->name);546 return IFD_ERROR_GENERIC;547 }548 if (slot->proto) {549 ifd_protocol_free(slot->proto);550 slot->proto = NULL;551 }552 slot->proto = p;553 ifd_debug(1, "success");554 return 0;555 }556 557 static int rutoken_card_status(ifd_reader_t * reader, int slot,558 int *status)559 {560 //ifd_debug(1, "");561 *status = IFD_CARD_PRESENT;562 return 0;563 }564 565 static int rutoken_send(ifd_reader_t * reader, unsigned int dad,566 const unsigned char *buffer, size_t len)567 {568 int ret;569 char status;570 ifd_debug(3, "usb send %s len %d", ct_hexdump(buffer, len), len);571 ret = ifd_usb_control(reader->device, 0x41, USB_ICC_XFR_BLOCK, 0, 0, (void *)buffer, len, -1);572 573 if (rutoken_getstatus(reader, &status) < 0)574 {575 ret = -1;576 ifd_debug(1, "error get status");577 }578 return ret;579 }580 581 static int rutoken_recv(ifd_reader_t * reader, unsigned int dad,582 unsigned char *buffer, size_t len, long timeout)583 {584 char status;585 int ret = len;586 // USB_ICC_DATA_BLOCK587 if( (ret = ifd_usb_control(reader->device, 0xc1, USB_ICC_DATA_BLOCK, 0, 0, buffer, len, timeout)) >= 0)588 if (rutoken_getstatus(reader, &status) < 0)589 {590 ret = -1;591 ifd_debug(1, "error get status, %0x", status);592 }593 ifd_debug(3, "usd recv %s len %d", ct_hexdump(buffer, ret), ret);594 return ret;595 }596 597 static int rutoken_recv_sw(ifd_reader_t * reader, int dad, unsigned char *sw)598 {599 unsigned char status;600 if(rutoken_getstatus(reader, &status) == ICC_STATUS_MUTE)601 { //If device not responsive602 ifd_debug(1, "status = ICC_STATUS_MUTE");603 return(rutoken_restart(reader));604 }605 if(status == ICC_STATUS_READY_SW)606 {607 ifd_debug(1, "status = ICC_STATUS_READY_SW;");608 if(rutoken_recv(reader, 0, sw, 2, 10000) < 0)609 return -5;610 ifd_debug(1, "Get SW %x %x", sw[0], sw[1]);611 return 2;612 }613 return -1;614 }615 616 // return how mach byte send617 // sbuf - APDU bufer618 // slen619 static int rutoken_send_tpducomand(ifd_reader_t * reader, int dad, const void *sbuf, size_t slen, void *rbuf, size_t rlen, int iscase4)620 {621 ifd_debug(1, "send tpdu command %s, len: %d", ct_hexdump(sbuf, slen), slen);622 int rrecv = 0;623 unsigned char status;624 unsigned char sw[2];625 ifd_iso_apdu_t iso;626 if ( ifd_iso_apdu_parse(sbuf, slen, &iso) < 0)627 return -1;628 unsigned char hdr[T0_HDR_LEN]={iso.cla, iso.ins, iso.p1, iso.p2, 0};629 switch(iso.cse){630 case IFD_APDU_CASE_1:631 // {cla, ins, p1, p2, 0};632 ifd_debug(1, "case 1");633 break;634 case IFD_APDU_CASE_2S:635 // {cla, ins, p1, p2, le};636 // Rutoken Bug!!!637 ifd_debug(1, "case 2");638 if(iso.ins == 0xa4){639 hdr[4] = 0x20;640 iso.le = 0x20;641 }642 else{643 hdr[4] = iso.le;644 }645 break;646 case IFD_APDU_CASE_3S:647 // {cla, ins, p1, p2, lc};648 ifd_debug(1, "case 3");649 hdr[4] = iso.lc;650 break;651 default:652 break;653 }654 //send TPDU header655 if (rutoken_send(reader, 0, hdr, T0_HDR_LEN) < 0)656 return -1;657 // send TPDU data or get answere and sw658 switch(iso.cse){659 case IFD_APDU_CASE_1:660 // get sw661 if (rutoken_recv_sw(reader, 0, sw) < 0)662 return -2;663 break;664 case IFD_APDU_CASE_2S:665 // get answere666 ifd_debug(1, "Get Data %d", iso.le);667 if(rutoken_getstatus(reader, &status) == ICC_STATUS_READY_DATA)668 {669 rrecv = rutoken_recv(reader, 0, rbuf, iso.le, 10000);670 if (rrecv < 0)671 return -2;672 ifd_debug(1, "Get TPDU Anser %s", ct_hexdump(rbuf, iso.le));673 }674 if (rutoken_recv_sw(reader, 0, sw) < 0)675 return -2;676 if ( sw[0] == 0x67) {677 // Le definitely not accepted678 break;679 }680 if ( (sw[0] == 0x6c) ) {681 unsigned char sbuftmp[slen];682 memcpy(sbuftmp, sbuf, slen);683 sbuftmp[4] = sw[1];684 return rutoken_send_tpducomand(reader, dad, sbuftmp, slen, rbuf, rlen, 0);685 }686 687 break;688 case IFD_APDU_CASE_3S:689 // send data690 ifd_debug(1, "Send Data %d", iso.lc);691 if(rutoken_getstatus(reader, &status) == ICC_STATUS_READY_DATA)692 {693 ifd_debug(1, "Send TPDU Data %s", ct_hexdump(iso.data, iso.lc));694 if (rutoken_send(reader, 0, iso.data, iso.lc) < 0) return -4;695 } else return -3;696 // get sw697 if (rutoken_recv_sw(reader, 0, sw) < 0)698 return -2;699 700 // NOT STANDART TPDU!!! BEGIN701 if ( sw[0]== 0x61){702 unsigned char lx = sw[1];703 hdr[0] = 0x00; // iso.cla; (ruTokens specific)704 hdr[1] = 0xc0; // ins get response705 hdr[2] = 0; // p1706 hdr[3] = 0; // p2707 hdr[4] = lx ; //lx (case 2)708 if(iscase4)709 return rutoken_send_tpducomand(reader, dad, hdr, T0_HDR_LEN, rbuf, rlen, 0);710 else {711 int recvtmp = rutoken_send_tpducomand(reader, dad, hdr, T0_HDR_LEN, rbuf, rlen, 0);712 rrecv = 0;713 memcpy(sw, rbuf+recvtmp-2, 2);714 break;715 }716 }717 718 if ( (sw[0] == 0x90) && (sw[1] == 0x00))719 {720 hdr[0] = 0x00; //iso.cla;721 hdr[1] = 0xc0; // ins get response722 hdr[2] = 0; // p1723 hdr[3] = 0; // p2724 hdr[4] = iso.le; // le (case 2)725 if(iscase4)726 return rutoken_send_tpducomand(reader, dad, hdr, T0_HDR_LEN, rbuf, rlen, 0);727 }728 // NOT STANDART TPDU!!! END729 730 break;731 default:732 break;733 }734 // Add SW to respond735 memcpy(((char *)rbuf)+rrecv, sw, 2);736 rrecv+=2;737 ifd_debug(1, "Recv %d bytes", rrecv);738 return rrecv;739 }740 741 static int rutoken_transparent( ifd_reader_t * reader, int dad,742 const void *sbuf, size_t slen,743 void *rbuf, size_t rlen)744 {745 int rrecv = 0;746 ifd_iso_apdu_t iso;747 ifd_debug(1, "buffer %s rlen = %d", ct_hexdump(sbuf, slen), rlen);748 if ( ifd_iso_apdu_parse(sbuf, slen, &iso) < 0)749 return -1;750 ifd_debug(1, "iso.le = %d", iso.le);751 switch(iso.cse){752 case IFD_APDU_CASE_1:753 case IFD_APDU_CASE_2S:754 case IFD_APDU_CASE_3S:755 return rutoken_send_tpducomand(reader, dad, sbuf, slen, rbuf, rlen, 0);756 break;757 case IFD_APDU_CASE_4S:758 // make send case 4 command759 rrecv = rutoken_send_tpducomand(reader, dad, sbuf, slen-1, rbuf, rlen, 1);760 return rrecv;761 break;762 default:763 break;764 }765 return -1;766 }767 768 static struct ifd_driver_ops rutoken_driver;769 770 void ifd_rutoken_register(void)771 {772 ifd_debug(1, "ifd_rutoken_register()\n");773 rutoken_driver.open = rutoken_open;774 rutoken_driver.activate = rutoken_activate;775 rutoken_driver.deactivate = rutoken_deactivate;776 rutoken_driver.card_reset = rutoken_card_reset;777 rutoken_driver.card_status = rutoken_card_status;778 rutoken_driver.set_protocol = rutoken_set_protocol;779 rutoken_driver.transparent = rutoken_transparent;780 781 ifd_driver_register("rutoken", &rutoken_driver);782 }
Note: See TracChangeset
for help on using the changeset viewer.
