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

Current PIV Answer to Select Parsing in piv_find_aid restricts answer to 129 bytes #2242

Closed
jo-bitsch opened this issue Feb 24, 2021 · 10 comments
Labels

Comments

@jo-bitsch
Copy link
Contributor

Debugging some extensions to the PivApplet that further extend the answer to select (https://github.com/arekinath/PivApplet/blob/master/src/net/cooperi/pivapplet/PivApplet.java#L855) I noticed that there is a minor logic error in the code of card-piv.c (

if (apdu.resp[0] != 0x6f || apdu.resp[1] > apdu.resplen - 2 )
)

in particular:
apdu.resp[1] > apdu.resplen - 2
restricts the response length to 129 bytes, as a field larger then 127 would be coded as 81 xx or 82 xx xx instead. I guess technically, the answer could be up to SC_MAX_EXT_APDU_RESP_SIZE and even use response chaining.

The PIV specification document(https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-73-4.pdf) = Section 3.1.1 of Interfaces for Personal Identity Verification – Part 2: PIV Card Application Card Command Interface does not make any reference to a length restriction. Maybe I'm missing something else?

@jo-bitsch
Copy link
Contributor Author

the relevant output from piv-tool -vvv --serial is

0x7fde966ba1c0 00:59:47.797 [piv-tool] card-piv.c:733:piv_select_aid: called
0x7fde966ba1c0 00:59:47.797 [piv-tool] card-piv.c:736:piv_select_aid: Got args: aid=0x7fde972e5060, aidlen=9, response=0x7fffbb91d020, responselen=261
0x7fde966ba1c0 00:59:47.797 [piv-tool] apdu.c:554:sc_transmit_apdu: called
0x7fde966ba1c0 00:59:47.797 [piv-tool] card.c:415:sc_lock: called
0x7fde966ba1c0 00:59:47.797 [piv-tool] card.c:455:sc_lock: returning with: 0 (Success)
0x7fde966ba1c0 00:59:47.797 [piv-tool] apdu.c:521:sc_transmit: called
0x7fde966ba1c0 00:59:47.797 [piv-tool] apdu.c:371:sc_single_transmit: called
0x7fde966ba1c0 00:59:47.797 [piv-tool] apdu.c:378:sc_single_transmit: CLA:0, INS:A4, P1:4, P2:0, data(9) 0x7fde972e5060
0x7fde966ba1c0 00:59:47.797 [piv-tool] reader-pcsc.c:284:pcsc_transmit: reader 'Virtual PCD 00 00'
0x7fde966ba1c0 00:59:47.797 [piv-tool] reader-pcsc.c:285:pcsc_transmit: 
Outgoing APDU (15 bytes):
00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 00 ...............
0x7fde966ba1c0 00:59:47.797 [piv-tool] reader-pcsc.c:213:pcsc_internal_transmit: called
0x7fde966ba1c0 00:59:47.801 [piv-tool] reader-pcsc.c:294:pcsc_transmit: 
Incoming APDU (133 bytes):
61 81 4F 06 00 00 10 00 01 00 79 0D 4F 0B A0 00 a.O.......y.O...
00 03 08 00 00 10 00 01 00 50 22 50 69 76 41 70 .........P"PivAp
70 6C 65 74 20 76 30 2E 38 2E 32 2D 64 65 76 2F plet v0.8.2-dev/
52 45 65 50 53 41 73 78 4C 72 61 44 58 5F 50 26 REePSAsxLraDX_P&
68 74 74 70 73 3A 2F 2F 67 69 74 68 75 62 2E 63 https://github.c
6F 6D 2F 61 72 65 6B 69 6E 61 74 68 2F 50 69 76 om/arekinath/Piv
41 70 70 6C 65 74 AC 1B 80 01 03 80 01 08 80 01 Applet..........
0A 80 01 0C 80 01 06 80 01 07 80 01 11 80 01 14 ................
06 01 00 90 00                                  .....
0x7fde966ba1c0 00:59:47.801 [piv-tool] apdu.c:390:sc_single_transmit: returning with: 0 (Success)
0x7fde966ba1c0 00:59:47.801 [piv-tool] apdu.c:543:sc_transmit: returning with: 0 (Success)
0x7fde966ba1c0 00:59:47.801 [piv-tool] card.c:465:sc_unlock: called
0x7fde966ba1c0 00:59:47.801 [piv-tool] card-piv.c:752:piv_select_aid: returning with: 0 (Success)
0x7fde966ba1c0 00:59:47.801 [piv-tool] apdu.c:554:sc_transmit_apdu: called
0x7fde966ba1c0 00:59:47.801 [piv-tool] card.c:415:sc_lock: called
0x7fde966ba1c0 00:59:47.801 [piv-tool] card.c:455:sc_lock: returning with: 0 (Success)
0x7fde966ba1c0 00:59:47.801 [piv-tool] apdu.c:521:sc_transmit: called
0x7fde966ba1c0 00:59:47.801 [piv-tool] apdu.c:371:sc_single_transmit: called
0x7fde966ba1c0 00:59:47.801 [piv-tool] apdu.c:378:sc_single_transmit: CLA:0, INS:A4, P1:4, P2:0, data(9) 0x7fde972e5060
0x7fde966ba1c0 00:59:47.801 [piv-tool] reader-pcsc.c:284:pcsc_transmit: reader 'Virtual PCD 00 00'
0x7fde966ba1c0 00:59:47.801 [piv-tool] reader-pcsc.c:285:pcsc_transmit: 
Outgoing APDU (15 bytes):
00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 00 ...............
0x7fde966ba1c0 00:59:47.801 [piv-tool] reader-pcsc.c:213:pcsc_internal_transmit: called
0x7fde966ba1c0 00:59:47.804 [piv-tool] reader-pcsc.c:294:pcsc_transmit: 
Incoming APDU (133 bytes):
61 81 4F 06 00 00 10 00 01 00 79 0D 4F 0B A0 00 a.O.......y.O...
00 03 08 00 00 10 00 01 00 50 22 50 69 76 41 70 .........P"PivAp
70 6C 65 74 20 76 30 2E 38 2E 32 2D 64 65 76 2F plet v0.8.2-dev/
52 45 65 50 53 41 73 78 4C 72 61 44 58 5F 50 26 REePSAsxLraDX_P&
68 74 74 70 73 3A 2F 2F 67 69 74 68 75 62 2E 63 https://github.c
6F 6D 2F 61 72 65 6B 69 6E 61 74 68 2F 50 69 76 om/arekinath/Piv
41 70 70 6C 65 74 AC 1B 80 01 03 80 01 08 80 01 Applet..........
0A 80 01 0C 80 01 06 80 01 07 80 01 11 80 01 14 ................
06 01 00 90 00                                  .....
0x7fde966ba1c0 00:59:47.804 [piv-tool] apdu.c:390:sc_single_transmit: returning with: 0 (Success)
0x7fde966ba1c0 00:59:47.804 [piv-tool] apdu.c:543:sc_transmit: returning with: 0 (Success)
0x7fde966ba1c0 00:59:47.804 [piv-tool] card.c:465:sc_unlock: called
0x7fde966ba1c0 00:59:47.804 [piv-tool] card-piv.c:838:piv_find_aid: returning with: -1208 (Card does not support the requested operation)

@jo-bitsch
Copy link
Contributor Author

I confirmed that it is working as intended when the answer to select is 129 bytes or shorter.

@jo-bitsch
Copy link
Contributor Author

By the way, the test output is from version 0.19.0 (debian10), that's why the debug output refers to https://github.com/OpenSC/OpenSC/blob/0.19.0/src/libopensc/card-piv.c#L838.

This part of the code didn't change though, since.

@dengert
Copy link
Member

dengert commented Feb 24, 2021

Will look at this later today.

@dengert
Copy link
Member

dengert commented Feb 24, 2021

I see two problems. First is the input data has the first tag length wrong. It is missing a extra "81"
Current opensc can not parse the template if more the 80 bytes.

That section of code was completely rewritten in #2053
If possible, could you try building and test with the PR?

In both cases the response is expected to fit in: SC_MAX_APDU_BUFFER_SIZE == 261 bytes.

But the data returned does not look correct either. (dropped 90 00 as it is not part of the data)

61 81 4F 06 00 00 10 00 01 00 79 0D 4F 0B A0 00 a.O.......y.O...
00 03 08 00 00 10 00 01 00 50 22 50 69 76 41 70 .........P"PivAp
70 6C 65 74 20 76 30 2E 38 2E 32 2D 64 65 76 2F plet v0.8.2-dev/
52 45 65 50 53 41 73 78 4C 72 61 44 58 5F 50 26 REePSAsxLraDX_P&
68 74 74 70 73 3A 2F 2F 67 69 74 68 75 62 2E 63 https://github.c
6F 6D 2F 61 72 65 6B 69 6E 61 74 68 2F 50 69 76 om/arekinath/Piv
41 70 70 6C 65 74 AC 1B 80 01 03 80 01 08 80 01 Applet..........
0A 80 01 0C 80 01 06 80 01 07 80 01 11 80 01 14 ................
06 01 00 

61 81 4F is being interpreted as tag 61 with 1 byte length of 4F

But if you look at 61 81 as tag 61 with length 0x81, then the rest of it parses.
So adding an extra 81:

61 81 81 4F 06 00 00 10 00 01 00 79 0D 4F 0B A0 00 
00 03 08 00 00 10 00 01 00 50 22 50 69 76 41 70 
70 6C 65 74 20 76 30 2E 38 2E 32 2D 64 65 76 2F 
52 45 65 50 53 41 73 78 4C 72 61 44 58 5F 50 26
68 74 74 70 73 3A 2F 2F 67 69 74 68 75 62 2E 63 
6F 6D 2F 61 72 65 6B 69 6E 61 74 68 2F 50 69 76 
41 70 70 6C 65 74 AC 1B 80 01 03 80 01 08 80 01 
0A 80 01 0C 80 01 06 80 01 07 80 01 11 80 01 14
06 01 00   

https://lapo.it/asn1js/
It parses it as:

Application 1 (5 elem)
Application 15 (6 byte) 000010000100
Application 25 (1 elem)
Offset: 11
Length: 2+13
(constructed)
Value:
(1 elem)
Application 15 (11 byte) A000000308000010000100
Application 16 (34 byte) PivApplet v0.8.2-dev/REePSAsxLraDX
Application 80 (38 byte) https://github.com/arekinath/PivApplet
[12] (9 elem)
[0] (1 byte) 03
[0] (1 byte) 08
[0] (1 byte)
[0] (1 byte) 0C
[0] (1 byte) 06
[0] (1 byte) 07
[0] (1 byte) 11
[0] (1 byte) 14
OBJECT IDENTIFIER 0.0

The AID command is really a iso7816 select file, "8.2.2.2 Application selection using AID as DF name" which expects an "8.2.1.3 Application template" But I do not see any limitations to to the size of the response on 1is 7816-4 or PIV specs.

Is this a new problem with the PIV Applet?
Because they have a problem in the construction of the template, and card-piv.c in current code, but should work in
#2053 because it uses sc_ans1_get_tag as long as it is les then 261 bytes.

@dengert
Copy link
Member

dengert commented Feb 24, 2021

I also see they are using the tag AC, which is new in NIST sp800-74-4 defines in Table 5. Which say before it:
" A PIV Card Application may use a subset of the cryptographic algorithms defined in SP 800-78. Tag 0xAC encodes the cryptographic algorithms supported by the PIV Card Application. The encoding of tag 0xAC shall be as specified in Table 5. Each instance of tag 0x80 shall encapsulate one algorithm. The presence of algorithm identifier '27' or '2E' indicates that the corresponding cipher suite is supported by the PIV Card Application for secure messaging and that the PIV Card Application possesses a PIV Secure Messaging key of the appropriate size for the specified cipher suite. Tag 0xAC shall be present and indicate algorithm identifier 0x27 or 0x2E (but not both) when the PIV Card Application supports secure messaging."

PivApplet added 9 elements and added "ALL" the algorithms supported by the card.

A Idemia demo card, that supports SM from sp800-74-4 only adds 2 elements:
AC 06 80 01 2E 06 01 00 i.e. is supports 2E and the OID is null.

sp800-73-3 does not define the "AC" tag.

It looks like Idemia interpreted table 5 to be added only when SM was supported as stated in bolded line above and did not report the standard required algorithms.
So if PivApplet can shorten the AC, or remove it or shorten comments by 2 bytes everything will work.

@jo-bitsch
Copy link
Contributor Author

Interestingly enough, when I just fixed the ASN1 structure generated from the code of the PivApplet:
https://github.com/arekinath/PivApplet/blob/806a035d39199c4d666b733e74194c35f0ff8063/src/net/cooperi/pivapplet/PivApplet.java#L855 to use push256 instead of push my quick test with piv-tool -vvv --serial worked again.

relevant output:

0x7f3493d2c1c0 22:01:49.995 [piv-tool] card-piv.c:770:piv_find_aid: called
0x7f3493d2c1c0 22:01:49.995 [piv-tool] card-piv.c:733:piv_select_aid: called
0x7f3493d2c1c0 22:01:49.995 [piv-tool] card-piv.c:736:piv_select_aid: Got args: aid=0x7f3494957060, aidlen=9, response=0x7ffc223d0fb0, responselen=261
0x7f3493d2c1c0 22:01:49.995 [piv-tool] apdu.c:554:sc_transmit_apdu: called
0x7f3493d2c1c0 22:01:49.995 [piv-tool] card.c:415:sc_lock: called
0x7f3493d2c1c0 22:01:49.995 [piv-tool] card.c:455:sc_lock: returning with: 0 (Success)
0x7f3493d2c1c0 22:01:49.995 [piv-tool] apdu.c:521:sc_transmit: called
0x7f3493d2c1c0 22:01:49.995 [piv-tool] apdu.c:371:sc_single_transmit: called
0x7f3493d2c1c0 22:01:49.995 [piv-tool] apdu.c:378:sc_single_transmit: CLA:0, INS:A4, P1:4, P2:0, data(9) 0x7f3494957060
0x7f3493d2c1c0 22:01:49.995 [piv-tool] reader-pcsc.c:284:pcsc_transmit: reader 'Virtual PCD 00 00'
0x7f3493d2c1c0 22:01:49.995 [piv-tool] reader-pcsc.c:285:pcsc_transmit: 
Outgoing APDU (15 bytes):
00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 00 ...............
0x7f3493d2c1c0 22:01:49.995 [piv-tool] reader-pcsc.c:213:pcsc_internal_transmit: called
0x7f3493d2c1c0 22:01:50.038 [piv-tool] reader-pcsc.c:294:pcsc_transmit: 
Incoming APDU (138 bytes):
61 81 85 4F 06 00 00 10 00 01 00 79 0D 4F 0B A0 a..O.......y.O..
00 00 03 08 00 00 10 00 01 00 50 26 50 69 76 41 ..........P&PivA
70 70 6C 65 74 20 76 30 2E 38 2E 32 2D 64 65 76 pplet v0.8.2-dev
65 6C 6F 70 2F 52 45 65 50 53 41 73 78 4C 72 61 elop/REePSAsxLra
44 58 5F 50 26 68 74 74 70 73 3A 2F 2F 67 69 74 DX_P&https://git
68 75 62 2E 63 6F 6D 2F 61 72 65 6B 69 6E 61 74 hub.com/arekinat
68 2F 50 69 76 41 70 70 6C 65 74 AC 1B 80 01 03 h/PivApplet.....
80 01 08 80 01 0A 80 01 0C 80 01 06 80 01 07 80 ................
01 11 80 01 14 06 01 00 90 00                   ..........
0x7f3493d2c1c0 22:01:50.038 [piv-tool] apdu.c:390:sc_single_transmit: returning with: 0 (Success)
0x7f3493d2c1c0 22:01:50.038 [piv-tool] apdu.c:543:sc_transmit: returning with: 0 (Success)
0x7f3493d2c1c0 22:01:50.038 [piv-tool] card.c:465:sc_unlock: called
0x7f3493d2c1c0 22:01:50.038 [piv-tool] card-piv.c:752:piv_select_aid: returning with: 0 (Success)
0x7f3493d2c1c0 22:01:50.038 [piv-tool] card-piv.c:782:piv_find_aid: found PIX
0x7f3493d2c1c0 22:01:50.038 [piv-tool] card-piv.c:794:piv_find_aid: returning with: 0 (Success)

This already returns in

LOG_FUNC_RETURN(card->ctx, i);

so it doesn't hit the code point and potential bug referenced above. (this again was tested with version 0.19.0 of OpenSC from debian10)

Thanks a lot to @dengert for finding the error in the returned ASN1. I really appreciate it. I should have checked the ASN1 myself fist before reporting an issue.

@dengert
Copy link
Member

dengert commented Feb 25, 2021

If the tag lengths are correct the parsing works at

tag = sc_asn1_find_tag(card->ctx, rbuf, resplen, 0x61, &taglen);

Then code finds the response looks like a PIV card because the response has the AID and returns from the function at

LOG_FUNC_RETURN(card->ctx, i);

The code starting at

/* for testing, we can force the use of a specific AID
is really only used to force a card to be selected, even if the response is not valid. This has been there since 2004, when there were many vendors/people trying to create PIV cards. There are still many people trying to write PIV applets, and this was a way to give them a circumvention i.e. force the selection of the card even if the response was wrong.

So I consider this issue is low priority issue because response was already invalid and the code will be removed by #2053 and would return at

LOG_FUNC_RETURN(card->ctx, SC_ERROR_NO_CARD_SUPPORT);

@frankmorgner
Copy link
Member

What's the status of this topic, is there anything to do?

@dengert
Copy link
Member

dengert commented Sep 1, 2021

#2053 fixes these problems as part of a major rewrite of card-piv.c. It will read up to SC_MAX_APDU_BUFFER_SIZE, and uses sc_asn1_find_tag to parse the response.

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

No branches or pull requests

3 participants