Skip to content

Desfire authentication issue on iPhone using react-native-nfc-manager due to Desfire EV2 bug #815

@prigaux

Description

@prigaux

Details of the Desfire EV2 bug

On a Desfire EV2 card, when it has no NDEF "application", reading the NDEF file returns a random “File Control Information” (6F ...), whereas on EV1 & EV3 cards it correctly returns “File not found” (6A 82). See at the end for details.

→ This bug causes the Desfire SELECT APPLICATION command (90 5A) - in same connection - to fail with status 91 1B (instead of 91 00), resulting in Desfire authentication failure.

After creating an NDEF application on the card the bug no longer occurs. (tested using the mifare-desfire-create-ndef tool from libfreefare).

Why the issue does not occur on Android

Android checks whether the NDEF application is unformatted:

In react-native-nfc-manager, NDEF reading only occurs if android.nfc.tech.Ndef is detected:

if (Arrays.asList(tag.getTechList()).contains(Ndef.class.getName())) {
    Ndef ndef = Ndef.get(tag);
}

→ on Android, react-native-nfc-manager never reads a missing NDEF application

→ this avoids triggering the Desfire EV2 bug

Why the issue appears on iPhone

On iPhone, the code react-native-nfc-manager/ios/NfcManager.m always attempts to read the NDEF application for Mifare cards (see getNDEFTagHandle).

→ This triggers the Desfire EV2 bug.

Workaround

If NDEF support is not needed, remove the call to:

if (ndefTag) {
    [ndefTag readNDEFWithCompletionHandler:^(NFCNDEFMessage *ndefMessage, NSError *error) {
        if (!error) {
            [rnTag setObject:[NfcManager convertNdefMessage:ndefMessage] forKey:@"ndefMessage"];
        }
        callback(@[[NSNull null], rnTag]);
    }];
    return;
}

in NfcManager.m.

This workaround has been tested and validated.

Suggested fix

Detect the Absence of NDEF on iOS (similar to Android)

Android’s detection of NdefFormatable is complex.
A protocol sniffer shows that iOS does not send the Desfire GET VERSION command.

A possible fix is

  • to explicitly use GET VERSION in react-native-nfc-manager on iOS, to detect wether NDEF application is available
  • use this information to avoid reading NDEF

Modify the react-native-nfc-manager API to allow calling getTag() without triggering NDEF reading

Possible approaches:

  • Add an optional parameter to getTag(), or
  • Introduce a new method: getTagDoNotNeedNdef().

This API modification could be useful for applications that never need to read NDEF, avoiding an uneeded APDU cmd.

Details

Why the issue appears on Android with nfc-relay-picc on PN532

Using nfc-relay-picc with two NFC readers changes the card behavior:

The PN532 does not emulate all metadata of a Desfire card.
Since the emulated tag differs, Android does not apply its special Desfire handling and therefore does not report the NdefFormatable Tech tag.

→ react-native-nfc-manager attempts to read the NDEF application.
→ This triggers the Desfire EV2 bug.

Details of the Desfire EV2 bug when reading NDEF application

  • NDEF Read Command (ISO Select)
C-APDU: 00 A4 04 00 07 D2 76 00 00 85 01 01 00
  • response example:
R-APDU: 6f 22 85 20 d2 92 0e 89 61 e2 36 4a 82 80 5d 56 e2 2d 16 ee 9c 22 32 66 a6 b4 f1 4a f2 cc 09 75 54 68 13 67 90 00

This is an ISO Select command for the NDEF application (AID = 07 D2 76 00 00 85 01 01).

  • The ending 90 00 indicates success, but the NDEF application does not exist.
  • The preceding bytes are a BER-TLV encoded File Control Information (FCI), but contain random, always changing, meaningless data.

Acknowledgements

Joint work by:

  • Vincent Rivière
  • Pascal Rigaux
  • Peniel Gloriel Mmen
  • Florian Nari
  • Vincent Bonamy
  • Aymar Anli

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions