diff --git a/README.md b/README.md index 53f8fd0..19dbe71 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ X25519 key agreement so the broker password is never transmitted. broker username, with the threat model. - [docs/enrollment-and-activation.md](docs/enrollment-and-activation.md): the FN-as-username and SN-as-username models compared. - [docs/mqtt-dynamic-security-rnd.md](docs/mqtt-dynamic-security-rnd.md): the original R&D notes. + - The diagrams are written and checked against **Mermaid 11.13.0** (the version bundled with Typora and Obsidian); + the sequence diagrams are also embedded as SVG images rendered with that version, with the source under each. - `go/`, `c/`, `c-libsodium/`, `cpp/`, `run.sh`, `run-libsodium.sh`: fixed-key programs that check the crypto libraries against the RFC test vectors and against each other. diff --git a/docs/diagrams/activation-flow.svg b/docs/diagrams/activation-flow.svg index d1adc2f..967124f 100644 --- a/docs/diagrams/activation-flow.svg +++ b/docs/diagrams/activation-flow.svg @@ -1 +1 @@ -Board (FN session)MosquittoGo backendOperator (UI)Board (FN session)MosquittoGo backendOperator (UI)fresh X25519 pair (b2, B2), nonce n2, SAS = digits(hash(B2, n2, FN))board/[FN]/activation/request [B2, n2]pending request FN, MAC label, SAS, timechoose SN, enter activation code, confirm SAS matches the boardDB: ACTIVATING (FN, SN, next generation), unique constraintephemeral (s2, S2), shared2, pw_sn = HKDF(shared2, salt=n2, info = label, SN, generation)dynsec create or update client SN: pw_sn, role vending-device, clientid = FNboard/[FN]/activation/response [SN, next generation, S2, sig]verify sig, derive pw_sn, persist SN, pw_sn and generation, reconnectCONNECT username=SN, clientId=FN, password=pw_snfirst message on device/[SN]/... (or presence)DB: ACTIVE, disable the FN client, audit \ No newline at end of file +Board (FN session)MosquittoGo backendOperator (UI)Board (FN session)MosquittoGo backendOperator (UI)fresh X25519 pair (b2, B2), nonce n2, SAS = digits(hash(B2, n2, FN))board/[FN]/activation/request [B2, n2]pending request FN, MAC label, SAS, timechoose SN, enter activation code, confirm SAS matches the boardDB: ACTIVATING (FN, SN, next generation), unique constraintephemeral (s2, S2), shared2, pw_sn = HKDF(shared2, salt=n2, info = label, SN, generation)dynsec create or update client SN: pw_sn, role vending-device, clientid = FNboard/[FN]/activation/response [SN, next generation, S2, sig]verify sig, derive pw_sn, persist SN, pw_sn and generation, reconnectCONNECT username=SN, clientId=FN, password=pw_snfirst message on device/[SN]/... (or presence)DB: ACTIVE, disable the FN client, audit \ No newline at end of file diff --git a/docs/diagrams/enrollment-protocol.svg b/docs/diagrams/enrollment-protocol.svg index 4a8df37..7180e4e 100644 --- a/docs/diagrams/enrollment-protocol.svg +++ b/docs/diagrams/enrollment-protocol.svg @@ -1 +1 @@ -Go backendMosquittoBoardGo backendMosquittoBoardrandom Client ID, X25519 pair (b, B), nonce n1CONNECT anonymous, clientId=random (TLS)SUBSCRIBE enroll/response/[cid] (own topic only)enroll/request/[cid] [B, n1, mac]reserve [cid], assign FN, ephemeral (s, S)shared = X25519(s, B), pw = HKDF(shared, salt=n1, info = label, FN)dynsec createClient FN, pw, clientid=FN, role board-bootstrapenroll/response/[cid] [FN, S, sig] (not retained)verify sig, shared = X25519(b, S), same pwpersist FN and pw to flash, then reconnect as FN \ No newline at end of file +Go backendMosquittoBoardGo backendMosquittoBoardrandom Client ID, X25519 pair (b, B), nonce n1CONNECT anonymous, clientId=random (TLS)SUBSCRIBE enroll/response/[cid] (own topic only)enroll/request/[cid] [B, n1, mac]reserve [cid], assign FN, ephemeral (s, S)shared = X25519(s, B), pw = HKDF(shared, salt=n1, info = label, FN)dynsec createClient FN, pw, clientid=FN, role board-bootstrapenroll/response/[cid] [FN, S, sig] (not retained)verify sig, shared = X25519(b, S), same pwpersist FN and pw to flash, then reconnect as FN \ No newline at end of file diff --git a/docs/diagrams/model-a-activation.svg b/docs/diagrams/model-a-activation.svg index c02f33d..cc62ef1 100644 --- a/docs/diagrams/model-a-activation.svg +++ b/docs/diagrams/model-a-activation.svg @@ -1 +1 @@ -Board (FN)MosquittoGo backendOperatorBoard (FN)MosquittoGo backendOperatorboard/[FN]/activation/requestpick SN, confirm code and short stringensure role machine-[SN] (literal ACLs device/[SN]/...)add roles machine-[SN] + capability roles to client FNboard/[FN]/activation/response [SN, sig]store SN, reconnect as FNuse device/[SN]/... topics \ No newline at end of file +Board (FN)MosquittoGo backendOperatorBoard (FN)MosquittoGo backendOperatorboard/[FN]/activation/requestpick SN, confirm code and short stringensure role machine-[SN] (literal ACLs device/[SN]/...)add roles machine-[SN] + capability roles to client FNboard/[FN]/activation/response [SN, sig]store SN, reconnect as FNuse device/[SN]/... topics \ No newline at end of file diff --git a/docs/diagrams/model-b-activation.svg b/docs/diagrams/model-b-activation.svg index 81f2515..8957be5 100644 --- a/docs/diagrams/model-b-activation.svg +++ b/docs/diagrams/model-b-activation.svg @@ -1 +1 @@ -Board (FN)MosquittoGo backendOperatorBoard (FN)MosquittoGo backendOperatornew ephemeral X25519 keypair (b2, B2)board/[FN]/activation/request [B2, n2]pick SN, confirm code and short stringephemeral (s2, S2), shared = X25519(s2, B2)pw = HKDF(shared, SN, n2, generation)create or update client SN: pw, clientId bound to board, role vending-deviceboard/[FN]/activation/response [SN, S2, sig]verify sig, derive same pw, store SN + pwreconnect as SN / pwdisable FN client (or keep for rescue / re-enrollment) \ No newline at end of file +Board (FN)MosquittoGo backendOperatorBoard (FN)MosquittoGo backendOperatornew ephemeral X25519 keypair (b2, B2)board/[FN]/activation/request [B2, n2]pick SN, confirm code and short stringephemeral (s2, S2), shared = X25519(s2, B2)pw = HKDF(shared, SN, n2, generation)create or update client SN: pw, clientId bound to board, role vending-deviceboard/[FN]/activation/response [SN, S2, sig]verify sig, derive same pw, store SN + pwreconnect as SN / pwdisable FN client (or keep for rescue / re-enrollment) \ No newline at end of file diff --git a/docs/diagrams/stage0-enrollment.svg b/docs/diagrams/stage0-enrollment.svg index 487485a..9a07633 100644 --- a/docs/diagrams/stage0-enrollment.svg +++ b/docs/diagrams/stage0-enrollment.svg @@ -1 +1 @@ -Go backendMosquittoBoardGo backendMosquittoBoardrandom Client ID, X25519 keypair (b, B), nonce n1CONNECT (TLS, anonymous, clientId=random)enroll/request/[cid] [B, n1, mac]create FN record, ephemeral (s, S)shared = X25519(s, B), pw = HKDF(shared, FN, n1)Dynamic Security: create client FN, pw, role board-bootstrapenroll/response/[cid] [FN, S, sig] (not retained)verify sig with pinned public keyshared = X25519(b, S), same pwpersist FN and pw to flashreconnect as FN / pw \ No newline at end of file +Go backendMosquittoBoardGo backendMosquittoBoardrandom Client ID, X25519 keypair (b, B), nonce n1CONNECT (TLS, anonymous, clientId=random)enroll/request/[cid] [B, n1, mac]create FN record, ephemeral (s, S)shared = X25519(s, B), pw = HKDF(shared, FN, n1)Dynamic Security: create client FN, pw, role board-bootstrapenroll/response/[cid] [FN, S, sig] (not retained)verify sig with pinned public keyshared = X25519(b, S), same pwpersist FN and pw to flashreconnect as FN / pw \ No newline at end of file