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

IAS-ECC/Pinpad couple does not support variable lenght pin #424

Closed
estieux-tehtri-security opened this issue Apr 2, 2015 · 57 comments
Closed

Comments

@estieux-tehtri-security
Copy link

I'm using a Morpho ypsid S3 card IAS-ECC card. With a basic card-reader, opensc tools are working correctly (key creation, PKCS11 interface, ...).

If I want to use the card with a pinpad reader (Gemalto CT710) I'm facing a problem. Every action requiring to type the PIN will fail and it seems that OpenSC is the culprit as the pin on the card may have variable length : Length : min_len:4, max_len:16, stored_len:4

So for example, if I use opensc-explorer to verify the PIN (verify CHVx), I always get the message "Different values for PIN min and max lengths is not actually compatible with PinPAD."

But if I comment out https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/card-iasecc.c lign 1804 to 1809, and keep a 4 digits pin, opensc is able to deal with the pinpad reader. If I use, let's say, a 6 digits pin, I just need to fix lign 1810.

So could it be possible to improve pinpad support for ias-ecc ? Is there a real technical limitation that prevent to deal with variable pin size ?

@viktorTarasov
Copy link
Member

The only PINPAD that I have is 'Gemalto GemPC PinPad' and apparently it has a bug and do not accept different values for min/max length in P10 data.

In 95ad11a this reader is separated in a special case,
but still I do not see how you are going to "fix lign 1810". Pull request is expected.

@dengert
Copy link
Member

dengert commented Apr 4, 2015

Have you looked at:
http:https://support.gemalto.com/fileadmin/user_upload/user_guide/Pinpad/PCPinpad_PC-SC_UserGuide.pdf
GemALto says Compliant with PC/SC 2.0 part 10 for Secure Pin Entry devices

I remember problems with the endian of integers with PCSC part 10. The wPinMaxExtraDigit is two bytes.
The examples use 0x0404 which is not a good example.

reader-pcsc.c handles the min max using this:

1368 tmp16 = (data->pin1.min_length << 8 ) + data->pin1.max_length;
1369 pin_verify->wPINMaxExtraDigit = HOST_TO_CCID_16(tmp16); /* Min Max */

I see card-iasecc.c has: if (pin_cmd->pin1.min_length != pin_cmd->pin1.max_length)

I have used the Omnikey 3821 pin pad, with pin.min_length = 4 and pin.max_length = 8
with the PIV card, without having to use extra code in the card-piv.c driver for a pinpad.

A opensc debug of the verify command sent to the reader to use the pinpad

Some things to look at:
Does the GemALto have a problem with the bytes of wPinMaxExtraDigit in the wrong order?
A patch in reader-pcsc.c to swap the bytes would show if it does.

 Can the card-iasecc.c use the code built into reader-pcsc.c and iso7816.c for pin processing?

 A opensc debug of the verify command sent to the reader to use the pinpad might show something...

On 4/4/2015 2:50 PM, viktorTarasov wrote:

The only PINPAD that I have is 'Gemalto GemPC PinPad' and apparently it has a bug and to not accept different values for min/max length in P10 data.

In 95ad11a 95ad11a this reader is separated in a special case,
but still I do not see how you are going to /"fix lign 1810"/. Pull request is expected.


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

Douglas E. Engert [email protected]

@dengert
Copy link
Member

dengert commented Apr 5, 2015

Note the debug line for the Omnikey 3821 pin pad, with pin.min_length = 4 and pin.max_length = 8, the max is before the min, 0804. The GemALto pdf above has in the example table:
5 wPinMaxExtraDigit 0x0404 Min value/Max value
Since the x0404 is a 16bit number, in host byte order, that would set the bytes as 0804 in little endian machines.

reader-pcsc.c:1667:pcsc_pin_cmd: PC/SC v2 pinpad block: 1E1E020800080402FF0000000000000D 0000000020008008FFFFFFFFFFFFFFFF

PCSC shows this:
00000036 ifdhandler.c:1360:IFDHControl() ControlCode: 0x42330006, usb:076b/3821:libudev:0:/dev/bus/usb/002/003 (lun: 0)
00000036 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
05075137 Control RxBuffer: 90 00

@dengert
Copy link
Member

dengert commented Apr 5, 2015

The real source of the problem this line in iasecc_chv_verify_pinpad:

pin_cmd->pin1.len = pin_cmd->pin1.min_length;

Should it have been:
pin_cmd->pin1.len = pin_cmd->pin1.max_length;

The template for a verify command needsto be long enough to hold the largest pin.
The reader will then pad the pin entered by the usder if it is shorter.

@viktorTarasov
Copy link
Member

In reality it has to be not the pin1.min_length but pin1.stored_length.
But there is no 'stored_length' member in PIN data.

Template of PIN VERIFY command in P10 data has to be exactly of length of expected PIN.
Using of PIN pad do not goes well with the non-padded PINs.

1E1E020800080402FF0000000000000D 0000000020008008FFFFFFFFFFFFFFFF

I your example the real PIN length for the card is always 8 bytes, but PIN pad allows to enter 4 of them, the rest will be filled with PAD character.

@LudovicRousseau
Copy link
Member

I have no problem with the Gemalto pinpad and min != max.

I think that https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/reader-pcsc.c#L1370 is wrong.

The application shall not change the byte order.

I propose to remove the use HOST_TO_CCID_16() in reader-pcsc.c

Yes, I agree it is a mess.

@dengert
Copy link
Member

dengert commented Apr 5, 2015

internal-winscard.h has:
#define HOST_TO_CCID_16(x) (x)
#define HOST_TO_CCID_32(x) (x)

@dengert
Copy link
Member

dengert commented Apr 5, 2015

@viktorTarasov
Are you saying the iasecc card will not accept a padded pin?
What does the iasecc verify APDU look like if a pin pad reader is not used?

I disagree with the statement:
"I your example the real PIN length for the card is always 8 bytes, but PIN pad allows to enter 4 of them, the rest will be filled with PAD character."

I say the card will accept between 4 and 8 byte PIN, padded if needed.
So if the pin was 123456, (which it is on a test card that does work)
the APDU that is sent to the card is:
0020008008313233343536FFFF
which would be the same if no pin-pad reader was used.

If the iasecc card does not accept a fixed length padded pin, PCSC revision 1.1 (I would expect this in v2.0) appears to allow the length of the pin typed on the pad to be inserted into the APDU. See
6.1.11.5 bmPINBlockString bits 7-4 and bit 3-0
6.1.11. bmPINLengthFormat.

reader-pcsc.c, looks like it tries to set bmPINBlockString bits 7-4 arount line 1325.
Line 1331 has if (data->pin1.length_offset > 4)
data->pin1.length_offset = 4 would be the Lc. ( I think.)
Also look at line 1392:
if (data->pin1.length_offset != 4) {

Can you use data->pin1.length_offset so it will be set?

card-sc-hsm.c and card-mcrd.c set data->pin1.length_offset = 4;

@dengert
Copy link
Member

dengert commented Apr 6, 2015

If the ADPU Lc is just the length of the PIN,
Try this attached diff, that will cause the reader to overwrite
the Lc value in the template with the length of the pin as typed by the user on the pin pad
followed by the pin typed.

I have not tried this, as I don't have a card that requires just the pin or the pinpad reader
in question.

Douglas E. Engert [email protected]

@viktorTarasov
Copy link
Member

Are you saying the iasecc card will not accept a padded pin?
What does the iasecc verify APDU look like if a pin pad reader is not used?

"Padded PIN" has no meaning at the card level.
"31323334" and "31323334FFFFFFFF" are two different PINs.

I disagree with the statement:

"I your example the real PIN length for the card is always 8 bytes, but PIN pad allows to enter 4 of them, the rest will be filled with PAD character."

I say the card will accept between 4 and 8 byte PIN, padded if needed.

"Padded if needed" means that card receives always 8 bytes.
It's not the same when card receives 4 bytes PIN, or 8 bytes PIN.

If the iasecc card does not accept a fixed length padded pin, ...

Iasecc card can accept fixed length, as a particular case of possibility to accept any (reasonable) length. There is no general convention for the length of PIN, neither no convention to use the PIN padding. In one case 4 bytes are used, in another 6 bytes.

Can you use data->pin1.length_offset so it will be set?
card-sc-hsm.c and card-mcrd.c set data->pin1.length_offset = 4;

Tried.
Not work for me.
P10 Verify data do not contain the place-hold for PIN value -- simple CASE-1 APDU.
No way to get know what is in reality sent to card.

Try this attached diff

Do not see the attached diff.

@viktorTarasov
Copy link
Member

@LudovicRousseau

I have no problem with the Gemalto pinpad and min != max.

After inspection it appears that in my case pin-pad do not accept max_length more then 8.
But still do no see how to get it working without knowledge of expected (non-padded) PIN length.

@martinpaljak
Copy link
Member

GemPC pinpad (depending on the firmware, probably) had limitations with min/max pin length and alos no support for the variable length PIN block, at least the (older?) versions I have.

@martinpaljak
Copy link
Member

@LudovicRousseau while pro-cleanup, I'm afraid it would mean that for usable software "compatibility" mode for some readers on Windows is necessary, based on reader name (much like the HP keyboard).

@dengert
Copy link
Member

dengert commented Apr 6, 2015

On 4/6/2015 5:12 AM, viktorTarasov wrote:

Can you use data->pin1.length_offset so it will be set?
card-sc-hsm.c and card-mcrd.c set data->pin1.length_offset = 4;

Tried.
Not work for me.
P10 Verify data do not contain the place-hold for PIN value -- simple CASE-1 APDU.

They way I read it, the offset = 4 effect tells the reader to use the size of the PIN the user types
as the Lc value of the APDU data.

No way to get know what is in reality sent to card.

Yes there is but requires hardware debug device between the reader and the card. I have seen a
hand made device many years ago, don't know if they commercially available.

Try this attached diff

Do not see the attached diff.

Github did not print attachment, this was it:

diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c
index ea6d497..ec5b52a 100644
--- a/src/libopensc/card-iasecc.c
+++ b/src/libopensc/card-iasecc.c
@@ -1741,13 +1741,7 @@ iasecc_chv_verify_pinpad(struct sc_card *card, struct sc_pin_cmd_data *pin_cmd,
LOG_FUNC_RETURN(ctx, SC_ERROR_READER);
}

  • if (pin_cmd->pin1.min_length != pin_cmd->pin1.max_length) {
  •   sc_log(ctx, "Different values for PIN min and max lengths is not actually compatible with PinPAD.");
    
  •   LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED,
    
  •           "Different values for PIN min and max lengths is not actually compatible with PinPAD.");
    

- }

  • pin_cmd->pin1.len = pin_cmd->pin1.min_length;
  • pin_cmd->pin1.len = pin_cmd->pin1.max_length;

memset(buffer, 0xFF, sizeof(buffer));
pin_cmd->pin1.data = buffer;
@@ -2151,6 +2145,7 @@ iasecc_pin_get_policy (struct sc_card *card, struct sc_pin_cmd_data *data)

data->pin1.encoding = SC_PIN_ENCODING_ASCII;
data->pin1.offset = 5;

  • data->pin1.length_offset = 4;

sc_log(ctx, "PIN policy: size max/min %i/%i, tries max/left %i/%i",
data->pin1.max_length, data->pin1.min_length,


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

Douglas E. Engert [email protected]

@dengert
Copy link
Member

dengert commented Apr 6, 2015

So it sounds like the pinpad support in isaecc was developed trying to use a non standard or defective pin-pad reader
the code was never tried with any other pinpad reader that would support the variable PIN block code in the CCID standards.
So card-issecc.c does not support any pinpad unless the size of the pin is fixed.

Does anyone have all the pieces (or some of the pieces )to address the original post?

i.e. isaecc card, were they could try different size pins and a a different pin pad reader that does support variable length PIN block.

Does any one have a sc-hsm or mcrd card and a GemAlto pin pad reader?
These cards appear to use the variable PIN block code, this could test the GemAlto reader.

@viktorTarasov if you try the patch, can you send the opensc-debug output of the
reader-pcsc.c:1667:pcsc_pin_cmd: PC/SC v2 pinpad block:
This would help identify what OpenSC is sending to the reader.

On 4/6/2015 6:03 AM, Martin Paljak wrote:

GemPC pinpad (depending on the firmware, probably) had limitations with min/max pin length and alos no support for the variable length PIN block, at least the (older?) versions I have.


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

Douglas E. Engert [email protected]

@dengert
Copy link
Member

dengert commented Apr 6, 2015

In my above comments Lc should have said Le.
Le value of the APDU data.

@dengert
Copy link
Member

dengert commented Apr 6, 2015

Disregard that, Its Lc, the size of the data sent to the card.

@LudovicRousseau
Copy link
Member

A way to debug a pinpad verify PIN is to use my test JavaCard applet https://anonscm.debian.org/viewvc/pcsclite/trunk/HandlerTest/JavaCard/

The applet implements a VERIFY command (INS=0x20) and also a DUMP command (INS=0x40) to get the PIN value sent to the card.
The applet does not support variable PIN length (the PIN is hard coded to 12345678). But it should be easy to implement it.

@viktorTarasov
Copy link
Member

@dengert
I tried your patch.

With Gemalto IAS/ECC it works, as it works without patch,
because for this card min_length == max_length == stored_pin_length.

With Morpho's IAS/ECC card, that has stored pin length 4, min_length 4, max_length 16:

  • not work, because this card has max_length = 16, that is rejected by pin-pad:

PC/SC v2 pinpad block: 1E1E0200001004020000000000000015 0000000020000110FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF

  • not work if the max_length is upper limited by 8, probably because 8 bytes PIN is applied to card:

PC/SC v2 pinpad block: 1E1E020000080402000000000000000D 0000000020000108FFFFFFFFFFFFFFFF

  • works if expected PIN length is set to 4 (as an actual PIN size):

PC/SC v2 pinpad block: 1E1E0200000804020000000000000009 0000000020000104FFFFFFFF

@dengert
Copy link
Member

dengert commented Apr 6, 2015

The more I look at this, I don't see if the IAS/ECC specifications say anything about
pin padding in the VERIFY command. It hints at no padding, when there are two pins in the
command, as it says the card will look up the first pin, and use the stored_len and assume
the next pin starts after the first.

I did see one note from 4 years ago. Both Viktor and I replied :)

http:https://opensc-devel.narkive.com/vOv8KYOK/iasecc-problem-with-oberthur-compliant-card

The interesting lines where in the VERIFY sent to the card has padding,the users says it was padded
and it appears to work....

00004576 APDU: 00 20 00 01 40 39 39 39 39 FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00041243 SW: 90 00

This could be a difference in how the card handles VERIFY or stores the PIN, could it have stored padding
when the pin was set?

If the IAS/ECC allows padding then there is no need for the variable length substitution.
It looks like the OpenSC does not allow the Lc on the template to be overridden.
Not clear is that is a limitation of the CCID spec or the OpenSC implementation.

I find it hard to believe that the big name card vendors who write the specs, make the card and pin-pad readers would
not make sure they would work together.

On 4/6/2015 10:04 AM, viktorTarasov wrote:

@dengert https://github.com/dengert
I tried your patch.

With Gemalto IAS/ECC it works, as it works without patch,
because for this card /min_length == max_length == stored_pin_length/.

With Morpho's IAS/ECC card, that has stored pin length 4, min_length 4, max_length 16:

  • not work, because this card has max_length = 16, that is rejected by pin-pad:

    PC/SC v2 pinpad block: 1E1E0200001004020000000000000015 0000000020000110FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF

  • not work if the max_length is upper limited by 8, probably because 8 bytes PIN is applied to card:

    PC/SC v2 pinpad block: 1E1E020000080402000000000000000D 0000000020000108FFFFFFFFFFFFFFFF

  • works if expected PIN length is set to 4 (as an actual PIN size):

    PC/SC v2 pinpad block: 1E1E0200000804020000000000000009 0000000020000104FFFFFFFF


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

Douglas E. Engert [email protected]

@viktorTarasov
Copy link
Member

@dengert
APDU that you cited is specific to the most of Oberthur's cards, that I've seen.
This specificity do not contradict the IAS/ECC specification, and they kept it for their IAS/ECC card.

Other IAS/ECC manufacturers do not use PIN padding: Gemalto, Morpho, ...

To use PIN pad one has to know the stored length .
It can be found in the properly formatted PKCS#15 data but not in the IAS/ECC card's own meta data .

If the IAS/ECC allows padding then there is no need ...

In IAS/ECC there are no obstacles to use padded PIN.

It looks like the OpenSC does not allow the Lc on the template to be overridden.

Do you think that the PIN-pad itself can overwrite Lc ?
Can you show here an example of P10-Verify data that incite the PIN-PAD to overwrite Lc ?

I find it hard to believe that the big name card vendors ...

Big name card vendors use their own middle-ware and have no obligation to be inter-compatible.
They are always ready to adjust their MW or cards to make them working (for exemple to be compatible with PIN-pad) in particular, non-tiny cases.

@dengert
Copy link
Member

dengert commented Apr 6, 2015

On 4/6/2015 2:30 PM, viktorTarasov wrote:

@dengert https://github.com/dengert
APDU that you cited is specific to the most of Oberthur's cards, that I've seen.
This specificity do not contradict the IAS/ECC specification, and they kept it for their IAS/ECC card.

Other IAS/ECC manufacturers do not use PIN padding: Gemalto, Morpho, ...

Unfortunately.

To use PIN pad one has to know the /stored length/ .
It can be found in the properly formatted PKCS#15 data but not in the IAS/ECC card's own meta data .

The IAS/ECC does mention ISO7816-15, does OpenSC need to support this too?
I would find it surprising that the card would let you read the length of the pin, sounds like
as security risk.

If the IAS/ECC allows padding then there is no need ...

In IAS/ECC there are no obstacles to use padded PIN.

It looks like the OpenSC does not allow the Lc on the template to be overridden.

Do you think that the PIN-pad itself can overwrite Lc ?

I would have designed it that way, but it looks like it may not.

Can you show here an example of P10-Verify data that incite the PIN-PAD to overwrite Lc ?

No, still looking.

If you have a card which claims to not support padding, say min=4 max=8 and the the pin is actually length=6, for example 123456
can you use opensc-tool -s "00:20:00:80:08:31:32:33:34:34:35:36:FF:FF"
From your above statement: Gemalto, Morpho, ... would fail.

I find it hard to believe that the big name card vendors ...

Big name card vendors use their own middle-ware and have no obligation to be inter-compatible.
They are always ready to adjust their MW or cards to make them working (for exemple to be compatible with PIN-pad) in particular, non-tiny cases.

So much for standards.

So sounds like you are stuck with a fixed size pin if you want to use a pinpad reader.


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

Douglas E. Engert [email protected]

@viktorTarasov
Copy link
Member

@dengert

I would find it surprising that the card would let you read the length of the pin, sounds like
as security risk.

Why? For example, everyone knows that PIN length (padded) for PIV card is 8 bytes. Make it less secure? There is always possibility to use longer PINs.

If you have a card which claims to not support padding, say min=4 max=8 and the the pin is actually length=6, for example 123456
can you use opensc-tool -s "00:20:00:80:08:31:32:33:34:34:35:36:FF:FF"
From your above statement: Gemalto, Morpho, ... would fail.

Many times you were saying "card support padding".
Card has nothing with padding.
Padding is implemented by middle-ware, even not by PIN-PAD.
Padding is a kind of convention around the card.
Something like "Card is formatted with PIN length of 8 bytes. If you don't need such a length -- middle-ware will pad it for you with 0xFF".

As for your example:
as I've already told: "313233343536" and "313233343536FFFF" are two different PINs.
To use the second PIN, once upon a time this value had to be sent to card in 'CREATE PIN' command (for some cards even not CHANGE PIN -- CREATE).
Only then you will be able to use padded PIN -- first part comes from user input, second is from middle-ware. Card itself will never know how this PIN was composed -- it will receive "313233343536FFFF".

As anecdote:
PIN "123456" can be verified with PIN PAD where first 4 characters taken from user input and the last two bytes padded. All is a question of APDU template in P10 verify data.

@estieux-tehtri-security
Copy link
Author

Just a few feedback :

  • I only managed to get a real pinpad validation when I explicitely set the real pin size in pin_cmd->pin1.len
  • The other way is to change my pin with a padded value but as Viktor said, the real pin is, for example 313233343536FFFF and not 313233343536 despite I only need to type 123456. Not sure it will be compatible with another system if I move my card.

I saw in http:https://www.acsiel.fr/iso_album/ias_ecc_v1_0_1_fr.pdf that, in paragraph 9.4.2, the applet change PIN is described and mention that the lenght of the PIN in stored in the PIN SDO. This is described in 3.4.5. Is this value used as "stored_length" shown by pkcs15-tool --list-pin ? Because it seems that this value is "public"

If we have no choice other than having a fixed-size pin length, maybe I could be possible to parameterize this in opensc.conf. Users may be warn that changing the default pin size (4) may break compatibility under other OS...

@estieux-tehtri-security
Copy link
Author

Just for information, I gave a try to http:https://git.gniibe.org/gitweb/?p=gnuk/gnuk.git;a=blob;f=tool/pinpadtest.py with my pinpad reader. I was able to check a PIN with a length of 6 successfully. (for 5 I needed to pass the -pinmin 4 option)

I just commented out openpgp verification in main() (l.238)

@dengert
Copy link
Member

dengert commented Apr 7, 2015

Main point: "SO WHY DID THIS PRACTICE CHANGE? See below.

On 4/7/2015 3:28 AM, viktorTarasov wrote:

@dengert https://github.com/dengert

I would find it surprising that the card would let you read the length of the pin, sounds like
as security risk.

Why? For example, everyone knows that PIN length (padded) for PIV card is 8 bytes. Make it less secure? There is always possibility to use longer PINs.

Minor concern, save for some other discussion.

If you have a card which claims to not support padding, say min=4 max=8 and the the pin is actually length=6, for example 123456
can you use opensc-tool -s "00:20:00:80:08:31:32:33:34:34:35:36:FF:FF"
 From your above statement: Gemalto, Morpho, ... would fail.

Many times you were saying /"card support padding"/.
Card has nothing with padding.

It could, depends on what the card does with pad characters. Let's say card receive 31:32:33:34:34:35:36:FF:FF
The card could say the PIN is 8 bytes and the last two happen to be FF:FF, Or the pin is 6 bytes and the card knows the last two are padding.
In the PIV case, what the card does is not part of the standard the card may store the padding as the part of the pin or strip it.
The application never sees how the card handles it. (one could experiment and create a pin with FF in the middle, but this does not help
in discussion.)

NIST 800-73-e Part 2 Section 2.4.3 Authentication of an Individual Says:

  "Personal identification numbers (PIV Card Application PINs and PUKs) presented to the card command
   interface shall be 8 bytes long. If the actual PIN length is less than 8 bytes it shall be padded to 8 bytes
   with 'FF'. The 'FF' padding bytes shall be appended to the actual PIN. The bytes comprising the PIV
   Card Application PIN shall be limited to values 0x30 – 0x39, the ASCII values for the decimal digits '0' – '9'.
   The bytes comprising the PUK shall be limited to the values 0x00 – 0xFE (i.e., shall not include 'FF')."

It goes on with some examples, and talks about any Global Pin.

This NIST wording works with a card that understands 'FF' as padding or just another character. And I think it was added
because of discussions like the one we are having, over what is a PIN, how is it stored, how is it used in verify
or change* commands and how can a user's pin can be used with a pinpad reader that only allows digits.

Is there any IAS-ECC statement like this on the PIN values and padding in any official documents?

(NIST is part of the US Department of Commerce. NIST 800-73-2 Part 3 enforces interoperability at the card edge.
Best I can tell the IAS/ECC standards were written by the vendors, all of whom were not so concerned with interoperability
at the card edge as they would supply the cards and middleware. This is just my observation, and not part of how to solve this problem
for the IAS/ECC cards.)

Padding is implemented by middle-ware, even not by PIN-PAD.

Pin pad can supply padding, With this sent to the reader, (spaces added) 1E 1E 02 08 00 0804 02 FF 0000000000000 D000000 00200080 08 FFFFFFFFFFFFFFFF
The reader is told overwrite the leading FFs with the PIN the user entered, thus if
pin was 1234, the reader would modify the APDU to: 00200080 08 31323334FFFFFFFF
So the card sees same APDU as if entered by software.

Padding is a kind of convention around the card.
Something like "Card is formatted with PIN length of 8 bytes. If you don't need such a length -- middle-ware will pad it for you with 0xFF".

As for your example:
as I've already told: "313233343536" and "313233343536FFFF" are two different PINs.

The padding could be any character like zero padding.
On IAS/ECC cards would 313233343536 and 3132333435360000 be the same?

Sounds like you saying the Gemalto, Morpho, ... store the length based on the length of the data.
and do not understand any type of padding, but Oberthur does not have the problem?
i.e. Does Oberthur card understands padding?

To use the second PIN, once upon a time this value had to be sent to card in 'CREATE PIN' command (for some cards even not CHANGE PIN -- CREATE).
Only then you will be able to use padded PIN -- first part comes from user input, second is from middle-ware. Card itself will never know how this PIN was composed -- it will receive "313233343536FFFF".

SO WHY DID THIS PRACTICE CHANGE?

If a 6 byte PIN was padded when created and padded to N bytes each time it is used, either by the middle ware,
or the pinpad reader, then problem is solved! (N could be the max_length, which you already retrieve from p15 data. PIV uses N=8)

How are the pins created on officially issued cards?

If officially issued cards are now created with unpadded pins, it sounds the change broke the use of pinpad readers with some cards
(or at least pinpad readers and software that can not force the pinpad reader to change the Lc of the APDU sent from the
reader to the card.)

As anecdote:
PIN "123456" can be verified with PIN PAD where first 4 characters taken from user input and the last two bytes padded. All is a question of APDU template in P10 verify data.

Are you saying users entered 1234 and padding is 56? i.e. 31323334 and 3536
That really is saying the padding is 56 (3536)

or did you mean "first 6 characters"?

The iso7816.c pin commands, understand how to extend padding with FF (or I think any other single character like 00)


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

Douglas E. Engert [email protected]

@dengert
Copy link
Member

dengert commented Apr 7, 2015

If the SDO can be read, then it could be used as the Lc value in the pinpad template.

On 4/7/2015 8:00 AM, estieux-tehtri-security wrote:

Just a few feedback :

  • I only managed to get a real pinpad validation when I explicitely set the real pin size in pin_cmd->pin1.len
  • The other way is to change my pin with a padded value but as Viktor said, the real pin is, for example 313233343536FFFF and not 313233343536 despite I only need to type 123456. Not sure it will be
    compatible with another system if I move my card.

I saw in http:https://www.acsiel.fr/iso_album/ias_ecc_v1_0_1_fr.pdf that, in paragraph 9.4.2, the applet change PIN is described and mention that the lenght of the PIN in stored in the PIN SDO. This is
described in 3.4.5. Is this value used as "stored_length" shown by pkcs15-tool --list-pin ? Because it seems that this value is "public"

If we have no choice other than having a fixed-size pin length, maybe I could be possible to parameterize this in opensc.conf. Users may be warn that changing the default pin size (4) may break
compatibility under other OS...


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

Douglas E. Engert [email protected]

@dengert
Copy link
Member

dengert commented Apr 7, 2015

Sounds like that is there way to get around the same problem if pinpad reader can not change the Lc value.
i.e. user enters on keyboard how long the pin will be. (Not sure if the middleware can ask user to enter length
on pinpad reader, so middleware can use this in actual pin entry.)

Is the SDO created by the card during a pin change operation, or is it updated
by the middleware after a pin change operation?

If it can be read and the middleware needs to update it, is there code missing in OpenSC to update it?

On 4/7/2015 9:01 AM, estieux-tehtri-security wrote:

Just for information, I gave a try to http:https://git.gniibe.org/gitweb/?p=gnuk/gnuk.git;a=blob;f=tool/pinpadtest.py with my pinpad reader. I was able to check a PIN with a length of 6 successfully. (for 5
I needed to pass the -pinmin 4 option)


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

Douglas E. Engert [email protected]

@estieux-tehtri-security
Copy link
Author

I think I misexplained : the tool mentioned does not need to know the
actual size of the PIN. It is just that the default min length
transmitted to pinpad was configured to 6. For smaller PIN, I needed to
indicate a smaller minimal PIN length. But I never indicated the real
size of the Pin and I used PIN with size different than the minimal PIN
size (or the maximal)

Le 07/04/2015 16:46, Doug Engert a écrit :

Sounds like that is there way to get around the same problem if pinpad
reader can not change the Lc value.
i.e. user enters on keyboard how long the pin will be. (Not sure if
the middleware can ask user to enter length
on pinpad reader, so middleware can use this in actual pin entry.)

Is the SDO created by the card during a pin change operation, or is it
updated
by the middleware after a pin change operation?

If it can be read and the middleware needs to update it, is there code
missing in OpenSC to update it?

On 4/7/2015 9:01 AM, estieux-tehtri-security wrote:

Just for information, I gave a try to
http:https://git.gniibe.org/gitweb/?p=gnuk/gnuk.git;a=blob;f=tool/pinpadtest.py
with my pinpad reader. I was able to check a PIN with a length of 6
successfully. (for 5
I needed to pass the -pinmin 4 option)


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

Douglas E. Engert [email protected]


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

@dengert
Copy link
Member

dengert commented Apr 7, 2015

Great find...

http:https://git.gniibe.org/gitweb/?p=gnuk/gnuk.git;a=blob;f=tool/pinpadtest.py

This has a lot of useful information, including pinpad readers that work with variable length,
and ones that do not. I am not very good with python but it looks like it can modify the Lc value.
We need to look at the iso7816.c module, and see if it could do the same.

This line looks interesting:
0x82, # bmFormatString: Byte, pos=0, left, ASCII.
the add_a_byte --add option looks interesting too.

Douglas E. Engert [email protected]

@dengert
Copy link
Member

dengert commented Apr 7, 2015

Even with your that explanation, I think the python script is doing something
that OpenSC can not do.

Can you:
restart pcscd to produce debug output:
/usr/sbin/pcscd -a -d -f

Then run the script with -pinmin 4 and other options as needed.
(and send the command and any output.)

Before entering the PIN,
look at the pcscd trace output (It should be the last line) for:
PC/SC v2 pinpad block:

recode what it is.

Then enter the 5 digit PIN on the pinpad.

Recode the status PCSC returns from the card, If it worked, it will be 9000.

What this should show is what working middleware send to the reader,
and how the reader should modify the APDU with the pin and length to sent to the card.

Can you also send
What is the reader, OS, PCSC version and CPU being used.

Thanks.

On 4/7/2015 10:00 AM, estieux-tehtri-security wrote:

I think I misexplained : the tool mentioned does not need to know the
actual size of the PIN. It is just that the default min length
transmitted to pinpad was configured to 6. For smaller PIN, I needed to
indicate a smaller minimal PIN length. But I never indicated the real
size of the Pin and I used PIN with size different than the minimal PIN
size (or the maximal)

Le 07/04/2015 16:46, Doug Engert a écrit :

Sounds like that is there way to get around the same problem if pinpad
reader can not change the Lc value.
i.e. user enters on keyboard how long the pin will be. (Not sure if
the middleware can ask user to enter length
on pinpad reader, so middleware can use this in actual pin entry.)

Is the SDO created by the card during a pin change operation, or is it
updated
by the middleware after a pin change operation?

If it can be read and the middleware needs to update it, is there code
missing in OpenSC to update it?

On 4/7/2015 9:01 AM, estieux-tehtri-security wrote:

Just for information, I gave a try to
http:https://git.gniibe.org/gitweb/?p=gnuk/gnuk.git;a=blob;f=tool/pinpadtest.py
with my pinpad reader. I was able to check a PIN with a length of 6
successfully. (for 5
I needed to pass the -pinmin 4 option)


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

Douglas E. Engert [email protected]


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

Laurent Estieux


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

Douglas E. Engert [email protected]

@viktorTarasov
Copy link
Member

@dengert

I have not seen cards that can strip the PIN and return OK on validating of only the part of received PIN.

Pin pad can supply padding, With this sent to the reader, (spaces added) 1E 1E 02 08 00 0804 02 FF 0000000000000 D000000 00200080 08 FFFFFFFFFFFFFFFF

Here APDU template in P10 verify data is composed by MW, including the padding.
Not by PIN-PAD.

On IAS/ECC cards would 313233343536 and 3132333435360000 be the same?

No, its two different PINS.

Sounds like you saying the Gemalto, Morpho, ... store the length based on the length of the data.
and do not understand any type of padding, but Oberthur does not have the problem?
i.e. Does Oberthur card understands padding?

In Oberthur's case there is convention to use padded PIN (64 bytes), adopted by Oberthur's MW for all their cards, not only IAS/ECC. The same was implemented in OpenSC to be compatible with native MW.
It's absolutely internal Oberthur's feature, not even compatible with PIN-PAD (too long).

No such convention was adopted by the others.

As anecdote:

Are you saying users entered 1234 and padding is 56? i.e. 31323334 and 3536
That really is saying the padding is 56 (3536)

I mean PIN "313233343536".
Let's say the following data is sent to PIN PAD as P10 verify block:
1E 1E 02 08 00 0804 02 FF 0000000000000 B000000 00200001 06 FFFFFFFF3536
User will enter first four bytes (31323334), the last two bytes come from APDU template.
Finally card receives "00200001 06 313233343536".

If the SDO can be read, then it could be used as the Lc value in the pinpad template.

In IAS/ECC PIN SDO meta data there is no 'stored-length' parameter. Only 'min' and 'max'.
Stored-length data has to be present in PKCS#15 data.

@estieux-tehtri-security
Copy link
Author

OK, here is my debugging output when launching python pinpadtest.py
--pinmin 4 and typing a 5 digits PIN.

My testing environment is ubuntu 14.04 LTS x64 in a virtualbox
environment. PCSC shipped with Ubuntu :
pcsc-lite version 1.8.10.
Copyright (C) 1999-2002 by David Corcoran [email protected].
Copyright (C) 2001-2011 by Ludovic Rousseau [email protected].
Copyright (C) 2003-2004 by Damien Sauveron [email protected].
Report bugs to [email protected].
Enabled features: Linux x86_64-pc-linux-gnu serial usb libudev
usbdropdir=/usr/lib/pcsc/drivers ipcdir=/var/run/pcscd
configdir=/etc/reader.conf.d

Pinpad reader is a Gemalto CT-710 (Bus 002 Device 021: ID 08e6:34c2
Gemplus).

tail -f log-pcsc.log |grep -v "CMD_GET_READERS_STATE" |grep -v
READER_STATE_CHANGE :

[...]
00151527 ifdhandler.c:1122:IFDHPowerICC() action: PowerDown,
usb:08e6/34c2:libudev:0:/dev/bus/usb/002/021 (lun: 0)
00005805 eventhandler.c:455:EHStatusHandlerThread() powerState:
POWER_STATE_UNPOWERED
00247600 winscard_msg_srv.c:230:ProcessEventsServer() Common channel
packet arrival
00000012 winscard_msg_srv.c:242:ProcessEventsServer()
ProcessCommonChannelRequest detects: 16
00000002 pcscdaemon.c:111:SVCServiceRunLoop() A new context thread
creation is requested: 16
00000075 winscard_svc.c:301:ContextThread() Thread is started:
dwClientID=16, threadContext @0x748320
00005240 winscard_svc.c:319:ContextThread() Received command:
CMD_VERSION from client 16
00000092 winscard_svc.c:331:ContextThread() Client is protocol
version 4:3
00000014 winscard_svc.c:351:ContextThread() CMD_VERSION rv=0x0 for
client 16
00000033 winscard_svc.c:319:ContextThread() Received command:
ESTABLISH_CONTEXT from client 16
00000028 winscard.c:193:SCardEstablishContext() Establishing
Context: 0x25F711D0
00000012 winscard_svc.c:412:ContextThread() ESTABLISH_CONTEXT rv=0x0
for client 16
00000090 winscard_msg_srv.c:230:ProcessEventsServer() Common channel
packet arrival
00000007 winscard_msg_srv.c:242:ProcessEventsServer()
ProcessCommonChannelRequest detects: 17
00000002 pcscdaemon.c:111:SVCServiceRunLoop() A new context thread
creation is requested: 17
00000058 winscard_svc.c:301:ContextThread() Thread is started:
dwClientID=17, threadContext @0x72d650
00000104 winscard_svc.c:319:ContextThread() Received command:
CMD_VERSION from client 17
00000035 winscard_svc.c:331:ContextThread() Client is protocol
version 4:3
00000011 winscard_svc.c:351:ContextThread() CMD_VERSION rv=0x0 for
client 17
00000025 winscard_svc.c:319:ContextThread() Received command:
ESTABLISH_CONTEXT from client 17
00000024 winscard.c:193:SCardEstablishContext() Establishing
Context: 0x2B180AD0
00000012 winscard_svc.c:412:ContextThread() ESTABLISH_CONTEXT rv=0x0
for client 17
00000092 winscard_svc.c:319:ContextThread() Received command:
CONNECT from client 17
00000031 winscard.c:235:SCardConnect() Attempting Connect to Gemalto
Ezio Shield (S1470138570755) 00 00 using protocol: 3
00000014 readerfactory.c:745:RFReaderInfo() RefReader() count was: 1
00024594 ifdhandler.c:1122:IFDHPowerICC() action: PowerUp,
usb:08e6/34c2:libudev:0:/dev/bus/usb/002/021 (lun: 0)
00170950 winscard.c:310:SCardConnect() power up complete.
00000013 Card ATR: 3B 7F 18 00 00 00 31 B8 64 50 23 EC C1 73 94 01
80 82 90 00
00000002 winscard.c:330:SCardConnect() powerState: POWER_STATE_INUSE
00000010 prothandler.c:87:PHSetProtocol() Attempting PTS to T=0
00000002 ifdhandler.c:668:IFDHSetProtocolParameters() protocol T=0,
usb:08e6/34c2:libudev:0:/dev/bus/usb/002/021 (lun: 0)
00000003 ifdhandler.c:2030:extra_egt() Extra EGT patch applied
00004888 winscard.c:409:SCardConnect() Active Protocol: T=0
00000007 winscard.c:429:SCardConnect() hCard Identity: 25d27eba
00000003 winscard.c:490:SCardConnect() UnrefReader() count was: 2
00000003 winscard_svc.c:453:ContextThread() CONNECT rv=0x0 for client 17
00000047 winscard_svc.c:319:ContextThread() Received command: STATUS
from client 17
00000004 readerfactory.c:772:RFReaderInfoById() RefReader() count was: 1
00000002 winscard.c:1291:SCardStatus() UnrefReader() count was: 2
00000002 winscard_svc.c:561:ContextThread() STATUS rv=0x0 for client 17
00001967 winscard_svc.c:319:ContextThread() Received command:
CONTROL from client 17
00000046 readerfactory.c:772:RFReaderInfoById() RefReader() count was: 1
00000005 ifdhandler.c:1360:IFDHControl() ControlCode: 0x42000D48,
usb:08e6/34c2:libudev:0:/dev/bus/usb/002/021 (lun: 0)
00000004 Control TxBuffer:
00000004 Control RxBuffer: 06 04 42 33 00 06 07 04 42 33 00 07 0A 04
42 33 00 0A 12 04 42 33 00 12 13 04 42 00 00 01
00000001 winscard.c:1350:SCardControl() UnrefReader() count was: 2
00000001 winscard_svc.c:652:ContextThread() CONTROL rv=0x0 for client 17
00000119 winscard_svc.c:319:ContextThread() Received command:
CONTROL from client 17
00000034 readerfactory.c:772:RFReaderInfoById() RefReader() count was: 1
00000003 ifdhandler.c:1360:IFDHControl() ControlCode: 0x42330006,
usb:08e6/34c2:libudev:0:/dev/bus/usb/002/021 (lun: 0)
00000003 Control TxBuffer: 00 00 82 00 00 0F 04 02 01 00 00 00 00 00
04 04 00 00 00 00 20 00 81

-- Here I type my PIN on pinpad

00012143 Control RxBuffer: 90 00
00002100 winscard.c:1350:SCardControl() UnrefReader() count was: 2
00000002 winscard_svc.c:652:ContextThread() CONTROL rv=0x0 for client 17
00000131 winscard_svc.c:319:ContextThread() Received command:
DISCONNECT from client 17
00000006 readerfactory.c:772:RFReaderInfoById() RefReader() count was: 1
00000001 winscard.c:850:SCardDisconnect() Active Contexts: 1
00000009 winscard.c:851:SCardDisconnect() dwDisposition: 2
00002194 ifdhandler.c:1122:IFDHPowerICC() action: PowerDown,
usb:08e6/34c2:libudev:0:/dev/bus/usb/002/021 (lun: 0)
00000656 ifdhandler.c:1122:IFDHPowerICC() action: PowerUp,
usb:08e6/34c2:libudev:0:/dev/bus/usb/002/021 (lun: 0)
00220103 winscard.c:917:SCardDisconnect() Reset complete.
00000022 Card ATR: 3B 7F 18 00 00 00 31 B8 64 50 23 EC C1 73 94 01
80 82 90 00
00000004 winscard.c:1016:SCardDisconnect() powerState:
POWER_STATE_GRACE_PERIOD
00000003 ifdhandler.c:362:IFDHGetCapabilities() tag: 0xFB2,
usb:08e6/34c2:libudev:0:/dev/bus/usb/002/021 (lun: 0)
00000002 winscard.c:1030:SCardDisconnect() Stopping polling thread
00000001 ifdhandler.c:327:IFDHStopPolling()
usb:08e6/34c2:libudev:0:/dev/bus/usb/002/021 (lun: 0)
00001068 winscard.c:1043:SCardDisconnect() UnrefReader() count was: 2
00000016 winscard_svc.c:490:ContextThread() DISCONNECT rv=0x0 for
client 17
00000211 winscard_svc.c:319:ContextThread() Received command:
RELEASE_CONTEXT from client 17
00000005 winscard.c:204:SCardReleaseContext() Releasing Context:
0x2B180AD0
00000003 winscard_svc.c:427:ContextThread() RELEASE_CONTEXT rv=0x0
for client 17
00001845 winscard_svc.c:311:ContextThread() Client die: 17
00000014 winscard_svc.c:933:MSGCleanupClient() Thread is stopping:
dwClientID=17, threadContext @0x72d650
00000004 winscard_svc.c:939:MSGCleanupClient() Freeing SCONTEXT
@0x72d650
00001075 winscard_svc.c:311:ContextThread() Client die: 16
00000017 winscard.c:204:SCardReleaseContext() Releasing Context:
0x25F711D0
00000005 winscard_svc.c:933:MSGCleanupClient() Thread is stopping:
dwClientID=16, threadContext @0x748320
00000002 winscard_svc.c:939:MSGCleanupClient() Freeing SCONTEXT
@0x748320
00254999 eventhandler.c:467:EHStatusHandlerThread() powerState:
POWER_STATE_POWERED
00237249 ifdhandler.c:1122:IFDHPowerICC() action: PowerDown,
usb:08e6/34c2:libudev:0:/dev/bus/usb/002/021 (lun: 0)
00005204 eventhandler.c:455:EHStatusHandlerThread() powerState:
POWER_STATE_UNPOWERED

Le 07/04/2015 18:21, Doug Engert a écrit :

Even with your that explanation, I think the python script is doing
something
that OpenSC can not do.

Can you:
restart pcscd to produce debug output:
/usr/sbin/pcscd -a -d -f

Then run the script with -pinmin 4 and other options as needed.
(and send the command and any output.)

Before entering the PIN,
look at the pcscd trace output (It should be the last line) for:
PC/SC v2 pinpad block:

recode what it is.

Then enter the 5 digit PIN on the pinpad.

Recode the status PCSC returns from the card, If it worked, it will be
9000.

What this should show is what working middleware send to the reader,
and how the reader should modify the APDU with the pin and length to
sent to the card.

Can you also send
What is the reader, OS, PCSC version and CPU being used.

Thanks.

@dengert
Copy link
Member

dengert commented Apr 8, 2015

Much of this discussion is also covered in:

#309

The Verification Data Structure is:
00 00 82 00 00 0F 04 02 01 00 00 00 00 00 04 04 00 00 00 00 20 00 81

bTimeOut = 0
bTimeout2 = 0
bmFormatString = 82 bit7 = 1:Bytes, bit 1-0 = 10:ASCI
bmPINBlockString = 00
bmPINLengthFormat = 00
wPINMaxExtraDigit = 0f04 Max = 15, min=4
bEntryValidationCondition = 02, end on validation key pressed
bNumberMessage = 01, Enter Pin type message.
wLangId = 0000
bMsgIndex = 00
bTeoPrologue = 00 00 04
ulDataLength = 04 00 00 00 length of abData
abData = 00 20 00 81 Verify APDU with no Lc or data.

I suspect the actual APDU used is:
00 20 00 81 05 3x 3x 3x 3x 3x
where 3X are the 5 digits of your pin, and the 05 is the length
of the data which is the length of the pin you typed.

The main difference I see with this vs what OpenSC does is the bmFormatString
bit7 = 1 indicating the system units is bytes. OpenSC does not set this
as best I can tell.

For some readers the script has a --add_byte which sounds like #309

Vikyor said: "The only PINPAD that I have is 'Gemalto GemPC PinPad' and apparently it has
a bug and do not accept different values for min/max length in P10 data"
Your reader sounds newer and may not have this problem.

Not clear type of card you have.

So to do this correctly, the bmFormatString which have bit7 = 1, for bytes.
Some readers need extra byte, but not clear which ones.

Some readers may never work with the variable length pin.

On 4/7/2015 5:04 PM, estieux-tehtri-security wrote:

OK, here is my debugging output when launching python pinpadtest.py
--pinmin 4 and typing a 5 digits PIN.

My testing environment is ubuntu 14.04 LTS x64 in a virtualbox
environment. PCSC shipped with Ubuntu :
pcsc-lite version 1.8.10.
Copyright (C) 1999-2002 by David Corcoran [email protected].
Copyright (C) 2001-2011 by Ludovic Rousseau [email protected].
Copyright (C) 2003-2004 by Damien Sauveron [email protected].
Report bugs to [email protected].
Enabled features: Linux x86_64-pc-linux-gnu serial usb libudev
usbdropdir=/usr/lib/pcsc/drivers ipcdir=/var/run/pcscd
configdir=/etc/reader.conf.d

Pinpad reader is a Gemalto CT-710 (Bus 002 Device 021: ID 08e6:34c2
Gemplus).

tail -f log-pcsc.log |grep -v "CMD_GET_READERS_STATE" |grep -v
READER_STATE_CHANGE :

[...]
00151527 ifdhandler.c:1122:IFDHPowerICC() action: PowerDown,
usb:08e6/34c2:libudev:0:/dev/bus/usb/002/021 (lun: 0)
00005805 eventhandler.c:455:EHStatusHandlerThread() powerState:
POWER_STATE_UNPOWERED
00247600 winscard_msg_srv.c:230:ProcessEventsServer() Common channel
packet arrival
00000012 winscard_msg_srv.c:242:ProcessEventsServer()
ProcessCommonChannelRequest detects: 16
00000002 pcscdaemon.c:111:SVCServiceRunLoop() A new context thread
creation is requested: 16
00000075 winscard_svc.c:301:ContextThread() Thread is started:
dwClientID=16, threadContext @0x748320
00005240 winscard_svc.c:319:ContextThread() Received command:
CMD_VERSION from client 16
00000092 winscard_svc.c:331:ContextThread() Client is protocol
version 4:3
00000014 winscard_svc.c:351:ContextThread() CMD_VERSION rv=0x0 for
client 16
00000033 winscard_svc.c:319:ContextThread() Received command:
ESTABLISH_CONTEXT from client 16
00000028 winscard.c:193:SCardEstablishContext() Establishing
Context: 0x25F711D0
00000012 winscard_svc.c:412:ContextThread() ESTABLISH_CONTEXT rv=0x0
for client 16
00000090 winscard_msg_srv.c:230:ProcessEventsServer() Common channel
packet arrival
00000007 winscard_msg_srv.c:242:ProcessEventsServer()
ProcessCommonChannelRequest detects: 17
00000002 pcscdaemon.c:111:SVCServiceRunLoop() A new context thread
creation is requested: 17
00000058 winscard_svc.c:301:ContextThread() Thread is started:
dwClientID=17, threadContext @0x72d650
00000104 winscard_svc.c:319:ContextThread() Received command:
CMD_VERSION from client 17
00000035 winscard_svc.c:331:ContextThread() Client is protocol
version 4:3
00000011 winscard_svc.c:351:ContextThread() CMD_VERSION rv=0x0 for
client 17
00000025 winscard_svc.c:319:ContextThread() Received command:
ESTABLISH_CONTEXT from client 17
00000024 winscard.c:193:SCardEstablishContext() Establishing
Context: 0x2B180AD0
00000012 winscard_svc.c:412:ContextThread() ESTABLISH_CONTEXT rv=0x0
for client 17
00000092 winscard_svc.c:319:ContextThread() Received command:
CONNECT from client 17
00000031 winscard.c:235:SCardConnect() Attempting Connect to Gemalto
Ezio Shield (S1470138570755) 00 00 using protocol: 3
00000014 readerfactory.c:745:RFReaderInfo() RefReader() count was: 1
00024594 ifdhandler.c:1122:IFDHPowerICC() action: PowerUp,
usb:08e6/34c2:libudev:0:/dev/bus/usb/002/021 (lun: 0)
00170950 winscard.c:310:SCardConnect() power up complete.
00000013 Card ATR: 3B 7F 18 00 00 00 31 B8 64 50 23 EC C1 73 94 01
80 82 90 00
00000002 winscard.c:330:SCardConnect() powerState: POWER_STATE_INUSE
00000010 prothandler.c:87:PHSetProtocol() Attempting PTS to T=0
00000002 ifdhandler.c:668:IFDHSetProtocolParameters() protocol T=0,
usb:08e6/34c2:libudev:0:/dev/bus/usb/002/021 (lun: 0)
00000003 ifdhandler.c:2030:extra_egt() Extra EGT patch applied
00004888 winscard.c:409:SCardConnect() Active Protocol: T=0
00000007 winscard.c:429:SCardConnect() hCard Identity: 25d27eba
00000003 winscard.c:490:SCardConnect() UnrefReader() count was: 2
00000003 winscard_svc.c:453:ContextThread() CONNECT rv=0x0 for client 17
00000047 winscard_svc.c:319:ContextThread() Received command: STATUS
from client 17
00000004 readerfactory.c:772:RFReaderInfoById() RefReader() count was: 1
00000002 winscard.c:1291:SCardStatus() UnrefReader() count was: 2
00000002 winscard_svc.c:561:ContextThread() STATUS rv=0x0 for client 17
00001967 winscard_svc.c:319:ContextThread() Received command:
CONTROL from client 17
00000046 readerfactory.c:772:RFReaderInfoById() RefReader() count was: 1
00000005 ifdhandler.c:1360:IFDHControl() ControlCode: 0x42000D48,
usb:08e6/34c2:libudev:0:/dev/bus/usb/002/021 (lun: 0)
00000004 Control TxBuffer:
00000004 Control RxBuffer: 06 04 42 33 00 06 07 04 42 33 00 07 0A 04
42 33 00 0A 12 04 42 33 00 12 13 04 42 00 00 01
00000001 winscard.c:1350:SCardControl() UnrefReader() count was: 2
00000001 winscard_svc.c:652:ContextThread() CONTROL rv=0x0 for client 17
00000119 winscard_svc.c:319:ContextThread() Received command:
CONTROL from client 17
00000034 readerfactory.c:772:RFReaderInfoById() RefReader() count was: 1
00000003 ifdhandler.c:1360:IFDHControl() ControlCode: 0x42330006,
usb:08e6/34c2:libudev:0:/dev/bus/usb/002/021 (lun: 0)
00000003 Control TxBuffer: 00 00 82 00 00 0F 04 02 01 00 00 00 00 00
04 04 00 00 00 00 20 00 81

--> Here I type my PIN on pinpad

00012143 Control RxBuffer: 90 00
00002100 winscard.c:1350:SCardControl() UnrefReader() count was: 2
00000002 winscard_svc.c:652:ContextThread() CONTROL rv=0x0 for client 17
00000131 winscard_svc.c:319:ContextThread() Received command:
DISCONNECT from client 17
00000006 readerfactory.c:772:RFReaderInfoById() RefReader() count was: 1
00000001 winscard.c:850:SCardDisconnect() Active Contexts: 1
00000009 winscard.c:851:SCardDisconnect() dwDisposition: 2
00002194 ifdhandler.c:1122:IFDHPowerICC() action: PowerDown,
usb:08e6/34c2:libudev:0:/dev/bus/usb/002/021 (lun: 0)
00000656 ifdhandler.c:1122:IFDHPowerICC() action: PowerUp,
usb:08e6/34c2:libudev:0:/dev/bus/usb/002/021 (lun: 0)
00220103 winscard.c:917:SCardDisconnect() Reset complete.
00000022 Card ATR: 3B 7F 18 00 00 00 31 B8 64 50 23 EC C1 73 94 01
80 82 90 00
00000004 winscard.c:1016:SCardDisconnect() powerState:
POWER_STATE_GRACE_PERIOD
00000003 ifdhandler.c:362:IFDHGetCapabilities() tag: 0xFB2,
usb:08e6/34c2:libudev:0:/dev/bus/usb/002/021 (lun: 0)
00000002 winscard.c:1030:SCardDisconnect() Stopping polling thread
00000001 ifdhandler.c:327:IFDHStopPolling()
usb:08e6/34c2:libudev:0:/dev/bus/usb/002/021 (lun: 0)
00001068 winscard.c:1043:SCardDisconnect() UnrefReader() count was: 2
00000016 winscard_svc.c:490:ContextThread() DISCONNECT rv=0x0 for
client 17
00000211 winscard_svc.c:319:ContextThread() Received command:
RELEASE_CONTEXT from client 17
00000005 winscard.c:204:SCardReleaseContext() Releasing Context:
0x2B180AD0
00000003 winscard_svc.c:427:ContextThread() RELEASE_CONTEXT rv=0x0
for client 17
00001845 winscard_svc.c:311:ContextThread() Client die: 17
00000014 winscard_svc.c:933:MSGCleanupClient() Thread is stopping:
dwClientID=17, threadContext @0x72d650
00000004 winscard_svc.c:939:MSGCleanupClient() Freeing SCONTEXT
@0x72d650
00001075 winscard_svc.c:311:ContextThread() Client die: 16
00000017 winscard.c:204:SCardReleaseContext() Releasing Context:
0x25F711D0
00000005 winscard_svc.c:933:MSGCleanupClient() Thread is stopping:
dwClientID=16, threadContext @0x748320
00000002 winscard_svc.c:939:MSGCleanupClient() Freeing SCONTEXT
@0x748320
00254999 eventhandler.c:467:EHStatusHandlerThread() powerState:
POWER_STATE_POWERED
00237249 ifdhandler.c:1122:IFDHPowerICC() action: PowerDown,
usb:08e6/34c2:libudev:0:/dev/bus/usb/002/021 (lun: 0)
00005204 eventhandler.c:455:EHStatusHandlerThread() powerState:
POWER_STATE_UNPOWERED

Le 07/04/2015 18:21, Doug Engert a écrit :

Even with your that explanation, I think the python script is doing
something
that OpenSC can not do.

Can you:
restart pcscd to produce debug output:
/usr/sbin/pcscd -a -d -f

Then run the script with -pinmin 4 and other options as needed.
(and send the command and any output.)

Before entering the PIN,
look at the pcscd trace output (It should be the last line) for:
PC/SC v2 pinpad block:

recode what it is.

Then enter the 5 digit PIN on the pinpad.

Recode the status PCSC returns from the card, If it worked, it will be
9000.

What this should show is what working middleware send to the reader,
and how the reader should modify the APDU with the pin and length to
sent to the card.

Can you also send
What is the reader, OS, PCSC version and CPU being used.

Thanks.

Laurent Estieux


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

Douglas E. Engert [email protected]

@LudovicRousseau
Copy link
Member

With "recent" Gemplus/Gemalto readers you can use FEATURE_CCID_ESC_COMMAND_Gemalto_features.py [1] to know the min and max PIN length supported by the reader.

You can see the results with some readers at [2].

If available, the information is reported by the CCID driver using PCSCv2_PART10_PROPERTY_bMinPINSize and PCSCv2_PART10_PROPERTY_bMaxPINSize

[1] https://anonscm.debian.org/viewvc/pcsclite/trunk/PCSC/UnitaryTests/FEATURE_CCID_ESC_COMMAND_Gemalto_features.py?view=markup
[2] https://anonscm.debian.org/viewvc/pcsclite/trunk/Drivers/ccid/readers/extra_features/

@estieux-tehtri-security
Copy link
Author

@dengert

I've done the same debuging using opensc-explorer with a fixed 5 digits pin (hardcoding it in opensc) and here is the debug output :

00000003 ifdhandler.c:1386:IFDHControl() ControlCode: 0x42330006, usb:08e6/34c2:libudev:0:/dev/bus/usb/002/024 (lun: 0)
00000005 Control TxBuffer: 1E 1E 02 00 00 10 04 02 FF 00 00 00 00 00 00 0A 00 00 00 00 20 00 01 05 FF FF FF FF FF 
16215644 Control RxBuffer: 90 00

Excepted an error from me, I see another difference (excepted timeout). The bTeoPrologue is 00 00 00 in pinpadtest.py. Don't know if it is important.

@dengert
Copy link
Member

dengert commented Apr 8, 2015

Original problem is card-iasecc.c only supports a fixed size pin when using a pinpad reader.
card-iasecc.c forced this restriction because the code was developed with pinpad reader
that may not be "recent" and this was the only solution that appeared to worked.

IAS/ECC cards will not accept a verify APDU with a fixed Lc and a padded pin.
they require verify APDU data to have only the PIN, and the Lc is length of pin.

card-sc-hsm.c and card-mrcd.c appear to require the same format of Lc is length of pin
and APDU data is the pin and set
data->pin1.length_offset = 4;
data->pin1.offset = 5;

#317 and #309

Both of the above issue discuss this and code was added to reader-pcsc.c to send the 4
bytes of the APDU to the pinpad reader and let the reader fill in the Lc and pin as entered
on the pinpad.

Both issues point out that PART10 does not appear to cover this situation yet most
more "recent" pinpad readers just do the right thing when presented with the
4 byte APDU in the abData field.

I would propose that the card-iasecc.c do what the card-sc-hsm.c and card-mrcd.c
drivers do and @viktorTarasov get a more "recent" pinpad reader for testing. It sounds like
@estieux-tehtri-security has one, the GemAlto CT710, and can do some testing.

To make sure SC_CCID_PIN_UNITS_BYTES is set, I would also propose that reader-pcsc.c line 1331
if (data->pin1.length_offset > 4) {
be changed to
if (data->pin1.length_offset >= 4) {
The python script for example sets this, and we are working with bytes, not bits in this situation.
Some reader may require this bit be set

If there are readers that are known not to work or require 5 byte APDU with the Lc set to zero
should be handled in the reader-pcsc.c, not in the card driver.
Any feedback from pcsc on readers that work or not could be helpful.

@LudovicRousseau can your list of supported readers be extended to list if they
support the 4 byte or 5 byte APDU in the abData field?
Sounds like @CardContact has tested many of the pinpad readers.

In the long run, PART10 should be updated to standardize how setting the Lc value from the pin length.

Douglas E. Engert [email protected]

@dengert
Copy link
Member

dengert commented Apr 8, 2015

I would expect that to work, as you sent the length of your pin in the abData (APDU template)
and 5 bytes to overwrite. Assuming your 5 byte pin is 12345, the pinpad reader takes:
00 20 00 01 05 FF FF FF FF FF
and overwrites it to produce
00 20 00 01 05 31 32 33 34 35

This should be the same APDU that would be sent to the card, if you did not use a pinpad reader.

I believe the reader-pcsc.c fills in the bTeoPrologue if T=1 is being used.

On 4/8/2015 8:33 AM, estieux-tehtri-security wrote:

@dengert https://github.com/dengert

I've done the same debuging using opensc-explorer with a fixed 5 digits pin (hardcoding it in opensc) and here is the debug output :

|00000003 ifdhandler.c:1386:IFDHControl() ControlCode: 0x42330006, usb:08e6/34c2:libudev:0:/dev/bus/usb/002/024 (lun: 0)
00000005 Control TxBuffer: 1E 1E 02 00 00 10 04 02 FF 00 00 00 00 00 00 0A 00 00 00 00 20 00 01 05 FF FF FF FF FF
16215644 Control RxBuffer: 90 00
|

Excepted an error from me, I see another difference (excepted timeout). The bTeoPrologue is 00 00 00 in pinpadtest.py. Don't know if it is important.


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

Douglas E. Engert [email protected]

@estieux-tehtri-security
Copy link
Author

@dengert @viktorTarasov

Feel free to ask me if I can help debugging. If necessary, I can even lend the reader.

@dengert
Copy link
Member

dengert commented Apr 9, 2015

They should be under $50.
I currently have a Omnikey 3821

The problem is I don't have a card that uses the variable length pin format, like the IAS/ECC cards.
Are they available in quantities of 1?
And which one would be best to test with?

If not a IAS/ECC card, what other card could I use?

On 4/9/2015 7:41 AM, estieux-tehtri-security wrote:

@dengert https://github.com/dengert @viktorTarasov https://github.com/viktorTarasov

Feel free to ask me if I can help debugging. If necessary, I can even lend the reader.


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

Douglas E. Engert [email protected]

@viktorTarasov
Copy link
Member

I tried CardMan 3821 but it do not works without full VERIFY PIN template:

00000019 Control TxBuffer: 1E 1E 82 00 00 04 04 02 FF 00 00 00 00 00 00 04 00 00 00 00 20 00 01 
07387832 Control RxBuffer: 67 00 

@estieux-tehtri-security
Afaiu, you have PIN length 6 bytes. What gives the following command with your card?
$ pkcs15-tool --aid E828BD080FD25047656E65726963 --list-pins

@estieux-tehtri-security
Copy link
Author

@viktorTarasov

Currently my PIN is 5 bytes and the result of the command is :
PIN [PIN User Global]
Object Flags : [0x2], modifiable
Auth ID : 02
ID : c1
Flags : [0x810], initialized, exchangeRefData
Length : min_len:4, max_len:16, stored_len:4
Pad char : 0x00
Reference : 1 (0x01)
Type : ascii-numeric

PIN [Puk pour Pin User]
Object Flags : [0x2], modifiable
ID : 02
Flags : [0x858], unblock-disabled, initialized, unblockingPin, exchangeRefData
Length : min_len:4, max_len:16, stored_len:4
Pad char : 0x00
Reference : 2 (0x02)
Type : ascii-numeric

@viktorTarasov
Copy link
Member

Current PIN is 5 bytes, but stored-len is 4.
Was it like this when you received this card? Have you changed this PIN? How?

@estieux-tehtri-security
Copy link
Author

Card was delivered with default 4 bytes length PIN (1234). I changed the PIN through pkcs15-tool --change-pin.

The applet on the card is not the latest, it is the 1.4.5 version (and not 1.6).

@dengert
Copy link
Member

dengert commented Apr 9, 2015

The python script on previous issues with pinpad readers point out that different readers
address this problem in different ways.

The APDU may need to be 5 bytes, i.e. add a Lc=0 byte.
The python script uses the --add option to do this. Some may need the Lc=0 and
additional bytes for a buffer to store the pin. The python script has the
--fixed option to add 255 bytes of zeros. (I don't have the script right now,
I may have the options wrong.)

The Omnikey 3821 (which may be the same as CardMan 3821 but newer) may need may need the lc = 0 byte.

I am attaching the lastest patch I have. It adds the Lc=0 byte, sets the system units are bytes,
makes sure the card-iasecc.c sets the offsets.
Disregards the PIV code, as it was for trying to simulate the variable length pin
using an 8 byte pin with the PIV. In this case the APDUs would look the same.

On 4/9/2015 11:20 AM, viktorTarasov wrote:

I tried CardMan 3821 but it do not works without full VERIFY PIN template:

|00000019 Control TxBuffer: 1E 1E 82 00 00 04 04 02 FF 00 00 00 00 00 00 04 00 00 00 00 20 00 01
07387832 Control RxBuffer: 67 00
|

@estieux-tehtri-security https://github.com/estieux-tehtri-security
Afaiu, you have PIN length 6 bytes. What gives the following command with your card?
$ pkcs15-tool --aid E828BD080FD25047656E65726963 --list-pins


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

Douglas E. Engert [email protected]

@viktorTarasov
Copy link
Member

@dengert
Thanks,
P10 data witn Lc=0 works for me when using CardMan 3821.
The same do not work with Gemalto PIN Pad.

@estieux-tehtri-security
Copy link
Author

@viktorTarasov
Would you like that I give a try to the gemalto CT-710 ? The http:https://git.gniibe.org/gitweb/?p=gnuk/gnuk.git;a=blob;f=tool/pinpadtest.py indicates at the end that they had problem with Gemalto GemPC pinpad and variable length PC pinpad.

@estieux-tehtri-security
Copy link
Author

@viktorTarasov

If forgot to say that when I changed the initial pin code to a 5 byte length (or another size) PIN, I used a non-pinpad smartcard reader.

@dengert
Copy link
Member

dengert commented Apr 10, 2015

The MODIFY is harder. The reader would have to add the length of the two pins
to store as Lc.

Next we need a way in reader-pcsc.c to look up reader variable length pin info,
i.e. does not work, needs only 4 byte APDU, needs 5 byte APDU,(Lc=0), needs longer
APDU with Lc=0 and data ANd if only VERIFY or MODIFY also works.

It would be nice if pcscd could return this, but when run on Windows, the Windows
version of PC/SC that is used. We could add parameters to opensc.conf

The comments in the python script, and maybe other places, is a start for the
information we need.

@LudovicRousseau could you add something like this to:
https://pcsclite.alioth.debian.org/ccid/

I see you have bPINSupport, Features and Limitations

Any suggestions on how to collect this information?

Any other developers of cards that use the variable length PIN info should also be interested in this.

On 4/10/2015 2:24 AM, viktorTarasov wrote:

@dengert https://github.com/dengert
Thanks,
P10 data witn Lc=0 works for me when using /CardMan 3821/.
The same do not work with /Gemalto PIN Pad/.


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

Douglas E. Engert [email protected]

@estieux-tehtri-security
Copy link
Author

I use the same script (pinpadtest.py) successfully to modify my pin on pinpad with various scenario like old and new PIN 4 bytes length or old and new PIN with different length.

@viktorTarasov
Copy link
Member

@estieux-tehtri-security
What gives the following command with your card?
$ iasecc-tool --list-sdos 01

@estieux-tehtri-security
Copy link
Author

iasecc-tool --list-sdos 01
Using reader with a card: Gemalto Ezio Shield
Found SDO class 1, reference 1
contact ACLs:   F1:00:00:17:00
size:   00:04
tries maximum:  03
tries remaining:    03
Found SDO class 1, reference 2
contact ACLs:   E1:00:00:00
size:   00:04
tries maximum:  03
tries remaining:    03

@viktorTarasov
Copy link
Member

@estieux-tehtri-security
This card really has User PIN 5 bytes?

@estieux-tehtri-security
Copy link
Author

my fault, I switched back to a 4 bytes PIN. Here's the output for a five-byte PIN (PUK is still 4-bytes)

Using reader with a card: Gemalto Ezio Shield
Found SDO class 1, reference 1
contact ACLs:   F1:00:00:17:00
size:   00:05
tries maximum:  03
tries remaining:    03
Found SDO class 1, reference 2
contact ACLs:   E1:00:00:00
size:   00:04
tries maximum:  03
tries remaining:    03

@viktorTarasov
Copy link
Member

@estieux-tehtri-security
Try current 'master'.
Have not succeeded to make working RESET PIN with PIN-PAD. Disabled for a while.

@estieux-tehtri-security
Copy link
Author

Functionnaly,it works. I saw that you implemented a way to catch the size of the PIN SDO and send an appropriate APDU with this size. The minor side effect is that if the card is waiting of a n bytes PIN and you type a wrong m (>n) bytes PIN, the error counter will not be incremented. Personally, I can live with that.

What I'm wondering is what can be the behavior of the pinpad reader if it implements a "firewall feature" ? Will it accept your APDU ? Mine (CT-710) is supposed to have a "firewall" feature but I saw that it does not work in reality (I was able to send PIN through command line). And is there any problem reusing the APDU seen in pinpadtest.py with a LC=0. I think I missed this point.

@dwmw2
Copy link

dwmw2 commented May 14, 2015

Commit 5757d82 breaks binary compatibility. You need to bump the soname to libopensc.so.4, don't you?

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

No branches or pull requests

6 participants