id: f4f47ebaa01242689958a58c140870fb
parent_id: b7d3ba7b589a41de9a6ac0fb5230833e
item_type: 1
item_id: 1fbaa70f2fb94ffcaabbeca7b39482da
item_updated_time: 1787042295725
title_diff: "[]"
body_diff: "[{\"diffs\":[[0,\"G** \"],[-1,\"now also live in the repo at\\\n> `docs/diagrams/` (created 2026-08-18, rendered via the public PlantUML server —\\\n> deflate+map6 encoder, `python render script`; ask Jan/Kilo session for the\\\n> script if needed). **Uncommitted as of 2026-08-18** — until committed, this note\\\n> remains the durable copy; once committed, the repo folder becomes canonical and\\\n> the embedded sources below can be dropped. PPT/Word embeds use the **SVG**\\\n> (scalable); PNG raster fallback sits alongside each.\\\n> Companions: **Keyfob Flow 1**, **Keyfob Flow 2** (sequence detail), audit note\\\n> (**Keyfob Station — Code Audit Open Items**).\\\n\\\n> **Review status 2026-08-14, updated 2026-08-17** — verified against the code\\\n> (kf-scp03 derive.rs, kf-provision perso.rs/helpers.rs, kf-source container.rs,\\\n> nfc_reader.rs):\\\n> - **Phase A–D KDF diagrams: correct as drawn.** Purposes 0x40/0x60/0x70, header\\\n>   `00^11‖p‖00‖0080‖01`, K1-for-full / K2-for-partial CMAC blocks, ECB call counts\\\n>   (7+8+5+3 = 23), Phase D CBC chaining — all match code + tests.\\\n> - **Phase D (A003 = AES-CBC, IV=0, M2) is CONFIRMED by hardware** and is what the\\\n>   KLMS has delivered since 2026-08-17; the station forwards the blob untouched\\\n>   (structure check only). The interim ECB mismatch and local conversion bridge are\\\n>   resolved and removed.\\\n> - Flow 2 diagrams updated: REST transport (was DLL), seed-based on-demand generation\\\n>   (was Flow-1 cache/NoPackage), INIT UPDATE response layout fixed (UID is read via\\\n>   GET DATA beforehand, not returned by INITIALIZE UPDATE), step 9 marked PENDING.\\\n\\\n## Diagrams\\\n\\\n| File | Shows |\\\n| --- | --- |\\\n| `kdf-overview.puml` | KDF phase overview — two-row flow (both rows start left; A003 feeds Phase D) |\\\n| `kdf-phase-a.puml` | Phase A full (master+UID → static keys) |\\\n| `kdf-phase-a-1.puml` | Phase A 1/2 (subkeys + S-ENC) — slide |\\\n| `kdf-phase-a-2.puml` | Phase A 2/2 (S-MAC + S-DEK) — slide |\\\n| `kdf-phase-b.puml` | Phase B full (session keys) |\\\n| `kdf-phase-b-1.puml` | Phase B 1/2 (subkeys + SES-ENC) — slide |\\\n| `kdf-phase-b-2.puml` | Phase B 2/2 (SES-MAC + SES-RMAC) — slide |\\\n| `kdf-phase-c.puml` | Phase C — cryptograms (card gate + host cg) |\\\n| `kdf-phase-d.puml` | Phase D — A003 AES-CBC + cleanup |\\\n| `flow-2-provisioning.puml` | Full end-to-end (Word full-page) |\\\n| `flow-2-provisioning-1.puml` | Flow 2a — Session establishment (slide, landscape) |\\\n| `flow-2-provisioning-2.puml` | Flow 2b — Personalize & finalize (slide) |\\\n\\\n## Rendering\\\n\\\n```sh\\\n# local (needs java + plantuml.jar)\\\nplantuml -tpng -tsvg <file>.puml\\\n\\\n# headless, no java — public server via deflate encoder\\\n# https://www.plantuml.com/plantuml/{png,svg}/<encoded>\\\n```\\\n\\\nFor PPT/Word embed the **SVG** (scalable).\\\n\\\n* * *\\\n\\\n## \"],[1,\"live in the repo under `docs/diagrams/`:\\\n> - **`docs/diagrams/KDF/`** — SCP03 key-derivation phases + provisioning flows (12 sets)\\\n> - **`docs/diagrams/HSM_Backup/`** — HSM deployment, key ceremonies & backups (5 sets, added 2026-08-18)\\\n>\\\n> Rendered via the public PlantUML server (deflate+map6 encoder). **Uncommitted as of\\\n> 2026-08-18** — until committed, this note remains the durable copy. PPT/Word embeds\\\n> use the **SVG** (scalable); PNG raster fallback sits alongside each.\\\n> Companions: **Keyfob Flow 1**, **Keyfob Flow 2** (sequence detail), audit note\\\n> (**Keyfob Station — Code Audit Open Items**).\\\n\\\n> **Review status 2026-08-14, updated 2026-08-17/18** — KDF diagrams verified against\\\n> the code (kf-scp03 derive.rs, kf-provision perso.rs/helpers.rs, kf-source\\\n> container.rs, nfc_reader.rs):\\\n> - **Phase A–D KDF diagrams: correct as drawn.** Purposes 0x40/0x60/0x70, header\\\n>   `00^11‖p‖00‖0080‖01`, K1-for-full / K2-for-partial CMAC blocks, ECB call counts\\\n>   (7+8+5+3 = 23), Phase D CBC chaining — all match code + tests.\\\n> - **Phase D (A003 = AES-CBC, IV=0, M2) is CONFIRMED by hardware** and is what the\\\n>   KLMS has delivered since 2026-08-17; the station forwards the blob untouched.\\\n> - Flow 2 diagrams reflect the REST transport, seed-based generation, corrected\\\n>   INIT UPDATE layout, step 9 PENDING.\\\n> - **HSM_Backup set (2026-08-18)** documents the key-custody architecture: KLMS\\\n>   failover pair (YubiHSM per VM) + NitroHSM; Ford decrypt key generated in\\\n>   YubiHSM-1 and backed up to YubiHSM-2; NXP master key inserted into the NitroHSM\\\n>   via an asymmetric key ceremony (public key to NXP, ciphertext back), backed up\\\n>   to YubiHSM-1. All transfers use one universal wrap-key ceremony.\\\n\\\n## Diagrams\\\n\\\n### KDF/ (12 sets)\\\n\\\n| File | Shows |\\\n| --- | --- |\\\n| `kdf-overview.puml` | KDF phase overview — two-row flow (both rows start left; A003 feeds Phase D) |\\\n| `kdf-phase-a.puml` | Phase A full (master+UID → static keys) |\\\n| `kdf-phase-a-1.puml` | Phase A 1/2 (subkeys + S-ENC) — slide |\\\n| `kdf-phase-a-2.puml` | Phase A 2/2 (S-MAC + S-DEK) — slide |\\\n| `kdf-phase-b.puml` | Phase B full (session keys) |\\\n| `kdf-phase-b-1.puml` | Phase B 1/2 (subkeys + SES-ENC) — slide |\\\n| `kdf-phase-b-2.puml` | Phase B 2/2 (SES-MAC + SES-RMAC) — slide |\\\n| `kdf-phase-c.puml` | Phase C — cryptograms (card gate + host cg) |\\\n| `kdf-phase-d.puml` | Phase D — A003 AES-CBC + cleanup |\\\n| `flow-2-provisioning.puml` | Full end-to-end (Word full-page) |\\\n| `flow-2-provisioning-1.puml` | Flow 2a — Session establishment (slide, landscape) |\\\n| `flow-2-provisioning-2.puml` | Flow 2b — Personalize & finalize (slide) |\\\n\\\n### HSM_Backup/ (5 sets)\\\n\\\n| File | Shows |\\\n| --- | --- |\\\n| `hsm-topology.puml` | Deployment + key placement: KLMS VM-1/VM-2 failover, YubiHSM-1/2, NitroHSM; which key lives where |\\\n| `hsm-backup-pattern.puml` | The universal transfer ceremony: target-generated wrap keypair, ciphertext-only transfer, plaintext never outside an HSM |\\\n| `decryption-key-create-and-backup.puml` | Ford bundle decryption key: generated in YubiHSM-1, public key to Ford, wrapped backup to YubiHSM-2 |\\\n| `nxp-master-key-ceremony.puml` | NXP master key: import keypair on NitroHSM, public key to NXP, NXP encrypts M, decrypt-inside import |\\\n| `nxp-master-key-backup.puml` | NXP master key backup: NitroHSM → YubiHSM-1 via the same wrap ceremony |\\\n\\\n## Rendering\\\n\\\n```sh\\\n# local (needs java + plantuml.jar)\\\nplantuml -tpng -tsvg <file>.puml\\\n\\\n# headless, no java — public server via deflate encoder\\\n# https://www.plantuml.com/plantuml/{png,svg}/<encoded>\\\n```\\\n\\\nFor PPT/Word embed the **SVG** (scalable).\\\n\\\n* * *\\\n\\\n## HSM_Backup/hsm-topology.puml — deployment & key placement\\\n\\\n```plantuml\\\n@startuml hsm-topology\\\n' HSM deployment: KLMS failover pair (each VM with a YubiHSM) + NitroHSM (NetHSM).\\\n' Key placement:\\\n'   Ford bundle decryption key: YubiHSM-1 (generated here) + YubiHSM-2 (backup)\\\n'   NXP master key:            NitroHSM (primary, SCP03 KDF) + YubiHSM-1 (backup)\\\n\\\nskinparam defaultFontName \\\"DejaVu Sans\\\"\\\nskinparam ArrowColor #444444\\\nskinparam node {\\\n  BackgroundColor #F4F8FF\\\n  BorderColor #3B6FB6\\\n}\\\nskinparam cloud {\\\n  BackgroundColor #FFFFFF\\\n  BorderColor #888888\\\n}\\\nskinparam storage {\\\n  BackgroundColor #FFF8E1\\\n  BorderColor #B8860B\\\n}\\\n\\\ntitle HSM Deployment & Key Placement — KLMS failover pair + NitroHSM\\\n\\\ncloud \\\"Ford IVSS / GIVIS\\\" as Ford\\\ncloud \\\"NXP (key ceremony)\\\" as NXP\\\n\\\nnode \\\"KLMS VM-1\\\\\n(primary)\\\" as VM1\\\nnode \\\"KLMS VM-2\\\\\n(standby)\\\" as VM2\\\n\\\nnode \\\"YubiHSM-1\\\" as Y1 {\\\n  storage \\\"**Ford decrypt key**\\\\\n(generated here)\\\" as DK1\\\n  storage \\\"**NXP master key**\\\\\n(backup)\\\" as MK1\\\n}\\\nnode \\\"YubiHSM-2\\\" as Y2 {\\\n  storage \\\"**Ford decrypt key**\\\\\n(backup)\\\" as DK2\\\n}\\\nnode \\\"NitroHSM\\\\\n(NetHSM — SCP03 KDF)\\\" as NH {\\\n  storage \\\"**NXP master key M**\\\\\n(primary — KDF3 + ECB)\\\" as MK0\\\n}\\\n\\\nFord -down-> VM1 : encrypted bundles\\\\\n(Flow 1, mTLS)\\\nFord -down-> VM2 : encrypted bundles\\\nVM1 <--> VM2 : failover\\\\\n(heartbeat)\\\nVM1 -down-> Y1 : USB\\\nVM2 -down-> Y2 : USB\\\nVM1 -right-> NH : AES-ECB calls\\\\\n(Flow 2 KDF)\\\nVM2 --> NH\\\n\\\nNXP ..> NH : master key M, wrapped\\\\\n(one-time key ceremony)\\\nY1 ..> Y2 : decrypt-key backup\\\\\n(wrapped, one-time)\\\nNH ..> Y1 : master-key backup\\\\\n(wrapped, one-time)\\\n\\\nnote bottom of NH\\\n  NitroHSM exposes single-block AES-ECB only.\\\n  Master key M never leaves in plaintext.\\\nend note\\\n@enduml\\\n```\\\n\\\n* * *\\\n\\\n## HSM_Backup/hsm-backup-pattern.puml — the universal transfer ceremony\\\n\\\n```plantuml\\\n@startuml hsm-backup-pattern\\\n' The universal key-transfer ceremony — used for:\\\n'   - NXP master key insertion (source = NXP, target = NitroHSM)\\\n'   - Ford decrypt-key backup  (YubiHSM-1 -> YubiHSM-2)\\\n'   - NXP master-key backup    (NitroHSM -> YubiHSM-1)\\\n' Invariant: plaintext key material exists only inside HSMs; operators only\\\n' ever handle public keys and ciphertext.\\\n\\\nskinparam defaultFontName \\\"DejaVu Sans\\\"\\\ntitle Key Transfer Pattern — target-generated wrap key, ciphertext-only transfer\\\n\\\nparticipant \\\"Operator\\\\\n(ceremony, dual control)\\\" as Op\\\nparticipant \\\"Key Holder\\\\\n(source HSM or NXP)\\\" as Src\\\nparticipant \\\"Target HSM\\\\\n(YubiHSM / NitroHSM)\\\" as Tgt\\\n\\\n== 1. Target generates a wrap keypair ==\\\nTgt -> Tgt : generate asymmetric **wrap keypair**\\\\\n(private key non-exportable)\\\nTgt --> Op : export wrap **public key** (cert)\\\nOp --> Src : import wrap public key\\\\\n(over a verified channel)\\\n\\\n== 2. Source wraps the key material ==\\\nSrc -> Src : encrypt (wrap) the key material\\\\\nunder the target wrap public key\\\nSrc --> Op : wrapped blob (ciphertext)\\\n\\\n== 3. Target imports and unwraps ==\\\nOp -> Tgt : import wrapped blob\\\nTgt -> Tgt : decrypt **inside** the HSM\\\\\n-> usable, non-exportable key object\\\n\\\nnote over Op, Tgt #E8FFE8\\\n  Invariants:\\\n  - plaintext key never crosses an HSM boundary\\\n  - operator handles only public keys + ciphertext\\\n  - same ceremony for every key and every backup\\\nend note\\\n@enduml\\\n```\\\n\\\n* * *\\\n\\\n## HSM_Backup/decryption-key-create-and-backup.puml\\\n\\\n```plantuml\\\n@startuml decryption-key-create-and-backup\\\n' Ford package decryption key: generated in YubiHSM-1 (primary),\\\n' public key to Ford, backup to YubiHSM-2 via the standard wrap ceremony.\\\n\\\nskinparam defaultFontName \\\"DejaVu Sans\\\"\\\ntitle Ford Bundle Decryption Key — creation in YubiHSM-1 + backup to YubiHSM-2\\\n\\\nparticipant \\\"Ford IVSS\\\" as Ford\\\nparticipant \\\"Operator\\\" as Op\\\nparticipant \\\"YubiHSM-1\\\\\n(primary)\\\" as Y1\\\nparticipant \\\"YubiHSM-2\\\\\n(standby)\\\" as Y2\\\n\\\n== Creation (in the primary YubiHSM) ==\\\nOp -> Y1 : generate bundle **decryption keypair**\\\nY1 -> Y1 : private key generated on-device,\\\\\nnon-exportable\\\nY1 --> Op : public key (cert)\\\nOp --> Ford : public key (verified channel)\\\nnote right of Ford : Ford encrypts every per-fob\\\\\ncontent bundle to this public key\\\\\n(Flow 1). Only the YubiHSMs\\\\\ncan decrypt.\\\n\\\n== Backup to the standby YubiHSM (standard wrap ceremony) ==\\\nY2 -> Y2 : generate **wrap keypair**\\\nY2 --> Op : wrap public key\\\nOp --> Y1 : import wrap public key\\\nY1 -> Y1 : export decryption private key\\\\\nwrapped under Y2 wrap public key\\\nY1 --> Op : wrapped blob (ciphertext)\\\nOp -> Y2 : import wrapped blob\\\nY2 -> Y2 : unwrap **inside** HSM\\\\\n-> decrypt key available on standby\\\n\\\nnote over Y1, Y2 #E8FFE8\\\n  Result: both YubiHSMs hold the decryption key;\\\n  either KLMS VM can run Flow 1 bundle decryption.\\\n  Plaintext never left an HSM.\\\nend note\\\n@enduml\\\n```\\\n\\\n* * *\\\n\\\n## HSM_Backup/nxp-master-key-ceremony.puml\\\n\\\n```plantuml\\\n@startuml nxp-master-key-ceremony\\\n' NXP master key insertion: asymmetric keypair generated on the NitroHSM,\\\n' public key handed to NXP, NXP encrypts the master key, import decrypts\\\n' inside the HSM.\\\n\\\nskinparam defaultFontName \\\"DejaVu Sans\\\"\\\ntitle NXP Master Key — Key Ceremony & Insertion into the NitroHSM\\\n\\\nparticipant \\\"NXP\\\" as NXP\\\nparticipant \\\"Operator\\\\\n(ceremony, dual control)\\\" as Op\\\nparticipant \\\"NitroHSM\\\\\n(NetHSM)\\\" as NH\\\n\\\n== Ceremony ==\\\nOp -> NH : generate asymmetric **import keypair**\\\nNH -> NH : private key non-exportable\\\nNH --> Op : import **public key** (cert)\\\nOp --> NXP : public key (verified / signed channel)\\\nNXP -> NXP : encrypt the **SCP03 master key M**\\\\\n(AES-128, KDF3 base key)\\\\\nunder the NitroHSM public key\\\nNXP --> Op : encrypted master-key blob (ciphertext)\\\nOp -> NH : import encrypted blob\\\nNH -> NH : decrypt **inside** the HSM\\\\\n-> master key M as a key object\\\n\\\n== Post-conditions ==\\\nnote over NH #FFF8E1\\\n  M is used only for:\\\n  - KDF3, Phase A (S-ENC / S-MAC / S-DEK)\\\n  - AES-ECB primitives (Phases A-D)\\\n  M is never exportable in plaintext;\\\n  backup only via the wrap ceremony\\\n  (see nxp-master-key-backup).\\\nend note\\\nnote over NXP #FFEEEE : NXP is the originator of M;\\\\\nhandover is logged and audited\\\n@enduml\\\n```\\\n\\\n* * *\\\n\\\n## HSM_Backup/nxp-master-key-backup.puml\\\n\\\n```plantuml\\\n@startuml nxp-master-key-backup\\\n' NXP master key backup: NitroHSM -> YubiHSM-1 via the standard wrap ceremony.\\\n\\\nskinparam defaultFontName \\\"DejaVu Sans\\\"\\\ntitle NXP Master Key — Backup from NitroHSM to YubiHSM-1 (primary)\\\n\\\nparticipant \\\"Operator\\\" as Op\\\nparticipant \\\"NitroHSM\\\\\n(NetHSM)\\\" as NH\\\nparticipant \\\"YubiHSM-1\\\\\n(primary)\\\" as Y1\\\n\\\nY1 -> Y1 : generate **wrap keypair**\\\\\n(private key non-exportable)\\\nY1 --> Op : wrap public key\\\nOp --> NH : import wrap public key\\\\\n(verified channel)\\\nNH -> NH : export master key M\\\\\nwrapped under Y1 wrap public key\\\nNH --> Op : wrapped blob (ciphertext)\\\nOp -> Y1 : import wrapped blob\\\nY1 -> Y1 : decrypt **inside** HSM\\\\\n-> backup copy of M\\\n\\\nnote over NH, Y1 #E8FFE8\\\n  Identical ceremony to the decrypt-key backup\\\n  (hsm-backup-pattern / decryption-key-create-and-backup):\\\n  every key and every backup is created and transferred\\\n  exactly the same way — wrap public key out,\\\n  ciphertext across, plaintext never outside an HSM.\\\nend note\\\nnote over Y1 #FFF8E1\\\n  YubiHSM-1 now holds:\\\n  - Ford decrypt key (generated)\\\n  - NXP master key (backup)\\\nend note\\\n@enduml\\\n```\\\n\\\n* * *\\\n\\\n## KDF/\"],[0,\"kdf-\"]],\"start1\":161,\"start2\":161,\"length1\":2712,\"length2\":10695},{\"diffs\":[[0,\"\\\n```\\\n\\\n* * *\\\n\\\n## \"],[1,\"KDF/\"],[0,\"kdf-phase-a.puml\"]],\"start1\":13280,\"start2\":13280,\"length1\":32,\"length2\":36},{\"diffs\":[[0,\"\\\n```\\\n\\\n* * *\\\n\\\n## \"],[1,\"KDF/\"],[0,\"kdf-phase-a-1.pu\"]],\"start1\":15080,\"start2\":15080,\"length1\":32,\"length2\":36},{\"diffs\":[[0,\"\\\n```\\\n\\\n* * *\\\n\\\n## \"],[1,\"KDF/\"],[0,\"kdf-phase-a-2.pu\"]],\"start1\":16256,\"start2\":16256,\"length1\":32,\"length2\":36},{\"diffs\":[[0,\"\\\n```\\\n\\\n* * *\\\n\\\n## \"],[1,\"KDF/\"],[0,\"kdf-phase-b.puml\"]],\"start1\":17235,\"start2\":17235,\"length1\":32,\"length2\":36},{\"diffs\":[[0,\"\\\n```\\\n\\\n* * *\\\n\\\n## \"],[1,\"KDF/\"],[0,\"kdf-phase-b-1.pu\"]],\"start1\":18600,\"start2\":18600,\"length1\":32,\"length2\":36},{\"diffs\":[[0,\"\\\n```\\\n\\\n* * *\\\n\\\n## \"],[1,\"KDF/\"],[0,\"kdf-phase-b-2.pu\"]],\"start1\":19564,\"start2\":19564,\"length1\":32,\"length2\":36},{\"diffs\":[[0,\"\\\n```\\\n\\\n* * *\\\n\\\n## \"],[1,\"KDF/\"],[0,\"kdf-phase-c.puml\"]],\"start1\":20368,\"start2\":20368,\"length1\":32,\"length2\":36},{\"diffs\":[[0,\"* *\\\n\\\n## \"],[1,\"KDF/\"],[0,\"kdf-phas\"]],\"start1\":21693,\"start2\":21693,\"length1\":16,\"length2\":20},{\"diffs\":[[0,\"\\\n```\\\n\\\n* * *\\\n\\\n## \"],[1,\"KDF/\"],[0,\"flow-2-provision\"]],\"start1\":22924,\"start2\":22924,\"length1\":32,\"length2\":36},{\"diffs\":[[0,\"\\\n```\\\n\\\n* * *\\\n\\\n## \"],[1,\"KDF/\"],[0,\"flow-2-provision\"]],\"start1\":27078,\"start2\":27078,\"length1\":32,\"length2\":36},{\"diffs\":[[0,\"* *\\\n\\\n## \"],[1,\"KDF/\"],[0,\"flow-2-p\"]],\"start1\":29615,\"start2\":29615,\"length1\":16,\"length2\":20}]"
metadata_diff: {"new":{},"deleted":[]}
encryption_cipher_text: 
encryption_applied: 0
updated_time: 2026-08-18T08:41:39.409Z
created_time: 2026-08-18T08:41:39.409Z
is_locked: 0
type_: 13