Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:pzb:smartcard
pcsc-ccid
ccid-1.2.1-svn.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File ccid-1.2.1-svn.patch of Package pcsc-ccid
Index: SCARDGETATTRIB.txt =================================================================== --- SCARDGETATTRIB.txt (revision 2363) +++ SCARDGETATTRIB.txt (working copy) @@ -43,9 +43,11 @@ SCARD_ATTR_MAXINPUT maximum size of an APDU supported by the reader. - Correct readers should support up to 261 bytes but some readers - support less (253 bytes only for example). It is a problem for T=1 - cards + format is unsigned 32-bit unsing the byte order of the platform. + Correct readers should support up to 261 bytes (CLA + INS + P1 + P2 + + Lc + 255 bytes of data) but some readers support less (253 bytes only + for example). It is a problem for T=1 cards when the reader works in + APDU mode instead of TPDU and for T=0 cards. Sample code Index: readers/SCR331.txt =================================================================== --- readers/SCR331.txt (revision 2363) +++ readers/SCR331.txt (working copy) @@ -2,15 +2,17 @@ iManufacturer: SCM Microsystems Inc. idProduct: 0xE001 iProduct: SCRx31 USB Smart Card Reader - bcdDevice: 5.18 (firmware release?) + bcdDevice: 5.22 (firmware release?) bLength: 9 bDescriptorType: 4 bInterfaceNumber: 0 bAlternateSetting: 0 bNumEndpoints: 3 + bulk-IN, bulk-OUT and Interrupt-IN bInterfaceClass: 0x0B [Chip Card Interface Device Class (CCID)] bInterfaceSubClass: 0 bInterfaceProtocol: 0 + bulk transfer, optional interrupt-IN iInterface: 4 CCID Class Descriptor bLength: 0x36 @@ -23,13 +25,13 @@ T=0 T=1 dwDefaultClock: 4.000 MHz - dwMaximumClock: 12.000 MHz + dwMaximumClock: 8.000 MHz bNumClockSupported: 0 (will use whatever is returned) - IFD does not support GET CLOCK FREQUENCIES request - dwDataRate: 9600 bps - dwMaxDataRate: 307200 bps + IFD does not support GET CLOCK FREQUENCIES request: Broken pipe + dwDataRate: 10753 bps + dwMaxDataRate: 344105 bps bNumDataRatesSupported: 0 (will use whatever is returned) - IFD does not support GET_DATA_RATES request + IFD does not support GET_DATA_RATES request: Broken pipe dwMaxIFSD: 252 dwSynchProtocols: 0x00000000 dwMechanical: 0x00000000 Index: readers/SCR3310.txt =================================================================== --- readers/SCR3310.txt (revision 2363) +++ readers/SCR3310.txt (working copy) @@ -2,15 +2,17 @@ iManufacturer: SCM Microsystems Inc. idProduct: 0x5116 iProduct: SCR3310 USB Smart Card Reader - bcdDevice: 5.18 (firmware release?) + bcdDevice: 5.22 (firmware release?) bLength: 9 bDescriptorType: 4 bInterfaceNumber: 0 bAlternateSetting: 0 bNumEndpoints: 3 + bulk-IN, bulk-OUT and Interrupt-IN bInterfaceClass: 0x0B [Chip Card Interface Device Class (CCID)] bInterfaceSubClass: 0 bInterfaceProtocol: 0 + bulk transfer, optional interrupt-IN iInterface: 4 CCID Class Descriptor bLength: 0x36 @@ -23,13 +25,13 @@ T=0 T=1 dwDefaultClock: 4.000 MHz - dwMaximumClock: 12.000 MHz + dwMaximumClock: 8.000 MHz bNumClockSupported: 0 (will use whatever is returned) - IFD does not support GET CLOCK FREQUENCIES request - dwDataRate: 9600 bps - dwMaxDataRate: 307200 bps + IFD does not support GET CLOCK FREQUENCIES request: Broken pipe + dwDataRate: 10753 bps + dwMaxDataRate: 344105 bps bNumDataRatesSupported: 0 (will use whatever is returned) - IFD does not support GET_DATA_RATES request + IFD does not support GET_DATA_RATES request: Broken pipe dwMaxIFSD: 252 dwSynchProtocols: 0x00000000 dwMechanical: 0x00000000 Index: readers/SCR3311.txt =================================================================== --- readers/SCR3311.txt (revision 2363) +++ readers/SCR3311.txt (working copy) @@ -2,15 +2,17 @@ iManufacturer: SCM Microsystems Inc. idProduct: 0x511D iProduct: SCR3311 USB Smart Card Reader - bcdDevice: 5.18 (firmware release?) + bcdDevice: 5.22 (firmware release?) bLength: 9 bDescriptorType: 4 bInterfaceNumber: 0 bAlternateSetting: 0 bNumEndpoints: 3 + bulk-IN, bulk-OUT and Interrupt-IN bInterfaceClass: 0x0B [Chip Card Interface Device Class (CCID)] bInterfaceSubClass: 0 bInterfaceProtocol: 0 + bulk transfer, optional interrupt-IN iInterface: 4 CCID Class Descriptor bLength: 0x36 @@ -23,13 +25,13 @@ T=0 T=1 dwDefaultClock: 4.000 MHz - dwMaximumClock: 12.000 MHz + dwMaximumClock: 8.000 MHz bNumClockSupported: 0 (will use whatever is returned) - IFD does not support GET CLOCK FREQUENCIES request - dwDataRate: 9600 bps - dwMaxDataRate: 307200 bps + IFD does not support GET CLOCK FREQUENCIES request: Broken pipe + dwDataRate: 10753 bps + dwMaxDataRate: 344105 bps bNumDataRatesSupported: 0 (will use whatever is returned) - IFD does not support GET_DATA_RATES request + IFD does not support GET_DATA_RATES request: Broken pipe dwMaxIFSD: 252 dwSynchProtocols: 0x00000000 dwMechanical: 0x00000000 Index: readers/SCR331-DI.txt =================================================================== --- readers/SCR331-DI.txt (revision 2363) +++ readers/SCR331-DI.txt (working copy) @@ -2,17 +2,19 @@ iManufacturer: SCM Microsystems Inc. idProduct: 0x5111 iProduct: SCR331-DI USB Smart Card Reader - bcdDevice: 6.22 (firmware release?) + bcdDevice: 6.32 (firmware release?) bLength: 9 bDescriptorType: 4 bInterfaceNumber: 0 bAlternateSetting: 0 bNumEndpoints: 3 + bulk-IN, bulk-OUT and Interrupt-IN bInterfaceClass: 0xFF NOT A CCID DEVICE Class is 0xFF (proprietary) bInterfaceSubClass: 0 bInterfaceProtocol: 0 + bulk transfer, optional interrupt-IN iInterface: 4 CCID Class Descriptor bLength: 0x36 @@ -27,11 +29,11 @@ dwDefaultClock: 4.000 MHz dwMaximumClock: 12.000 MHz bNumClockSupported: 0 (will use whatever is returned) - IFD does not support GET CLOCK FREQUENCIES request - dwDataRate: 9600 bps - dwMaxDataRate: 307200 bps + IFD does not support GET CLOCK FREQUENCIES request: Broken pipe + dwDataRate: 10753 bps + dwMaxDataRate: 344105 bps bNumDataRatesSupported: 0 (will use whatever is returned) - IFD does not support GET_DATA_RATES request + IFD does not support GET_DATA_RATES request: Broken pipe dwMaxIFSD: 252 dwSynchProtocols: 0x00000000 dwMechanical: 0x00000000 Index: readers/supported_readers.txt =================================================================== --- readers/supported_readers.txt (revision 2363) +++ readers/supported_readers.txt (working copy) @@ -76,7 +76,8 @@ 0x0D46:0x3001:KOBIL KAAN Base 0x0D46:0x3002:KOBIL KAAN Advanced 0x0d46:0x3003:KOBIL KAAN SIM III -0x0d46:0x4000:KOBIL mIDentity +0x0d46:0x4000:KOBIL mIDentity Basic +0x0d46:0x4001:KOBIL mIDentity Classic # Eutron 0x073D:0x0C00:Eutron SIM Pocket Combo @@ -105,3 +106,6 @@ # RSA 0x15E1:0x2007:RSA SecurID +# Fujitsu Siemens Computers +0x0BF8:0x1005:Fujitsu Siemens SmartCard Keyboard USB 2A +0x0BF8:0x1006:Fujitsu Siemens SmartCard USB 2A Index: readers/Makefile.am =================================================================== --- readers/Makefile.am (revision 2363) +++ readers/Makefile.am (working copy) @@ -26,6 +26,8 @@ CryptoIdentity.txt \ DellSCRK.txt \ DellSK-3106.txt \ + FujitsuSiemens_SmartCard_Keyboard_USB_2A.txt \ + FujitsuSiemens_SmartCard_USB_2A.txt \ GemCoreSIMPro.txt \ GemPC433_SL.txt \ GemPC_Express.txt \ Index: readers/FujitsuSiemens_SmartCard_Keyboard_USB_2A.txt =================================================================== --- readers/FujitsuSiemens_SmartCard_Keyboard_USB_2A.txt (revision 0) +++ readers/FujitsuSiemens_SmartCard_Keyboard_USB_2A.txt (revision 2507) @@ -0,0 +1,170 @@ + idVendor: 0x0BF8 + iManufacturer: Fujitsu Siemens Computers + idProduct: 0x1005 + iProduct: SmartCard Keyboard USB 2A + bcdDevice: 1.06 (firmware release?) + bLength: 9 + bDescriptorType: 4 + bInterfaceNumber: 1 + bAlternateSetting: 0 + bNumEndpoints: 3 + bInterfaceClass: 0x0B [Chip Card Interface Device Class (CCID)] + bInterfaceSubClass: 0 + bInterfaceProtocol: 0 + iInterface: 4 + CCID Class Descriptor + bLength: 0x36 + bDescriptorType: 0x21 + bcdCCID: 1.00 + bMaxSlotIndex: 0x00 + bVoltageSupport: 0x07 + 5.0V + 3.0V + 1.8V + dwProtocols: 0x0000 0x0003 + T=0 + T=1 + dwDefaultClock: 4.800 MHz + dwMaximumClock: 8.000 MHz + bNumClockSupported: 4 + Got 256 clock frequencies but was expecting 4 + Support 4000 kHz + Support 4800 kHz + Support 6000 kHz + Support 8000 kHz + dwDataRate: 10752 bps + dwMaxDataRate: 412903 bps + bNumDataRatesSupported: 106 + Got 256 data rates but was expecting 106 + Support 10752 bps + Support 21505 bps + Support 43010 bps + Support 86021 bps + Support 172043 bps + Support 344086 bps + Support 129032 bps + Support 215053 bps + Support 12903 bps + Support 25806 bps + Support 51612 bps + Support 103225 bps + Support 206451 bps + Support 412903 bps + Support 154838 bps + Support 258064 bps + Support 7168 bps + Support 14336 bps + Support 28673 bps + Support 57347 bps + Support 114695 bps + Support 229390 bps + Support 143369 bps + Support 8602 bps + Support 17204 bps + Support 34408 bps + Support 68817 bps + Support 137634 bps + Support 275268 bps + Support 5376 bps + Support 64516 bps + Support 107526 bps + Support 6451 bps + Support 77419 bps + Support 8064 bps + Support 16129 bps + Support 32258 bps + Support 96774 bps + Support 161290 bps + Support 3584 bps + Support 71684 bps + Support 4301 bps + Support 2688 bps + Support 53763 bps + Support 3225 bps + Support 38709 bps + Support 4032 bps + Support 48387 bps + Support 80645 bps + Support 2150 bps + Support 2580 bps + Support 5161 bps + Support 10322 bps + Support 20645 bps + Support 41290 bps + Support 82580 bps + Support 30967 bps + Support 7812 bps + Support 15625 bps + Support 31250 bps + Support 62500 bps + Support 125000 bps + Support 250000 bps + Support 93750 bps + Support 156250 bps + Support 9375 bps + Support 18750 bps + Support 37500 bps + Support 75000 bps + Support 150000 bps + Support 300000 bps + Support 112500 bps + Support 187500 bps + Support 5208 bps + Support 10416 bps + Support 20833 bps + Support 41666 bps + Support 83333 bps + Support 166666 bps + Support 104166 bps + Support 6250 bps + Support 12500 bps + Support 25000 bps + Support 50000 bps + Support 100000 bps + Support 200000 bps + Support 3906 bps + Support 46875 bps + Support 78125 bps + Support 4687 bps + Support 56250 bps + Support 5859 bps + Support 11718 bps + Support 23437 bps + Support 70312 bps + Support 117187 bps + Support 2604 bps + Support 52083 bps + Support 3125 bps + Support 1953 bps + Support 39062 bps + Support 2343 bps + Support 28125 bps + Support 2929 bps + Support 35156 bps + Support 58593 bps + dwMaxIFSD: 254 + dwSynchProtocols: 0x00000007 + 2-wire protocol + 3-wire protocol + I2C protocol + dwMechanical: 0x00000000 + No special characteristics + dwFeatures: 0x000207B2 + ....02 Automatic parameter configuration based on ATR data + ....10 Automatic ICC clock frequency change according to parameters + ....20 Automatic baud rate change according to frequency and Fi, Di params + ....80 Automatic PPS made by the CCID + ..01.. CCID can set ICC in clock stop mode + ..02.. NAD value other than 00 accepted (T=1) + ..04.. Automatic IFSD exchange as first exchange (T=1) + 02.... Short APDU level exchange + dwMaxCCIDMessageLength: 271 bytes + bClassGetResponse: 0xFF + echoes the APDU class + bClassEnveloppe: 0xFF + echoes the APDU class + wLcdLayout: 0x0000 + bPINSupport: 0x03 + PIN Verification supported + PIN Modification supported + bMaxCCIDBusySlots: 1 Index: readers/FujitsuSiemens_SmartCard_USB_2A.txt =================================================================== --- readers/FujitsuSiemens_SmartCard_USB_2A.txt (revision 0) +++ readers/FujitsuSiemens_SmartCard_USB_2A.txt (revision 2507) @@ -0,0 +1,170 @@ + idVendor: 0x0BF8 + iManufacturer: Fujitsu Siemens Computers + idProduct: 0x1006 + iProduct: SmartCard USB 2A + bcdDevice: 2.03 (firmware release?) + bLength: 9 + bDescriptorType: 4 + bInterfaceNumber: 1 + bAlternateSetting: 0 + bNumEndpoints: 3 + bInterfaceClass: 0x0B [Chip Card Interface Device Class (CCID)] + bInterfaceSubClass: 0 + bInterfaceProtocol: 0 + iInterface: 4 + CCID Class Descriptor + bLength: 0x36 + bDescriptorType: 0x21 + bcdCCID: 1.00 + bMaxSlotIndex: 0x00 + bVoltageSupport: 0x07 + 5.0V + 3.0V + 1.8V + dwProtocols: 0x0000 0x0003 + T=0 + T=1 + dwDefaultClock: 4.800 MHz + dwMaximumClock: 8.000 MHz + bNumClockSupported: 4 + Got 256 clock frequencies but was expecting 4 + Support 4000 kHz + Support 4800 kHz + Support 6000 kHz + Support 8000 kHz + dwDataRate: 10752 bps + dwMaxDataRate: 412903 bps + bNumDataRatesSupported: 106 + Got 256 data rates but was expecting 106 + Support 10752 bps + Support 21505 bps + Support 43010 bps + Support 86021 bps + Support 172043 bps + Support 344086 bps + Support 129032 bps + Support 215053 bps + Support 12903 bps + Support 25806 bps + Support 51612 bps + Support 103225 bps + Support 206451 bps + Support 412903 bps + Support 154838 bps + Support 258064 bps + Support 7168 bps + Support 14336 bps + Support 28673 bps + Support 57347 bps + Support 114695 bps + Support 229390 bps + Support 143369 bps + Support 8602 bps + Support 17204 bps + Support 34408 bps + Support 68817 bps + Support 137634 bps + Support 275268 bps + Support 5376 bps + Support 64516 bps + Support 107526 bps + Support 6451 bps + Support 77419 bps + Support 8064 bps + Support 16129 bps + Support 32258 bps + Support 96774 bps + Support 161290 bps + Support 3584 bps + Support 71684 bps + Support 4301 bps + Support 2688 bps + Support 53763 bps + Support 3225 bps + Support 38709 bps + Support 4032 bps + Support 48387 bps + Support 80645 bps + Support 2150 bps + Support 2580 bps + Support 5161 bps + Support 10322 bps + Support 20645 bps + Support 41290 bps + Support 82580 bps + Support 30967 bps + Support 7812 bps + Support 15625 bps + Support 31250 bps + Support 62500 bps + Support 125000 bps + Support 250000 bps + Support 93750 bps + Support 156250 bps + Support 9375 bps + Support 18750 bps + Support 37500 bps + Support 75000 bps + Support 150000 bps + Support 300000 bps + Support 112500 bps + Support 187500 bps + Support 5208 bps + Support 10416 bps + Support 20833 bps + Support 41666 bps + Support 83333 bps + Support 166666 bps + Support 104166 bps + Support 6250 bps + Support 12500 bps + Support 25000 bps + Support 50000 bps + Support 100000 bps + Support 200000 bps + Support 3906 bps + Support 46875 bps + Support 78125 bps + Support 4687 bps + Support 56250 bps + Support 5859 bps + Support 11718 bps + Support 23437 bps + Support 70312 bps + Support 117187 bps + Support 2604 bps + Support 52083 bps + Support 3125 bps + Support 1953 bps + Support 39062 bps + Support 2343 bps + Support 28125 bps + Support 2929 bps + Support 35156 bps + Support 58593 bps + dwMaxIFSD: 254 + dwSynchProtocols: 0x00000007 + 2-wire protocol + 3-wire protocol + I2C protocol + dwMechanical: 0x00000000 + No special characteristics + dwFeatures: 0x000207B2 + ....02 Automatic parameter configuration based on ATR data + ....10 Automatic ICC clock frequency change according to parameters + ....20 Automatic baud rate change according to frequency and Fi, Di params + ....80 Automatic PPS made by the CCID + ..01.. CCID can set ICC in clock stop mode + ..02.. NAD value other than 00 accepted (T=1) + ..04.. Automatic IFSD exchange as first exchange (T=1) + 02.... Short APDU level exchange + dwMaxCCIDMessageLength: 271 bytes + bClassGetResponse: 0xFF + echoes the APDU class + bClassEnveloppe: 0xFF + echoes the APDU class + wLcdLayout: 0x0000 + bPINSupport: 0x03 + PIN Verification supported + PIN Modification supported + bMaxCCIDBusySlots: 1 Index: configure.in =================================================================== --- configure.in (revision 2363) +++ configure.in (working copy) @@ -3,8 +3,8 @@ # $Id$ -# Require autoconf 2.52 -AC_PREREQ(2.52) +# Require autoconf 2.61 +AC_PREREQ(2.61) AC_INIT(ccid, 1.2.1) AC_CONFIG_SRCDIR(src/ifdhandler.c) @@ -69,7 +69,7 @@ AC_HEADER_TIME # Checks for library functions. -AC_CHECK_FUNCS(select strerror strncpy memcpy) +AC_CHECK_FUNCS(select strerror strncpy memcpy strlcpy) # Select OS specific versions of source files. AC_SUBST(BUNDLE_HOST) @@ -261,6 +261,9 @@ aclocal/Makefile src/Makefile readers/Makefile + contrib/Makefile + contrib/Kobil_mIDentity_switch/Makefile + contrib/RSA_SecurID/Makefile examples/Makefile) AC_OUTPUT Index: src/ifdhandler.c =================================================================== --- src/ifdhandler.c (revision 2363) +++ src/ifdhandler.c (working copy) @@ -24,6 +24,7 @@ #include <stdlib.h> #include <arpa/inet.h> #include "misc.h" +#include "config.h" #include <pcsclite.h> #include <ifdhandler.h> #include <reader.h> @@ -31,7 +32,6 @@ #include "ccid.h" #include "defs.h" #include "ccid_ifdhandler.h" -#include "config.h" #include "debug.h" #include "utils.h" #include "commands.h" @@ -953,7 +953,10 @@ rx_length = *RxLength; return_value = CmdXfrBlock(reader_index, TxLength, TxBuffer, &rx_length, RxBuffer, SendPci.Protocol); - *RxLength = rx_length; + if (IFD_SUCCESS == return_value) + *RxLength = rx_length; + else + *RxLength = 0; return return_value; } /* IFDHTransmitToICC */ @@ -981,6 +984,7 @@ int reader_index; DEBUG_INFO3("lun: %X, ControlCode: 0x%X", Lun, dwControlCode); + DEBUG_INFO_XXD("Control TxBuffer: ", TxBuffer, TxLength); reader_index = LunToReaderIndex(Lun); if ((-1 == reader_index) || (NULL == pdwBytesReturned)) @@ -1067,6 +1071,10 @@ *pdwBytesReturned = iBytesReturned; } + if (IFD_SUCCESS != return_value) + *pdwBytesReturned = 0; + + DEBUG_INFO_XXD("Control RxBuffer: ", RxBuffer, *pdwBytesReturned); return return_value; } /* IFDHControl */ Index: src/commands.c =================================================================== --- src/commands.c (revision 2363) +++ src/commands.c (working copy) @@ -23,6 +23,7 @@ #include <string.h> #include <stdlib.h> +#include <errno.h> #include <pcsclite.h> #include <ifdhandler.h> #include <reader.h> @@ -39,6 +40,11 @@ * I use code to change the user command and make the firmware happy */ #define BOGUS_PINPAD_FIRMWARE +/* The firmware of SCM readers reports dwMaxCCIDMessageLength = 263 + * instead of 270 so this prevents from sending a full length APDU + * of 260 bytes since the driver check this value */ +#define BOGUS_SCM_FIRMWARE_FOR_dwMaxCCIDMessageLength + #define max( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) #define IFD_ERROR_INSUFFICIENT_BUFFER 700 @@ -78,6 +84,84 @@ RESPONSECODE return_value = IFD_SUCCESS; _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index); + if (ICCD_A == ccid_descriptor->bInterfaceProtocol) + { + int r; + unsigned char pcbuffer[SIZE_GET_SLOT_STATUS]; + + /* first power off to reset the ICC state machine */ + r = CmdPowerOff(reader_index); + if (r != IFD_SUCCESS) + return r; + + /* wait for ready */ + r = CmdGetSlotStatus(reader_index, pcbuffer); + if (r != IFD_SUCCESS) + return r; + + /* Power On */ + r = ControlUSB(reader_index, 0xA1, 0x62, 0, buffer, *nlength); + + /* we got an error? */ + if (r < 0) + { + DEBUG_INFO2("ICC Power On failed: %s", strerror(errno)); + return IFD_COMMUNICATION_ERROR; + } + + *nlength = r; + + return IFD_SUCCESS; + } + + if (ICCD_B == ccid_descriptor->bInterfaceProtocol) + { + int r; + unsigned char tmp[MAX_ATR_SIZE+1]; + + /* first power off to reset the ICC state machine */ + r = CmdPowerOff(reader_index); + if (r != IFD_SUCCESS) + return r; + + /* Power On */ + r = ControlUSB(reader_index, 0x21, 0x62, 1, NULL, 0); + + /* we got an error? */ + if (r < 0) + { + DEBUG_INFO2("ICC Power On failed: %s", strerror(errno)); + return IFD_COMMUNICATION_ERROR; + } + + /* Data Block */ + r = ControlUSB(reader_index, 0xA1, 0x6F, 0, tmp, sizeof(tmp)); + + /* we got an error? */ + if (r < 0) + { + DEBUG_INFO2("ICC Data Block failed: %s", strerror(errno)); + return IFD_COMMUNICATION_ERROR; + } + + if (tmp[0] != 0x00) + { + DEBUG_CRITICAL2("bResponseType: 0x%02X", tmp[0]); + + /* Status Information? */ + if (0x40 == tmp[0]) + ccid_error(tmp[2], __FILE__, __LINE__, __FUNCTION__); + return IFD_COMMUNICATION_ERROR; + } + + DEBUG_INFO_XXD("Data Block: ", tmp, r); + if (*nlength > r-1) + *nlength = r-1; + memcpy(buffer, tmp+1, *nlength); + + return IFD_SUCCESS; + } + /* store length of buffer[] */ length = *nlength; @@ -118,12 +202,12 @@ ((GEMPC433 == ccid_descriptor->readerID) || (CHERRYXX33 == ccid_descriptor->readerID))) { - unsigned char cmd[] = {0x1F, 0x01}; - unsigned char res[1]; - unsigned int res_length = sizeof(res); + unsigned char cmd_tmp[] = {0x1F, 0x01}; + unsigned char res_tmp[1]; + unsigned int res_length = sizeof(res_tmp); - if ((return_value = CmdEscape(reader_index, cmd, sizeof(cmd), res, - &res_length)) != IFD_SUCCESS) + if ((return_value = CmdEscape(reader_index, cmd_tmp, + sizeof(cmd_tmp), res_tmp, &res_length)) != IFD_SUCCESS) return return_value; /* avoid looping if we can't switch mode */ @@ -188,21 +272,18 @@ if (TxLength > 19+CMD_BUF_SIZE) /* command too large? */ { DEBUG_INFO3("Command too long: %d > %d", TxLength, 19+CMD_BUF_SIZE); - *RxLength = 0; return IFD_NOT_SUPPORTED; } if (TxLength < 19+4 /* 4 = APDU size */) /* command too short? */ { DEBUG_INFO3("Command too short: %d < %d", TxLength, 19+4); - *RxLength = 0; return IFD_NOT_SUPPORTED; } if (dw2i(TxBuffer, 15) + 19 != TxLength) /* ulDataLength field coherency */ { DEBUG_INFO3("Wrong lengths: %d %d", dw2i(TxBuffer, 15) + 19, TxLength); - *RxLength = 0; return IFD_NOT_SUPPORTED; } @@ -288,16 +369,16 @@ if ((SPR532 == ccid_descriptor->readerID) && (TxBuffer[15] == 4)) { RESPONSECODE return_value; - unsigned char cmd[] = { 0x80, 0x02, 0x00 }; - unsigned char res[1]; - unsigned int res_length = sizeof(res); + unsigned char cmd_tmp[] = { 0x80, 0x02, 0x00 }; + unsigned char res_tmp[1]; + unsigned int res_length = sizeof(res_tmp); /* the SPR532 will append the PIN code without any padding */ - return_value = CmdEscape(reader_index, cmd, sizeof(cmd), res, - &res_length); + return_value = CmdEscape(reader_index, cmd_tmp, sizeof(cmd_tmp), + res_tmp, &res_length); if (return_value != IFD_SUCCESS) { - ccid_error(res[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__); + ccid_error(res_tmp[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__); return return_value; } } @@ -308,10 +389,7 @@ ccid_descriptor -> readTimeout = max(30, TxBuffer[0]+10); /* at least 30 seconds */ if (WritePort(reader_index, a, cmd) != STATUS_SUCCESS) - { - *RxLength = 0; return IFD_COMMUNICATION_ERROR; - } ret = CCID_Receive(reader_index, RxLength, RxBuffer, NULL); @@ -355,6 +433,9 @@ _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index); int old_read_timeout; RESPONSECODE ret; +#ifdef BOGUS_PINPAD_FIRMWARE + int bNumberMessages = 0; /* for GemPC Pinpad */ +#endif cmd[0] = 0x69; /* Secure */ cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */ @@ -369,21 +450,18 @@ if (TxLength > 24+CMD_BUF_SIZE) /* command too large? */ { DEBUG_INFO3("Command too long: %d > %d", TxLength, 24+CMD_BUF_SIZE); - *RxLength = 0; return IFD_NOT_SUPPORTED; } if (TxLength < 24+4 /* 4 = APDU size */) /* command too short? */ { DEBUG_INFO3("Command too short: %d < %d", TxLength, 24+4); - *RxLength = 0; return IFD_NOT_SUPPORTED; } if (dw2i(TxBuffer, 20) + 24 != TxLength) /* ulDataLength field coherency */ { DEBUG_INFO3("Wrong lengths: %d %d", dw2i(TxBuffer, 20) + 24, TxLength); - *RxLength = 0; return IFD_NOT_SUPPORTED; } @@ -391,7 +469,6 @@ if (TxBuffer[11] > 3) { DEBUG_INFO2("Wrong bNumberMessage: %d", TxBuffer[11]); - *RxLength = 0; return IFD_NOT_SUPPORTED; } @@ -441,6 +518,7 @@ /* the reader does not support any other value than 3 for the number * of messages */ + bNumberMessages = TxBuffer[11]; if (0x03 != TxBuffer[11]) { DEBUG_INFO2("Correct bNumberMessages for GemPC Pinpad (was %d)", @@ -519,6 +597,9 @@ { cmd[21] = 0x00; /* set bNumberMessages to 0 */ } + + if (GEMPCPINPAD == ccid_descriptor->readerID) + cmd[21] = bNumberMessages; /* restore the real value */ #endif /* We know the size of the CCID message now */ @@ -528,10 +609,7 @@ ccid_descriptor -> readTimeout = max(30, TxBuffer[0]+10); /* at least 30 seconds */ if (WritePort(reader_index, a, cmd) != STATUS_SUCCESS) - { - *RxLength = 0; return IFD_COMMUNICATION_ERROR; - } ret = CCID_Receive(reader_index, RxLength, RxBuffer, NULL); @@ -662,6 +740,51 @@ RESPONSECODE return_value = IFD_SUCCESS; _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index); + if (ICCD_A == ccid_descriptor->bInterfaceProtocol) + { + int r; + + /* PowerOff */ + r = ControlUSB(reader_index, 0x21, 0x63, 0, NULL, 0); + + /* we got an error? */ + if (r < 0) + { + DEBUG_INFO2("ICC Power Off failed: %s", strerror(errno)); + return IFD_COMMUNICATION_ERROR; + } + + return IFD_SUCCESS; + } + + if (ICCD_B == ccid_descriptor->bInterfaceProtocol) + { + int r; + unsigned char buffer[3]; + + /* PowerOff */ + r = ControlUSB(reader_index, 0x21, 0x63, 0, NULL, 0); + + /* we got an error? */ + if (r < 0) + { + DEBUG_INFO2("ICC Power Off failed: %s", strerror(errno)); + return IFD_COMMUNICATION_ERROR; + } + + /* SlotStatus */ + r = ControlUSB(reader_index, 0xA1, 0x81, 0, buffer, sizeof(buffer)); + + /* we got an error? */ + if (r < 0) + { + DEBUG_INFO2("ICC SlotStatus failed: %s", strerror(errno)); + return IFD_COMMUNICATION_ERROR; + } + + return IFD_SUCCESS; + } + cmd[0] = 0x63; /* IccPowerOff */ cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */ cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */ @@ -706,6 +829,80 @@ RESPONSECODE return_value = IFD_SUCCESS; _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index); + if (ICCD_A == ccid_descriptor->bInterfaceProtocol) + { + int r; + unsigned char status[1]; + +again_status: + /* SlotStatus */ + r = ControlUSB(reader_index, 0xA1, 0xA0, 0, status, sizeof(status)); + + /* we got an error? */ + if (r < 0) + { + DEBUG_INFO2("ICC Slot Status failed: %s", strerror(errno)); + if (ENODEV == errno) + return IFD_NO_SUCH_DEVICE; + return IFD_COMMUNICATION_ERROR; + } + + /* busy */ + if (status[0] & 0x40) + { + DEBUG_INFO2("Busy: 0x%02X", status[0]); + usleep(1000 * 10); + goto again_status; + } + + /* simulate a CCID bStatus */ + /* present and active by default */ + buffer[7] = CCID_ICC_PRESENT_ACTIVE; + + /* mute */ + if (0x80 == status[0]) + buffer[7] = CCID_ICC_ABSENT; + + /* store the status for CmdXfrBlockCHAR_T0() */ + buffer[0] = status[0]; + + return IFD_SUCCESS; + } + + if (ICCD_B == ccid_descriptor->bInterfaceProtocol) + { + int r; + unsigned char buffer_tmp[3]; + + /* SlotStatus */ + r = ControlUSB(reader_index, 0xA1, 0x81, 0, buffer_tmp, + sizeof(buffer_tmp)); + + /* we got an error? */ + if (r < 0) + { + DEBUG_INFO2("ICC Slot Status failed: %s", strerror(errno)); + if (ENODEV == errno) + return IFD_NO_SUCH_DEVICE; + return IFD_COMMUNICATION_ERROR; + } + + /* simulate a CCID bStatus */ + switch (buffer_tmp[1] & 0x03) + { + case 0: + buffer[7] = CCID_ICC_PRESENT_ACTIVE; + break; + case 1: + buffer[7] = CCID_ICC_PRESENT_INACTIVE; + break; + case 2: + case 3: + buffer[7] = CCID_ICC_ABSENT; + } + return IFD_SUCCESS; + } + cmd[0] = 0x65; /* GetSlotStatus */ cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */ cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */ @@ -785,8 +982,6 @@ case CCID_CLASS_EXTENDED_APDU: return_value = CmdXfrBlockAPDU_extended(reader_index, tx_length, tx_buffer, rx_length, rx_buffer); - if (return_value != IFD_SUCCESS) - *rx_length = 0; break; case CCID_CLASS_CHARACTER: @@ -802,7 +997,6 @@ break; default: - *rx_length = 0; return_value = IFD_COMMUNICATION_ERROR; } @@ -822,6 +1016,46 @@ _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index); status_t ret; + if (ICCD_A == ccid_descriptor->bInterfaceProtocol) + { + int r; + + /* Xfr Block */ + r = ControlUSB(reader_index, 0x21, 0x65, 0, tx_buffer, tx_length); + + /* we got an error? */ + if (r < 0) + { + DEBUG_INFO2("ICC Xfr Block failed: %s", strerror(errno)); + return IFD_COMMUNICATION_ERROR; + } + + return IFD_SUCCESS; + } + + if (ICCD_B == ccid_descriptor->bInterfaceProtocol) + { + int r; + + /* nul block so we are chaining */ + if (NULL == tx_buffer) + rx_length = 0x10; /* bLevelParameter */ + + /* Xfr Block */ + DEBUG_COMM2("chain parameter: %d", rx_length); + r = ControlUSB(reader_index, 0x21, 0x65, rx_length << 8, tx_buffer, + tx_length); + + /* we got an error? */ + if (r < 0) + { + DEBUG_INFO2("ICC Xfr Block failed: %s", strerror(errno)); + return IFD_COMMUNICATION_ERROR; + } + + return IFD_SUCCESS; + } + cmd[0] = 0x6F; /* XfrBlock */ i2dw(tx_length, cmd+1); /* APDU length */ cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */ @@ -860,14 +1094,103 @@ unsigned char cmd[10+CMD_BUF_SIZE]; /* CCID + APDU buffer */ unsigned int length; RESPONSECODE return_value = IFD_SUCCESS; + _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index); status_t ret; + if (ICCD_A == ccid_descriptor->bInterfaceProtocol) + { + int r; + + /* Data Block */ + r = ControlUSB(reader_index, 0xA1, 0x6F, 0, rx_buffer, *rx_length); + + /* we got an error? */ + if (r < 0) + { + DEBUG_INFO2("ICC Data Block failed: %s", strerror(errno)); + return IFD_COMMUNICATION_ERROR; + } + + return IFD_SUCCESS; + } + + if (ICCD_B == ccid_descriptor->bInterfaceProtocol) + { + int r; + unsigned char rx_tmp[4]; + + /* read a nul block. buffer need to be at least 4-bytes */ + if (NULL == rx_buffer) + { + rx_buffer = rx_tmp; + *rx_length = sizeof(rx_tmp); + } + +time_request_ICCD_B: + /* Data Block */ + r = ControlUSB(reader_index, 0xA1, 0x6F, 0, rx_buffer, *rx_length); + + /* we got an error? */ + if (r < 0) + { + DEBUG_INFO2("ICC Data Block failed: %s", strerror(errno)); + return IFD_COMMUNICATION_ERROR; + } + + /* bResponseType */ + switch (rx_buffer[0]) + { + case 0x00: + /* the abData field contains the information created by the + * preceding request */ + break; + + case 0x40: + /* Status Information */ + ccid_error(rx_buffer[2], __FILE__, __LINE__, __FUNCTION__); + return IFD_COMMUNICATION_ERROR; + + case 0x80: + /* Polling */ + { + int delay; + + delay = (rx_buffer[2] << 8) + rx_buffer[1]; + DEBUG_COMM2("Pooling delay: %d", delay); + + if (0 == delay) + /* host select the delay */ + delay = 1; + usleep(delay * 1000 * 10); + goto time_request_ICCD_B; + } + + case 0x01: + case 0x02: + case 0x03: + case 0x10: + /* Extended case + * Only valid for Data Block frames */ + if (chain_parameter) + *chain_parameter = rx_buffer[0]; + break; + + default: + DEBUG_CRITICAL2("Unknown bResponseType: 0x%02X", rx_buffer[0]); + return IFD_COMMUNICATION_ERROR; + } + + memmove(rx_buffer, rx_buffer+1, r-1); + *rx_length = r-1; + + return IFD_SUCCESS; + } + time_request: length = sizeof(cmd); ret = ReadPort(reader_index, &length, cmd); if (ret != STATUS_SUCCESS) { - *rx_length = 0; if (STATUS_NO_SUCH_DEVICE == ret) return IFD_NO_SUCH_DEVICE; return IFD_COMMUNICATION_ERROR; @@ -876,7 +1199,6 @@ if (length < STATUS_OFFSET+1) { DEBUG_CRITICAL2("Not enough data received: %d bytes", length); - *rx_length = 0; return IFD_COMMUNICATION_ERROR; } @@ -902,11 +1224,9 @@ return IFD_SUCCESS; case 0xFD: /* Parity error during exchange */ - *rx_length = 0; /* nothing received */ return IFD_PARITY_ERROR; default: - *rx_length = 0; /* nothing received */ return IFD_COMMUNICATION_ERROR; } } @@ -953,6 +1273,15 @@ unsigned int local_rx_length, received_length; int buffer_overflow = 0; + if (ICCD_B == ccid_descriptor->bInterfaceProtocol) + { + /* length is on 16-bits only + * if a size > 0x1000 is used then usb_control_msg() fails with + * "Invalid argument" */ + if (*rx_length > 0x1000) + *rx_length = 0x1000; + } + DEBUG_COMM2("T=0 (extended): %d bytes", tx_length); /* send the APDU */ @@ -1087,9 +1416,20 @@ /* command length too big for CCID reader? */ if (tx_length > ccid_descriptor->dwMaxCCIDMessageLength-10) { - DEBUG_CRITICAL3("Command too long (%d bytes) for max: %d bytes", +#ifdef BOGUS_SCM_FIRMWARE_FOR_dwMaxCCIDMessageLength + if (263 == ccid_descriptor->dwMaxCCIDMessageLength) + { + DEBUG_INFO3("Command too long (%d bytes) for max: %d bytes." + " SCM reader with bogus firmware?", tx_length, ccid_descriptor->dwMaxCCIDMessageLength-10); - return IFD_COMMUNICATION_ERROR; + } + else +#endif + { + DEBUG_CRITICAL3("Command too long (%d bytes) for max: %d bytes", + tx_length, ccid_descriptor->dwMaxCCIDMessageLength-10); + return IFD_COMMUNICATION_ERROR; + } } /* command length too big for CCID driver? */ @@ -1335,9 +1675,76 @@ unsigned int exp_len, in_len; unsigned char ins, *in_buf; RESPONSECODE return_value = IFD_SUCCESS; + _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index); DEBUG_COMM2("T=0: %d bytes", snd_len); + if (ICCD_A == ccid_descriptor->bInterfaceProtocol) + { + unsigned char pcbuffer[SIZE_GET_SLOT_STATUS]; + + /* Command to send to the smart card (must be 5 bytes) */ + memset(cmd, 0, sizeof(cmd)); + if (snd_len == 4) + { + memcpy(cmd, snd_buf, 4); + snd_buf += 4; + snd_len -= 4; + } + else + { + memcpy(cmd, snd_buf, 5); + snd_buf += 5; + snd_len -= 5; + } + + /* at most 5 bytes */ + return_value = CCID_Transmit(reader_index, 5, cmd, 0, 0); + if (return_value != IFD_SUCCESS) + return return_value; + + /* wait for ready */ + return_value = CmdGetSlotStatus(reader_index, pcbuffer); + if (return_value != IFD_SUCCESS) + return return_value; + + if ((0x20 != pcbuffer[0]) && (snd_len > 0)) + { + /* continue sending the APDU */ + return_value = CCID_Transmit(reader_index, snd_len, snd_buf, 0, 0); + if (return_value != IFD_SUCCESS) + return return_value; + } + else + { + if ((0x20 == pcbuffer[0]) && (*rcv_len > 2)) + /* we will just read SW1-SW2 */ + *rcv_len = 2; + + return_value = CCID_Receive(reader_index, rcv_len, rcv_buf, NULL); + if (return_value != IFD_SUCCESS) + DEBUG_CRITICAL("CCID_Receive failed"); + + return return_value; + } + + /* wait for ready */ + return_value = CmdGetSlotStatus(reader_index, pcbuffer); + if (return_value != IFD_SUCCESS) + return return_value; + + if ((0x20 == pcbuffer[0]) && (*rcv_len > 2)) + /* we will just read SW1-SW2 */ + *rcv_len = 2; + + /* read SW1-SW2 */ + return_value = CCID_Receive(reader_index, rcv_len, rcv_buf, NULL); + if (return_value != IFD_SUCCESS) + DEBUG_CRITICAL("CCID_Receive failed"); + + return return_value; + } + in_buf = tmp_buf; in_len = 0; *rcv_len = 0; @@ -1473,10 +1880,7 @@ tx_buffer, tx_length, rx_buffer, *rx_length); if (ret < 0) - { - *rx_length = 0; return_value = IFD_COMMUNICATION_ERROR; - } else *rx_length = ret; Index: src/ccid.c =================================================================== --- src/ccid.c (revision 2363) +++ src/ccid.c (working copy) @@ -73,7 +73,7 @@ { #define L10N_HEADER_SIZE 5 #define L10N_STRING_MAX_SIZE 16 -#define L10N_NB_STRING 9 +#define L10N_NB_STRING 10 unsigned char cmd[L10N_HEADER_SIZE + L10N_NB_STRING * L10N_STRING_MAX_SIZE]; unsigned char res[20]; @@ -89,7 +89,8 @@ "Delai depasse", "* essai restant", "Inserer carte", - "Erreur carte" }; + "Erreur carte", + "PIN bloque" }; const char *de[] = { "PIN eingeben", @@ -100,7 +101,8 @@ "Zeit abgelaufen", "* Versuche ubrig", "Karte einstecken", - "Fehler Karte" }; + "Fehler Karte", + "PIN blockiert" }; const char *es[] = { "Introducir PIN", @@ -111,7 +113,8 @@ "Tiempo Agotado", "* ensayos quedan", "Introducir Tarj.", - "Error en Tarjeta" }; + "Error en Tarjeta", + "PIN bloqueado" }; const char *it[] = { "Inserire PIN", @@ -122,8 +125,45 @@ "Tempo scaduto", "* prove rimaste", "Inserire Carta", - "Errore Carta" }; + "Errore Carta", + "PIN ostruito"}; + const char *pt[] = { + "Insira PIN", + "Novo PIN", + "Conf. novo PIN", + "PIN OK", + "PIN falhou!", + "Tempo expirou", + "* tentiv. restam", + "Introduza cartao", + "Erro cartao", + "PIN bloqueado" }; + + const char *nl[] = { + "Inbrengen code", + "Nieuwe code", + "Bevestig code", + "Code aanvaard", + "Foute code", + "Time out", + "* Nog Pogingen", + "Kaart inbrengen", + "Kaart fout", + "Kaart blok" }; + + const char *tr[] = { + "PIN Giriniz", + "Yeni PIN", + "PIN Onayala", + "PIN OK", + "Yanlis PIN", + "Zaman Asimi", + "* deneme kaldi", + "Karti Takiniz", + "Kart Hatasi", + "Kart Kilitli" }; + const char *en[] = { "Enter PIN", "New PIN", @@ -133,7 +173,8 @@ "Time Out", "* retries left", "Insert Card", - "Card Error" }; + "Card Error", + "PIN blocked" }; char *lang; const char **l10n; @@ -151,6 +192,12 @@ l10n = es; else if (0 == strncmp(lang, "it", 2)) l10n = it; + else if (0 == strncmp(lang, "pt", 2)) + l10n = pt; + else if (0 == strncmp(lang, "nl", 2)) + l10n = nl; + else if (0 == strncmp(lang, "tr", 2)) + l10n = tr; else l10n = en; } @@ -233,6 +280,38 @@ break; } + /* ICCD type A */ + if (ICCD_A == ccid_descriptor->bInterfaceProtocol) + { + unsigned char tmp[MAX_ATR_SIZE]; + unsigned int n = sizeof(tmp); + + DEBUG_COMM("ICCD type A"); + CmdPowerOff(reader_index); + CmdPowerOn(reader_index, &n, tmp, CCID_CLASS_AUTO_VOLTAGE); + CmdPowerOff(reader_index); + } + + /* ICCD type B */ + if (ICCD_B == ccid_descriptor->bInterfaceProtocol) + { + unsigned char tmp[MAX_ATR_SIZE]; + unsigned int n = sizeof(tmp); + + DEBUG_COMM("ICCD type B"); + if (CCID_CLASS_SHORT_APDU == + (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)) + { + /* use the extended APDU comm alogorithm */ + ccid_descriptor->dwFeatures &= ~CCID_CLASS_EXCHANGE_MASK; + ccid_descriptor->dwFeatures |= CCID_CLASS_EXTENDED_APDU; + } + + CmdPowerOff(reader_index); + CmdPowerOn(reader_index, &n, tmp, CCID_CLASS_AUTO_VOLTAGE); + CmdPowerOff(reader_index); + } + return 0; } /* ccid_open_hack */ Index: src/ccid.h =================================================================== --- src/ccid.h (revision 2363) +++ src/ccid.h (working copy) @@ -90,6 +90,11 @@ * Card protocol */ int cardProtocol; + + /* + * bInterfaceProtocol (CCID, ICCD-A, ICCD-B) + */ + int bInterfaceProtocol; } _ccid_descriptor; /* Features from dwFeatures */ @@ -118,6 +123,10 @@ #define CCID_COMMAND_FAILED 0x40 /* 01 0000 00 */ #define CCID_TIME_EXTENSION 0x80 /* 10 0000 00 */ +/* bInterfaceProtocol for ICCD */ +#define ICCD_A 1 /* ICCD Version A */ +#define ICCD_B 2 /* ICCD Version B */ + /* Product identification for special treatments */ #define GEMPC433 0x08E64433 #define GEMPCKEY 0x08E63438 Index: src/parse.c =================================================================== --- src/parse.c (revision 2363) +++ src/parse.c (working copy) @@ -126,7 +126,7 @@ { struct usb_interface_descriptor *usb_interface; unsigned char *extra; - char buffer[255]; + unsigned char buffer[256*sizeof(int)]; /* maximum is 256 records */ /* * Vendor/model name @@ -166,6 +166,23 @@ printf(" bAlternateSetting: %d\n", usb_interface->bAlternateSetting); printf(" bNumEndpoints: %d\n", usb_interface->bNumEndpoints); + switch (usb_interface->bNumEndpoints) + { + case 0: + printf(" Control only\n"); + break; + case 1: + printf(" Interrupt-IN\n"); + break; + case 2: + printf(" bulk-IN and bulk-OUT\n"); + break; + case 3: + printf(" bulk-IN, bulk-OUT and Interrupt-IN\n"); + break; + default: + printf(" UNKNOWN value\n"); + } printf(" bInterfaceClass: 0x%02X", usb_interface->bInterfaceClass); if (usb_interface->bInterfaceClass == 0x0b) @@ -184,8 +201,20 @@ printf(" UNSUPPORTED SubClass\n"); printf(" bInterfaceProtocol: %d\n", usb_interface->bInterfaceProtocol); - if (usb_interface->bInterfaceProtocol) - printf(" UNSUPPORTED InterfaceProtocol\n"); + switch (usb_interface->bInterfaceProtocol) + { + case 0: + printf(" bulk transfer, optional interrupt-IN\n"); + break; + case 1: + printf(" ICCD Version A, Control transfers, (no interrupt-IN)\n"); + break; + case 2: + printf(" ICCD Version B, Control transfers, (optional interrupt-IN)\n"); + break; + default: + printf(" UNSUPPORTED InterfaceProtocol\n"); + } printf(" iInterface: %d\n", usb_interface->iInterface); @@ -243,7 +272,6 @@ printf(" bNumClockSupported: %d %s\n", extra[18], extra[18] ? "" : "(will use whatever is returned)"); { - unsigned char buffer[256*sizeof(int)]; /* maximum is 256 records */ int n; /* See CCID 3.7.2 page 25 */ @@ -252,13 +280,20 @@ 0x02, /* GET CLOCK FREQUENCIES */ 0x00, /* value */ usb_interface->bInterfaceNumber, /* interface */ - (char *)buffer, + buffer, sizeof(buffer), 2 * 1000); /* we got an error? */ if (n <= 0) - printf(" IFD does not support GET CLOCK FREQUENCIES request\n"); + { + printf(" IFD does not support GET CLOCK FREQUENCIES request: %s\n", strerror(errno)); + if (EBUSY == errno) + { + printf(" \33[01;31mPlease, stop pcscd and retry\33[0m\n\n"); + return TRUE; + } + } else if (n % 4) /* not a multiple of 4 */ printf(" wrong size for GET CLOCK FREQUENCIES: %d\n", n); @@ -286,7 +321,6 @@ printf(" bNumDataRatesSupported: %d %s\n", extra[27], extra[27] ? "" : "(will use whatever is returned)"); { - unsigned char buffer[256*sizeof(int)]; /* maximum is 256 records */ int n; /* See CCID 3.7.3 page 25 */ @@ -295,13 +329,14 @@ 0x03, /* GET DATA RATES */ 0x00, /* value */ usb_interface->bInterfaceNumber, /* interface */ - (char *)buffer, + buffer, sizeof(buffer), 2 * 1000); /* we got an error? */ if (n <= 0) - printf(" IFD does not support GET_DATA_RATES request\n"); + printf(" IFD does not support GET_DATA_RATES request: %s\n", + strerror(errno)); else if (n % 4) /* not a multiple of 4 */ printf(" wrong size for GET_DATA_RATES: %d\n", n); @@ -368,6 +403,8 @@ printf(" ..02.. NAD value other than 00 accepted (T=1)\n"); if (extra[41] & 0x04) printf(" ..04.. Automatic IFSD exchange as first exchange (T=1)\n"); + if (extra[41] & 0x08) + printf(" ..08.. Unknown (ICCD?)\n"); switch (extra[42] & 0x07) { case 0x00: Index: src/ccid_usb.c =================================================================== --- src/ccid_usb.c (revision 2363) +++ src/ccid_usb.c (working copy) @@ -82,7 +82,7 @@ /* The _usbDevice structure must be defined before including ccid_usb.h */ #include "ccid_usb.h" -static int get_end_points(struct usb_device *dev, _usbDevice *usb_device); +static int get_end_points(struct usb_device *dev, _usbDevice *usbdevice); int ccid_check_firmware(struct usb_device *dev); static unsigned int *get_data_rates(unsigned int reader_index, struct usb_device *dev); @@ -428,6 +428,7 @@ usbDevice[reader_index].ccid.bCurrentSlotIndex = 0; usbDevice[reader_index].ccid.readTimeout = DEFAULT_COM_READ_TIMEOUT; usbDevice[reader_index].ccid.arrayOfSupportedDataRates = get_data_rates(reader_index, dev); + usbDevice[reader_index].ccid.bInterfaceProtocol = usb_interface->altsetting->bInterfaceProtocol; goto end; } } @@ -596,7 +597,7 @@ * get_end_points * ****************************************************************************/ -static int get_end_points(struct usb_device *dev, _usbDevice *usb_device) +static int get_end_points(struct usb_device *dev, _usbDevice *usbdevice) { int i; int bEndpointAddress; @@ -605,7 +606,7 @@ /* * 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out */ - for (i=0; i<3; i++) + for (i=0; i<usb_interface->altsetting->bNumEndpoints; i++) { if (usb_interface->altsetting->endpoint[i].bmAttributes != USB_ENDPOINT_TYPE_BULK) continue; @@ -613,10 +614,10 @@ bEndpointAddress = usb_interface->altsetting->endpoint[i].bEndpointAddress; if ((bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN) - usb_device->bulk_in = bEndpointAddress; + usbdevice->bulk_in = bEndpointAddress; if ((bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_OUT) - usb_device->bulk_out = bEndpointAddress; + usbdevice->bulk_out = bEndpointAddress; } return 0; @@ -727,14 +728,11 @@ unsigned int *int_array; /* See CCID 3.7.3 page 25 */ - n = usb_control_msg(usbDevice[reader_index].handle, + n = ControlUSB(reader_index, 0xA1, /* request type */ 0x03, /* GET_DATA_RATES */ 0x00, /* value */ - usbDevice[reader_index].interface, /* interface */ - (char *)buffer, - sizeof(buffer), - usbDevice[reader_index].ccid.readTimeout * 1000); + buffer, sizeof(buffer)); /* we got an error? */ if (n <= 0) @@ -785,3 +783,23 @@ return int_array; } +int ControlUSB(int reader_index, int requesttype, int request, int value, + unsigned char *bytes, unsigned int size) +{ + int ret; + + DEBUG_COMM2("request: 0x%02X", request); + + if (0 == (requesttype & 0x80)) + DEBUG_XXD("send: ", bytes, size); + + ret = usb_control_msg(usbDevice[reader_index].handle, requesttype, + request, value, usbDevice[reader_index].interface, (char *)bytes, size, + usbDevice[reader_index].ccid.readTimeout * 1000); + + if (requesttype & 0x80) + DEBUG_XXD("receive: ", bytes, ret); + + return ret; +} + Index: src/ccid_usb.h =================================================================== --- src/ccid_usb.h (revision 2363) +++ src/ccid_usb.h (working copy) @@ -21,6 +21,8 @@ * $Id$ */ +#ifndef __CCID_USB_H__ +#define __CCID_USB_H__ status_t OpenUSB(unsigned int reader_index, int channel); status_t OpenUSBByName(unsigned int reader_index, /*@null@*/ char *device); @@ -37,3 +39,7 @@ /*@null@*/ struct usb_interface *get_ccid_usb_interface(struct usb_device *dev); #endif +int ControlUSB(int reader_index, int requesttype, int request, int value, + unsigned char *bytes, unsigned int size); + +#endif Index: src/pcscd_ccid.rules =================================================================== --- src/pcscd_ccid.rules (revision 2363) +++ src/pcscd_ccid.rules (working copy) @@ -1,27 +1,32 @@ # udev rules for pcscd and CCID readers # Gemplus PCMCIA Card -#SUBSYSTEMS=="pcmcia", DRIVER=="serial_cs", ACTION=="add", SYSFS{prod_id1}=="Gemplus", SYSFS{prod_id2}=="SerialPort", SYSFS{prod_id3}=="GemPC Card", RUN+="/usr/sbin/pcscd --hotplug" +#SUBSYSTEMS=="pcmcia", DRIVER=="serial_cs", ACTION=="add", ATTRS{prod_id1}=="Gemplus", ATTRS{prod_id2}=="SerialPort", ATTRS{prod_id3}=="GemPC Card", RUN+="/usr/sbin/pcscd --hotplug" +# Kobil mIDentity +BUS=="usb", ATTRS{idVendor}=="0d46", ATTRS{idProduct}=="4081", ACTION=="add", RUN+="/usr/sbin/Kobil_mIDentity_switch" + # generic CCID device -BUS=="usb", SYSFS{bInterfaceClass}=="0b", ACTION=="add", RUN+="/usr/sbin/pcscd --hotplug" +BUS=="usb", ATTRS{bInterfaceClass}=="0b", ACTION=="add", RUN+="/usr/sbin/pcscd --hotplug" # non CCID generic (InterfaceClass: 0xFF) # CherrySmartTerminalST2XXX.txt -BUS=="usb", SYSFS{idVendor}=="046a", SYSFS{idProduct}=="003e", ACTION=="add", RUN+="/usr/sbin/pcscd --hotplug" +BUS=="usb", ATTRS{idVendor}=="046a", ATTRS{idProduct}=="003e", ACTION=="add", RUN+="/usr/sbin/pcscd --hotplug" # DellSK-3106.txt -BUS=="usb", SYSFS{idVendor}=="413c", SYSFS{idProduct}=="2100", ACTION=="add", RUN+="/usr/sbin/pcscd --hotplug" +BUS=="usb", ATTRS{idVendor}=="413c", ATTRS{idProduct}=="2100", ACTION=="add", RUN+="/usr/sbin/pcscd --hotplug" # MySmartPad.txt -BUS=="usb", SYSFS{idVendor}=="09be", SYSFS{idProduct}=="0002", ACTION=="add", RUN+="/usr/sbin/pcscd --hotplug" +BUS=="usb", ATTRS{idVendor}=="09be", ATTRS{idProduct}=="0002", ACTION=="add", RUN+="/usr/sbin/pcscd --hotplug" # SCR331-DI-NTTCom.txt -BUS=="usb", SYSFS{idVendor}=="04e6", SYSFS{idProduct}=="5120", ACTION=="add", RUN+="/usr/sbin/pcscd --hotplug" +BUS=="usb", ATTRS{idVendor}=="04e6", ATTRS{idProduct}=="5120", ACTION=="add", RUN+="/usr/sbin/pcscd --hotplug" # SCR331-DI.txt -BUS=="usb", SYSFS{idVendor}=="04e6", SYSFS{idProduct}=="5111", ACTION=="add", RUN+="/usr/sbin/pcscd --hotplug" +BUS=="usb", ATTRS{idVendor}=="04e6", ATTRS{idProduct}=="5111", ACTION=="add", RUN+="/usr/sbin/pcscd --hotplug" # SDI010.txt -BUS=="usb", SYSFS{idVendor}=="04e6", SYSFS{idProduct}=="5121", ACTION=="add", RUN+="/usr/sbin/pcscd --hotplug" +BUS=="usb", ATTRS{idVendor}=="04e6", ATTRS{idProduct}=="5121", ACTION=="add", RUN+="/usr/sbin/pcscd --hotplug" # SPR532.txt -BUS=="usb", SYSFS{idVendor}=="04e6", SYSFS{idProduct}=="e003", ACTION=="add", RUN+="/usr/sbin/pcscd --hotplug" +BUS=="usb", ATTRS{idVendor}=="04e6", ATTRS{idProduct}=="e003", ACTION=="add", RUN+="/usr/sbin/pcscd --hotplug" # Verisign_secure_storage_token.txt -BUS=="usb", SYSFS{idVendor}=="08e6", SYSFS{idProduct}=="1359", ACTION=="add", RUN+="/usr/sbin/pcscd --hotplug" +BUS=="usb", ATTRS{idVendor}=="08e6", ATTRS{idProduct}=="1359", ACTION=="add", RUN+="/usr/sbin/pcscd --hotplug" # Verisign_secure_token.txt -BUS=="usb", SYSFS{idVendor}=="08e6", SYSFS{idProduct}=="ace0", ACTION=="add", RUN+="/usr/sbin/pcscd --hotplug" +BUS=="usb", ATTRS{idVendor}=="08e6", ATTRS{idProduct}=="ace0", ACTION=="add", RUN+="/usr/sbin/pcscd --hotplug" +# SchlumbergerSema Cyberflex Access e-gate +BUS=="usb", ATTRS{idVendor}=="0973", ATTRS{idProduct}=="0003", ACTION=="add", RUN+="/usr/sbin/pcscd --hotplug" Index: src/debug.h =================================================================== --- src/debug.h (revision 2363) +++ src/debug.h (working copy) @@ -71,6 +71,8 @@ #define DEBUG_INFO4(fmt, data1, data2, data3) if (LogLevel & DEBUG_LEVEL_INFO) Log4(PCSC_LOG_INFO, fmt, data1, data2, data3) +#define DEBUG_INFO_XXD(msg, buffer, size) if (LogLevel & DEBUG_LEVEL_INFO) log_xxd(PCSC_LOG_INFO, msg, buffer, size) + /* DEBUG_PERIODIC */ #define DEBUG_PERIODIC(fmt) if (LogLevel & DEBUG_LEVEL_PERIODIC) Log1(PCSC_LOG_DEBUG, fmt) Index: Makefile.am =================================================================== --- Makefile.am (revision 2363) +++ Makefile.am (working copy) @@ -1,6 +1,6 @@ # $Id$ -SUBDIRS = aclocal src readers examples +SUBDIRS = aclocal src readers examples contrib AUX_DIST = \ $(ac_aux_dir)/aclocal.m4 \ @@ -24,7 +24,7 @@ $(SHELL) ./config.status --recheck ChangeLog: - svn2cl.sh --group-by-day --stdout --include-rev \ + svn2cl --group-by-day --stdout --include-rev \ | perl -pe 's/ rousseau/ Ludovic Rousseau/; \ s+trunk/Drivers/ccid/++g;' > $@ Index: README =================================================================== --- README (revision 2363) +++ README (working copy) @@ -49,7 +49,6 @@ - Kobil KAAN Base [19] - Kobil KAAN Advanced [20] - Kobil KAAN SIM III [21] -- Kobil mIDentity [22] - OmniKey CardMan 3121 [5] - RSA SecureID SID800 [50] - SCM Micro SCR 331 [6] @@ -85,6 +84,8 @@ - C3PO TLTC2USB - C3PO KBR36 - Gemplus GemPC Express +- Fujitsu Siemens Computers SmartCard USB 2A [53] +- Fujitsu Siemens Computers SmartCard Keyboard USB 2A [54] - HP USB Smart Card Keyboard [44] - HP USB Smartcard Reader - id3 Semiconductors CL1356D [45] (tested by me but I don't have the @@ -124,6 +125,11 @@ powerup fails with a Setcos card does work with the belgium eID (the reader is sold for this application) +- Kobil mIDentity [22] + Time requests are not managed correctly and make the firmware fails. + This is not a problem unless you use a time-consuming APDU like RSA + key generation. + A new firmware will correct the bug. Supported operating systems: @@ -533,6 +539,8 @@ [50] http://www.rsasecurity.com/products/securid/datasheets/SID800_DS_0205.pdf [51] http://www.omnikey.com/?id=products&tx_okprod_pi1[product]=39 [52] http://www.teobyxiring.com/ +[53] http://www.fujitsu-siemens.com/solutions/business_solutions/security/security_products/smartcase_scr_usbex.html +[54] http://www.fujitsu-siemens.com/solutions/business_solutions/security/security_products/smartcase_kbpc_cx.html $Id$ Index: examples/scardcontrol.c =================================================================== --- examples/scardcontrol.c (revision 2363) +++ examples/scardcontrol.c (working copy) @@ -30,8 +30,8 @@ #include <winscard.h> #include <reader.h> -#define VERIFY_PIN -#undef MODIFY_PIN +#undef VERIFY_PIN +#define MODIFY_PIN #ifndef TRUE #define TRUE 1 @@ -416,6 +416,12 @@ printf(" Secure modify PIN\n"); pin_modify = (PIN_MODIFY_STRUCTURE *)bSendBuffer; + /* Table for bConfirmPIN and bNumberMessage + * bConfirmPIN = 3, bNumberMessage = 3: "Enter Pin" "New Pin" "Confirm Pin" + * bConfirmPIN = 2, bNumberMessage = 2: "Enter Pin" "New Pin" + * bConfirmPIN = 1, bNumberMessage = 2: "New Pin" "Confirm Pin" + * bConfirmPIN = 0, bNumberMessage = 1: "New Pin" + */ /* PC/SC v2.0.2 Part 10 PIN verification data structure */ pin_modify -> bTimerOut = 0x00; pin_modify -> bTimerOut2 = 0x00; @@ -424,11 +430,11 @@ pin_modify -> bmPINLengthFormat = 0x00; pin_modify -> bInsertionOffsetOld = 0x00; /* offset from APDU start */ pin_modify -> bInsertionOffsetNew = 0x04; /* offset from APDU start */ - pin_modify -> wPINMaxExtraDigit = HOST_TO_CCID_16(0x0404); /* Min Max */ + pin_modify -> wPINMaxExtraDigit = HOST_TO_CCID_16(0x0408); /* Min Max */ pin_modify -> bConfirmPIN = 0x03; /* b0 set = confirmation requested */ /* b1 set = current PIN entry requested */ pin_modify -> bEntryValidationCondition = 0x02; /* validation key pressed */ - pin_modify -> bNumberMessage = 0x03; /* 3 for GemPC Pinpad, 0 for SPR532 */ + pin_modify -> bNumberMessage = 0x03; /* see table above */ pin_modify -> wLangId = HOST_TO_CCID_16(0x0904); pin_modify -> bMsgIndex1 = 0x00; pin_modify -> bMsgIndex2 = 0x00; @@ -477,7 +483,6 @@ fd_set fd; #endif struct timeval timeout; - int i; /* old PIN, new PIN, confirmation PIN */ /* if the command is aborted we will not read every "PIN" */ Index: contrib/GPL-2 =================================================================== --- contrib/GPL-2 (revision 0) +++ contrib/GPL-2 (revision 2507) @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. Index: contrib/RSA_SecurID/RSA_SecurID_getpasswd.1 =================================================================== --- contrib/RSA_SecurID/RSA_SecurID_getpasswd.1 (revision 0) +++ contrib/RSA_SecurID/RSA_SecurID_getpasswd.1 (revision 2507) @@ -0,0 +1,14 @@ +.TH RSA_SecurID_getpasswd 8 "February 2008" +.SH NAME +RSA_SecurID_getpasswd \- get the one-use password from a RSA sid-800 +token +. +.SH SYNOPSIS +.B RSA_SecurID_getpasswd +. +.SH DESCRIPTION +RSA_SecurID_getpasswd sends to stdout the one-use password also +displayed on the screen of a RSA sid-800 USB token. +. +.SH AUTHOR +Ludovic Rousseau <ludovic.rousseau@free.fr> Index: contrib/RSA_SecurID/RSA_SecurID_getpasswd.c =================================================================== --- contrib/RSA_SecurID/RSA_SecurID_getpasswd.c (revision 0) +++ contrib/RSA_SecurID/RSA_SecurID_getpasswd.c (revision 2507) @@ -0,0 +1,162 @@ +/* + RSA_SecurID_getpasswd.c: get the one-use password from a RSA sid-800 token + Copyright (C) 2006 Ludovic Rousseau <ludovic.rousseau@free.fr> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <winscard.h> + +/* PCSC error message pretty print */ +#define PCSC_ERROR_EXIT(rv, text) \ +if (rv != SCARD_S_SUCCESS) \ +{ \ + printf(text ": %s (0x%lX)\n", pcsc_stringify_error(rv), rv); \ + goto end; \ +} + +int main(void) +{ + unsigned char cmd1[] = { 0x00, 0xa4, 0x04, 0x00, 0x0a, 0xa0, 0x00, 0x00, 0x00, 0x63, 0x86, 0x53, 0x49, 0x44, 0x01}; + unsigned char cmd2[] = { 0x80, 0x56, 0x00, 0x00, 0x04 }; + unsigned char cmd3[] = { 0x80, 0x48, 0x00, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff }; + unsigned char cmd4[] = { 0x80, 0x44, 0x00, 0x00, 0x05}; + LONG rv; + SCARDCONTEXT hContext; + DWORD dwReaders; + LPSTR mszReaders = NULL; + char **readers = NULL; + SCARDHANDLE hCard; + DWORD dwActiveProtocol; + unsigned char bRecvBuffer[MAX_BUFFER_SIZE]; + DWORD length; + SCARD_IO_REQUEST pioRecvPci; + SCARD_IO_REQUEST pioSendPci; + + rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); + if (rv != SCARD_S_SUCCESS) + { + printf("SCardEstablishContext: Cannot Connect to Resource Manager %lX\n", rv); + return 1; + } + + /* Retrieve the available readers list */ + rv = SCardListReaders(hContext, NULL, NULL, &dwReaders); + PCSC_ERROR_EXIT(rv, "SCardListReader"); + + if (dwReaders < 4) + { + printf("No reader found!\n"); + return -1; + } + + mszReaders = malloc(sizeof(char)*dwReaders); + if (mszReaders == NULL) + { + printf("malloc: not enough memory\n"); + goto end; + } + + rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders); + PCSC_ERROR_EXIT(rv, "SCardListReader"); + + /* connect to the first reader */ + dwActiveProtocol = -1; + rv = SCardConnect(hContext, mszReaders, SCARD_SHARE_EXCLUSIVE, + SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol); + PCSC_ERROR_EXIT(rv, "SCardConnect") + + switch(dwActiveProtocol) + { + case SCARD_PROTOCOL_T0: + pioSendPci = *SCARD_PCI_T0; + break; + case SCARD_PROTOCOL_T1: + pioSendPci = *SCARD_PCI_T1; + break; + default: + printf("Unknown protocol\n"); + return -1; + } + + /* APDU select applet */ + length = sizeof(bRecvBuffer); + rv = SCardTransmit(hCard, &pioSendPci, cmd1, sizeof cmd1, + &pioRecvPci, bRecvBuffer, &length); + PCSC_ERROR_EXIT(rv, "SCardTransmit") + if ((length != 2) || (bRecvBuffer[0] != 0x90) || (bRecvBuffer[1] != 0x00)) + { + printf("cmd1 failed: %02X%02X\n", bRecvBuffer[0], bRecvBuffer[1]); + goto end; + } + + /* non ISO APDU */ + length = sizeof(bRecvBuffer); + rv = SCardTransmit(hCard, &pioSendPci, cmd2, sizeof cmd2, + &pioRecvPci, bRecvBuffer, &length); + PCSC_ERROR_EXIT(rv, "SCardTransmit") + if ((length != 6) || (bRecvBuffer[4] != 0x90) || (bRecvBuffer[5] != 0x00)) + { + printf("cmd2 failed (%ld) : %02X%02X\n", length, bRecvBuffer[4], + bRecvBuffer[5]); + goto end; + } + + /* get the argument for cmd3 from result of cmd2 */ + memcpy(cmd3+5, bRecvBuffer, 4); + + /* non ISO APDU */ + length = sizeof(bRecvBuffer); + rv = SCardTransmit(hCard, &pioSendPci, cmd3, sizeof cmd3, + &pioRecvPci, bRecvBuffer, &length); + PCSC_ERROR_EXIT(rv, "SCardTransmit") + if ((length != 2) || (bRecvBuffer[0] != 0x90) || (bRecvBuffer[1] != 0x00)) + { + printf("cmd2 failed (%ld) : %02X%02X\n", length, bRecvBuffer[0], + bRecvBuffer[1]); + goto end; + } + + /* non iSO APDU */ + length = sizeof(bRecvBuffer); + rv = SCardTransmit(hCard, &pioSendPci, cmd4, sizeof cmd4, + &pioRecvPci, bRecvBuffer, &length); + PCSC_ERROR_EXIT(rv, "SCardTransmit") + if ((length != 7) || (bRecvBuffer[5] != 0x90) || (bRecvBuffer[6] != 0x00)) + { + printf("cmd3 failed (%ld): %02X%02X\n", length, bRecvBuffer[5], + bRecvBuffer[6]); + goto end; + } + + printf("%02X%02X%02X\n", bRecvBuffer[2], bRecvBuffer[3], bRecvBuffer[4]); + +end: + /* We try to leave things as clean as possible */ + rv = SCardReleaseContext(hContext); + if (rv != SCARD_S_SUCCESS) + printf("SCardReleaseContext: %s (0x%lX)\n", pcsc_stringify_error(rv), + rv); + + /* free allocated memory */ + free(mszReaders); + free(readers); + + return 0; +} /* main */ + Index: contrib/RSA_SecurID/Makefile.am =================================================================== --- contrib/RSA_SecurID/Makefile.am (revision 0) +++ contrib/RSA_SecurID/Makefile.am (revision 2507) @@ -0,0 +1,9 @@ +bin_PROGRAMS = RSA_SecurID_getpasswd +RSA_SecurID_getpasswd_SOURCES = RSA_SecurID_getpasswd.c + +RSA_SecurID_getpasswd_CFLAGS = $(PCSC_CFLAGS) +RSA_SecurID_getpasswd_LDADD = $(PCSC_LIBS) + +man_MANS = RSA_SecurID_getpasswd.1 + +EXTRA_DIST = $(man_MANS) Index: contrib/Kobil_mIDentity_switch/README_Kobil_mIDentity_switch.txt =================================================================== --- contrib/Kobil_mIDentity_switch/README_Kobil_mIDentity_switch.txt (revision 0) +++ contrib/Kobil_mIDentity_switch/README_Kobil_mIDentity_switch.txt (revision 2507) @@ -0,0 +1,250 @@ +The midswitch program is used to activate the Kobil mIDenty smart card +CCID reader. + +The USB device is by default: + ID 0d46:4081 Kobil Systems GmbH mIDentity Basic/Classic (installationless) +and will be switched to: + ID 0d46:4001 Kobil Systems GmbH mIDentity Basic/Classic (composite device) + + +Bus 005 Device 016: ID 0d46:4081 Kobil Systems GmbH mIDentity Basic/Classic (installationless) +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0d46 Kobil Systems GmbH + idProduct 0x4081 mIDentity Basic/Classic (installationless) + bcdDevice 0.00 + iManufacturer 1 KOBIL Systems + iProduct 2 mIDentity M + iSerial 3 SN_K_05C901085 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 57 + bNumInterfaces 2 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 400mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 8 Mass Storage + bInterfaceSubClass 6 SCSI + bInterfaceProtocol 80 Bulk (Zip) + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x86 EP 6 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 3 Human Interface Devices + bInterfaceSubClass 1 Boot Interface Subclass + bInterfaceProtocol 0 None + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 8 + UNRECOGNIZED: 09 21 00 01 00 01 22 22 00 +Device Qualifier (for other device speed): + bLength 10 + bDescriptorType 6 + bcdUSB 2.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + bNumConfigurations 1 +Device Status: 0x0002 + (Bus Powered) + Remote Wakeup Enabled + + +Bus 005 Device 015: ID 0d46:4001 Kobil Systems GmbH mIDentity Basic/Classic (composite device) +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0d46 Kobil Systems GmbH + idProduct 0x4001 mIDentity Basic/Classic (composite device) + bcdDevice 0.00 + iManufacturer 1 KOBIL Systems + iProduct 2 mIDentity M + iSerial 3 SN_K_05C901085 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 134 + bNumInterfaces 3 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 400mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 8 Mass Storage + bInterfaceSubClass 6 SCSI + bInterfaceProtocol 80 Bulk (Zip) + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x86 EP 6 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 11 Chip/SmartCard + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + ChipCard Interface Descriptor: + bLength 54 + bDescriptorType 33 + bcdCCID 1.00 + nMaxSlotIndex 0 + bVoltageSupport 7 5.0V 3.0V 1.8V + dwProtocols 3 T=0 T=1 + dwDefaultClock 4000 + dwMaxiumumClock 4000 + bNumClockSupported 0 + dwDataRate 10752 bps + dwMaxDataRate 250000 bps + bNumDataRatesSupp. 0 + dwMaxIFSD 254 + dwSyncProtocols 00000000 + dwMechanical 00000000 + dwFeatures 000206BA + Auto configuration based on ATR + Auto voltage selection + Auto clock change + Auto baud rate change + Auto PPS made by CCID + NAD value other than 0x00 accpeted + Auto IFSD exchange + Short APDU level exchange + dwMaxCCIDMsgLen 271 + bClassGetResponse echo + bClassEnvelope echo + wlcdLayout none + bPINSupport 0 + bMaxCCIDBusySlots 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x04 EP 4 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x88 EP 8 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 2 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 3 Human Interface Devices + bInterfaceSubClass 1 Boot Interface Subclass + bInterfaceProtocol 0 None + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 10 + UNRECOGNIZED: 09 21 00 01 00 01 22 22 00 +Device Qualifier (for other device speed): + bLength 10 + bDescriptorType 6 + bcdUSB 2.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + bNumConfigurations 1 +Device Status: 0x0002 + (Bus Powered) + Remote Wakeup Enabled Index: contrib/Kobil_mIDentity_switch/Kobil_mIDentity_switch.c =================================================================== --- contrib/Kobil_mIDentity_switch/Kobil_mIDentity_switch.c (revision 0) +++ contrib/Kobil_mIDentity_switch/Kobil_mIDentity_switch.c (revision 2507) @@ -0,0 +1,201 @@ +/* + Activate the smartcard interface on the kobil midentity usb device + Copyright (C) 2006 Norbert Federa <norbert.federa@neoware.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Author: Norbert Federa <norbert.federa@neoware.com> +Date: 2006-04-06 + + +Description: + +This tool is needed to activate the smartcard interface on the kobil midentity +usb device (vendor 0x04D6 id 0x4081) + +Kobil's own implementation was a kernel usb driver which did just send a +usb_control_msg in the probe routine. + +We do the same via libusb and call this program from our /sbin/hotblug script +if the mIDentity gets added. + +The kobil switcher driver was found inside this zip ... +http://www.kobil.com/download/partner/KOBIL_mIDentity_SDK_Build_20060320_RELEASE.zip +... under Interfaces/Linux/module_with_binary_final.tar.gz. + +Here the interesting part of the kernel driver inside the probe function: + + if (dev->descriptor.idVendor == KOBIL_VENDOR_ID){ + printk("!!!!! DEVICE FOUND !!! !\n"); + ret = usb_control_msg(dev, + send_pipe, + 0x09, + 0x22, + 0x0200, + 0x0001, + switchCmd, + sizeof(switchCmd), + 5000); + } + +Initally the it did not work with libusb because the ioctl gets ignored with +the used RequestType of 0x22 in combination with index 0x0001, but index 0x0002 +worked. See usb/devio.c functions proc_control() -> check_ctrlrecip() -> +findintfep() in order to understand why. +*/ + +#include <stdio.h> +#include <string.h> +#include <usb.h> +#include <errno.h> + + +#define KOBIL_VENDOR_ID 0x0D46 +#define MID_DEVICE_ID 0x4081 +#define KOBIL_TIMEOUT 5000 +#define VAL_STARTUP_4080 1 +#define VAL_STARTUP_4000 2 +#define VAL_STARTUP_4020 3 +#define VAL_STARTUP_40A0 4 +#define HIDCMD_SWITCH_DEVICE 0x0004 + +#define bmRequestType 0x22 +#define bRequest 0x09 +#define wValue 0x0200 +#define wIndex 0x0002 /* this was originally 0x0001 */ + + +static int kobil_midentity_control_msg(usb_dev_handle *usb) +{ + int ret; + + char switchCmd[10]; + + unsigned char Sleep = 1; + unsigned char hardDisk = 1; + + unsigned char param = ((hardDisk)<<4) | (Sleep); + + memset(switchCmd, 0x0, sizeof(switchCmd)); + switchCmd[0] = HIDCMD_SWITCH_DEVICE>>8; + switchCmd[1] = HIDCMD_SWITCH_DEVICE; + switchCmd[5] = VAL_STARTUP_4000; + switchCmd[9] = param; + + ret = usb_control_msg(usb, bmRequestType, bRequest, wValue, wIndex, + switchCmd, sizeof(switchCmd), KOBIL_TIMEOUT); + + return(!(ret==sizeof(switchCmd))); +} + + +static int kobil_midentity_claim_interface(usb_dev_handle *usb, int ifnum) +{ + int rv; + + printf("claiming interface #%d ...\n", ifnum); + rv = usb_claim_interface(usb, ifnum); + if (rv == 0) + { + printf("success\n"); + return(rv); + } + +#ifndef __APPLE__ + printf("failed with error %d, trying to detach kernel driver ....\n", rv); + rv = usb_detach_kernel_driver_np(usb, ifnum); + if (rv == 0) + { + printf("success, claiming interface again ..."); + rv = usb_claim_interface(usb, ifnum); + if (rv == 0) + { + printf("success\n"); + return(rv); + } + } +#endif + printf("failed with error %d, giving up.\n", rv); + return(rv); +} + + +int main(int argc, char *argv[]) +{ + struct usb_bus *bus; + struct usb_device *dev = NULL; + struct usb_device *found_dev = NULL; + usb_dev_handle *usb = NULL; + int rv; + + usb_init(); + + usb_find_busses(); + usb_find_devices(); + + for (bus = usb_busses; bus; bus = bus->next) + { + for (dev = bus->devices; dev; dev = dev->next) + { + printf("vendor/product: %04X %04X\n", + dev->descriptor.idVendor, dev->descriptor.idProduct); + if (dev->descriptor.idVendor == KOBIL_VENDOR_ID + && dev->descriptor.idProduct ==MID_DEVICE_ID) + { + found_dev = dev; + } + } + } + + if (found_dev == NULL) + { + printf("device not found. aborting.\n"); + exit(1); + } + + printf("Device found, opening ... "); + usb = usb_open(found_dev); + if (!usb) + { + printf("failed, aborting.\n"); + exit(2); + } + printf("success\n"); + + rv = kobil_midentity_claim_interface(usb, 0); + if (rv < 0) + { + usb_close(usb); + exit(3); + } + rv = kobil_midentity_claim_interface(usb, 1); + if (rv < 0) + { + usb_close(usb); + exit(3); + } + + printf("Activating the CCID configuration .... "); + rv = kobil_midentity_control_msg(usb); + if (rv == 0) + printf("success\n"); + else + printf("failed with error %d, giving up.\n", rv); + + usb_close(usb); + + return 0; +} + Index: contrib/Kobil_mIDentity_switch/Makefile.am =================================================================== --- contrib/Kobil_mIDentity_switch/Makefile.am (revision 0) +++ contrib/Kobil_mIDentity_switch/Makefile.am (revision 2507) @@ -0,0 +1,10 @@ +sbin_PROGRAMS = Kobil_mIDentity_switch +Kobil_mIDentity_switch_SOURCES = Kobil_mIDentity_switch.c +Kobil_mIDentity_switch_CFLAGS = $(LIBUSB_CFLAGS) +Kobil_mIDentity_switch_LDADD = $(LIBUSB_LIBS) + +doc_DATA = README_Kobil_mIDentity_switch.txt + +man_MANS = Kobil_mIDentity_switch.8 + +EXTRA_DIST = $(doc_DATA) $(man_MANS) Index: contrib/Kobil_mIDentity_switch/Kobil_mIDentity_switch.8 =================================================================== --- contrib/Kobil_mIDentity_switch/Kobil_mIDentity_switch.8 (revision 0) +++ contrib/Kobil_mIDentity_switch/Kobil_mIDentity_switch.8 (revision 2507) @@ -0,0 +1,19 @@ +.TH Kobil_mIDentity_switch 8 "February 2008" +.SH NAME +Kobil_mIDentity_switch \- activate mIDentity CCID reader +. +.SH SYNOPSIS +.B Kobil_mIDentity_switch +. +.SH DESCRIPTION +Kobil_mIDentity_switch is used to activate the CCID reader of the Kobil +mIDentity device. +.PP +The USB device is by default: + ID 0d46:4081 Kobil Systems GmbH mIDentity Basic/Classic (installationless) +and will be switched to: + ID 0d46:4001 Kobil Systems GmbH mIDentity Basic/Classic (composite device) +. +.SH AUTHORS +Norbert Federa <norbert.federa@neoware.com> wrote the tool. +Ludovic Rousseau <ludovic.rousseau@free.fr> wrote this manpage. Index: contrib/Makefile.am =================================================================== --- contrib/Makefile.am (revision 0) +++ contrib/Makefile.am (revision 2507) @@ -0,0 +1 @@ +SUBDIRS = Kobil_mIDentity_switch RSA_SecurID
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor