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

APDU parser has multiple errors #565

Open
micolous opened this issue Oct 23, 2022 · 2 comments
Open

APDU parser has multiple errors #565

micolous opened this issue Oct 23, 2022 · 2 comments
Labels
bug Something isn't working

Comments

@micolous
Copy link

micolous commented Oct 23, 2022

I found a couple of bugs while reviewing the OpenSK APDU parser, because while writing a FIDO client library, I noticed many FIDO implementations have buggy ISO 7816 implementations. I haven't run this on "real hardware" to try it out properly.

  1. APDU parser does not handle extended form with Nc = 0 and Ne > 0 ("Case 2E"). It would error out with WRONG_LENGTH.

    Example request, where Nc = 0 and Ne = 0x1234:

    CLA INS P1 P2 0x00 0x12 0x34
    

    U2F GET_VERSION is impacted by this, other U2F commands and CTAP2 (over an ISO 7816 transport) always have command payloads.

    The parser appears to only handle "Case 2S" (short form Nc = 0 and Ne > 0), but supporting extended form is required for all transports, and supporting short form is only required over NFC.

  2. APDU parser accepts malformed 3 byte Lc + 3 byte Le.

    Per ISO 7816-4:2005 Section 5.1 (Command-response pairs), when Nc > 0 and Ne > 0 and using extended form ("Case 4E"), the correct representation is:

    CLA INS P1 P2 0x00 {Nc as uint16_be} {command bytes} {Ne as uint16_be}
    

    The implementation here appears to also incorrectly accept malformed requests of the form:

    CLA INS P1 P2 0x00 {Nc as uint16_be} {command bytes} 0x00 {Ne as uint16_be}
    

    The only reason Le should be prefixed with 0x00 is if the Lc field is absent and Le is in extended form ("Case 2E").

    Accepting malformed requests can cause implementers "testing against OpenSK" to make mistakes which are only exposed when testing with another FIDO implementation which follows ISO 7816 correctly. I've already seen subtle differences in existing FIDO certified devices with malformed inputs.

Note: "Case 2E", "Case 2S" and "Case 4E" references to ISO 7816-3:2006 section 12.1.3 (Decoding conventions for command APDUs); S = short form, E = extended form.

Case Command Data Field Response Length Field Total length
Case 1 None None 4 bytes
Case 2S None Present (1 byte) 5 bytes
Case 2E None Present (3 bytes) 7 bytes
Case 3S Present (1 byte) None 5 + (command data length) bytes
Case 3E Present (3 bytes) None 7 + (command data length) bytes
Case 4S Present (1 byte) Present (1 byte) 6 + (command data length) bytes
Case 4E Present (3 bytes) Present (2 bytes) 9 + (command data length) bytes
@kaczmarczyck kaczmarczyck added the bug Something isn't working label Oct 24, 2022
@kaczmarczyck
Copy link
Collaborator

Hi, thanks for the writeup, this is useful!
Our NFC implementation is still work in progress, and these bugs will be great test cases when we continue working on it.

@micolous
Copy link
Author

micolous commented Feb 2, 2023

By the way, after getting my hands on more FIDO2 keys, as far as I can tell pretty much only Yubikey implements the NFC side of things even close to correctly (there are bugs, just minor ones). Feitian, Hideez and Token2 keys don't implement extended Lc/Le at all (as required by the CTAP spec), even though they are allegedly "certified"... so OpenSK is already doing better. 😄

Relatedly, I wasn't able to find where OpenSK's ATR was, but that needs to flag its extended Lc/Le in the "card capabilities" field (per ISO 7816-4 §8.1.1.2.7); again that's another case where only Yubikey seems to do this correctly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants