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

Fix Lc byte in VERIFY PIN block for PC/SC PIN PAD reader #317

Merged
merged 1 commit into from
Nov 3, 2014

Conversation

CardContact
Copy link
Member

The SmartCard-HSM uses a variable-length PIN, whose length is indicated in Lc.

This patch changes the PC/SC PIN Block used for PIN PAD reader and removes the Lc byte, which is automatically added by the reader.

This patch partially fixes #309, however while PIN verification now works on Windows, PIN modify fails with this reader on Linux. The issue is related to a firmware bug confirmed by Identiv.

@martinpaljak
Copy link
Member

Last time I checked (a long time ago, I must admit) PIN change worked without problems. Has anything changed in the past few years for SPR532 firmware ?

martinpaljak added a commit that referenced this pull request Nov 3, 2014
sc-hsm: Fix Lc byte in VERIFY PIN block for PC/SC PIN PAD reader
@martinpaljak martinpaljak merged commit 0154ee0 into OpenSC:master Nov 3, 2014
@martinpaljak
Copy link
Member

This is similar to Micardo. What is still left to be fixed ?

@dengert
Copy link
Member

dengert commented Nov 3, 2014

Reading CCID revision 1.1 2005, in all the examples in section 8, the abPINApdu includes
CLS, INS, P1, P2, Lc, and Preliminary data. The Lc is the length of the Preliminary data.

In the discussion, it looks no Preliminary data is sent, leaving it up to the CCID,
or the card to fill it in. (Which maybe uninitialized storage?)

In the examples, when the pin length it to be modified, the Lc is not modified, but the first byte after the Lc is
modified.

None of the examples modify the Lc. Are you sure that the readers can handle modifying the Lc?

You say the card is expecting variable length pin, but is that as the first length byte of the pin data, or the Lc?

With the last example, 8.2.2, a pin modification with PIN length management the Preliminary data
sent is CLS, INS, P1, P2, 10, 20FFFFFFFFFFFFFF, 20FFFFFFFFFFFFFF.
The reader then prompts for both pins, and changes the 20 byte to be the length of the corresponding pin.
The position of the new pin is set at 8, even if it shorter.

Note the FF padding bytes will still be the command, and Lc is not changed.

There is no way to change the Lc to work with a PIN modification command with truncated pins.
You either have to use fix length and padded, or use the first byte to hold the length, and ot looks
like padding is still sent.

IMHO, Expecting the reader to change the Lc, is not what the standards define or the reader expecting.

To looks like sending the Preliminary data is what should be done, and either use padding, with no
PIN length management, or use the PIN length management in the first byte of the pin as in the examples.

On 11/3/2014 9:20 AM, CardContact Software & System Consulting wrote:

The SmartCard-HSM uses a variable-length PIN, whose length is indicated in Lc.

This patch changes the PC/SC PIN Block used for PIN PAD reader and removes the Lc byte, which is automatically added by the reader.

This patch partially fixes #309 #309, however while PIN verification now works on Windows, PIN modify fails with this reader on Linux. The issue is related to
a firmware bug confirmed by Identiv.


    You can merge this Pull Request by running

git pull https://github.com/CardContact/OpenSC fix-Lc-in-PINblock

Or view, comment on, or merge it at:

#317

    Commit Summary


Reply to this email directly or view it on GitHub #317.

Douglas E. Engert [email protected]

@martinpaljak
Copy link
Member

As I said, the specification as it happened (starting with "teletrust spec") did not cover this (variable length PIN) use case but this is what seems to work with most of the pinpad readers that are otherwise credible, testing has shown.

@CardContact
Copy link
Member Author

I agree with Martin, it's what we observe with the readers we are testing with.

And btw. an ASCII encoded PIN with length in Lc or a PIN with F2B are the only two formats I've seen in the wild. I have no idea where all this stuff with shifting, converting, padding is good for.

Same for modify PIN, you either have 00 24 00 P2 10 F2B_PIN_OLD F2B_PIN_NEW or 00 24 00 P2 Lc OLD_PIN NEW_PIN as the card knows the length of the old PIN.

I guess what's really missing is a common test standard for PIN PAD readers. I'm in the process of adding some functionality to our APDU test applet, so that it records incoming APDUs. This way we can build a test framework to check the different encodings.

@martinpaljak
Copy link
Member

It would be nice if we could rather somehow initiate a CCID spec amendment? Not a short trip but eventually something that would be needed.

@CardContact CardContact deleted the fix-Lc-in-PINblock branch November 3, 2014 20:59
@dengert
Copy link
Member

dengert commented Nov 4, 2014

On 11/3/2014 2:14 PM, CardContact Software & System Consulting wrote:

I agree with Martin, it's what we observe with the readers we are testing with.

And btw. an ASCII encoded PIN with length in Lc or a PIN with F2B are the only two formats I've seen in the wild. I have no idea where all this stuff with shifting, converting, padding is good for.

Well padding is used, so the Lc in the verify (or other pin commands) isset to the max pin length, and the card only uses the non padding bytes for the pin.

For example, using an Omnikey 3821, and a NIST PIV demo card with max pin = 8 with pin 123456 OpenSC sends:

0x7fe8d8181740 16:53:11.516 [opensc-pkcs11] ../../../src/src/libopensc/pkcs15-pin.c:293:sc_pkcs15_verify_pin: called
0x7fe8d8181740 16:53:11.516 [opensc-pkcs11] ../../../src/src/libopensc/pkcs15-pin.c:294:sc_pkcs15_verify_pin: PIN(type:0;method:1;len:)
0x7fe8d8181740 16:53:11.516 [opensc-pkcs11] ../../../src/src/libopensc/card.c:325:sc_lock: called
0x7fe8d8181740 16:53:11.516 [opensc-pkcs11] ../../../src/src/libopensc/reader-pcsc.c:517:pcsc_lock: called
0x7fe8d8181740 16:53:11.516 [opensc-pkcs11] ../../../src/src/libopensc/sec.c:157:sc_pin_cmd: called
0x7fe8d8181740 16:53:11.516 [opensc-pkcs11] ../../../src/src/libopensc/reader-pcsc.c:1623:pcsc_pin_cmd: called
0x7fe8d8181740 16:53:11.516 [opensc-pkcs11] ../../../src/src/libopensc/reader-pcsc.c:182:pcsc_internal_transmit: called
0x7fe8d8181740 16:53:11.516 [opensc-pkcs11] ../../../src/src/libopensc/reader-pcsc.c:1663:pcsc_pin_cmd: PC/SC v2 pinpad block: 1E1E020800080402FF0000000000000D 0000000020008008FFFFFFFFFFFFFFFF
0x7fe8d8181740 16:53:11.516 [opensc-pkcs11] ../../../src/src/libopensc/reader-pcsc.c:182:pcsc_internal_transmit: called
0x7fe8d8181740 16:53:19.649 [opensc-pkcs11] ../../../src/src/libopensc/sec.c:204:sc_pin_cmd: returning with: 0 (Success)
0x7fe8d8181740 16:53:19.649 [opensc-pkcs11] ../../../src/src/libopensc/pkcs15-pin.c:366:sc_pkcs15_verify_pin: PIN cmd result 0

The above appears to match 8.1.5 Pin uses ASCII format conversion with padding.
with bEntryValidatyionCondition 02, press enter, and English

pcscd:

00000010 Control TxBuffer: 1E 1E 02 08 00 08 04 02 FF 00 00 00 00 00 00 0D 00 00 00 00 20 00 80 08 FF FF FF FF FF FF FF FF
08133176 Control RxBuffer: 90 00

When not using a pin pad reader, OpenSC would send
00 20 00 80 08 31 32 33 34 35 36 FF FF

Using a HSM without a pin pad, (I see where you are setting Lc=pinlen)

pcscd:

00000008 APDU: 00 20 00 81 06 31 32 33 34 35 36
00000008 ifdhandler.c:1266:IFDHTransmitToICC() usb:04e6/5410:libudev:0:/dev/bus/usb/002/004 (lun: 0)
00095865 SW: 90 00

If I try doing a verify using the padding using opensc-tool

opensc-tool -s 00:20:00:81:08:31:32:33:34:35:36:FF:FF

APDU: 00 20 00 81 08 31 32 33 34 35 36 FF FF
00000016 ifdhandler.c:1266:IFDHTransmitToICC() usb:04e6/5410:libudev:0:/dev/bus/usb/002/005 (lun: 0)
00011874 SW: 6E 00

So as you say the HSM does not understand padding.

If it the HSM did understand the padding, the Lc could stay constant...

Same for modify PIN, you either have 00 24 00 P2 10 F2B_PIN_OLD F2B_PIN_NEW or 00 24 00 P2 Lc OLD_PIN NEW_PIN as the card knows the length of the old PIN.

I guess what's really missing is a common test standard for PIN PAD readers. I'm in the process of adding some functionality to our APDU test applet, so that it records incoming APDUs. This way we can
build a test framework to check the different encodings.


Reply to this email directly or view it on GitHub #317 (comment).

Douglas E. Engert [email protected]

@dengert
Copy link
Member

dengert commented Nov 4, 2014

I assume F2B is Format 2 PIN block and is also used in ISO 9564 :according to
http:https://en.wikipedia.org/wiki/ISO_9564#Part_3:_Requirements_for_offline_PIN_handling_in_ATM_and_POS_systems

In the format they refer to the fill nibbles, of 15
This is the same as CCID 8.1.3 PIN uses a BCD format conversion with PIN length insertion.
It is padded with fill nibbles so the Lc stays constant.

The point I am trying to make, is PIN PAD readers are more likely to support the CCID standards,
where in all the examples the abPINApdu contains a fixed Lc, and Preliminary data with the
the fill bytes of FF, and if needed the 0x20 format 2 byte which gets the length.
Although the bmPINLengthFormat implies the Lc can be changed, there are no examples of this.

The CCID standard I have is 1.1 from April 2005, Is there a newer version?

where bmPINLengthFormat is clarified, or an example of changing Lc?

It appears that Lc in the CCID 1.1 is not defined as a single byte, thus opening up the ability to
use xtended APDUs. I bring this up as Oberthur has a card with on board fingerprint matching,
that uses the verify command to send the fingerprint. Its not clear if this requires extended APDU
or not. The next step would be a reader that reads the fingerprint and sends it to the card using
the "PIN PAD" features.

On 11/3/2014 2:14 PM, CardContact Software & System Consulting wrote:

I agree with Martin, it's what we observe with the readers we are testing with.

And btw. an ASCII encoded PIN with length in Lc or a PIN with F2B are the only two formats I've seen in the wild. I have no idea where all this stuff with shifting, converting, padding is good for.

Same for modify PIN, you either have 00 24 00 P2 10 F2B_PIN_OLD F2B_PIN_NEW or 00 24 00 P2 Lc OLD_PIN NEW_PIN as the card knows the length of the old PIN.

I guess what's really missing is a common test standard for PIN PAD readers. I'm in the process of adding some functionality to our APDU test applet, so that it records incoming APDUs. This way we can
build a test framework to check the different encodings.


Reply to this email directly or view it on GitHub #317 (comment).

Douglas E. Engert [email protected]

@CardContact
Copy link
Member Author

CCID 1.1 is the current version.

The whole PIN verification mechanism goes back to the MKT specifications written in 1990s for the German e-Health card. Verify with Lc denoting the PIN length was pretty much the standard at that time. It changed to F2B format, because several manufacturer introduced a self-encrypted PIN format, where the 8 byte F2B block was encrypted using the same data as key in a single DES operation.

Later the MKT specs and their French equivalent (was it called SCP ?) were the basis for CCID, which then was the basis for PC/SC part 10.

It's been the same people from various card [reader] manufacturer involved in writing those specs.

So it's not a surprise, that their reader (in particular Reiner-SCT, Identiv / SCM and Omnikey / HID) support this format.

The examples in the CCID specs are probably showing just the more complex constructions.

Anyway, we should probably go for better specifications and a proper comformance test.

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 this pull request may close these issues.

PIN Verification fails on Windows with SPR 332/532
3 participants