Windows 7 - Bug in CCID driver?

Asked By Precise Biometrics on 30-Jun-10 08:56 AM
Problem Description
A customer of ours reported that their Card Management System (CMS) product,
does not work with Precise 250 MC reader (a combined fingerprint/smartcard
reader, see http://www.precisebiometrics.com/?id=2718&cid=2723 for details)
on the Windows Vista or Windows 7 platforms. The same product works on
Windows XP (since Precise Biometrics has developed own drivers for XP).

The CMS product is able to detect and identify the smart card. But when
trying to access the certificates and keys tab in the software, only
fragments of the data from the smart card is shown.

The smart card uses T=1 protocol. The Precise 250 MC uses APDU level of
exchange.


Analysis
The initial analysis was performed on Windows 7 which also showed the same
symptoms but in a different way, see the corresponding Vista analysis in the
end of the analysis description.

Traces on APDU command request and responses in the Precise 250 MC reader do
not show any errors or strange behavior. But further investigation has lead
us to focus on this APDU command which seems to fetch the certificate:

-> 80 30 B0 00 00 00 0E 8A 81 06 41 54 48 45 4E 41 8B 81 02 06 01 02 00

The response from this APDU command is 270 bytes as revealed by traces taken
from Precise 250 MC. Traces also show that the USB communication works as
expected. The host fetches all data.

When this command is issued from a simple smartcard test application the
result is:

SCARD_S_SUCCESS: Received = 0 bytes, error code = 0

As we see there is no error indication but no data is actually returned. So
it appears that the message has been corrupted on the way, but as it turns
out it is the Microsoft CCID driver, usbccid.sys, that probably cannot handle
the CCID message since it is too large for the driver's receive buffer.

But first an experiment by modifying the APDU request length expected, Le,
value. Setting it to 257 will request a smaller chunk of data from the card:

SCARD_S_SUCCESS: Received = 259 bytes, error code = 0
00 06 06 01 01 ....

With Le=257 we get 257+2=259 bytes result including the status code, and
this time we indeed get all requested data. As it turns out this is the
absolute limit on how much data can be handled. Le=258 does not work:

SCARD_S_SUCCESS: Received = 0 bytes, error code = 0

But why can the driver handle 259 bytes, seems like an odd number? Larger
than a short APDU result (258 bytes) but not even close to handle a larger
sized extended APDU (65538 bytes).

Oddly as it seems the value 259 can be shown to be connected to the readers'
dwIFSD value. The IFSD value is used in the T=1 protocol and specifies how
much payload the card may send to the card in one T=1 packet. It does not
have anything to do with the CCID message sizes - but as we see it - it does
in this case.

The Precise 250 MC dwIFSD has the value of 254, not an uncommon value, the
largest possible value for the T=1 protocol. A T=1 packet has 3 bytes header
and up to 2 bytes CRC. And it just so happens that 254+5 = 259!

And it turns out that Microsoft CCID driver, usbccid.sys, actually uses the
dwIFSD value when allocating the receive buffer. This can be seen from the
result of the following experiment. The dwIFSD value in the Precise 250 MC
firmware is changed from 254 to 255 and the command that just failed is now
accepted:

SCARD_S_SUCCESS: Received = 260 bytes, error code = 0
00 06 06 01 01 ....

Microsoft???s own description of the CCID driver, usbccid.sys, is that it
works best in TPDU exchange mode, which means that it handles the T=1
protocol by itself. In this scenario the largest sized CCID message will
indeed be exactly the size allocated by the driver and work perfect and
handle any sized result.

Is the Microsoft CCID driver, usbccid.sys, using a too small receive buffer?
Well, the CCID specification includes the dwMaxCCIDMessageLength parameter.
It is a device property just like the dwIFSD. The Precise 250 MC reader has
it defined to 65550. This is a very large value when compared to any other
reader but still within the acceptable range as specified in the CCID
specification.

But what is the semantics of this property? It is clear that no CCID message
that is sent may be larger that this value. It can be showed that Microsoft
CCID driver, usbccid.sys, honors the dwMaxCCIDMessageLength in one case. If a
message is larger than this value it sends the data in two or more parts. But
more interestingly is that Microsoft CCID driver, usbccid.sys, does not split
an APDU into several request unless it is larger than dwMaxCCIDMessageLength.


Doron Holan [MSFT] replied to Precise Biometrics on 30-Jun-10 12:28 PM
I think you need to open an incident with WDK support.  IIRC, if this is a
bug in the microsoft stack, you will not be charged.

d


Problem Description
A customer of ours reported that their Card Management System (CMS) product,
does not work with Precise 250 MC reader (a combined fingerprint/smartcard
reader, see http://www.precisebiometrics.com/?id=2718&cid=2723 for details)
on the Windows Vista or Windows 7 platforms. The same product works on
Windows XP (since Precise Biometrics has developed own drivers for XP).

The CMS product is able to detect and identify the smart card. But when
trying to access the certificates and keys tab in the software, only
fragments of the data from the smart card is shown.

The smart card uses T=1 protocol. The Precise 250 MC uses APDU level of
exchange.


Analysis
The initial analysis was performed on Windows 7 which also showed the same
symptoms but in a different way, see the corresponding Vista analysis in the
end of the analysis description.

Traces on APDU command request and responses in the Precise 250 MC reader do
not show any errors or strange behavior. But further investigation has lead
us to focus on this APDU command which seems to fetch the certificate:

-> 80 30 B0 00 00 00 0E 8A 81 06 41 54 48 45 4E 41 8B 81 02 06 01 02 00

The response from this APDU command is 270 bytes as revealed by traces taken
from Precise 250 MC. Traces also show that the USB communication works as
expected. The host fetches all data.

When this command is issued from a simple smartcard test application the
result is:

SCARD_S_SUCCESS: Received = 0 bytes, error code = 0

As we see there is no error indication but no data is actually returned. So
it appears that the message has been corrupted on the way, but as it turns
out it is the Microsoft CCID driver, usbccid.sys, that probably cannot
handle
the CCID message since it is too large for the driver's receive buffer.

But first an experiment by modifying the APDU request length expected, Le,
value. Setting it to 257 will request a smaller chunk of data from the card:

SCARD_S_SUCCESS: Received = 259 bytes, error code = 0
00 06 06 01 01 ....

With Le=257 we get 257+2=259 bytes result including the status code, and
this time we indeed get all requested data. As it turns out this is the
absolute limit on how much data can be handled. Le=258 does not work:

SCARD_S_SUCCESS: Received = 0 bytes, error code = 0

But why can the driver handle 259 bytes, seems like an odd number? Larger
than a short APDU result (258 bytes) but not even close to handle a larger
sized extended APDU (65538 bytes).

Oddly as it seems the value 259 can be shown to be connected to the readers'
dwIFSD value. The IFSD value is used in the T=1 protocol and specifies how
much payload the card may send to the card in one T=1 packet. It does not
have anything to do with the CCID message sizes - but as we see it - it does
in this case.

The Precise 250 MC dwIFSD has the value of 254, not an uncommon value, the
largest possible value for the T=1 protocol. A T=1 packet has 3 bytes header
and up to 2 bytes CRC. And it just so happens that 254+5 = 259!

And it turns out that Microsoft CCID driver, usbccid.sys, actually uses the
dwIFSD value when allocating the receive buffer. This can be seen from the
result of the following experiment. The dwIFSD value in the Precise 250 MC
firmware is changed from 254 to 255 and the command that just failed is now
accepted:

SCARD_S_SUCCESS: Received = 260 bytes, error code = 0
00 06 06 01 01 ....

Microsoft???s own description of the CCID driver, usbccid.sys, is that it
works best in TPDU exchange mode, which means that it handles the T=1
protocol by itself. In this scenario the largest sized CCID message will
indeed be exactly the size allocated by the driver and work perfect and
handle any sized result.

Is the Microsoft CCID driver, usbccid.sys, using a too small receive buffer?
Well, the CCID specification includes the dwMaxCCIDMessageLength parameter.
It is a device property just like the dwIFSD. The Precise 250 MC reader has
it defined to 65550. This is a very large value when compared to any other
reader but still within the acceptable range as specified in the CCID
Precise Biometrics replied to Doron Holan [MSFT] on 01-Jul-10 10:04 AM
Ok, will do. Thanks for your reply.