-
Notifications
You must be signed in to change notification settings - Fork 342
Description
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:
- On Desfire cards, the OS uses the Desfire
GET VERSIONcommand: https://android.googlesource.com/platform/packages/modules/Nfc/+/refs/heads/main/NfcNci/nci/jni/NativeNfcTag.cpp#1544 - If the NDEF application is missing, the OS exposes
android.nfc.tech.NdefFormatable. - If the NDEF application is present, it exposes
android.nfc.tech.Ndef.
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 VERSIONin 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 00indicates 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