NFC: Files from DESFire cards appear truncated; more reads may be necessary
Summary
The DESFire card "poller" does not appear to be able to adequately dump more than 472 bytes from any DESFire card file, even if the file's metadata indicates it is larger.
Background
The Mifare DESFire is a particular kind of ISO 14443-compliant "smart card" which, amongst other things, provides several file-based abstractions for saving and retrieving data on the card. The flipperzero NFC framework has wonderful support for querying and interacting with such cards, including an automatic "poller" which attempts to dump as much information as possible from the card when read in the NFC application.
The issue at hand may be related to how the poller attempts to read file data from the card.
Theories
Tracking down the source to the entire process, I direct your attention to line 403 in https://github.com/flipperdevices/flipperzero-firmware/blob/7eeb60e17ecd31b964cdc169f60ae314c6e9831d/lib/nfc/protocols/mf_desfire/mf_desfire_poller_i.c#L403
wherein the PDU to read the file data is constructed and sent to the card. The PDU requests to read the entire file in one go, which may be an issue due to limitations in PDU response size.
Next, observe where the response to the file read request is processed in https://github.com/flipperdevices/flipperzero-firmware/blob/7eeb60e17ecd31b964cdc169f60ae314c6e9831d/lib/nfc/protocols/mf_desfire/mf_desfire_i.c#L228
Note that the response handler doesn't check (nor have enough information to check) whether the response data actually includes all of the bytes requested.
It may be that underlying ISO 14443 restrictions prevent read responses from exceeding a certain size, and as such, a state machine might have to be set up to read such files in smaller chunks, using multiple read requests, until satisfied.
Reproduction
- Acquire a Mifare DESFire card with any type 00 ("standard") file containing 473 or more bytes of data. Example: San Francisco Bay Area "Clipper" transportation card.
- Using the "Read" function of the FlipperZero's NFC application, read the card.
- Save the card data to a file (choose "Save", pick a filename).
- Plug in the Flipper Zero into a Desktop machine using a USB cable.
- Using the Flipper Desktop application, download the file from the
/nfc/directory on the SD Card. - Using a text editor, inspect the requisite
.nfcfile. - Identify files, metadata, and their contents in the file. Example:
Application 9111f2 File 14 Size: 512
Application 9111f2 File 14: 10 00 00 04 00 00 ...
- Notice that the file's metadata notes the file size as, say, 512 bytes.
- Count the retrieved bytes in the next line and notice that they only amount to 472 bytes.
Target
No response
Logs
No response
Anything else?
I discovered this issue while attempting to write a "ride history" display in my Clipper card parser at https://github.com/flipperdevices/flipperzero-firmware/pull/3344
@gornekich I was thinking you might know and have some ideas
See https://discord.com/channels/740930220399525928/954422716138676254/1193342799215603814 for more information.
I think this was intentional to either prevent OOM or simplify memory management.
@gornekich I noticed something important that might inform that this bug actually is due to a buffer sizing problem elsewhere in the code. When reading my "large" cards, even with this new loop code, I see this in the logs:
60018327 [I][NfcScanner] Detected 1 protocols
60018607 [W][MfDesfirePoller] RX buffer overflow: ignoring 41 bytes
60018674 [W][MfDesfirePoller] RX buffer overflow: ignoring 60 bytes
60018682 [W][MfDesfirePoller] RX buffer overflow: ignoring 60 bytes
60018690 [W][MfDesfirePoller] RX buffer overflow: ignoring 60 bytes
60018700 [W][MfDesfirePoller] RX buffer overflow: ignoring 60 bytes
60018709 [W][MfDesfirePoller] RX buffer overflow: ignoring 60 bytes
60018718 [W][MfDesfirePoller] RX buffer overflow: ignoring 60 bytes
60018727 [W][MfDesfirePoller] RX buffer overflow: ignoring 60 bytes
60018736 [W][MfDesfirePoller] RX buffer overflow: ignoring 60 bytes
60018745 [W][MfDesfirePoller] RX buffer overflow: ignoring 60 bytes
60018753 [W][MfDesfirePoller] RX buffer overflow: ignoring 60 bytes
60018761 [W][MfDesfirePoller] RX buffer overflow: ignoring 60 bytes
60018769 [W][MfDesfirePoller] RX buffer overflow: ignoring 60 bytes
60018777 [W][MfDesfirePoller] RX buffer overflow: ignoring 60 bytes
60018785 [W][MfDesfirePoller] RX buffer overflow: ignoring 42 bytes
60018846 [W][MfDesfirePoller] RX buffer overflow: ignoring 60 bytes
60018854 [W][MfDesfirePoller] RX buffer overflow: ignoring 60 bytes
60018862 [W][MfDesfirePoller] RX buffer overflow: ignoring 60 bytes
60018872 [W][MfDesfirePoller] RX buffer overflow: ignoring 60 bytes
60018882 [W][MfDesfirePoller] RX buffer overflow: ignoring 60 bytes
60018889 [W][MfDesfirePoller] RX buffer overflow: ignoring 42 bytes
It could be that the card is responding with the full file PDU, but the poller code simply isn't being set up to handle such large responses.
Fixed in dev. Please, reopen if the issue persists