Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PIN Verification fails on Windows with SPR 332/532 #309

Closed
CardContact opened this issue Oct 27, 2014 · 7 comments · Fixed by #317
Closed

PIN Verification fails on Windows with SPR 332/532 #309

CardContact opened this issue Oct 27, 2014 · 7 comments · Fixed by #317

Comments

@CardContact
Copy link
Member

Using the SPR 332/532 PIN PAD reader with OpenSC and the SmartCard-HSM on Windows fails during PIN verification. It works on Linux and using other PIN PAD readers like cyberjack or Omnikey.

Apparently the issues tracks down to the PIN block send to the reader. OpenSC sends for SC_CCID_PIN_ENCODING_ASCII the following block:

1E1E0200000F06020000000000000005 0000000020008100

The last 5 bytes are the VERIFY APDU that the reader should use. The APDU already includes Lc=00. While this works for other readers, the SPR will not touch the Lc byte, thus PIN verification fails.

IMHO the correct block would be

1E1E0200000F06020000000000000005 00000000200081

What puzzles me, is why part10_build_verify_pin_block() at the end copies Lc and the (in this case empty) data area of the APDU, if pin1.length_offset is not 4. Default value for length_offset is 0 and as far as I can see only the Micardo driver is using this field.

What is also unclear, is why this problem does not exist on Linux, even though the PIN block is a CCID structure transparently send to the reader.

@LudovicRousseau
Copy link
Member

Maybe the Windows driver does extra checks or is bogus.

Note that if you remove the Lc byte you have to change ulDataLength from 5 to 4.

@CardContact
Copy link
Member Author

Identiv claims that the Linux driver does some modification to the last byte to make it work ;-)

@martinpaljak
Copy link
Member

Make sure you have the latest firmware for the reader and also the latest driver. This device behaved very differently depending on the firmware version (that interpreted certain values in different order). The ability to work with variable length input PIN blocks (like Micardo) where Lc field matters and depends on user input, was not covered initially by the specification, but this is what "worked" and what is also used by others. The point being that CCID spec allowed specifying the effective PIN length only in the data block of the APDU (where offset 0 is one byte after Lc).

@martinpaljak
Copy link
Member

So for the pinpad code to work with your card driver of choice, make sure that you initialize the sc_pin_cmd_data structure correctly for your card before delegating to ISO function (that in turn gets activated in the PC/SC driver). I don't know if we can have a sensible default anywhere ?

@CardContact
Copy link
Member Author

The issue is not related to OpenSC code. Most interestingly it's works fine on Linux and fails on Windows with the same OpenSC code base (which I see as a trend more often ;-) .

According to Identiv the reader firmware should fail the way the PIN block is prepared by OpenSC (The firmware does not change the Lc byte, so the VERIFY APDU send to the card by the reader is supposed to be 00 20 00 81 00 31 32 33 34).

Apparently it doesn't fail on Linux. What we've found so far, is that the CCID frame looks different on Windows, with an additional A4 appended to the Lc byte. Might be, that this causes the issue with the reader firmware.

Btw. we are not touching sc_pin_cmd and leave it the way it's initialized from sc_pkcs15_auth_info.

I can also not see, how I could disable in sc_pin_cmd_data the transmission of Lc in the PIN block.

In our sc-hsm-embedded PKCS#11 module we just use CLA INS P1 P2 in the PIN block and that works for all readers we've tested with (Variable PIN and F2B PIN).

@martinpaljak
Copy link
Member

If you have variable length PIN-s you should set the length_offset to 4 in your driver("00 20 XX YY 04 31 32 33 34" for an effective VERIFY command sent to the card, where Lc is set by the driver), especially with the SPR532 reader (what was once the "reference driver" when I worked with pinpad code). Last time I checked it worked on Winodws as well as Linux but maybe things have changed.

Otherwise I don't see what could be done from OpenSC side thus there is no achievable result for this issue...

@CardContact
Copy link
Member Author

I've tried that and it removes the Lc from the APDU.

With the cyberjack it still works, but with SPR332 it breaks PIN change (Wrong length returned by card).

What puzzles me, is that this should be pretty much the default mechanism for the majority of cards.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants