diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..9e05a76 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "firmware"] + path = firmware + url = https://github.com/dangerous-tac0s/proxmark3-pm3py.git + branch = main diff --git a/docs/SLIX2_COMMAND_AUDIT.md b/docs/SLIX2_COMMAND_AUDIT.md index 96e8c6e..e44edf2 100644 --- a/docs/SLIX2_COMMAND_AUDIT.md +++ b/docs/SLIX2_COMMAND_AUDIT.md @@ -31,54 +31,81 @@ Commands marked MISSING need implementation in the Python transponder model + ta | Code | Name | Status | Priority | Notes | |------|------|--------|----------|-------| -| 0xA0 | INVENTORY READ | MISSING | Nice to have | Like inventory but returns data blocks | -| 0xA1 | FAST INVENTORY READ | MISSING | Nice to have | Same as A0 at double data rate | -| 0xA2 | SET EAS | MISSING | Nice to have | Enables EAS mode (password protected) | -| 0xA3 | RESET EAS | MISSING | Nice to have | Disables EAS mode | -| 0xA4 | LOCK EAS | MISSING | Nice to have | Permanently locks EAS state | -| 0xA5 | EAS ALARM | MISSING | Nice to have | Returns 256-bit EAS sequence | -| 0xA6 | PASSWORD PROTECT EAS/AFI | MISSING | Nice to have | Enables password protection for EAS/AFI | -| 0xA7 | WRITE EAS ID | MISSING | Nice to have | Writes 16-bit EAS identifier | -| 0xAB | GET NXP SYSTEM INFO | MISSING | **Must have** | Returns PP, PP conditions, lock bits, feature flags | -| 0xB2 | GET RANDOM NUMBER | OK | - | Firmware native handler | -| 0xB3 | SET PASSWORD | OK | - | Firmware native + table entries | -| 0xB4 | WRITE PASSWORD | MISSING | Should have | Changes password value (requires prior SET PASSWORD) | -| 0xB5 | LOCK PASSWORD | MISSING | Should have | Permanently locks a password | -| 0xB6 | PROTECT PAGE | MISSING | **Must have** | Sets protection pointer + access conditions | -| 0xB7 | LOCK PAGE PROTECTION | MISSING | Should have | Permanently locks protection config | -| 0xB9 | DESTROY | MISSING | Should have | Irreversibly kills tag (XOR password) | -| 0xBA | ENABLE PRIVACY | MISSING | **Must have** | Enters privacy mode (separate from SET PASSWORD) | -| 0xBB | 64-BIT PASSWORD PROTECTION | MISSING | Should have | Requires both R+W passwords | -| 0xBC | STAY QUIET PERSISTENT | MISSING | Nice to have | Persistent quiet survives power cycles | -| 0xBD | READ SIGNATURE | MISSING | **Must have** | Returns 32-byte ECC originality signature | +| 0xA0 | INVENTORY READ | OK | - | Like inventory but returns data blocks | +| 0xA1 | FAST INVENTORY READ | OK | - | Same as A0 at double data rate | +| 0xA2 | SET EAS | OK | - | Enables EAS mode (password protected) | +| 0xA3 | RESET EAS | OK | - | Disables EAS mode | +| 0xA4 | LOCK EAS | OK | - | Permanently locks EAS state | +| 0xA5 | EAS ALARM | OK | - | Returns 256-bit EAS sequence | +| 0xA6 | PASSWORD PROTECT EAS/AFI | OK | - | Enables password protection for EAS/AFI | +| 0xA7 | WRITE EAS ID | OK | - | Writes 16-bit EAS identifier | +| 0xAB | GET NXP SYSTEM INFO | OK | - | Returns PP, PP conditions, lock bits, feature flags | +| 0xB2 | GET RANDOM NUMBER | OK | - | Firmware native handler + Python model | +| 0xB3 | SET PASSWORD | OK | - | XOR password with GET_RANDOM, firmware + table entries | +| 0xB4 | WRITE PASSWORD | OK | - | Changes password value (requires prior SET PASSWORD) | +| 0xB5 | LOCK PASSWORD | OK | - | Permanently locks a password | +| 0xB6 | PROTECT PAGE | OK | - | Sets protection pointer + access conditions (requires write auth) | +| 0xB7 | LOCK PAGE PROTECTION | OK | - | Permanently locks protection config | +| 0xB9 | DESTROY | OK | - | Irreversibly kills tag (XOR password) | +| 0xBA | ENABLE PRIVACY | OK | - | Enters privacy mode (separate from SET PASSWORD, XOR password) | +| 0xBB | 64-BIT PASSWORD PROTECTION | OK | - | Requires both R+W passwords | +| 0xBC | STAY QUIET PERSISTENT | OK | - | Persistent quiet survives power cycles | +| 0xBD | READ SIGNATURE | OK | - | Returns 32-byte ECC originality signature | ### Model Issues -1. **Password ID 0x10 (EAS/AFI) missing** — datasheet lists 5 IDs: 0x01=Read, 0x02=Write, 0x04=Privacy, 0x08=Destroy, 0x10=EAS/AFI. Model only has 4. +1. ~~**Password ID 0x10 (EAS/AFI) missing**~~ — FIXED: pwd_id 0x10 now in model. -2. **Privacy mode behavior** — datasheet says tag responds to GET RANDOM NUMBER AND SET PASSWORD in privacy mode. Model only allows SET PASSWORD. +2. ~~**Privacy mode behavior**~~ — FIXED: GET_RANDOM now works in privacy mode. -3. **ENABLE PRIVACY (0xBA) is separate** from SET PASSWORD — uses XOR'd password, specifically enters privacy mode. Model conflates with SET PASSWORD pwd_id=privacy. +3. ~~**ENABLE PRIVACY (0xBA) is separate**~~ — FIXED: 0xBA implemented as dedicated command with XOR password. -4. **16-bit counter (block 79)** has special increment-only semantics via WRITE with specific data format. Not modeled. +4. ~~**16-bit counter (block 79)**~~ — FIXED: `BlockAccess.write_mode="counter"` in memory model, LE16 increment with 0xFFFF saturation. 5. **Protection pointer access conditions** — datasheet defines Page L / Page H with separate read/write protection bits (Extended Protection Status byte). Model uses simpler `protection_pointer` integer. +6. ~~**CC byte 3 MBREAD flag missing**~~ — FIXED: NFC Type 5 CC byte 3 was `0x00` (no MBREAD), causing phones to never send READ MULTIPLE BLOCKS. Real SLIX2 tags advertise `0x01` (MBREAD supported). Without this flag, Android NFC reads CC + system info then gives up — it won't fall back to READ SINGLE BLOCK for NDEF data. Fixed in `NfcType5Tag._write_cc()` for all Type 5 tags. + ### Implementation Priority -**Next session — must haves:** -1. GET NXP SYSTEM INFO (0xAB) — static response from tag config -2. READ SIGNATURE (0xBD) — static 32-byte signature -3. ENABLE PRIVACY (0xBA) — XOR password, enter privacy mode -4. EAS/AFI password (pwd_id 0x10) — add to model -5. PROTECT PAGE (0xB6) — set protection pointer via RF +**Completed (2026-03-17):** +1. ~~GET NXP SYSTEM INFO (0xAB)~~ — model + table compiler +2. ~~READ SIGNATURE (0xBD)~~ — model + table compiler +3. ~~ENABLE PRIVACY (0xBA)~~ — model + table compiler +4. ~~EAS/AFI password (pwd_id 0x10)~~ — model + table compiler +5. ~~PROTECT PAGE (0xB6)~~ — model (write auth required) +Also: Fixed 0xA1/0xA2 names (FAST INVENTORY READ / SET EAS), removed fake config registers, +fixed privacy mode to allow GET_RANDOM, SET_PASSWORD uses XOR with GET_RANDOM. -**After that — should haves:** -6. WRITE PASSWORD (0xB4) -7. LOCK PASSWORD (0xB5) -8. DESTROY (0xB9) -9. LOCK PAGE PROTECTION (0xB7) -10. 64-BIT PASSWORD PROTECTION (0xBB) +**Completed (2026-03-18):** +6. ~~WRITE PASSWORD (0xB4)~~ — model (requires prior SET PASSWORD auth, XOR password) +7. ~~LOCK PASSWORD (0xB5)~~ — model (permanently locks password, prevents WRITE PASSWORD) +8. ~~DESTROY (0xB9)~~ — model (irreversibly kills tag, XOR password, no prior auth) +9. ~~LOCK PAGE PROTECTION (0xB7)~~ — model (permanently locks PP config, requires write auth) +10. ~~64-BIT PASSWORD PROTECTION (0xBB)~~ — model (requires both read + write auth) -**Later — nice to haves:** -11-16. EAS subsystem, INVENTORY READ, STAY QUIET PERSISTENT, counter handling +**Completed (2026-03-18):** +11. ~~EAS subsystem (0xA2-0xA7)~~ — SET/RESET/LOCK EAS, EAS ALARM, PASSWORD PROTECT EAS/AFI, WRITE EAS ID +12. ~~INVENTORY READ / FAST INVENTORY READ (0xA0/0xA1)~~ — returns UID + block data +13. ~~STAY QUIET PERSISTENT (0xBC)~~ — survives power cycles + +**Completed (2026-03-18):** +14. ~~Block 79 counter~~ — `write_mode="counter"` in BlockAccess, LE16 increment with saturation at 0xFFFF + +**All SLIX2 commands implemented.** No remaining gaps. + +### Cross-IC Command Scope (2026-03-18) + +Full transponder audit against datasheets (SL2S2002, SL2S3003, SL2S6002, NTP5210, NTA5332, AN11809) found command scope issues in the class hierarchy: + +1. **SLIX (SL2S2002) had 3 excess commands** — 0xAB (GET NXP SYSTEM INFO), 0xBD (READ SIGNATURE), 0xA7 (WRITE EAS ID) were dispatched at the SLIX/NxpIcodeTag level but are SLIX2+ only per SL2S2002 datasheet and AN11809. Moved dispatch to IcodeSlix2Tag. + +2. **NTAG 5 had STAY QUIET PERSISTENT (0xBC) but shouldn't** — inherited from IcodeSlix2Tag. NTP5210 and NTA5332 datasheets omit it; feature flags confirm PERS_QUIET=0b. Blocked at Ntag5PlatformTag. + +3. **NTAG 5 was missing WRITE SRAM (0xD3)** — NTA5332 Table 122 lists it. Added to Ntag5LinkTag. + +4. **NTAG 5 was missing AREA_1 password IDs (0x40/0x80)** — NTP5210/NTA5332 datasheets list these. Added to Ntag5PlatformTag. + +5. **NTAG 5 was missing PICK RANDOM UID (0xC2)** — NTA5332 datasheet 8.2.4.9.15. Added to Ntag5PlatformTag (AES mode). + +See `docs/plans/2026-03-18-transponder-audit-fixes.md` for full audit plan. diff --git a/firmware b/firmware new file mode 160000 index 0000000..8f8b9c5 --- /dev/null +++ b/firmware @@ -0,0 +1 @@ +Subproject commit 8f8b9c51a1a58d85f6e124d0dd0708b1566ecdae