mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2026-07-17 12:51:59 +00:00
dev
8276
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
3dcdb353f2 |
[NFC] Fix MIFARE Plus 2K SL1 transit parsers (#1037) (#1038)
* [NFC] Fix MIFARE Plus 2K SL1 transit parsers after MfClassicType2k After #1016 promoted genuine MIFARE Plus S/X 2K cards in SL1 (SAK 0x08 + Plus ATS) from MfClassicType1k to the new MfClassicType2k, the supported- card parsers for those cards stopped working: - Type gates (get_card_config / extract_purse_data) knew only 1K/4K, so parse() rejected 2K -- plantain, troika. - mf_classic_is_card_read() now needs all 32 sectors / 64 keys for a 2K card, so a targeted read() that keys only its own sectors returns MfClassicErrorPartialRead -> is_read = false -> the app diverts to the dict-attack scene and never reaches parse() -- sevppk, szppk_so, two_cities (and the above). Handle MfClassicType2k explicitly as the Classic 1K these cards present (same lower-sector keys / data sector), and accept a partial read in the plugins' read() so parse() runs and validates the key. social_moscow / kazan (plain Classic) and sk_tk (4K) are not promoted to 2K and are left unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(changelog): note Plus 2K SL1 transit parser fix (PR #1038) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
3b160a5e0e | bump apps tag | ||
|
|
f629d2cb98 | bump apps tag | ||
|
|
d71868364f |
disable bot completely due to endless email spam [ci skip]
todo: disable comments for old PRs and issues, keep them only for new ones |
||
|
|
9bcabc0134 | bump apps tag and sync api | ||
|
|
17ad4461a4 | Merge remote-tracking branch 'OFW/dev' into dev [ci skip] | ||
|
|
7432d21a7e |
CCID: move USB layer from firmware HAL into ccid_test app (#4407)
* CCID: move USB layer from firmware HAL into ccid_test app
The CCID USB device interface no longer needs to live in the firmware.
A FAP can define its own FuriHalUsbInterface and drive the libusb_stm32
device stack directly: the usbd_* helpers are inline static in
usbd_core.h and dispatch through the dev->driver vtable, and those
headers already ship in the app SDK, so no new symbols must be exported.
- Move furi_hal_usb_ccid.{c,h} into applications/debug/ccid_test as
ccid_usb.{c,h} (interface renamed usb_ccid -> ccid_usb_interface,
furi_hal_usb_ccid_* -> ccid_usb_*). String-descriptor indices are
hardcoded since furi_hal_usb_i.h is not part of the SDK.
- Delete the firmware CCID module and its extern/include hooks.
- Drop the 4 CCID entries from f7 + f18 api_symbols.csv (keeping the
libusb usb_ccid.h header), bump API 87.3 -> 88.0 (breaking).
Frees ~1.7 KB of base-firmware flash; CCID code now only costs space
in the FAP while the app runs. Verified on hardware: enumerates as a
CCID reader (076b:3a21, class 0x0b) and passes the app's APDU tests.
* apply fbt format
---------
Co-authored-by: Štefan Croitoru <66339601+turbospok@users.noreply.github.com>
|
||
|
|
48b6484ce2 | bump apps tag | ||
|
|
568c456f52 |
[CI] Add lock-threads workflow (lock closed issues/PRs after 14d idle) [ci skip]
Daily dessant/lock-threads@v6 sweep + manual dispatch. Locks only closed threads that have been inactive for 14 days; never closes anything and open threads are untouched. Leaves a comment pointing users to open a fresh issue. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
d1019d3bb3 |
Fix User Documentation link in index.dox (#4410)
Updated the link to the User Documentation by removing the trailing slash, which was pointing to an incorrectly rendered page |
||
|
|
71280128a3 |
Apply clang-format to recently merged NFC/RPC/CCID files [ci skip]
Run `fbt format` over the tree; normalizes whitespace, comment spacing and argument wrapping in the bambu parser, Network/GPS RPC services and ccid_test USB layer. No functional change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
473476300a | bump apps tag | ||
|
|
fd2ec5878d |
[SubGHz] Fix crash when exiting CLI subghz chat with external CC1101 (#1036)
* [SubGHz] Fix crash when exiting CLI `subghz chat` with external CC1101 Pressing Ctrl+C to exit `subghz chat` while using an external CC1101 crashed the Flipper (null-pointer dereference + reboot). The exit path called subghz_devices_deinit() before stopping the chat worker. deinit unloads the external CC1101 radio-device plugin, freeing its SubGhzDevice struct and interconnect vtable; the TxRx worker thread sleeps/ends that device from its own thread on shutdown, so joining it after deinit dereferenced freed plugin memory. The internal CC1101 is a static device that deinit never frees, which is why the crash was external-only. Stop and free the worker before subghz_devices_deinit(), matching the teardown order already used by subghz_cli_command_rx. Also add the missing deinit + radio power-off to the "tx not allowed" early return so a subsequent subghz command's subghz_devices_init() does not furi_check-fail on an already-valid registry. Fixes #829 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * changelog: SubGHz crash exiting CLI chat with external CC1101 (PR #1036, Fixes #829) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
e4e8a8ef2b |
[NFC] Trim MIFARE Plus generator & admin-key mapping (in-place cleanup) (#1035)
* [NFC] Data-drive MIFARE Plus manual-add generators Replace the 18 near-identical MIFARE Plus generator thunks and their handler-table entries with a data-driven mf_plus_generator_configs[] table (uid_len / type / size / ATS per variant), dispatched via a small range predicate. The Ultralight/NTAG and Classic types keep their bespoke handlers, so the handler table now stops before the MF Plus range. Also drop mf_plus_ats_hist_ev, which was byte-identical to mf_plus_ats_hist_s (EV1/EV2 are identified by GetVersion, not the ATS). Pure refactor: the Add-Manually menu entries, the generated cards and the public SDK API are all unchanged. Trims firmware flash by removing the per-variant functions and the duplicate blob; a _Static_assert pins the config table to the enum range so a future type can't desync it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MIFARE Plus: single source for admin-key addresses Fold the three copies of the admin-key address<->type mapping (0x9000 CardMaster, 0x9001 CardConfig, 0x9003 L3Switch, 0x9004 SL1CardAuth) into one mf_plus_admin_key_addresses[] table with a forward helper (mf_plus_get_admin_key_address, replaces the poller's local id array) and a reverse helper (mf_plus_admin_key_type_from_address, replaces two identical switch statements in the listener's key-resolve and write-store paths). Behavior-preserving: both listener default fall-throughs are kept (resolve returns false; store falls through to data/config block handling), the poller authenticates the same addresses, and a _Static_assert pins the table to MfPlusAdminKeyNum. Internal helpers only; no SDK API change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] Changelog: MIFARE Plus generator/admin-map cleanup Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
45c3762c06 |
[NFC]: Added support for Mifare Plus in SL3 to NFC (#1032)
* [NFC] Add MIFARE Plus SL3 crypto primitives (mf_plus_crypto) Foundation for native MIFARE Plus SL3 support: AES-128 ECB/CBC (firmware mbedtls), AES-CMAC + the MFP 8-byte truncation, AN10922 session-key derivation, MAC assembly, and the data-encryption IV builders. IV layout follows Proxmark3 mfp_data_crypt(), verified against source: single low counter byte; read R_lo@[0/4/8]+TI, write W_lo@[7/11/15]+TI. The write-direction IV is not yet hardware-validated -- flagged in-header for confirmation before the write/emulation paths (PR6/7). No callers yet; poller/listener land in later PRs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * [NFC] Add RFC 4493 self-test for MIFARE Plus SL3 crypto Known-answer vectors for mf_plus_crypto: the four RFC 4493 AES-CMAC cases (empty / single / partial-final / multi-block) plus the cmac8 odd-index truncation, and a regression test locking the PM3-matched data-IV byte layout (read R_lo@[0/4/8]+TI, write W_lo@[7/11/15]+TI, low-byte-only). Added to the nfc unit-test suite; the four mf_plus_crypto_* symbols are exported via the test-only API table (unit_test_api_table, api 0.0) so the test plugin resolves them at runtime. Builds clean (firmware + test_nfc plugin); on-device run via the unit_tests CLI. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * [NFC] Extend MfPlusData with SL3 block/key model + versioned dump PR2 of native MIFARE Plus SL3. MfPlusData now holds SL3 content: data blocks + a read bitmap, per-sector AES KeyA/KeyB (+ found masks), admin keys (CMK/CCK/L3-switch/SL1-auth), config blocks (0xB0xx), and the originality signature. Keys are stored separately from block data (SL3 keys are in the 0x40xx keyspace, not data memory, unlike Classic's sector-trailer layout). Adds a versioned .nfc save/load mirroring mf_classic (dense 'hex or ??' per-block lines, a 'Data format version' key, backward-compatible with legacy metadata-only dumps). is_equal now diffs blocks+keys+config+signature so emulation writeback to .shd can be detected. Review hardening: mf_plus_str_to_bytes parses into a local and commits on success (out untouched on failure), guards a truncated-line OOB read, and logs corrupt hex vs a legitimate '??'; load refuses an unknown newer data-format version; alloc zeroes via reset; compile-time asserts lock the mask-fits-domain invariants. Builds clean (fbt firmware_all). Gated: code/silent-failure/type-design/comment review + simplify. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * [NFC] Add MIFARE Plus SL3 read poller (auth + read + signature) PR3 of native MIFARE Plus SL3. Extends the previously detection-only mf_plus poller with the SL3 secure-messaging read flow, composing over the existing iso14443_4a poller. Primitives (ported byte-faithfully from the flipperzero-mfp-reader fork onto the PR1 crypto): AuthFirst (0x70/0x72) with the rrot(RndA)/rol(RndB) token + session-key derivation, encrypted+MAC'd block read (0x31) with the pre/post-increment r_ctr counter model, and the plaintext originality signature (Read_Sig 0x3C). State machine (mirroring mf_classic's mode/event API): after detection, RequestMode -> ReadSignature -> per-sector RequestKey -> AuthSector -> ReadSectorBlocks -> ReadSuccess, gated on SL3 + read mode. The app supplies candidate keys via RequestKey and tracks progress via DataUpdate; RequestMode defaults to Info so the existing detect/info scan is unchanged. The app-side dictionary driver lands in PR4. Also lands the PR2-deferred accessor family + per-sector geometry and routes the serializer through the atomic setters. Review hardening: a genuine wrong key (Auth) advances to the next candidate while a comms fault fails loudly instead of silently dropping a key; a response-MAC mismatch aborts the sector (counter desync) rather than cascading; the SL3 path is logged throughout. Builds clean (fbt firmware_all). Gated: code + silent-failure review + simplify. On-device read of a real SL3 card is manual QA. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * [NFC] Add MIFARE Plus SL3 dictionary attack Recover SL3 sector AES keys by dictionary and read all sectors, exposed as "Unlock with Dictionary" on the read and saved menus (gated on SL3; SL0/1/2 never reach this path). - New scene nfc_scene_mf_plus_dict_attack: the SL3 poller has no resume-from-prior-data path, so the user and built-in system dictionaries are consumed in a SINGLE poller pass (user keys first) rather than as separate runs, which would discard already-recovered keys. Restarts the combined key stream per (sector, key type) since the poller has no NextSector event. - System dictionary asset (mf_plus_dict.nfc): union of PM3 g_mifare_plus_default_keys and client/dictionaries/mfp_default_keys.dic, deduplicated and upper-cased (33 AES-128 keys). - Reuses the shared dict_attack view in its sector-oriented layout; sets the type explicitly on entry (the shared view keeps whatever type the last scene left it in). - mf_plus_is_card_read(): a block-completeness check used to grade the outcome full vs semi success, instead of the poller's sector counter (which also counts sectors that aborted mid-read). A terminal ReadFailed (lost card / comms fault) is logged and always graded semi-success, never a clean read. - Expose mf_plus_get_sector_count and mf_plus_is_card_read in the public SDK API (the NFC app is an external FAP and calls them), mirroring the mf_classic geometry/status helpers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] Add MIFARE Plus user key management scenes Add "MIFARE Plus Keys" to Extra Actions, mirroring the MIFARE Classic and Ultralight C key managers, so users can grow the SL3 dictionary the "Unlock with Dictionary" attack consults. - Scenes: keys (Add/List menu with system+user key counts), keys_add (byte input, rejects duplicates), keys_list (pick a user key), keys_delete (confirm + delete), keys_warn_duplicate. Keys are 16-byte AES-128, stored in the lazily-created user dictionary (NFC_APP_MF_PLUS_DICT_USER_PATH). - keys_delete hoists the load-key-at-index walk into a helper shared by on_enter and on_event and tolerates a stale index (falls back to the list) instead of asserting; keys_list uses a distinct inner loop index rather than shadowing the outer one. - Route save/delete success back to the MIFARE Plus keys menu. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] Recover MIFARE Plus SL3 admin keys and config blocks Extend the SL3 read scan with an admin-key phase after the sectors: recover the 0x90xx admin keys by dictionary and, once the Card Master or Config key is found, read the 0xB0xx configuration blocks with it. - Generalize the auth primitive to a raw 16-bit key address (mf_plus_poller_authenticate_key_id); the sector variant now delegates to it. Admin key addresses: CMK 0x9000, CCK 0x9001, L3 switch 0x9003, SL1 auth 0x9004 (the enum skips 0x9002, so a lookup table maps them). Auth is the same 0x70/0x72 flow as sector keys, little-endian address. - Generalize the encrypted read with a block-address high byte: data blocks pass 0x00, config blocks pass 0xB0 (both in the frame and the command MAC). - New states RequestAdminKey -> AuthAdminKey -> ReadConfig. Config is read interleaved while the CMK/CCK session is fresh, and tracked by the per-block config mask so a CCK pass fills blocks a CMK pass could not read. - The admin/config phase is best-effort (the sectors are already captured before it runs): a wrong candidate asks for the next, an absent admin slot (AUTH_FIRST rejection) is skipped, and a lost card finishes with the complete data instead of failing an otherwise-complete read. - The dictionary-attack scene answers admin-key requests from the same dictionaries and restarts the key stream when the request target changes (sector key <-> admin key, or which admin key). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] Render recovered MIFARE Plus SL3 content The "More info" view showed only GetVersion data; now it also dumps the SL3 content recovered by the dictionary attack: originality signature, sector keys A/B, admin keys (0x90xx), config blocks (0xB0xx) and the data blocks, each shown as hex or "??" when not recovered. Section is gated on SL3 (the poller populates this content only for SL3 read mode). - Expose the read-only accessors (mf_plus_get_block_count, mf_plus_is_block_read, mf_plus_is_key_found, mf_plus_is_admin_key_found, mf_plus_is_config_block_read) and a mf_plus_get_admin_key_name getter in the public SDK API so the NFC app (an external FAP) can render them; the matching set_* accessors stay internal. Mirrors the mf_classic public accessor surface. Folded into the existing 87.12 API bump for this feature (no further version bump). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] Add MIFARE Plus SL3 native listener (auth + read emulation) Emulate a recovered SL3 card so a reader can authenticate and read it. The listener is the card-side mirror of the read poller, reusing the same mf_plus_crypto primitives with reader/card roles reversed. - mf_plus_listener composes over the ISO14443-4A listener (registered in nfc_listener_defs.c). run() dispatches received APDUs on the command byte. - AUTH_FIRST (0x70): resolve the sector/admin key from the recovered MfPlusData, generate RndB, reply E(key, RndB). AUTH_CONTINUE (0x72): verify the RndB echo, derive the session keys from rrot(RndA)+RndB (same inputs as the poller), and echo rol(RndA) so both this port's poller and a PM3-style reader accept it. - READ (0x31): verify the command MAC (pre-increment r_ctr), then reply with the encrypted block + response MAC using the post-increment counter/IV, byte-for- byte matching the poller's read. Serves data blocks and 0xB0xx config blocks. - READ_SIG (0x3C): returns the stored originality signature. Unknown commands (GetVersion, WritePerso probe) are left unanswered so the reader falls back to ATS identification. - Runtime get_features gate: SL3 -> EmulateFull, SL0/1/2 -> EmulateUid only, so non-SL3 cards are not offered full emulation. Emulate scene allocates the native MfPlus listener for SL3 (required for a future .shd writeback) and falls back to a UID-only ISO14443-4A listener otherwise. Reader-write handling and .shd writeback come next; the write path is not yet included here. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MFP: sector read-progress helper + drop the empty signature dump line - mf_plus_get_read_sectors_and_keys(): counts fully-read sectors (all blocks captured) and recovered sector keys, for the read-progress screens (mirrors mf_classic_get_read_sectors_and_keys). Public so the app FAP can use it. - The originality signature is now written to the .nfc last and only when the card actually has one; a card with no signature (MFP X/EV0) no longer gets a misleading "Signature: ??" line, and its absence loads as "no signature". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MFP: align read-success and info screens with MIFARE Classic The read-success and info screens now show name / UID / Keys Found / Sectors Read (and Tech / ATQA / SAK on the full info), matching the MIFARE Classic layout via nfc_render_iso14443_3a_info + the new sectors/keys helper. The ISO14443-4 protocol detail (ATS, bit rates) moved from the info screen into "More info", where the full SL3 dump lives. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MFP: auto-run the dictionary attack after reading an SL3 card The read poller callback now reports the SL3 identity scan as "incomplete" and the read scene auto-continues into the dictionary attack, so recovering keys no longer requires the manual "Unlock with Dictionary" tap -- mirroring the MIFARE Classic read flow. SL0/SL1/SL2 finish at the read-success screen as before. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MFP: group Keys under MIFARE Classic; shorten the save-name prefix - Move "MIFARE Plus Keys" directly under "MIFARE Classic Keys" in Extra Actions. - Abbreviate " Plus" -> "P" in the auto-generated save name, so MIFARE Plus dumps prefill as "MFP..." (and NTAG I2C Plus as "NTAG I2CP...") instead of the "MF+" the generic " Plus" -> "+" rule produced. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MIFARE Plus SL3: support plaintext (0x33) block reads Some SL3 cards require plaintext block reads (command 0x33) instead of the encrypted default (0x31), governed by the per-block access conditions. A card like the MIFARE Plus S rejects 0x31 with status 0x0B ("command not available at current card state") on every data block, so it authenticates all keys yet reads zero sectors. Poller: mf_plus_poller_read_block() gains a `plain` flag selecting the opcode; in plain mode the data travels in the clear (no CBC-decrypt) and the response MAC is verified over the transmitted plaintext. A new MfPlusError value, Rejected, distinguishes a card status-byte refusal (a bare status frame that leaves r_ctr in sync) from a comms/RF fault (Protocol). The sector-read handler probes the mode in-line: on a Rejected while the mode is still unlocked, it re-authenticates the sector (resetting the counter) and retries the SAME block in the other mode, adopting that mode card-wide only on a successful read. A transient comms fault never flips the mode, and a block refused in both modes is skipped while the next block re-probes, so neither an encrypted nor a plain-only card can be mislocked by an unreadable first block. Listener: mf_plus_listener_read_handler() answers both 0x31 and 0x33 (plaintext + response MAC), so an emulated S-style card round-trips. SL0/SL1/SL2 are unaffected; config (0xB0xx) reads stay encrypted. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MIFARE Plus SL3: answer WritePerso probe in the listener A reader's info scan (PM3 `hf mfp info`) identifies a MIFARE Plus card by sending the SL0-only WritePerso command (0xA8) to the invalid block 0x9090 and reading the rejection status byte: a card in SL3 refuses it with 0x0B ("command not available at the current card state"), which the reader reads as Plus + SL3. Our SL3 listener left 0xA8 unanswered, so an emulated card returned "No card response" to that probe and the reader printed "Identification failed" even though UID/ATQA/SAK/ATS were all emulated correctly. Add a stateless handler that answers WritePerso with 0x0B. WritePerso is rejected by a real card regardless of block address or authentication state, so the handler ignores the frame and needs no session; it touches neither the listener state nor the crypto counters. GetVersion (0x60) and Read_Sig (0x3C) are intentionally still left unanswered for an EV0/X/SE card, which genuinely has neither -- matching real-card behaviour. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MIFARE Plus SL3: NAK unsupported commands in the listener A reader's info scan (PM3 `hf mfp info` / `hf 14a info`) sends GetVersion (0x60) and Read_Sig (0x3C) while identifying a card. Our SL3 listener left those (and any other unimplemented command) unanswered, so an emulated card returned an empty frame and the reader printed "No card response" for each -- an EV0/S/X part has neither command, but a real one still answers rather than going mute. A real MIFARE Plus S 2K (EV0) confirms this: to GetVersion it replies with a bare 0x0B status ("command not available at the current card state"): Rdr | 02 90 60 00 00 00 .. | GET VERSION Tag | 02 0B .. | INF = 0x0B Mirror that: unimplemented commands, and Read_Sig on a card with no signature, now NAK with 0x0B via a small mf_plus_listener_send_status() helper (shared with the WritePerso handler). The reader's scan completes instead of timing out, and reading the emulation back still falls through to ATS-based typing (GetVersion 0x0B -> version parse fails -> ATS; Read_Sig 0x0B -> signature absent). GetVersion is intentionally not answered with a fabricated version: 0x0B is what a real EV0 returns. Replaying a stored version for EV1/EV2 is a later item. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MIFARE Plus: drop the manual "Unlock with Dictionary" menu item The SL3 dictionary attack now runs automatically on read (the read scene enters the dict-attack scene on PollerIncomplete), so the manual "Unlock with Dictionary" entry on the read and saved menus was redundant. Remove it: delete the submenu item, its enum, and its event handler, and point both menus at the common empty scene handlers. The standard Save/Emulate/Info/etc. items are added by the framework and are unaffected. The dict-attack scene stays reachable through the automatic read flow; only the manual entry point is gone. mf_plus_is_sl3 is kept (the runtime feature gate still uses it). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MIFARE Plus SL3: NAK failed authentication in the listener When a reader (or key check like PM3 `hf mfp chk`) authenticates with a wrong key, our SL3 listener answered AUTH_FIRST but then went silent on the AUTH_CONTINUE whose RndB echo didn't match. The reader timed out and desynced its whole scan -- a sector with a custom key poisoned the checks of later factory-key sectors. A real MIFARE Plus S 2K (EV0) confirms the correct behaviour: to a wrong-key AUTH_CONTINUE it replies with a bare 0x06 status (authentication error): Rdr | 0B 00 72 D0 78 .. | SECOND AUTH STEP (wrong key) Tag | 0B 00 06 84 E9 | INF = 0x06 Mirror that. Every auth failure -- malformed AUTH_FIRST/AUTH_CONTINUE, a key the emulated (partial) dump never recovered, AUTH_CONTINUE without a prior AUTH_FIRST, and the wrong-key RndB-echo mismatch -- now NAKs with 0x06 via the shared status helper instead of staying silent. The reader records a miss and advances to the next key. Our own poller already reads a non-0x90 AUTH_CONTINUE status as MfPlusErrorAuth ("wrong key, next candidate"), so reading the emulation back is unaffected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MIFARE Plus SL3: add a "Show Keys" screen Mirror the MIFARE Classic "Show Keys" viewer for MIFARE Plus SL3. A new scene lists the recovered per-sector AES keys (A/B) and the four admin keys (Card Master, Card Config, L3 Switch, SL1 Card Auth) in a scrollable widget, offered via a "Show Keys" item on both the read and saved menus for SL3 cards. Like the MFC viewer it lists only sectors with a recovered key and omits the unknown ones to stay compact on a partially-read card; keys print as compact uppercase hex (16-byte AES keys are too long for per-byte spacing). It adds an explicit "No keys recovered yet." line for the empty case and a footer with the A / B / admin found counts. The item is always present for SL3 so the view is reachable even before any key is recovered. All accessors and key fields are already public, so no API change is needed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MIFARE Plus SL3: switch data IV to the fork's validated two-counter layout The data-encryption IV builders followed PM3's single-low-byte layout, which is only PM3-source-derived and never hardware-validated for the write direction. Switch both to the reference fork's layout instead: a little-endian {R_ctr, W_ctr} word {R_lo, R_hi, W_lo, W_hi} repeated across the IV, with TI at IV[12..15] for reads and IV[0..3] for writes. This is the layout validated end-to-end by a U-Prox encoder writing keys to the fork's emulation, so it is the trustworthy basis for the encrypted write path (0xA1) coming next. For a read-only session (W_ctr == 0, R_ctr < 256) the word collapses to {R_lo, 0, 0, 0} and the read IV is byte-for-byte identical to the old PM3 layout, so the hardware-validated read path is unaffected -- both read-IV callers (poller, listener) simply pass their session's W_ctr (0 until a write). Unit-test IV vectors updated to the new layout, including two full-counter cases that pin every R/W byte position; the test-only API-table signatures follow the new 4-arg form. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MIFARE Plus SL3: emulate writes (0xA1/0xA3) for .shd writeback Add the card-side write handler to the SL3 listener so a reader writing to the emulated card mutates MfPlusData, which the generic emulate-exit diff then auto-saves as a .shd. This completes the emulation-with-change path (e.g. a U-Prox encoder re-keying the emulated card). The handler is a native port of the reference fork's validated handle_write: - Frame [cmd, BNr_lo, BNr_hi, data(16), cmd_mac(8)]. Command MAC over {BNr_lo, BNr_hi, data-as-transmitted} with the pre-increment W_ctr; response is 0x90 + MAC over the post-increment W_ctr (mirrors the read counter model). - 0xA1 (keys) CBC-decrypts the block with the write IV; 0xA3 (data) carries plaintext. W_ctr advances only on an accepted write, so a NAK (bad MAC, short frame, unknown address, not authenticated) never desyncs the reader. - store_write resolves the 2-byte address to a sector key (0x40xx), admin key (0x90xx), data block (high 0x00) or config block (0xB0xx) and calls the matching mf_plus_set_* mutator (field + found/read mask), so is_equal detects the change and a key write rotates the stored key for the re-auth round-trip. Not yet hardware-validated: the encrypted-write IV rests on the fork's U-Prox-validated layout (see the crypto commit), to be confirmed on-device. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MIFARE Plus SL3: poller write path (write-to-card) Add the reader-side write to the SL3 poller, the card-side counterpart of the already-validated listener write handler. This is the protocol core of "Write to Initial Card"; the UI wiring follows in a separate commit. - mf_plus_poller_write_block(): 0xA1 encrypted (CBC-encrypt the block with the write IV) / 0xA3 plain, mirroring mf_plus_poller_read_block. Command MAC over {block_low, block_high, data-as-transmitted} with the pre-increment W_ctr; a status rejection (0x0B) returns MfPlusErrorRejected without advancing W_ctr, an accepted write advances it once and verifies the response MAC over the post-increment value. - Write state machine: RequestWriteSector (ask the app for the sector's recovered key) -> AuthWriteSector -> RequestWriteBlock (ask for the block data) -> WriteBlock. Writes only the sectors/blocks present in the dump; a sector whose key isn't in the dump is skipped. - Write-mode probe: like the read probe, the first block is tried encrypted and, on a status rejection, the sector is re-authenticated and the block retried plain, adopting whichever mode succeeds card-wide. The user's note that write, like read, has both plain and encrypted forms is handled here. - New MfPlusPollerModeWrite + RequestWriteSector/RequestWriteBlock/WriteSuccess/ WriteFailed events; the ISO14443-4a fault path reports WriteFailed in write mode. Not yet hardware-validated on the poller side (the write crypto itself is HW-proven via the listener + U-Prox); confirm with a real-card write. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MIFARE Plus SL3: "Write to Initial Card" UI Wire the app UI for writing a saved SL3 dump back to its source card, using the generic write-scene machinery (the same approach as MIFARE Classic). - Advertise NfcProtocolFeatureWrite for SL3 only (runtime get_features gate), so SL0/1/2 -- which have no recovered blocks -- never offer it. - The generic "Write" item is relabelled "Write to Initial Card" on the saved menu and removed from the read menu (writing right after a read makes no sense), mirroring MIFARE Classic. Both menus keep "Show Keys". - The write scene starts the poller in write mode; its callback gates on a UID match (write only the card the dump came from), then feeds the recovered sector keys (preferring key A) and data blocks from the loaded dump. A sector/block the dump lacks is skipped by leaving key/block_provided false. Completes the "Write to Initial Card" feature (poller path landed in the previous commit). Not yet hardware-validated end-to-end; confirm on a real card. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MIFARE Plus SL3: "Update from Initial Card" Add the re-read-and-refresh flow (card -> saved dump + shadow), mirroring MIFARE Classic. Offered on the saved menu for SL3; runs no dictionary attack -- it re-reads the source card using the dump's already-recovered keys. - Three scenes (update_initial + success + wrong_card) mirroring the MIFARE Classic ones. The worker runs the read poller in read mode: UID-gate on RequestMode, then feed the recovered sector/admin keys from the dump. - Loop guard: the read poller re-requests a (sector, key) after a failed auth to get the next dictionary candidate, but here there is only the one recovered key -- so a re-keyed card would loop. feed_once() feeds each key exactly once (scene state = last-fed-id + 1) and answers "no key" on an immediate repeat. - Merge, don't replace: the poller reports ReadSuccess even if its best-effort admin/config/signature phase is cut short (early card lift), so a wholesale set_data could silently drop keys/config the dump already had. New public helper mf_plus_merge_update() overlays every field the re-read recovered onto a clone of the old dump without clearing anything, so the refresh only adds/ updates. Exposed in api_symbols.csv (still 87.12) for the FAP. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MIFARE Plus: detect S/X/SE by ATS nibbles, not full match A real MIFARE Plus SE presents ATS historical bytes C1 05 21 30 00 77 C1 -- the trailing bytes (caps + CRC16) differ from the AN10833 values (...F6 D1), so the exact 7-byte match failed and the SE was mis-detected as a generic Plus. Match the discriminating nibbles instead, the way PM3 does. The block is C1 05 <type/size> <gen> <caps> <crc16>; only the type/size nibbles are stable: - S / X mask their size (byte2/3 = 2F 2F); the caps byte's SVC bit separates them (set = X, clear = S). - SE reveals its size (byte2 = 0x21 = 1K, byte3 = 0x30). The C1 05 + high-nibble-2 gate keeps a DESFire (also SAK 0x20) from being mis-claimed. The SAK 0x08/0x18 SL1 cases now use the same matcher, so SE 1K SL1 is recognized too while S/X classify exactly as before. Removes the now-unused mf_plus_ats_t1_tk_values table (its SE entries held the unreliable AN10833 tail); the mf_classic SL1 probe keeps its own local S/X pair. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [gui] elements_text_box: word-wrap instead of breaking mid-word The multiline text box wrapped character by character, so a long line broke in the middle of a word (e.g. an emulated "MIFARE Plus S 2K SL3" name split as "...2K S" / "L3"). Track the last space on the current line and, on overflow, break there so the whole trailing word moves to the next line; fall back to the original character wrap when a single word is itself wider than the box. A word containing an inline font marker (\e#, \e*, \e!) still character-wraps: rewinding across an already-applied marker would re-toggle the emphasis and corrupt the width measurement, so `marker_since_space` blocks the word-wrap branch for those words. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MIFARE Plus SL3: MFC-style block dump + ISO14443-4 "More" page Rework the SL3 "More info" so the block layout reads like MIFARE Classic and the protocol/hardware detail moves to a second page. - The block dump is now per-sector: each block as hex, and the sector trailer shows the recovered Key A + the trailer block's access bits (its bytes 6-9) + Key B. SL3 keeps the AES keys in a separate keyspace, so the raw trailer's key bytes are meaningless -- substituting the recovered keys is what makes it read like a Classic dump. The separate "Sector Keys" section is dropped (its keys now live in the trailers). Hex is emitted in space-separated 2-byte groups so long lines wrap between groups. - nfc_render_mf_plus_data is split into nfc_render_mf_plus_dump (blocks + admin keys + config + signature) and nfc_render_mf_plus_iso4 (GetVersion + ISO14443-4). The block-dump page gains a "More" button to a new MfPlusIso4Info scene holding the ISO14443-4 details that used to be inline. - mf_plus_sector_get_first_block / _block_count are promoted to the public header (+ api_symbols.csv, still 87.12) so the app-side render can walk the per-sector geometry. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MIFARE Plus SL3: answer AUTH_FIRST for unrecovered sectors When emulating a partially-recovered dump, a reader authenticating a sector whose key we never recovered was NAK'd at AUTH_FIRST (phase 1) with 0x06. A real card always answers AUTH_FIRST -- it holds every key and only rejects a wrong key at AUTH_CONTINUE -- so a phase-1 NAK is unlike any real card, and some readers (a U-Prox encoder) abort the whole exchange when they see it, leaving the auth "unfinished". Verified on hardware: to AUTH_FIRST the real card answers 90 02 BE AA.. (0x90 + E(RndB)); our emulation answered 06 58 B3. Now an unrecovered key runs the handshake with a random placeholder: phase 1 completes normally, and since the placeholder can't match the reader's key, the reader's phase-2 token fails to echo our RndB and we NAK 0x06 at AUTH_CONTINUE -- exactly as a real card rejects a wrong key. No false-successful auth (the reader would have to guess our per-session random 16 bytes, and even then the sector's blocks were never recovered so nothing is exposed). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MIFARE Plus: restructure More-info into a hub + fix dump OOM The Info screen's "More" button now opens a small hub (View Dump / ISO14443-4 Data), DESFire-style, instead of the block dump directly: - View Dump (SL3 only): the Classic-style block dump, now rendered in a memory-light text_box (stores the pointer, lays out visible lines lazily) rather than a text-scroll widget. The widget deep-copies the whole string AND allocates a FuriString per wrapped line, which for a multi-KB 2K/4K dump exploded into hundreds of allocations and OOM'd on the ~30 KB-free NFC thread. Also furi_string_reserve the dump up front so the many cat calls don't grow by doubling (that transient ~2x realloc was the intermittent "opened on the 3rd try" OOM). - ISO14443-4 Data: the ISO14443-4 protocol details as a widget with a "More" button to a new GetVersion page. Dump layout: block number on its own line with hex below, so a 16-byte block wraps into two even 2-byte-group lines instead of colliding with the "N:" prefix; dropped the leading blank line. Splits nfc_render_mf_plus_iso4 into nfc_render_mf_plus_iso14443_4 + nfc_render_mf_plus_version_info for the two new pages. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MIFARE Plus: add 18 "Add Manually" variants Add SE / S 2K / S 4K / X 2K / X 4K / EV1 2K+4K / EV2 2K+4K generators, each in a 4-byte and 7-byte UID flavour, to the core nfc_data_generator (they auto-appear in the app's "Add Manually" list, which iterates the generator enum). All are built at SL3 -- the native ISO14443-4 presentation this app fully supports -- with a random NXP UID, product-correct ATQA/SAK, and a well-formed ATS. Defaults follow real/known values where available and sensible placeholders otherwise: - ATS historical bytes: SE uses a real capture (C1 05 21 30 00 77 C1); S/X use AN10833 (2F 2F, SVC bit distinguishes them) -- validated byte-identical against real S/X cards' ATS. EV1/EV2 identify via GetVersion so they reuse the generic Plus block. S/X share their ATS across 2K/4K (the size is masked there; ATQA carries it). - EV1/EV2 get a plausible GetVersion response (hw_major 0x11/0x22, hw_storage 0x16/0x18) and a random 56-byte originality signature; the EV0 products (SE/S/X) have neither, matching real silicon. - SL3 sector/admin keys and blocks are left empty -- a synthetic card has no recovered keys. Generated cards round-trip through save/load and re-detect as the intended product (type/size/SL are stored explicitly). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] Add Manually: keep the list cursor on the picked type Opening a card type from "Add Manually" and pressing Back re-entered the type list at the top instead of on the row just opened. The set_type scene rebuilds its submenu on every entry (including on Back) but never restored the selection. Save the picked row in the scene state (stored +1 so the default 0 means "nothing picked yet" -> top) and restore it in on_enter. Applies to every protocol's Add Manually list, not just MIFARE Plus. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] iso14443-4: don't crash on an I-block with no INF field Decoding a received I-block copied its INF field with bit_buffer_copy_right(input, prologue_len), which furi_check-crashes (bit_buffer.c: size must be > start_index) when the I-block carries no INF at all -- total size <= its prologue length. A bare PCB-only I-block, or a CID-flagged empty I-block on a CID-supporting card, trips it. Every other malformed case in this decoder already returns Skip; this one asserted and took the whole device down. Guard it the same way: skip an I-block whose size is <= its prologue length instead of asserting. Also catches a truncated frame whose PCB claims a CID/NAD byte it is too short to contain. Found on hardware emulating a MIFARE Plus SL3 card to an NXP TagInfo reader: TagInfo desyncs into an R(NAK) retransmission storm and emits empty I-blocks, crashing within seconds. Fix is in the shared 14443-4 transport, so it hardens all 14443-4 emulation (DESFire, Type-4, ...), not just MIFARE Plus. HW-confirmed: no more crash. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MIFARE Plus: recognize the second SE ATS fingerprint NXP TagInfo (v6.2.0, reverse-engineered) matches TWO Plus SE ATS historical-byte fingerprints -- C1 05 21 30 00 77 C1 and C1 05 20 30 00 AB 9B -- differing only in the size/gen nibble (byte2 0x21 vs 0x20). We only matched 0x21, so a real SE carrying the 0x20 fingerprint fell through to Unknown. Match SE on byte3 == 0x30 with byte2 in {0x20, 0x21}; S/X keep byte3 == 0x2F, so no overlap and no regression. Real S/X ATS are already byte-identical to TagInfo's table. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MIFARE Plus: emulate GetVersion for EV1/EV2 An emulated EV1/EV2 now answers GetVersion so a reader (NXP TagInfo, PM3) classifies it correctly instead of falling back to a generic Plus. GetVersion is an application-level command (no transport support), so the listener crafts the chained response itself. It replays the stored 28-byte MfPlusVersion as three frames, matching a real EV1 capture byte-for-byte: 0x60 -> 0xAF + 7 HW bytes 0xAF -> 0xAF + 7 SW bytes 0xAF -> 0x90 + 14 UID/batch/date bytes (final status 0x90, NOT DESFire's 0x00) Both the native form and the ISO7816-wrapped 0x90-CLA form (data first, 0x91 <status> trailer) are handled, with a small get_version_stage chain-state on the listener (reset on field-off/halt and when any other command interrupts the chain). Gated on a real version being present (EV1/EV2: hw_vendor 0x04, family nibble 0x02); EV0 parts (S/X/SE) have none and keep NAKing 0x0B, which is faithful and is TagInfo's EV gate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MIFARE Plus Add Manually: blank-format memory + real EV1 version Manually-added MIFARE Plus cards were identity-only: every block and key read as "??", which is useless to emulate or inspect. Fill a blank-formatted factory state, the MIFARE-Plus analogue of the Classic generator's 0x00 blocks + default keys: - data blocks zeroed and marked read; block 0 rebuilt as the manufacturer block (UID + BCC on 4-byte UIDs + SAK + ATQA + 0xFF), since mf_plus_set_uid doesn't populate block 0 - every sector and admin AES key set to the all-FF default and marked found; config blocks zeroed Also align the EV1/EV2 generator version bytes to a real EV1 GetVersion capture (hw_proto 0x04; the software version reports its own major/minor 0x01/0x01, independent of the hardware major), so an emulated Add-Manually EV card's GetVersion matches real silicon. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] docs: MIFARE Plus detection reference (NXP TagInfo RE) Static-analysis notes on how NXP TagInfo classifies a MIFARE Plus card (variant / security level / size) via SAK routing, ATS fingerprinting, GetVersion, Read-Signature and the VCA applet -- the reference our detection and emulation are aligned to. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MIFARE Plus SL3: changelog entry + API 87.12 Add the "Native MIFARE Plus support in SL3" changelog line and bump the listed Current API from 87.11 to 87.12 (the single API bump this feature introduces). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] Show full raw ATS on the ISO14443-4 info screen Add the complete ATS frame (TL T0 [TA1] [TB1] [TC1] + historical bytes) as a raw line at the top of the shared ISO14443-4a extra renderer, before the decoded protocol info, so every 14443-4 protocol (MIFARE Plus, DESFire, NTAG4xx, Type-4, plain 14443-4a) exposes the exact ATS. The dedicated [Historical bytes] section is kept, mirroring PM3's separate ATS and Historical bytes blocks. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] Cache recovered MIFARE Plus SL3 keys per UID Mirror the MIFARE Classic key cache for SL3: on save, persist the recovered sector AES keys (A/B) and 0x90xx admin keys to /ext/nfc/.cache/{UID}.mfpkeys. On a later read, feed the cached key for each (sector, key type) / admin target before the dictionaries, so a known card authenticates on the first try instead of re-running the whole dictionary attack. A wrong cached key (re-keyed card) falls through to the dictionaries, and a cache miss runs the attack exactly as before. A distinct .mfpkeys extension and file header keep it from colliding with the MIFARE Classic {UID}.keys cache (a Plus card read in SL1 is MIFARE Classic). The cache helper is bundled into the nfc_mf_plus plugin sources (its own link unit), mirroring nfc_mf_classic. SL0/SL1/SL2 are unaffected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [NFC] MIFARE Plus SL3: note per-UID key cache in changelog Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * [GUI] Fix elements_text_box line[] overflow on 8+ line boxes elements_text_box bounded line_num only by the height break, which on a near-full-height box (>=63px tall with 9px leading) commits a 7th line and then writes line[ELEMENTS_MAX_LINES_NUM] -- index 7 of a 7-element array -- a stack out-of-bounds write. The word-wrap change (less dense than char wrap) lets text that previously fit in <=7 lines reach 8, exposing the latent gap. Add the missing line_num >= ELEMENTS_MAX_LINES_NUM bound so line[] is never indexed past its last slot. Hardens the shared primitive for every firmware text box. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
68659ee8cd |
OFW CCID: move USB layer from firmware HAL into ccid_test app [ci skip]
https://github.com/flipperdevices/flipperzero-firmware/pull/4407/changes |
||
|
|
b1b1f94c42 |
[NFC] Fix memory leaks & double-frees in supported-card parsers, app lifecycle & DESFire (#1030)
* nfc: fix double-free of card_number_str in Plantain parser printf_plantain_data() freed purse->card_number_str, then the caller freed the same (non-NULL) pointer again at the end of the parse -> double-free / heap corruption on every Plantain card. Remove the free inside the print helper; the caller that allocated it owns the free. Part of #1029 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * nfc: fix double-free + secondary-ticket leak in SZPPK parser In the second-ticket branch the cleanup freed primary_ticket.* (already freed just above) instead of the freshly-allocated secondary_ticket.*, causing a double-free of the primary strings and a leak of all four secondary strings on two-trip tickets. Free the secondary_ticket.* members. Part of #1029 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * nfc: fix double-free + secondary-ticket leak in SEVPPK parser Same copy-paste bug as SZPPK: the second-ticket branch freed primary_ticket.* (already freed) instead of secondary_ticket.*, double-freeing the primary strings and leaking the secondary ones on two-trip tickets. Free the secondary_ticket.* members. Part of #1029 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * nfc: fix double-free + secondary-ticket leak in SK parser Same copy-paste bug as SZPPK/SEVPPK: the second-ticket branch freed primary_ticket.* (already freed) instead of secondary_ticket.*, double-freeing the primary strings and leaking the secondary ones on two-trip tickets. Free the secondary_ticket.* members. Part of #1029 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * nfc: fix restricted_weekday_string leak in Saflok parser restricted_weekday_string was allocated and only read via furi_string_get_cstr; the file had no furi_string_free at all, leaking one FuriString on every Saflok card parse (both MFC and UL-C variants). Free it before the do/while(false) exits (after #endif so it applies to both SL_PROTO builds). Part of #1029 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * nfc: free api_resolver in nfc_app_free (fix per-launch leak) instance->api_resolver (composite_api_resolver_alloc + two composite_api_resolver_add nodes) was never freed; nfc_supported_cards only borrows it. Leaked the resolver struct plus its two list nodes on every NFC-app open->close. Free it after nfc_supported_cards_free (its only user). Part of #1029 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * nfc: fix Stream + storage-record leak on CUID dict open failure When a CUID dictionary passed keys_dict_check_presence but buffered_file_stream_open then failed, cleanup did only buffered_file_stream_close + free(dict), leaking the Stream object and the RECORD_STORAGE reference opened just above. Use keys_dict_free(dict), which closes+frees the stream, frees the dict, and closes RECORD_STORAGE, matching the total_keys==0 path. Part of #1029 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * nfc: fix ~15x RAM over-allocation of DESFire file_data array mf_desfire_file_data_array_config.type_size used sizeof(MfDesfireData) (~60+ bytes) but the element type is MfDesfireFileData ({ SimpleArray* data; } = 4 bytes), so every file slot over-allocated ~15x, scaled by (files x applications) on the card. Use sizeof(MfDesfireFileData). Consistent stride, so no behavior change beyond reduced heap use. Part of #1029 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * changelog: NFC memory leaks & double-frees (PR #1030, Fixes #1029) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
eb49a89441 |
ci: auto-bump issue-template stable version on release publish [ci skip]
Add a workflow that, when a stable `unlshd-*` release is published, rewrites the bug-report template's "Found in version" dropdown to keep exactly one stable option (the new release tag) + "dev", then commits it to dev. - Prerelease/non-unlshd tags are skipped. - Surgical regex edit (minimal one-line diff), validated with yq before commit. - Pushes via GITHUB_TOKEN don't retrigger CI; [ci skip] added to match convention. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
34c3c9f072 |
issue templates: use dev build number for Dev version field [ci skip]
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
d9842247ab |
issue templates: capture firmware version in bug report, fix typos
- Bug report: drop the unused `Target` field; add a required "Found in version" dropdown (unlshd-089 / dev) plus an optional "Dev version" text input for the exact dev build identifier. - Fix typos: "a bug reports" -> "a bug report", "whetever" -> "whether". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
37c6dd97f5 | testing push notifications for qUnleashed app | ||
|
|
056d3ea328 |
upd changelog
hotel parser might conflict with current saflok parser? disabling just in case |
||
|
|
ad60eeada0 | Merge remote-tracking branch 'OFW/dev' into dev | ||
|
|
101c20d736 | NFC Plugin to identify some hotel systems (#4323) | ||
|
|
d4b023ce53 |
CCID: add interrupt support (#4198)
* CCID: add interrupt support Allow smartcard to be inserted or removed by calling the following functions: - furi_hal_usb_ccid_insert_smartcard - furi_hal_usb_ccid_remove_smartcard These functions will use the interrrupt endpoint to send a notify change message * Clang format * Fixes * fbt format and logs to debug --------- Co-authored-by: Štefan Croitoru <66339601+turbospok@users.noreply.github.com> |
||
|
|
1be39664c9 | Merge remote-tracking branch 'OFW/dev' into dev | ||
|
|
86d9141bb4 | Fix broken docs links (#4405) | ||
|
|
5cdf9b3374 |
ci: post Build & analyze report on fork PRs via workflow_run (#1027)
* ci: post Build & analyze report on fork PRs via workflow_run The Comment PR report step in pr-build.yml fails with 403 "Resource not accessible by integration" on fork PRs: GitHub gives `pull_request` runs from forks a read-only GITHUB_TOKEN (they build untrusted code), so issues.createComment is forbidden and the whole f7 build check goes red even though the firmware built fine. Split delivery from analysis: - pr-build.yml keeps all build/size/API analysis on the fork's code with the read-only token, but instead of commenting it uploads the assembled report + PR number as the `pr-report` artifact. Drops pull-requests:write. - pr-comment.yml (new) is triggered on workflow_run when the build completes. It runs from the default branch in the base-repo context, so it gets a read-write token even for fork-triggered builds, downloads the artifact, and posts/updates the comment. It never checks out or runs PR code. The PR number travels via the artifact because workflow_run.pull_requests is empty for fork PRs. Same-repo PRs keep working; fork PRs now get the report comment a few seconds later, and the build check is no longer falsely red. Closes #1026 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci: harden fork-PR comment workflow after review Review + simplify pass on the workflow_run split: - pr-comment.yml: add `actions: read` — an explicit permissions block sets unlisted scopes to none, and a cross-run download-artifact needs it; without it the download 403s, continue-on-error swallows it, and the comment silently never posts. This is the fix that makes the feature actually work on forks. - pr-comment.yml: skip cancelled/skipped builds in the job `if`, and warn (job annotation) when the artifact can't be downloaded, so a genuine failure isn't a green check with no comment and no signal. - pr-comment.yml: add a concurrency group (keyed on the build run id, since workflow_run.pull_requests is empty for forks) so a re-run can't race the find-or-create into duplicate comments; log incomplete artifact at warning, not info; per_page:100 on listComments to cut pagination round-trips. - pr-build.yml: mark the report upload continue-on-error so a transient upload hiccup can't redden an otherwise-green build (the point of the split); fix two comment overstatements (push/dispatch summary omits the PR-only API section; concurrency also covers pushes to dev). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
b8c5858f40 |
[RFID]: Fix reading T5577 tags that hold multiple EM4100 IDs (#1025)
* [LFRFID]: Fix reading T5577 tags that hold multiple EM4100 IDs A T5577 configured to emit more than one EM4100 frame per cycle (e.g. two IDs written by the T5577 Multi Writer app) hung on Read. The Electra protocol (2024) gave the EM4100 decoder a 64-bit "the frame must be followed by a header" lookahead to tell EM4100 and Electra apart. That pushed each decode ~128 bits past the read worker's per-decode reset, so a two-frame tag locked into rigid A/B alternation and never produced the 3 identical decodes in a row that Read requires. Only a 9-bit lookahead is actually needed (Electra's epilogue never begins with 9 ones), so shrink the epilogue register to 9 bits. This restores the pre-Electra decode timing while keeping EM4100/Electra disambiguation. Also reset encoded_epilogue in decoder_start, which the original change omitted. Fixes #1024 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * [LFRFID]: Reset encoded_data in PAC/Stanley decoder_start protocol_pac_stanley_decoder_start reset data/inverted/got_preamble but never the encoded_data shift buffer - missing since the protocol was added, and unlike every sibling decoder. Latent in practice (the buffer self-refreshes and decoding is preamble/parity/checksum-gated), fixed for consistency. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * [LFRFID]: Changelog for multi-EM4100 T5577 read fix (#1025) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
7cff5faae7 |
[NFC]: Show a loading screen while a large CUID dictionary loads on Read (#1022)
* [NFC]: Show loading spinner while a large CUID dictionary loads on Read
Reading a MIFARE Classic tag that has a per-UID ("CUID") key dictionary
scans the whole mf_classic_dict_<cuid>.nfc up front (to count keys and
build the key-index bitmap) in prepare_view(), which runs from on_enter
before the dictionary-attack progress view is shown. For a large
dictionary the screen stays blank and looks like the app has hung.
Wrap that scan in the existing animated loading popup (the same one used
for the supported-cards cache load), gated on CUID-dictionary presence so
ordinary MF Classic reads are unchanged (no spinner flicker). The CUID
dictionary path is factored into a small shared helper.
Closes #1021
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* [NFC]: Label the CUID-dictionary loading screen
Replace the plain centered spinner shown while a per-UID ("CUID")
dictionary loads with a dedicated view that draws the animated spinner on
the left and a "CUID dictionary is loading" label on the right, so it is
clear what the Flipper is doing during the (possibly long) scan.
Implemented as a self-contained NFC view (loading_label) using only
already-exported API symbols, so it needs no firmware API changes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs: changelog for CUID dictionary loading screen
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
bcc05f2bcb |
ci: auto-label PRs with area/* by changed paths (#1019) [ci skip]
Adds actions/labeler config + workflow that tags each PR with the relevant area/* label(s) based on the files it touches, so the subsystem taxonomy stays applied to PRs without manual effort. - sync-labels is off: labels are only added, never stripped, so hand-applied labels are preserved. - Uses pull_request_target so PRs from forks can be labeled; the workflow never checks out or executes PR code. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
ad2f900253 |
chore: align issue-template labels with new namespaced taxonomy (#1018) [ci skip]
Repo labels were reorganized into type/*, status/*, resolution/* and area/* namespaces. Update the auto-applied template labels to match: - bug report -> type/bug - feature request -> type/feature - enhancements -> type/enhancement (previously applied no label) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
9ef0b565ef |
[NFC]: Read MIFARE Plus 2K (SL1) as full 32 sectors / 64 keys (#1016)
A MIFARE Plus 2K in Security Level 1 is byte-identical to a Classic 1K in SAK (0x08) and ATQA (0x0004), so it was mis-sized as 1K and only the lower half of the card (16 sectors) was read. Tell them apart via the ISO14443-4 ATS: a genuine Plus answers RATS with a Plus S/X product signature, a Classic 1K never answers RATS. - Add MfClassicType2k (32 sectors / 128 blocks / 64 keys) - Probe RATS in the Classic poller's sak & 0x08 branch; promote to 2K only on an exact Plus S/X ATS historical-byte match. Plus SE (1K, distinct ATS), SmartMX, magic "Perfect CUID" and plain 1K stay 1K - Harden the sync detector so the appended enum value can't make every card mis-probe as 2K - Accept 2K in the NDEF supported-card guard - Fix a pre-existing NfcProtocol[] memcpy size bug in the scanner that multi-protocol (Classic + Plus) cards exercise Closes #917 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
3833290ce9 |
upd apps tag [ci skip]
updated pack was used with previous commit |
||
|
|
68952d814a |
[NFC]: Align MIFARE type detection with AN10833 (Classic SAK sizing, UL/NTAG GetVersion typing, Plus SL0/SL3/EV1/EV2, Ultralight AES) (#1014)
* 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> |
||
|
|
6c8dcb3f9a | Merge remote-tracking branch 'OFW/dev' into dev [ci skip] | ||
|
|
05792f1a91 |
Storage: add retry on file copy to Flipper (#4402)
* Updater test: fail fast on hung copy + reboot-retry on bench storage.py waits for timeout during a file copy updater_test.yml splitted and added retry loop in a build-once / try -> hard-reset -> retry. * Updater test: restore 5-minute step timeouts |
||
|
|
8c653cce54 | Fixed side menu in the FZ dev docs (#4403) | ||
|
|
0d123bdfa5 | Merge remote-tracking branch 'OFW/dev' into dev | ||
|
|
ffc1280a2c |
Fix USB HID keyboard LED state reporting (#4162) (#4338)
Add missing OUT endpoint to USB HID keyboard interface so the host can send LED state reports (CapsLock, NumLock, ScrollLock) to the device. This makes furi_hal_hid_get_led_state() return the actual host LED state instead of always returning 0. |
||
|
|
0dd3681f63 |
NFC: Fix stack buffer overflows in MFUL FAST_READ and DESFire file settings parsers (#4369)
mf_ultralight_listener.c: FAST_READ handler wrote page_cnt*4 bytes into a fixed pages[64] stack buffer without checking page_cnt <= 64. For tags with pages_total > 64 (NTAG215: 135, NTAG216: 231) a reader could trigger an overflow of up to 668 bytes. Fix: reject requests where page_cnt exceeds COUNT_OF(pages) with NAK. mf_desfire_i.c: additional_access_rights_len (a count) was validated against MF_DESFIRE_MAX_KEYS * sizeof(MfDesfireFileAccessRights) (= 28) instead of MF_DESFIRE_MAX_KEYS - 1 (= 13), allowing a rogue tag to write up to 56 bytes into a 26-byte stack slot. Fix: compare count against MF_DESFIRE_MAX_KEYS - 1. Co-authored-by: Leke Hapciu <imudheash@gmail.com> |
||
|
|
de0e3cf3b1 | Fix condition for cleaning up dict attack resources (#4400) | ||
|
|
ed0c63d8a9 |
Make view_port_send_to_back public (#4320)
`view_dispatcher_send_to_back` and `view_holder_send_to_back` are public, as `view_port_send_to_front`. |
||
|
|
ec6d0c906f |
GUI: add canvas_buffer to public api (#4399)
* GUI: add canvas_buffer to public api * GUI: add canvas_buffer to public api (f18) |
||
|
|
093d77e5b7 |
NFC: Fix BusFault in Write to Initial Card (#4362)
mode_ctx is a union where write_ctx.tag_block overlaps with dict_attack_ctx.nested_nonce.nonces. In "Write to Initial Card" it causes mf_classic_poller_free calling free on a garbage pointer |
||
|
|
8bdf46beed | Address utf8 support when uploading JavaScript application (#4364) | ||
|
|
f536d3e503 |
SEN recovery optimizations (#4337)
* SEN recovery optimizations * fbt format --------- Co-authored-by: Štefan Croitoru <66339601+turbospok@users.noreply.github.com> |
||
|
|
842b8a4b09 |
NFC: ISO 15693-3 emulation READ_MULTI and GET_BLOCK_SECURITY fixes (#4334)
Co-authored-by: Aaron Tulino <git@aaronjamt.com> |
||
|
|
0682ef3de8 | NFC: Fix sending 32+ byte ISO 15693-3 commands (#4333) | ||
|
|
225d416b44 | Update js_gui.md to reflect firmware 1.4 changes and fix a typo in the js_notification.md (#4329) |