Open mistial-dev opened 1 year ago
Looks like this is a potentially a duplicate of / related to #4. I've seen this behaviour in the wild as well as in the implementation I'm working on, so I can't help but wonder if there are compatibility issues out in the wild due to it.
Hi @mistial-dev, thanks for bringing this to our attention. Yes this was addressed by FEATURE_STRICT_APDU_CHAINING for issue #4. This was later reviewed and removed as it was clear enough that ISO 7816 intends remaining data to be skipped if not needed, so it wasn't necessary to be an option (From ISO 7816-4 5.3.4):
"contrary to command chaining, this possible termination is normal when the outside world considers that it has received enough data: the exchange should continue normally with an arbitrary C-RP."
So it looks like processIncomingObject
behaves correctly, but not processIncomingAPDU
. This is a bug and will be fixed. I will also add some specific regression tests to make sure this stays the case. ChainBuffer has been re-written for the FIPS version so I will make sure the fix goes in this too.
One additional note; 5.3.4 also states:
"however, this document does not define the behaviour of the card if the outside world tries to resume response chaining after e.g. the execution of a command on another logical channel. The behaviour may be defined by the application."
I believe the best approach here is to explicitly clear any remaining data if any other command breaks the response chain, but if you can think of any scenario where you might want to a) get the first part; b) issue some other command; c) get the remaining part
, please let me know.
Thank you for your response.
I'm not intentionally chaining the APDUs. Class is 0x00, and I'm setting Le to a length less than the object length. It's terminating normally, just short of the full object length.
Understood, in this context I was using the term chaining to refer to both large command and response processing, though I know it's typically used just for commands. In any case I will review the functionality for both to make sure it covers the standard.
One big change being made for the FIPS accreditation is putting all testing in JIRA using Zephyr Scale to capture all tests and scripts. This helps change tracking so that any bugs or features that come up can be linked to the tests that cover them. Once I've got it migrated across I'll be progressively opening up access to it so that the community can also review issues and tests as well as code.
I'm setting Le to a length less than the object length.
The current OpenSC PIV driver does this intentionally. It will do GET_DATA for 8 bytes, then determine the size of the object allocate a buffer then do GET_DATA followed by GET_RESPONSE(s) to read the full object. (This was done because of the way OpenSC code was doing GET_RESPONSE) https://github.com/OpenSC/OpenSC/pull/2053 allocates a very large buffer first to avoid the extra operation.
If you can think of any scenario where you might want to a) get the first part; b) issue some other command; c) get the remaining part
That appears to violate ISO, especially if the other command returns any data. Any GET_RESPONSE would be for the last command - at least if on the same logical channel. I do not recall if PIV defines or intended to support logical channels. I don't see any use of logical channels other then 0 in any OpenSC card driver.
The trace in original post does not appear to have anything to do with the CHUID, Is this the wrong trace? The instruction in question:
00 87 11 9E 26 7C24 8200 8120 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
Appears to be GENERAL AUTHENTICATE (sign) for key 9E with EC-256. over ISO14443A - contactless, which should work, but returns 6985 - "Conditions of use not satisfied" but 69 85 is not defined in 800-73-4
That's the next APDU, the one that shows the error. Doing a bit of an explanation in case someone comes across this later.
The trace in original post does not appear to have anything to do with the CHUID, Is this the wrong trace? The instruction in question:
00 87 11 9E 26 7C24 8200 8120 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
Appears to be GENERAL AUTHENTICATE (sign) for key 9E with EC-256. over ISO14443A - contactless, which should work, but returns 6985 - "Conditions of use not satisfied" but 69 85 is not defined in 800-73-4
That's where the error occurs. We're basically trying to do a PIV auth as fast as it is possible to do.
Step 1: load PIV applet (if not implicit select). 00A4040009A0000003080000100000
.
Step 2: identify card: 00CB3FFF055C035FC10238
Appendix A states:
The SP 800-73-4 specification does not provide mechanisms to read partial contents of a PIV data object. Individual access to the TLV elements within a container is not supported. For each container, compliant cards shall return all TLV elements of the container in the order listed in this appendix.
The CHUID is in 5FC102. That APDU gets the CHUID. We know the data is in order, and we know the maximum size of a field.
The optional but deprecated buffer length is 2 bytes. 25 bytes for the fasc-n, 4 bytes for the optional but deprecated organizational identifier, 9 for the DUNS, 16 for the GUID. Add the tags, and 5 more bytes (61 total) gets you the GUID and FASC-N for any PIV-compliant card (without the signatures or rest of the data). The sample APDU didn't add in the overhead of the tags themselves, a mistake that has since been corrected.
The reason we don't care about the CHUID's signature is that we're using attested, generated-on-card keys with pre-enrolled certificates. If the signature validates, the card is correct. So, the next APDU sends a challenge over the contactless, and lets the PKI path validation do the walking. 3 APDUs, and we've validated a PIV card. 2 with implicit select.
Unfortunately, this bug means that when we do this with current OpenFIPS201 cards, it just fails, because it thinks we're mid transaction for chaining. We're quite done with the data at this point, and read only what was necessary to identify the card, even for PIV-I cards that all use the same FASC-N and depend on the GUID.
if you can think of any scenario where you might want to
a) get the first part; b) issue some other command; c) get the remaining part
, please let me know.
I can’t, and that sounds like something that could cause problems, to be honest. By and large, within a logical channel, smart cards do one thing at a time.
When reading the CHUID, it's often not necessary to grab the entire data structure if pre-enrollment has occurred.
SP 800-73-4 Appendix A states "For each container, compliant cards shall return all TLV elements of the container in the order listed in this appendix."
Looking at the Cardholder Unique Identifier, there is one optional element before the FASC-N (2 bytes), a 25-byte FASC-N, 4 bytes of Organizational Identifier, 9 bytes of DUNS, and 16 bytes of GUID at the beginning of the element. Thus, for a compliant card you can get the first 0x38 bytes of the CHUID and have both the FASC-N and GUID. With a pre-enrolled card, and signature verification at enrollment, this is fine. I successfully do this with other cards without issue.
When I attempt to do this with OpenFIPS201 cards, the following operation results in a "Conditions of use not satisfied."
This appears to be a result of ChainBuffer class.
https://github.com/makinako/OpenFIPS201/blob/25cb2e63268777b0916069313dd1b52d157997f6/src/com/makina/security/openfips201/ChainBuffer.java#L218-L224
This does not seem to be correct behaviour as far as I can tell. Is this how the applet is intended to behave?