id: ecd200e242434f0abcd5e86837a1b9da
parent_id: 
item_type: 1
item_id: 445891dba8674cae8b865a6fd2a3faf1
item_updated_time: 1780902147532
title_diff: "[{\"diffs\":[[1,\"Ford EoL Key Fob Provisioning System (SCP03)\"]],\"start1\":0,\"start2\":0,\"length1\":0,\"length2\":44}]"
body_diff: "[{\"diffs\":[[1,\"## Project Overview\\\n\\\n**End-of-Line (EoL) provisioning station** that writes key material to NFC key fobs using **Secure Channel Protocol 03 (SCP03)**. Built in **Rust** for **Windows**, communicating with industrial-grade NFC readers via USB.\\\n\\\n| Detail | Value |\\\n|---|---|\\\n| OEM | Ford |\\\n| KLMS | SecOps \\\"Clypeum\\\" |\\\n| Language | Rust |\\\n| Target OS | Windows |\\\n| Protocol | GlobalPlatform SCP03 |\\\n| Smart Card Platform | JCOP 4 |\\\n| Hardware | Industrial NFC reader via USB (CCID) |\\\n\\\n---\\\n\\\n## Architecture\\\n\\\n### Final System Architecture\\\n\\\nThe EoL station is a **lean APDU pipeline**:\\\n\\\n1. Read fob UID via `pcsc`\\\n2. POST UID to Clypeum KLMS via REST API (mTLS)\\\n3. KLMS returns pre-diversified static keys + Ford's payload\\\n4. Perform session KDF (Phase 2) in software\\\n5. SCP03 wrap → inject key material → lock ISD → zeroize memory\\\n\\\n### Key Design Decision: KLMS Does All KDF\\\n\\\nThe architecture evolved from local Nitrokey HSM-based key derivation to having the **Clypeum KLMS server perform all KDF**. The EoL station is considered an untrusted factory floor environment.\\\n\\\n**Phase 1 (NXP KDF3)** — Performed by Clypeum inside their HSM:\\\n- Master Key → S-ENC, S-MAC, S-DEK using AES-CMAC\\\n- Labels: `00000001` (ENC), `00000002` (MAC), `00000003` (DEK)\\\n- Context: 10-byte JCOP UID\\\n- Key length: `0080` (128-bit)\\\n\\\n**Phase 2 (GP SCP03)** — Performed by EoL station in RAM:\\\n- Static keys → Session keys (SES-ENC, SES-MAC, SES-RMAC) using AES-CMAC\\\n- Context: `SeqCnt(3 bytes) || RND.IC(8 bytes) || RND.CC(8 bytes)`\\\n\\\n---\\\n\\\n## SCP03 Protocol Flow\\\n\\\n### Step 1: INITIALIZE UPDATE\\\n- Command: `80 50 00 00 08 [Key Version] 00 00 00`\\\n- Response contains: Host Challenge (RND.IC), Card Challenge (RND.CC), Key Info, Sequence Counter (SeqCnt)\\\n\\\n### Step 2: Derive Session Keys\\\n- SES-ENC, SES-MAC, SES-RMAC derived from static keys + SeqCnt + RND.IC + RND.CC\\\n- Uses AES-CMAC (RustCrypto `cmac` crate)\\\n\\\n### Step 3: EXTERNAL AUTHENTICATE\\\n- Calculate Host Cryptogram: `AES-CMAC(S-MAC, RND.IC || RND.CH || RND.CC)`\\\n- Wrap APDU: encrypt data with S-ENC (AES-CBC, ISO 9797-1 Method 2 padding), append MAC with S-MAC\\\n- Command: `84 82 00 00 [Lc] [Encrypted Data] [MAC]`\\\n- Success: `90 00`\\\n\\\n### Step 4: Secure Messaging (Wrap/Unwrap)\\\nFor every subsequent APDU:\\\n1. Increment local Sequence Counter\\\n2. Pad payload (ISO 9797-1 Method 2)\\\n3. Encrypt with SES-ENC (AES-CBC, IV=0)\\\n4. Calculate MAC over header + encrypted payload using SES-MAC\\\n5. Append MAC\\\n\\\n### Step 5: Key Injection\\\n- Send Ford's payload via STORE DATA (`80 DA ...`) or PUT KEY (`80 D8 ...`) APDU\\\n- Must be SCP03-wrapped\\\n\\\n### Step 6: ISD Lock (Defense-in-Depth)\\\n- Lock Issuer Security Domain: `80 F0 0F 00 00` (SCP03-wrapped)\\\n- Cryptographically invalidates static keys\\\n- Makes RAM exposure window (~400ms) negligible\\\n\\\n---\\\n\\\n## KLMS API Contract\\\n\\\n### Request (EoL → Clypeum)\\\n```json\\\n{\\\n  \\\"fob_uid\\\": \\\"112233445566778899AA\\\",\\\n  \\\"reader_id\\\": \\\"LINE_04_READER_01\\\"\\\n}\\\n```\\\n\\\n### Response (Clypeum → EoL)\\\n```json\\\n{\\\n  \\\"transaction_id\\\": \\\"trx_889900\\\",\\\n  \\\"key_version\\\": 3,\\\n  \\\"scp03_static_keys\\\": {\\\n    \\\"enc\\\": \\\"A1B2C3D4E5F600A1B2C3D4E5F60011\\\",\\\n    \\\"mac\\\": \\\"A1B2C3D4E5F600A1B2C3D4E5F60022\\\",\\\n    \\\"dek\\\": \\\"A1B2C3D4E5F600A1B2C3D4E5F60033\\\"\\\n  },\\\n  \\\"ford_payload\\\": {\\\n    \\\"apdu_cla_ins_p1_p2\\\": \\\"80DA0100\\\",\\\n    \\\"data_hex\\\": \\\"F1E2D3...\\\"\\\n  }\\\n}\\\n```\\\n\\\n### Audit Response (EoL → Clypeum)\\\n```json\\\n{\\\n  \\\"transaction_id\\\": \\\"trx_889900\\\",\\\n  \\\"fob_uid\\\": \\\"11223344556677\\\",\\\n  \\\"timestamp_iso8601\\\": \\\"2023-10-27T14:32:01.123Z\\\",\\\n  \\\"overall_result\\\": \\\"SUCCESS\\\",\\\n  \\\"stage_reached\\\": \\\"PAYLOAD_DELIVERY\\\",\\\n  \\\"apdu_trace\\\": [\\\n    {\\\"direction\\\": \\\"TX\\\", \\\"apdu_hex\\\": \\\"8050000008000300000000\\\"},\\\n    {\\\"direction\\\": \\\"RX\\\", \\\"apdu_hex\\\": \\\"0000314A2B3C...9000\\\", \\\"sw1\\\": \\\"90\\\", \\\"sw2\\\": \\\"00\\\"}\\\n  ],\\\n  \\\"eol_station_id\\\": \\\"LINE-04-PC-12\\\"\\\n}\\\n```\\\n\\\n---\\\n\\\n## Roles & Responsibilities\\\n\\\n| Role | Entity | Responsibility |\\\n|---|---|---|\\\n| OEM | Ford | Provides application data to be stored on fob |\\\n| Card Issuer | Supplier (us) | Manages SCP03 channel keys, provisions card, locks ISD |\\\n| KLMS | SecOps (Clypeum) | Stores master keys, performs KDF, delivers static keys + payload |\\\n| EoL Station | Our Rust app | PC/SC pipe, session KDF, SCP03 state machine, audit reporting |\\\n\\\nFord has **no involvement** in card management keys.\\\n\\\n---\\\n\\\n## Key Diversification (JCOP 4)\\\n\\\n> **Reference:** [NXP AN10922 — Symmetric Key Diversifications](https://www.nxp.com/docs/en/application-note/AN10922.pdf)\\\n\\\n### KDF3 Input Structure (Phase 1)\\\n```\\\n[Counter: 01] || [Label: 00 00 00 01/02/03] || [Separator: 00] || [Context: 10-byte UID] || [Length: 00 80]\\\n```\\\n\\\n### Session Key Context (Phase 2)\\\n```\\\nSeqCnt (3 bytes) || RND.IC (8 bytes) || RND.CC (8 bytes)\\\n```\\\n\\\nThe 10-byte UID from JCOP is only part of the diversification data. Remaining bytes are **issuer-defined** (Ford/security policy) and can include random nonces, batch IDs, or system constants. Must be consistent between KLMS and card.\\\n\\\n---\\\n\\\n## NFC Reader Recommendations\\\n\\\n### Development\\\n- **ACS ACR1252U** — Widely compatible, CCID compliant, successor to end-of-life ACR122U\\\n- **ACS ACR1255U-J1** — Compact alternative\\\n\\\n### Production (Industrial Grade)\\\n- **ACS ACR1281U-C1 DualBoost II** — Dual-interface (contact/contactless), ISO 7816 + ISO 14443, 24/7 rated\\\n- **HID OMNIKEY 5027 CL** — Enterprise/industrial durability, CCID compliant\\\n\\\n### Selection Criteria\\\n- CCID compliance (generic Windows driver, no vendor drivers)\\\n- ISO 14443 A/B support\\\n- Extended Length APDU support (most industrial readers support this)\\\n- Panel-mount form factor for production\\\n\\\n---\\\n\\\n## Rust Technology Stack\\\n\\\n| Crate | Purpose |\\\n|---|---|\\\n| `pcsc` | Windows Smart Card API (WinSCard.dll) |\\\n| `aes` | AES encryption (RustCrypto) |\\\n| `cmac` | AES-CMAC for key derivation and MACing |\\\n| `cbc` | AES-CBC for APDU encryption |\\\n| `serde` / `serde_json` | KLMS JSON parsing |\\\n| `reqwest` | KLMS REST API client (with mTLS) |\\\n| `zeroize` | Secure memory wiping after ISD lock |\\\n| `hex` | APDU debugging |\\\n| `tracing` | Structured logging |\\\n\\\n### Key Code: Memory Zeroization\\\n```rust\\\nuse zeroize::Zeroize;\\\n\\\nstruct CardStaticKeys {\\\n    s_enc: [u8; 16],\\\n    s_mac: [u8; 16],\\\n    s_dek: [u8; 16],\\\n}\\\n\\\nimpl Zeroize for CardStaticKeys {\\\n    fn zeroize(&mut self) {\\\n        self.s_enc.zeroize();\\\n        self.s_mac.zeroize();\\\n        self.s_dek.zeroize();\\\n    }\\\n}\\\n```\\\n\\\n### Key Code: Session Key Derivation\\\n```rust\\\nuse aes::Aes128;\\\nuse cmac::{Cmac, Mac};\\\n\\\ntype Aes128Cmac = Cmac<Aes128>;\\\n\\\nlet mut mac = Aes128Cmac::new_from_slice(&s_enc).unwrap();\\\nmac.update(&build_kdf3_input(Label::Enc, &session_context));\\\nlet ses_enc = mac.finalize().into_bytes();\\\n```\\\n\\\n---\\\n\\\n## Error Handling (APDU Status Words)\\\n\\\n| SW1/SW2 | Meaning | Action |\\\n|---|---|---|\\\n| `90 00` | Success | Proceed |\\\n| `69 82` | Security status not satisfied | Halt — wrong key/MAC. Flag for review. |\\\n| `6A 86` | Incorrect P1/P2 | Halt — bug in APDU construction |\\\n| `67 00` | Wrong length | Halt — bug in APDU construction |\\\n| `6D 00` | Instruction not supported | Halt — wrong applet selected? |\\\n| `65 81` | Memory failure | Halt — defective card |\\\n| `63 CX` | Verify fail, X retries left | Analyze — `63 C0` = permanently locked |\\\n\\\n---\\\n\\\n## Windows-Specific Considerations\\\n\\\n- Use **generic Windows CCID driver** (`infocard.dll`) — do not install vendor proprietary drivers\\\n- Handle `Error::RemovedCard` gracefully for flaky NFC fields\\\n- Standard APDU max = 255 bytes; use Extended Length APDUs if payload is larger\\\n- Sequence counter is 3 bytes, Big-Endian (watch for byte order bugs)\\\n\\\n---\\\n\\\n## Items to Confirm with SecOps/Clypeum\\\n\\\n- [ ] REST API contract (request/response JSON format)\\\n- [ ] Mutual TLS (mTLS) for KLMS↔EoL network link\\\n- [ ] Exact NXP KDF3 byte layout (UID padding: raw, left-padded, or right-padded)\\\n- [ ] Exact APDU for Ford's data injection (STORE DATA vs PUT KEY)\\\n- [ ] Key Version strategy (how to know which version the fob expects)\\\n- [ ] Audit payload format and Ford compliance requirements\\\n- [ ] TTL on issued key packages (recommended: 5 seconds)\\\n- [ ] KLMS logging and audit trail capabilities\\\n\\\n---\\\n\\\n## Development Sequence\\\n\\\n1. Procure **ACS ACR1252U** for dev; **ACR1281U-C1** and **HID OMNIKEY 5027 CL** for production eval\\\n2. Build minimal Rust CLI using `pcsc` — connect to reader, send SELECT/GET DATA APDU\\\n3. Implement session key derivation (Phase 2) with unit tests against GlobalPlatform test vectors\\\n4. Implement full SCP03 state machine: INITIALIZE UPDATE → session keys → EXTERNAL AUTHENTICATE → secure messaging\\\n5. Integrate KLMS REST API client (`reqwest` with mTLS)\\\n6. Implement ISD locking and memory zeroization\\\n7. End-to-end test on both development and production readers\\\n\\\n---\\\n\\\n*Source: Z.ai chat session (2025-06-08)*\"]],\"start1\":0,\"start2\":0,\"length1\":0,\"length2\":8581}]"
metadata_diff: {"new":{"id":"445891dba8674cae8b865a6fd2a3faf1","parent_id":"283dd54f183a4ce69366648f091336d1","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":1780901497561,"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-06-08T07:03:34.052Z
created_time: 2026-06-08T07:03:34.052Z
type_: 13