id: 0392390150144b75bc6271079e36028c
parent_id: 
item_type: 1
item_id: bb3506f46ead40df8a7f965a73339928
item_updated_time: 1786695124640
title_diff: "[{\"diffs\":[[1,\"Keyfob Station — Code Audit Open Items\"]],\"start1\":0,\"start2\":0,\"length1\":0,\"length2\":38}]"
body_diff: "[{\"diffs\":[[1,\"# Keyfob Station — Code Audit Open Items\\\n\\\nLast updated: 2026-08-14\\\n\\\nTwo full workspace audits completed. 80+ issues found and fixed across both rounds.\\\nRemaining items below.\\\n\\\n## KLMS Team Action Required\\\n\\\nThese cannot be fixed on our side without KLMS changes:\\\n\\\n| # | Issue | What's needed |\\\n|---|-------|---------------|\\\n| C1 | `danger_accept_invalid_certs(true)` in klms_client.rs | CA cert returns BadSignature — need correct root CA or fix the cert chain |\\\n| M5 | Heuristic EC scalar extraction (`04 20` scan) in worker.rs | KLMS should provide raw PKCS#8 DER or pre-encrypted 48-byte scalar (AES-128-ECB + ISO 9797-1 M2) instead of the current AES-128-CBC encrypted full DER (144 bytes) |\\\n| M10 | B252 dev DEK used to decrypt+re-encrypt KLMS private key | Once M5 is fixed (KLMS provides correct format), remove `prepare_klms_private_key()` and `b252_dek()` from the KLMS path entirely |\\\n\\\n**Private key format issue (M5/M10 detail):**\\\n\\\nThe KLMS currently provides field[8] as 144 bytes of AES-128-CBC encrypted PKCS#8 DER\\\n(IV=0, S-DEK key, PKCS7 padding). The card expects 48 bytes of AES-128-ECB encrypted\\\n32-byte EC scalar (ISO 9797-1 M2 padding). Three mismatches:\\\n\\\n- Content: full PKCS#8 DER (138 bytes) vs 32-byte scalar\\\n- Encryption: AES-128-CBC (chained) vs AES-128-ECB (independent blocks)\\\n- Padding: PKCS7 (`06 06 06 06 06 06`) vs ISO 9797-1 M2 (`80 00 00...`)\\\n- Size: 144 bytes vs 48 bytes\\\n\\\nFix: KLMS provides field[8] as already DEK-encrypted 48-byte scalar (AES-128-ECB + M2) — we forward as-is.\\\n\\\n## Documented as Intentional (won't fix)\\\n\\\n| # | Issue | Resolution |\\\n|---|-------|------------|\\\n| H1 | IAM auth sends empty username/password (`grant_type=password`, `username=\\\"\\\"`, `password=\\\"\\\"`) | Commented in klms_client.rs — `ccs` is a public client, auth via mTLS only, matches Clypeum reference |\\\n| H4 | Hand-rolled RSA signature verification (textbook `sig^e mod n`) | Commented in container_parser.rs — Clypeum container format defines textbook RSA, not PKCS#1 v1.5 |\\\n| M17 | Wrapper key KDF reverse-engineered (NIST 800-108 with zero LABEL/CONTEXT) | Commented in container_parser.rs — works correctly, not formally spec-verified. Constants documented for traceability |\\\n\\\n## Deferred — High-Risk Refactoring (assessed 2026-08-14, not actionable as quick wins)\\\n\\\nThese need a dedicated session with comprehensive testing:\\\n\\\n| # | Issue | Assessment |\\\n|---|-------|------------|\\\n| H7 | SCP03 handshake duplicated 5× (scp03_setup, provision/lib, klms.rs, worker.rs, nfc_reader.rs) | **8 instances found.** Only 2 delegate to `scp03_setup::establish()`. Worker can't delegate without API changes (needs session keys exposed). KLMS paths inherently different (no local derivation). ISD SELECT has 3 variants (empty-data, explicit-AID, both) — cosmetic only. |\\\n| M20 | God functions: `run_klms_auto_provision_inner` (231 lines), `run_production` (219 lines), `Provisioner::run_inner` (193 lines), `KlmsProvisioner::run_inner` (165 lines), `StationApp::update` (149 lines) | Decomposition risks breaking critical SCP03/provisioning flow. `run_production` is the safest target (clean phase separation). |\\\n| H2 | Audit trace doc mismatch (doc claims redaction, code stores full APDU) | **RESOLVED 2026-08-14** — doc updated to match reality. Nothing is secret in SCP03-wrapped communication. |\\\n\\\n## Functional Items (within our control)\\\n\\\n| # | Issue | Status |\\\n|---|-------|--------|\\\n| — | NFC poll interval | Already at 100ms (`MONITOR_POLL_INTERVAL` in pcsc.rs:25) |\\\n| — | Session key logging in nfc_reader.rs | **RESOLVED 2026-08-14** — S-ENC, S-MAC, S-RMAC, Host Cryptogram now redacted. Encrypted private key shown; plaintext scalar redacted. |\\\n| — | Audit trace doc (H2) | **RESOLVED 2026-08-14** — doc updated, no redaction needed |\\\n| — | `report_usage` not wired into KLMS flow | Open — method exists in klms_client.rs but nfc_reader auto-provision never calls it |\\\n| — | KLMS provisioning fails (6A 80 on DGI A003) | Open — workaround (decrypt CBC → extract scalar → DEK encrypt) runs but card still rejects. Files flow with same Provisioner/DEK works. May be KLMS key format issue (M5). |\\\n\\\n## Cosmetic (acknowledged, no action)\\\n\\\n- `kf-provision/lib.rs` has local `KF_APPLET_SELECT_AID` copy (can't import from kf-dev-station — dependency direction)\\\n- `STATIC_KEY_TABLE` in kf-klms duplicates dev_profiles.toml (intentional for test isolation)\\\n- ISD SELECT inconsistency (3 variants) — cosmetic, all work on JCOP\"]],\"start1\":0,\"start2\":0,\"length1\":0,\"length2\":4432}]"
metadata_diff: {"new":{"id":"bb3506f46ead40df8a7f965a73339928","parent_id":"c924c03f3d2f4ff8af7fc876083ef4cb","latitude":"0.00000000","longitude":"0.00000000","altitude":"0.0000","author":"","source_url":"","is_todo":0,"todo_due":0,"todo_completed":0,"source":"joplin-desktop","source_application":"net.cozic.joplin-desktop","application_data":"","order":1786652374178,"markup_language":1,"is_shared":0,"share_id":"","conflict_original_id":"","master_key_id":"","user_data":"","deleted_time":0},"deleted":[]}
encryption_cipher_text: 
encryption_applied: 0
updated_time: 2026-08-14T08:20:00.269Z
created_time: 2026-08-14T08:20:00.269Z
is_locked: 0
type_: 13