mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2026-07-02 17:41:52 +00:00
68952d814a
* nfc: size MIFARE Classic from SAK per AN10833 The Classic poller sized cards purely behaviorally (auth-probe block 254 -> 4K, else block 62 -> 1K, else Mini) and ignored the SAK it already captures at activation. A magic CUID that answers every block was thus mis-sized as 4K despite its 1K SAK. Derive the size from the SAK bit map first (AN10833: 0x09 -> Mini, bit4 -> 4K, bit3 -> 1K) and fall back to the behavioral block probe only when the SAK is not a recognized Classic value. Genuine cards are unchanged (their SAK already matches their size); clones with a standard SAK are now sized to what they claim instead of what every-block-answers implies. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * nfc: report unmodelled GetVersion Ultralight as Unknown, not Origin mf_ultralight_get_type_by_version defaulted an unrecognized GetVersion response to MfUltralightTypeOrigin. But answering GetVersion at all proves the IC is not an original Ultralight (which has no GetVersion), so a modern card such as Ultralight AES was silently mislabelled a 16-page original. Add MfUltralightTypeUnknown (conservative, Origin-identical features; not offered for Write since the app's allow-list omits it) and default to it. Reserves Origin for the no-GetVersion fallback path. The NTAG212/UL21 storage-size collision and full support for new product types are left for a follow-up that adds those types with correct page counts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * nfc: derive MIFARE Plus security level from SAK bit map (AN10833) The Plus version path inferred the security level from a binary SAK==0x20 test (SL3, else SL1), which collapsed SL2 entirely and mislabelled genuine SL2 cards as SL1. Use the SAK bit map instead: 0x20 -> SL3, 0x10/0x11 -> SL2, 0x08/0x18 -> SL1, anything else -> Unknown rather than a guessed SL1. GetVersion stays authoritative for type and size; the SAK only refines the level. The no-GetVersion ISO4 fallback (which still relies on ATS/ATQA, against AN10833) is intentionally untouched here and left for a follow-up. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * nfc: identify Ultralight/NTAG by GetVersion product family (AN10833) get_type_by_version keyed on storage_size alone, so ICs that share a storage size across families were mistyped: NTAG212 read as UL21, NTAG210 fell through to a false original, and Ultralight AES (storage 0x0F) was mislabelled NTAG213. Gate on the GetVersion product-family nibble (0x03 Ultralight, 0x04 NTAG) first, then size within the family by storage_size. NTAG I2C stays anchored on subtype/major since its nibble is unreliable (real silicon 0x07 vs the in-tree generator 0x04). Add NTAG210 (= UL11 layout), NTAG212 (= UL21 layout), and Ultralight AES (detect/label only -- AES auth is not implemented, with a conservative read-only page count pending datasheet validation). NTAG210/212 are also added to the NDEF parser allow-list and NTAG212 to the listener dynamic- lock granularity. The new types are read-only (omitted from the write allow-list, so the write-end-page assert is never reached). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * nfc: drop forbidden ATQA/ATS over-claims in MIFARE Plus iso4 type-ID mf_plus_get_type_from_iso4 asserted "Plus X" from a bare SAK 0x10/0x11 and sized SL3 cards from the ATQA nibble -- both signals AN10833 says never to use for type identification. Report SAK 0x10/0x11 as a generic Plus 2K/4K SL2 (drop the unjustified X), and leave SL3 size Unknown instead of reading ATQA. The ATS-historical-byte match is kept as the SL3 detection gate on purpose: SAK 0x20 is shared with DESFire and MfPlus is probed before MfDesfire, so claiming Plus on a bare SAK would hijack DESFire detection. Dropping the ATQA gate also means an SL3 Plus with a non-standard ATQA is now detected (size Unknown) instead of missed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * nfc: never report an Ultralight AES read as complete The UltralightAES feature set omits PasswordAuth, so mf_ultralight_is_all_data_read returned true once the (conservative, unverified) page count was read -- silently presenting a truncated dump as complete, even though the IC's memory is protected by AES authentication that the poller does not perform. Treat AES as never-complete so the read honestly surfaces as partial. Found in PR review. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * nfc: tidy MIFARE type-id comments and hoist a local (no behavior change) Trim the verbose AN10833/SL3/Unknown/AES comments to a single "why" line each per the project's concise comment style, and hoist the repeated SAK deref in mf_plus_get_type_from_version to a local. Pure cleanup from the simplify pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * nfc: type Ultralight/NTAG by storage_size, family nibble only for collisions The family-nibble gate from the previous commit was too strict: a card whose GetVersion prod_type low-nibble is neither 0x03 nor 0x04 (common on magic/clone Ultralight cards) fell through to MfUltralightTypeUnknown, whose config_page is 0 -- so PWD/PACK stopped rendering and the poller skipped PWD auth. The legacy dev logic keyed purely on storage_size and typed such cards as UL11/UL21. Restore storage_size-primary typing and use the product-family nibble only to disambiguate the storage values that collide across families (NTAG210/UL11 0x0B, NTAG212/UL21 0x0E, NTAG213/Ultralight AES 0x0F). Keeps the three collision fixes without regressing odd-nibble clones; Unknown now only for an unrecognized storage_size. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * nfc: probe MIFARE Plus SL0 vs SL3 actively (AN10833/PM3 hf mfp info) SAK 0x20 + ATS is shared by a Plus in SL0, a Plus in SL3, and a DESFire, so it cannot be classified passively. Detection previously hard-coded SAK 0x20 -> SL3, so a card in SL0 (personalization state) was reported as SL3, and any SL3 Plus whose ATS was not in the S/X/SE table fell to Unknown. Mirror PM3: after activation, send WritePerso (0xA8) to the intentionally invalid block 0x9090 and classify the reply -- 0x09 means SL0 (block rejected, nothing written), 67 00 / 1C 83 0C / 6D 00 mean DESFire or unsupported (not Plus), anything else is SL3. The probe runs only for SAK 0x20 and feeds the resolved level into both the GetVersion and ISO-4 type paths. Because the probe positively rules out DESFire, the ISO-4 SAK-0x20 path can now report a generic Mifare Plus for an untabled/short ATS instead of Unknown. When the probe yields no usable result the old strict ATS-table gate is kept, so DESFire is never hijacked. 2K vs 4K still needs the AN10833-forbidden ATQA nibble, so SL3 size stays Unknown. Builds clean; not yet validated on real Plus hardware (SL0 + SL3). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * nfc: harden MIFARE Plus SL probe (PR-review fixes) Address review findings on the SL0/SL3 WritePerso probe: - Classify the reply by an allowlist, not a denylist. Plus answers 0x09 (SL0) or 0x06/0x0B (SL3); every other reply becomes NotPlus. This fixes two issues at once: (1) a single-byte 0x09 SL0 reply was misread as SL3 due to a spurious "len > 1" guard, defeating SL0 detection; (2) the old "anything else maps to SL3" default could promote an unanticipated DESFire reply to a confident Plus and hijack DESFire in the ISO-4 path. No real DESFire native status code is 0x06/0x09/0x0B, so unknown replies now fall through DESFire-safe. Also removes the fragile multi-byte denylist. - Version path: only log "(probe)" when the probe actually resolved the level; the SL3 fallback now logs "(default)" instead of claiming the probe ran. - Log the raw WritePerso status byte (FURI_LOG_D) to aid the pending on-hardware validation. - Initialize the probe result local defensively (fail-safe NotPlus). - Rename the converter to mf_plus_poller_resolve_sak20_security_level to distinguish it from the probe, and trim duplicated comments. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * nfc: simplify MIFARE Plus SL probe (post-/simplify) Quality cleanups from the /simplify pass, no detection-behavior change: - Extract mf_plus_type_from_ats() and use it at both SAK-0x20 sites, removing the duplicated ATS-historical-bytes -> S/X/SE memcmp ladder that the probe change had introduced a second copy of. - Skip the active probe on the detect-phase version path. There the SL is written to a throwaway detect poller and discarded, and DESFire is already excluded by the GetVersion family nibble, so the probe could not change the detect result -- only waste one WritePerso RF round-trip per EV-Plus/DESFire scan cycle. The iso4 fallback still probes, since that is where the probe provides real detection coverage. - Route the probe through nxp_native_command_iso14443_4a_poller (the same plain-mode path read_version uses) and read its status_code out-param, instead of hand-rolling iso14443_4a_poller_send_block + manual byte-0 extraction. Behaviour-equivalent (an empty reply yields LENGTH_ERROR -> NotPlus, as before). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * nfc: derive MIFARE Plus SL0/SL3 size from ATQA SL0/SL3 cards expose no product-independent storage byte, so size showed Unknown for any Plus reaching the ISO-4 / probe path (GetVersion absent or hw_storage unrecognized). Once the active probe has confirmed the card is a Plus, fall back to the ATQA size coding -- bit 2 (0x0004) = 2K, bit 1 (0x0002) = 4K -- the same signal PM3 hf mfp info uses. This is size refinement of an already-confirmed Plus, not ATQA-based type identification, so AN10833's caution against ATQA for product ID does not apply. SE stays 1K regardless; a recognized GetVersion hw_storage still wins, with ATQA only as the fallback when it is Unknown. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * nfc: gate Ultralight detection on SAK/ATQA, not a bare read mf_ultralight_poller_detect only sent a READ page 0 (0x30) and treated any reply as Ultralight. A magic/Chinese MIFARE Classic clone (gen1a/gen2) answers an unauthenticated READ 0x30 through its backdoor exactly like an Ultralight, so such a card was offered to the user as BOTH MIFARE Classic (correct -- e.g. a Mini) and NTAG/Ultralight (false positive). A genuine Classic NAKs the unauthenticated read, which is why only clones misfired. Gate the probe read behind mf_ultralight_detect_protocol() (SAK 0x00 + ATQA 0x0044) so only cards advertising the Ultralight/NTAG SAK/ATQA are read as Ultralight. This mirrors PM3, which routes SAK 0x00 to the Ultralight path and aborts UL detection when atqa[1] != 0x00 || sak != 0x00 before ever issuing READ 0x30. The Chinese Mini clone (SAK 0x09, ATQA 0x0004) now fails the gate and is detected as Classic/Mini only; genuine and magic Ultralight/NTAG (SAK 0x00, ATQA 0x0044) are unaffected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * nfc: loosen Ultralight detect gate to PM3's SAK/ATQA (PR-review fix) mf_ultralight_detect_protocol required ATQA exactly 0x0044 (atqa[0]==0x44), but that low byte encodes UID size (0x44 = 7-byte, 0x04 = 4-byte), so the strict term silently excluded a 4-byte-UID Ultralight/NTAG -- e.g. a magic UL configured with a 4-byte UID (ATQA 0x0004) -- which the previous bare read would have detected. The strict term also contributes nothing to the magic-Classic-clone fix it shipped with: those carry a non-zero Classic SAK (Mini 0x09, 1K 0x08, 4K 0x18) and are already rejected by the SAK term. Gate on atqa[1]==0x00 && sak==0x00 only, matching PM3 (which rejects solely when atqa[1] != 0x00 || sak != 0x00). Magic Classic clones still fail on SAK; 4-byte-UID UL/NTAG are no longer wrongly dropped. Also trims the detect comment. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * nfc: collapse mf_ultralight_detect_protocol to a direct return (/simplify) Drop the single-use mfu_detected temporary; the comment already documents the expression. No behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * nfc: detect MIFARE Plus EV1/EV2 via GetVersion (trust valid reply) A MIFARE Plus EV1/EV2 answers GetVersion (0x60) with the full, correct 28-byte version block but terminates the native frame exchange with a status byte other than 0x00 (unlike DESFire), so mf_plus_poller_send_chunks reported MfPlusErrorProtocol and read_version discarded a perfectly valid version. The card then fell back to ATS-based typing, which mis-identified every EV1/EV2 as the older "Plus X" -- EV1/EV2 share the Plus-X ATS historical bytes, so GetVersion is the only way to tell them apart. The EV1/EV2 typing itself (hw_major 0x11 -> EV1, 0x22 -> EV2; storage 0x16 -> 2K, 0x18 -> 4K) was already correct but never reached. Trust the assembled version whenever it parses as a genuine NXP Plus (vendor 0x04, family nibble 0x02), regardless of the terminal status; otherwise propagate the real error so older Plus S/X/SE (which do not answer GetVersion) still fall back to ATS. Reset the result buffer before the exchange so a first-frame transport failure can't leave stale bytes that the payload-trust check would accept (nxp_native_command only clears it after its first frame succeeds). HW-validated: a Plus EV1 4K in SL0 now reads as "MIFARE Plus EV1 4K SL0" (was "Plus X 4K SL0"). DESFire (family nibble 0x01) and older Plus S/X/SE are unaffected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * nfc: handle MIFARE Ultralight AES as identity-only (no read hang) A MIFARE Ultralight AES (MF0AES20) needs AES-128 authentication for every page and returns a 48-byte signature (our reader expects 32), neither of which the firmware implements. The read poller therefore failed at the signature/page reads -> ReadFailed, and the app's Ultralight read callback retries on failure, so the poller restarted from Idle endlessly and the read froze on "Don't move" forever (confirmed by an on-device poller state trace). Treat UL-AES as identity-only, like MIFARE Plus (which reads its version/ATS and stops without dumping memory): - Poller: GetFeatureSet routes UltralightAES straight to ReadSuccess after GetVersion, skipping the AES-gated signature/page reads that can never succeed. The card is identified and the read terminates. - Render: show UL-AES like MIFARE Plus -- Tech + UID (+ ATQA/SAK in Full) -- instead of "Pages Read: 0/40" / "Password-protected pages!" / counters. The Short (read-result) form of iso14443_3a_info omits the Tech line, so it is added explicitly to match the Plus result screen. - Per-card features: add an optional get_features() hook to NfcProtocolSupportBase (overrides the static .features bitmask when set) and have mf_ultralight report EmulateUid (no MoreInfo/Write/EmulateFull) for UL-AES. This drives the menu label ("Emulate UID"), the emulate screen ("Emulating UID"), and the now-hidden empty page-dump "More" view from one place instead of scattered scene hacks. - Emulate: UL-AES emulates UID only (Iso14443_3a listener) -- a full emulation would be an empty card (no readable memory, no AES-auth listener). - Menu: don't offer "Unlock" for UL-AES; only the unimplemented AES auth could unlock it, so the password-based flow can't help. No full UL-AES read/emulate (that needs UL-AES AES-128 auth, a separate feature). Other UL/NTAG types are unaffected: get_features returns the full set, and every other protocol keeps its static features. HW-validated: no more hang; result screen and menu match MIFARE Plus. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * nfc: name MIFARE Mini per NXP product name (drop "Classic") Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(changelog): AN10833 type-detection alignment; drop fixed Mini-clone regression Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: MX <10697207+xMasterX@users.noreply.github.com>
Structure
debug
Applications for factory testing the Flipper.
accessor- Wiegand serverbattery_test_app- Battery debug appblink_test- LED blinkerbt_debug_app- BT test app. Requires full BT stack installeddisplay_test- Various display tests & tweaksfile_browser_test- Test UI for file pickerkeypad_test- Keypad testlfrfid_debug- LF RFID debug tooltext_box_test- UI testsuart_echo- UART mode testunit_tests- Unit testsusb_mouse- USB HID testusb_test- Other USB testsvibro_test- Vibro test
main
Applications for main Flipper menu.
archive- Archive and file managerbad_usb- Bad USB applicationgpio- GPIO application: includes USART bridge and GPIO controlibutton- iButton application, onewire keys and moreinfrared- Infrared application, controls your IR deviceslfrfid- LF RFID applicationnfc- NFC application, HF rfid, EMV and etcsubghz- SubGhz application, 433 fobs and etcu2f- U2F Application
services
Background services providing system APIs to applications.
applications.h- Firmware application list headerbt- BLE service and applicationcli- Console service and APIcrypto- Crypto cli toolsdesktop- Desktop servicedialogs- Dialogs service: GUI Dialogs for your appdolphin- Dolphin service and supplementary appsgui- GUI service and APIinput- Input serviceloader- Application loader servicenotification- Notification servicepower- Power servicerpc- RPC service and APIstorage- Storage service, internal + sdcard
settings
Small applications providing configuration for basic firmware and its services.
about- Small About application that shows flipper infobt_settings_app- Bluetooth optionsdesktop_settings- Desktop configurationdolphin_passport- Dolphin passport appnotification_settings- LCD brightness, sound volume, etc configurationpower_settings_app- Basic power optionsstorage_settings- Storage settings appsystem- System settingsinput_settings_app- Basic input options
system
Utility apps not visible in other menus, plus few external apps pre-packaged with the firmware.
hid_app- BLE & USB HID remotejs_app- JS engine runnersnake_game- Snake gamestorage_move_to_sd- Data migration tool for internal storageupdater- Update service & application