id: e1b86b15c63643eeae519a63b65d7e4f
parent_id: 1968143690504d698c5e3e66eaf48339
item_type: 1
item_id: 445891dba8674cae8b865a6fd2a3faf1
item_updated_time: 1781533905984
title_diff: "[]"
body_diff: "[{\"diffs\":[[0,\"26-06-15\"],[1,\", rev 2\"],[0,\")\\\n\\\nA 7-c\"]],\"start1\":595,\"start2\":595,\"length1\":16,\"length2\":23},{\"diffs\":[[0,\"pace\"],[-1,\" has been implemented and committed (`0e0243b`)\"],[0,\". Ev\"]],\"start1\":633,\"start2\":633,\"length1\":55,\"length2\":8},{\"diffs\":[[0,\"plet. **\"],[-1,\"54\"],[1,\"63\"],[0,\" unit te\"]],\"start1\":720,\"start2\":720,\"length1\":18,\"length2\":18},{\"diffs\":[[0,\"clean.**\"],[1,\" The pipeline now mirrors the **real JCShell provisioning flow** (DGI-based STORE DATA with lifecycle transition).\"],[0,\"\\\n\\\n### Wo\"]],\"start1\":782,\"start2\":782,\"length1\":16,\"length2\":130},{\"diffs\":[[0,\"builders\"],[1,\" (STORE DATA E2, lifecycle transition)\"],[0,\" | ✅ Don\"]],\"start1\":1168,\"start2\":1168,\"length1\":16,\"length2\":54},{\"diffs\":[[0,\"pApplet`\"],[1,\" (C-MAC only, lifecycle states)\"],[0,\" | ✅ Don\"]],\"start1\":1425,\"start2\":1425,\"length1\":16,\"length2\":47},{\"diffs\":[[0,\"gSource`\"],[1,\", **`FileContainerSource`**\"],[0,\" | ✅ Don\"]],\"start1\":1559,\"start2\":1559,\"length1\":16,\"length2\":43},{\"diffs\":[[0,\"tRecord`\"],[1,\" + **`perso` module (DGI encoding + block splitting + S-DEK encryption)**\"],[0,\" | ✅ Don\"]],\"start1\":1659,\"start2\":1659,\"length1\":16,\"length2\":89},{\"diffs\":[[0,\".\\\n- \"],[-1,\"Simulated JCOP applet handles the complete handshake + STORE DATA / PUT KEY / SET STATUS\"],[1,\"**DGI-based personalization flow** matching the real JCShell script: encode items as DGIs → S-DEK encrypt private key → split into 245-byte blocks → STORE DATA (INS=E2) with incrementing P2 → lifecycle transition (P1=0x80) → raw post-personalization commands.\\\n- **Container directory parser** reads `FESN.txt`, `irk_keyfob.key` (base64), `keyfob_private.der` (PKCS#8 EC scalar extraction), `keyfob_public.der` (device cert) → builds `ProvisioningInput`.\\\n- Simulated JCOP applet: C-MAC only mode, DGI data buffering, lifecycle transition to FACTORY, raw post-perso command acceptance\"],[0,\".\\\n- \"]],\"start1\":2052,\"start2\":2052,\"length1\":96,\"length2\":590},{\"diffs\":[[0,\"ock \"],[-1,\"(54\"],[1,\"+ real fixture data (63\"],[0,\" tes\"]],\"start1\":2675,\"start2\":2675,\"length1\":11,\"length2\":31},{\"diffs\":[[0,\"enge\"],[-1,\" (`getrandom`)\"],[0,\", co\"]],\"start1\":2761,\"start2\":2761,\"length1\":22,\"length2\":8},{\"diffs\":[[0,\"ares\"],[-1,\" (`ct_eq`)\"],[0,\", ze\"]],\"start1\":2785,\"start2\":2785,\"length1\":18,\"length2\":8},{\"diffs\":[[0,\"il.\\\n\"],[-1,\"- Audit records carry real ISO-8601 UTC timestamps + typed error cause.\\\n\\\n### Stubbed Behind Traits (pending external decisions / hardware)\\\n- **File container parser** — `ProvisioningSource` trait ready; awaits sample containers.\"],[1,\"\\\n### Stubbed Behind Traits (pending external decisions / hardware)\"],[0,\"\\\n- *\"]],\"start1\":2836,\"start2\":2836,\"length1\":236,\"length2\":74},{\"diffs\":[[0,\"ardware.\"],[1,\"\\\n- **ICA/Root certificates (DGI A004/A005)** — not in per-fob container; need source (fixed config or DLL/SO).\"],[0,\"\\\n\\\n### Bu\"]],\"start1\":3147,\"start2\":3147,\"length1\":16,\"length2\":126},{\"diffs\":[[0,\"teps\"],[-1,\" (awaiting input)\\\n1. **File container + JCShell script** — user will provide container(s) of provisioning content and the JCShell script(s) that provision them. These will drive the `FileC\"],[1,\"\\\n1. **Real-card validation** — run the pipeline against a real JCOP 4.5 sample to validate the SCP03 test vector and the R-ENC path.\\\n2. **ICA/Root cert source** — determine where DGI A004/A005 certificates come from (factory-wide c\"],[0,\"on\"],[1,\"s\"],[0,\"ta\"],[-1,\"inerSource` implementation and confirm the exact APDU sequence / lock command.\\\n2\"],[1,\"nts, DLL/SO, or KLMS).\\\n3. **DLL/SO content provider** — implement once the interface spec is available.\\\n4\"],[0,\". **\"],[-1,\"Real-card validation** — run the pipeline against a real JCOP 4.5 sample to validate the self-derived SCP03 test vector and the R-ENC path.\\\n\\\n---\\\n\\\n## Contacts & Escalation\\\n\\\n| Area | Contact |\\\n|---|---|\\\n| IT | Tony |\\\n| Technical Topics | Ashish |\\\n| Project Questions | Onoyom |\\\n| Manufacturing | Daniel |\\\n| SW Development | Mindu |\\\n| Escalation | John, Abdel |\\\n| Ford IVSS | Mustafa, Antony Mihalopulous |\\\n| Project CS | Joe |\\\n\\\n---\\\n\\\n## Development Samples (OEF B212)\\\n\\\nDevelopment samples arrive with **OEF B212** and a **pre-defined static SCP03 key set** already loaded on the chip.\\\n\\\n- No KLMS key diversification needed for dev samples — use the known static keys directly\\\n- Only **Phase 2** (session key derivation) is requi\"],[1,\"KLMS REST client** — implement once the API contract is finalized.\\\n\\\n---\\\n\\\n## JCShell Provisioning Flow (from reference script)\\\n\\\n### Key Parameters\\\n\\\n| Parameter | Value |\\\n|---|---|\\\n| Applet AID | `A000000857` |\\\n| Key Version | 255 (0xFF) |\\\n| Security Level | C-MAC only (`auth mac`, P1=0x01 in EXTERNAL AUTHENTICATE) |\\\n| S-ENC | `8b4b8d7ec45dfa503a35f6df8f6bbdd9` |\\\n| S-MAC | `42fd95e83821260c5b90463af7996313` |\\\n| S-DEK | `1b988a47ac94632f7020734ca172eed8` |\\\n\\\n### DGI Tags & Personalization Items\\\n\\\n| DGI | Description | Data | Encrypted |\\\n|---|---|---|---|\\\n| `A003` | Private key scalar (P-256) | 32 bytes → AES-CBC(S-DEK, M2 pad) → 48 bytes | Yes (S-DEK) |\\\n| `A001` | SPID | ASCII hex string (40 bytes = 20-byte hash as text) | No |\\\n| `A002` | Device certificate | DER (424 bytes) | No |\\\n| `A004` | ICA certificate | DER (~435 bytes) | No |\\\n| `A005` | CMS/Root certificate | DER (~722 bytes) | No |\\\n| `A006` | BLE IRK | 16 bytes | No |\\\n\\\n### DGI Wire Encoding\\\n\\\n```\\\nTAG(2 bytes) || length || data\\\n```\\\n\\\nLength encoding:\\\n- `< 255`: 1-byte direct length (0x00–0xFE)\\\n- `≥ 255`: `0xFF` + 2-byte big-endian length\\\n\\\n### STORE DATA Block Protocol\\\n\\\n- **INS = 0xE2** (not 0xDA)\\\n- **P1**: `0x00` = normal block, `0x80` = last block (lifecycle transition)\\\n- **P2**: global incrementing block counter (starts at 0x00)\\\n- **Max block data**: 245 bytes (255-byte short APDU limit − 8-byte MAC − 2-byte slack)\\\n- Large DGIs split: first block carries DGI header, continuation blocks carry raw data\\\n- **Lifecycle transition**: final STORE DATA with `P1=0x80`, empty data → applet transitions to FACTORY state\\\n\\\n### S-DEK Pre-Encryption (for DGI A003)\\\n\\\nPrivate key scalar is encrypted **before** DGI wrapping:\\\n1. Pad 32-byte scalar with ISO 9797-1 Method 2 → 48 bytes\\\n2. AES-CBC encrypt with S-DEK, IV = all zeros\\\n3. Result (48 bytes) becomes the DGI A003 payload\\\n\\\n### Post-Personalization Commands\\\n\\\nAfter lifecycle transition, raw (non-SM) commands re-configu\"],[0,\"re\"],[-1,\"d\"],[0,\" t\"],[-1,\"o establish the SCP03 channel\\\n- Use these samples f\"],[1,\"he applet:\\\n```\\\n00 DB 00 00 03 0A 01 01   — enable UICC transport\\\n00 DB 00 00 03 0B 01 01   — enable BLE transport\\\n```\\\n\\\n---\\\n\\\n## Container Directory Format\\\n\\\nEach fob's provisioning data arrives as a direct\"],[0,\"or\"],[1,\"y\"],[0,\":\\\n\"],[-1,\"  - Validating INITIALIZE UPDATE / EXTERNAL AUTHENTICATE flow\\\n  - Testing secure messaging wrap/unwrap\\\n  - Verifying APDU construction before production key infrastructure is ready\\\n\\\n> T\"],[1,\"\\\n| File | Format | Content | DGI |\\\n|---|---|---|---|\\\n| `FESN.txt` | ASCII (8 bytes) | Serial number (e.g. `1KM0001E`) | — (dir name component) |\\\n| `irk_keyfob.key` | Base64 (24 chars) | BLE IRK (16 bytes decoded) | `A006` |\\\n| `keyfob_private.der` | DER (138 bytes) | PKCS#8 EC P-256 private key | `A003` (scalar extracted, S-DEK encrypted) |\\\n| `keyfob_public.der` | DER (424 bytes) | Device certificate | `A002` |\\\n\\\nDirectory name format: `<FESN>-<SPID_HEX>` where `<SPID_HEX>` is a 40-char \"],[0,\"he\"],[1,\"x\"],[0,\" st\"],[-1,\"atic key set for OEF B212 must be obtained from the card issuer / NXP delivery package and stored securely for development use\"],[1,\"ring used as the DGI `A001` payload (stored as ASCII hex bytes, not raw binary).\\\n\\\n**Private key scalar extraction**: In PKCS#8 DER, the 32-byte scalar appears as `OCTET STRING(04) || length(20) || 32 bytes`. We scan for the `04 20` byte pair, unique in this encoding.\\\n\\\n**IRK decoding**: Base64 standard alphabet → 16 raw bytes\"],[0,\".\\\n\\\n-\"]],\"start1\":3603,\"start2\":3603,\"length1\":1385,\"length2\":3324},{\"diffs\":[[0,\"ect \"],[-1,\"key material → lock ISD\"],[1,\"DGI personalization data → lifecycle transition\"],[0,\" → z\"]],\"start1\":7225,\"start2\":7225,\"length1\":31,\"length2\":55},{\"diffs\":[[0,\" 50 \"],[-1,\"00\"],[1,\"<KVN>\"],[0,\" 00 08 \"],[-1,\"[Key Version] 00 00 00`\\\n- Response contains: Host Challenge (RND.IC), Card C\"],[1,\"<Host_Challenge(8)>`\\\n- Response (S8 mode): `div(10) || key_info(1) || seq_counter(3) || KVN(2) || card_c\"],[0,\"hallenge\"],[-1,\" (RND.CC), Key Info, Sequence Counter (SeqCnt)\"],[1,\"(8) || card_cryptogram(8)`\"],[0,\"\\\n\\\n##\"]],\"start1\":8216,\"start2\":8216,\"length1\":147,\"length2\":158},{\"diffs\":[[0,\"CMAC\"],[-1,\" (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),\"],[1,\"\\\n- Derivation constants: S-ENC=0x04, S-MAC=0x06, S-RMAC=0x07\\\n\\\n### Step 3: EXTERNAL AUTHENTICATE (C-MAC only)\\\n- P1 = 0x01 (C-MAC only security level)\\\n- Calculate Host Cryptogram: `AES-CMAC(S-MAC, derivation_block)`\\\n- Wrap APDU: MAC\"],[0,\" append\"],[-1,\" MAC\"],[1,\"ed\"],[0,\" wit\"]],\"start1\":8496,\"start2\":8496,\"length1\":232,\"length2\":247},{\"diffs\":[[0,\"-MAC\"],[-1,\"\\\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\"],[1,\" chaining\\\n- Success: `90 00`\\\n\\\n### Step 4: Secure Messaging — STORE DATA (INS = E2)\\\n- Each DGI encoded: `TAG(2) || length || data`\\\n- Optional S-DEK pre-encryption for private key DGIs\\\n- Split into 245-byte blocks\\\n- SCP03 C-MAC wrap each block\\\n- P2 = incrementing global counter\\\n\\\n### Step 5: Lifecycle Transition\\\n- Final STORE DATA: `84 E2 80 <P2> 00` (P1=0x80, empty data)\\\n- Applet transitions UNPERSONALIZED → FACTORY\\\n\\\n### Step 6: Post-Personalization (Raw, No SM)\\\n- Re-configure transport modes via `00 DB 00 00` commands\\\n- Sent outside the SCP03 secure channel\"],[0,\"\\\n\\\n--\"]],\"start1\":8746,\"start2\":8746,\"length1\":670,\"length2\":570},{\"diffs\":[[0,\"\\\n  \\\"\"],[-1,\"ford_payload\\\": {\\\n    \\\"apdu_cla_ins_p1_p2\\\": \\\"80DA0100\\\",\\\n    \\\"data_hex\\\": \\\"F1E2D3...\\\"\\\n  }\"],[1,\"personalization_items\\\": [\\\n    {\\\"dgi\\\": \\\"a003\\\", \\\"data\\\": \\\"EE0783A0...\\\", \\\"encrypt_with_dek\\\": true},\\\n    {\\\"dgi\\\": \\\"a001\\\", \\\"data\\\": \\\"3539393138...\\\", \\\"encrypt_with_dek\\\": false}\\\n  ],\\\n  \\\"post_perso_commands\\\": [\\\n    {\\\"cla\\\": 0, \\\"ins\\\": 219, \\\"p1\\\": 0, \\\"p2\\\": 0, \\\"data\\\": \\\"0A0101\\\"}\\\n  ]\"],[0,\"\\\n}\\\n`\"]],\"start1\":9714,\"start2\":9714,\"length1\":94,\"length2\":274},{\"diffs\":[[0,\"\\\"202\"],[-1,\"3-10-27\"],[1,\"6-06-15\"],[0,\"T14:\"]],\"start1\":10125,\"start2\":10125,\"length1\":15,\"length2\":15},{\"diffs\":[[0,\": \\\"P\"],[-1,\"AYLOAD_DELIVERY\"],[1,\"OST_PERSONALIZATION\"],[0,\"\\\",\\\n \"]],\"start1\":10197,\"start2\":10197,\"length1\":23,\"length2\":27},{\"diffs\":[[0,\"}\\\n```\\\n\\\n---\\\n\\\n\"],[1,\"## Provisioning Pipeline Stages\\\n\\\n| Stage | Description |\\\n|---|---|\\\n| `ReadUid` | Read fob UID from transport |\\\n| `FetchKeys` | Fetch static keys + personalization items from source |\\\n| `InitializeUpdate` | SCP03 INITIALIZE UPDATE |\\\n| `ExternalAuthenticate` | SCP03 EXTERNAL AUTHENTICATE (C-MAC) |\\\n| `PayloadDelivery` | STORE DATA blocks with DGI personalization data |\\\n| `LifecycleTransition` | Final STORE DATA P1=0x80 → FACTORY |\\\n| `PostPersonalization` | Raw commands (enable transports) |\\\n\\\n---\\\n\\\n## Contacts & Escalation\\\n\\\n| Area | Contact |\\\n|---|---|\\\n| IT | Tony |\\\n| Technical Topics | Ashish |\\\n| Project Questions | Onoyom |\\\n| Manufacturing | Daniel |\\\n| SW Development | Mindu |\\\n| Escalation | John, Abdel |\\\n| Ford IVSS | Mustafa, Antony Mihalopulous |\\\n| Project CS | Joe |\\\n\\\n---\\\n\\\n## Development Samples (OEF B212)\\\n\\\nDevelopment samples arrive with **OEF B212** and a **pre-defined static SCP03 key set** already loaded on the chip.\\\n\\\n- No KLMS key diversification needed for dev samples — use the known static keys directly\\\n- Only **Phase 2** (session key derivation) is required to establish the SCP03 channel\\\n- Use these samples for:\\\n  - Validating INITIALIZE UPDATE / EXTERNAL AUTHENTICATE flow\\\n  - Testing secure messaging wrap/unwrap\\\n  - Verifying APDU construction before production key infrastructure is ready\\\n\\\n---\\\n\\\n\"],[0,\"## Roles & R\"]],\"start1\":10430,\"start2\":10430,\"length1\":24,\"length2\":1349},{\"diffs\":[[0,\"--\\\n\\\n\"],[-1,\"## 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\"],[0,\"## R\"]],\"start1\":12892,\"start2\":12892,\"length1\":635,\"length2\":8},{\"diffs\":[[0,\"ecode |\\\n\"],[1,\"| `base64` | BLE IRK decoding from container files |\\\n\"],[0,\"| `traci\"]],\"start1\":13372,\"start2\":13372,\"length1\":16,\"length2\":69},{\"diffs\":[[0,\"--\\\n\\\n\"],[-1,\"## 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\"],[0,\"## I\"]],\"start1\":14129,\"start2\":14129,\"length1\":361,\"length2\":8},{\"diffs\":[[0,\"-padded)\\\n- [\"],[-1,\" \"],[1,\"x\"],[0,\"] \"],[1,\"~~\"],[0,\"Exact APDU f\"]],\"start1\":14352,\"start2\":14352,\"length1\":27,\"length2\":29},{\"diffs\":[[0,\"njection\"],[1,\"~~ →\"],[0,\" \"],[-1,\"(\"],[0,\"STORE DA\"]],\"start1\":14397,\"start2\":14397,\"length1\":18,\"length2\":21},{\"diffs\":[[0,\"ATA \"],[-1,\"vs PUT KEY)\"],[1,\"(INS=E2) with DGI tags\"],[0,\"\\\n- [\"]],\"start1\":14417,\"start2\":14417,\"length1\":19,\"length2\":30},{\"diffs\":[[0,\"ies\\\n\"],[-1,\"\\\n---\\\n\\\n## Development Sequence\\\n\\\n1. ~~Proc\"],[1,\"- [ ] So\"],[0,\"ur\"],[1,\"c\"],[0,\"e \"],[-1,\"**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 APDUs~~ *(mock transport covers this headless)*\\\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. ~~Implement ISD locking and memory zeroization~~ ✅\\\n6. Implement file container parser (awaiting sample containers)\\\n7. Integrate KLMS REST API client (`reqwest` with mTLS)\\\n8. End-to-end test on both development and production readers\\\n\\\n---\\\n\\\n*Source: Z.ai chat session (2025-06-08). Updated 2026-06-15 with implementation status\"],[1,\"of ICA/Root certificates (DGI A004/A005) — factory-wide or per-fob?\\\n\\\n---\\\n\\\n*Source: Z.ai chat session (2025-06-08). Updated 2026-06-15 rev 2 with JCShell analysis + DGI personalization flow + container parser\"],[0,\".*\"]],\"start1\":14677,\"start2\":14677,\"length1\":826,\"length2\":226}]"
metadata_diff: {"new":{},"deleted":[]}
encryption_cipher_text: 
encryption_applied: 0
updated_time: 2026-06-15T14:36:56.730Z
created_time: 2026-06-15T14:36:56.730Z
type_: 13