flipperdevices / flipperzero-firmware

Flipper Zero firmware source code
https://flipperzero.one
GNU General Public License v3.0
12.95k stars 2.74k forks source link

NFC: Files from DESFire cards appear truncated; more reads may be necessary #3347

Closed ke6jjj closed 5 months ago

ke6jjj commented 10 months ago

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

  1. 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.
  2. Using the "Read" function of the FlipperZero's NFC application, read the card.
  3. Save the card data to a file (choose "Save", pick a filename).
  4. Plug in the Flipper Zero into a Desktop machine using a USB cable.
  5. Using the Flipper Desktop application, download the file from the /nfc/ directory on the SD Card.
  6. Using a text editor, inspect the requisite .nfc file.
  7. 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 ...
  8. Notice that the file's metadata notes the file size as, say, 512 bytes.
  9. 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

bettse commented 10 months ago

@gornekich I was thinking you might know and have some ideas

ke6jjj commented 10 months ago

See https://discord.com/channels/740930220399525928/954422716138676254/1193342799215603814 for more information.

dogtopus commented 10 months ago

I think this was intentional to either prevent OOM or simplify memory management.

ke6jjj commented 10 months ago

@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.

gornekich commented 5 months ago

Fixed in dev. Please, reopen if the issue persists