Skip to content

Avoid LIBUSB_ERROR_OVERFLOW errors#164

Open
bluetech wants to merge 1 commit intoLudovicRousseau:masterfrom
bluetech:usb-overflow
Open

Avoid LIBUSB_ERROR_OVERFLOW errors#164
bluetech wants to merge 1 commit intoLudovicRousseau:masterfrom
bluetech:usb-overflow

Conversation

@bluetech
Copy link
Copy Markdown
Contributor

I am trying to get the CCID driver to work with a bit finicky industrial device. Occasionally the communication with the device fails with error LIBUSB_TRANSFER_OVERFLOW, and then things stop working. The reason for this error is described here:
https://libusb.sourceforge.io/api-1.0/libusb_packetoverflow.html

The errors look like this:

pcscd 99999999 src/ccid_usb.c:1082:ReadUSB() read failed (1/14): LIBUSB_ERROR_OVERFLOW
pcscd 00000038 src/ifdhandler.c:1244:IFDHPowerICC() PowerDown failed
pcscd 63039068 src/ccid_usb.c:1082:ReadUSB() read failed (1/14): LIBUSB_ERROR_TIMEOUT
pcscd 00000022 src/ifdhandler.c:1296:IFDHPowerICC() PowerUp failed
pcscd 00000005 winscard.c:333:SCardConnect() Error powering up card: rv=SCARD_E_NOT_TRANSACTED
pcscd 00000004 prothandler.c:86:PHSetProtocol() Protocol T=1 requested but unsupported by the card

Reader:
idVendor: 0x0483
iManufacturer: TITENG
idProduct: 0x3258
iProduct: TIT-RFREADR-CL

As described in the libusb doc, I was able to resolve the problem by tweaking the buffer sizes that CCID is passing to ReadPort (AKA ReadUSB) in the commands.c file. In principle, the needed tweak is to make the buffer sizes a multiple of the endpoint's wMaxPacketSize. This value can be queried from libusb. In all CCID readers I have, the value is always 64 bytes, however in the latest USB version (3.2, very unlikely to actually be used by CCID readers) it can go up to 1024 bytes if I understand correctly. So we can avoid dealing with wMaxPacketSize and just assume 1024.

Fixes #161

unsigned int length, unsigned char buffer[])
{
unsigned char cmd[10+length+2]; /* CCID + Protocol Data Structure */
unsigned char cmd[ROUND_UP_BUF(10+length+2)]; /* CCID + Protocol Data Structure */
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am wary of using VLAs (see e.g. here). It might be better to use malloc. Though I checked and in this case all actual length arguments are small constant size, so it's not exploitable or such.

LudovicRousseau added a commit that referenced this pull request Apr 10, 2025
The unsigned char buffer[] must have size of (at least)
SIZE_GET_SLOT_STATUS.

Thanks to Ran Benita for the patch
" Avoid LIBUSB_ERROR_OVERFLOW errors #164 "
#164
@LudovicRousseau
Copy link
Copy Markdown
Owner

It would be easier to just modify ReadUSB() to use a temporary big buffer. Then no need to touch anything in commands.c

Can you generate a pcscd trace with your patch applied?
Be sure to generate it as documented in https://ccid.apdu.fr/#support

I am trying to get the CCID driver to work with a bit finicky industrial
device. Occasionally the communication with the device fails with error
LIBUSB_TRANSFER_OVERFLOW, and then things stop working. The reason for
this error is described here:
https://libusb.sourceforge.io/api-1.0/libusb_packetoverflow.html

The errors look like this:

pcscd 99999999 src/ccid_usb.c:1082:ReadUSB() read failed (1/14): LIBUSB_ERROR_OVERFLOW
pcscd 00000038 src/ifdhandler.c:1244:IFDHPowerICC() PowerDown failed
pcscd 63039068 src/ccid_usb.c:1082:ReadUSB() read failed (1/14): LIBUSB_ERROR_TIMEOUT
pcscd 00000022 src/ifdhandler.c:1296:IFDHPowerICC() PowerUp failed
pcscd 00000005 winscard.c:333:SCardConnect() Error powering up card: rv=SCARD_E_NOT_TRANSACTED
pcscd 00000004 prothandler.c:86:PHSetProtocol() Protocol T=1 requested but unsupported by the card

Reader:
idVendor: 0x0483
iManufacturer: TITENG
idProduct: 0x3258
iProduct: TIT-RFREADR-CL

As described in the libusb doc, I was able to resolve the problem by
tweaking the buffer sizes that CCID is passing to ReadPort (AKA ReadUSB)
in the commands.c file. In principle, the needed tweak is to make the
buffer sizes a multiple of the endpoint's wMaxPacketSize. This value can
be queried from libusb. In all CCID readers I have, the value is always
64 bytes, however in the latest USB version (3.2, very unlikely to
actually be used by CCID readers) it can go up to 1024 bytes if I
understand correctly. So we can avoid dealing with wMaxPacketSize and
just assume 1024.

Fixes LudovicRousseau#161
@bluetech
Copy link
Copy Markdown
Contributor Author

I rebased to fix some conflicts, no other code changes.

It would be easier to just modify ReadUSB() to use a temporary big buffer. Then no need to touch anything in commands.c

I did try to avoid this extra copying in the transmit path. Adding the few ROUND_UP_BUFs seemed preferable to me...

Can you generate a pcscd trace with your patch applied?
Be sure to generate it as documented in https://ccid.apdu.fr/#support

I'll try to do it. Unfortunately it's a bit of a hassle for me to get the devices set up and reproduce the issue with logging etc. so I need to find some time to do this.

For reference the reader in question is the one embedded in card printers/dispensers from this company: https://www.pointman.co.kr/ENG/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Avoiding LIBUSB_ERROR_OVERFLOW errors

2 participants