From fdb50b8256f1038d5bc4f906b41605cacc769bf4 Mon Sep 17 00:00:00 2001 From: Dimitri Staessens Date: Sun, 14 Jun 2026 16:16:03 +0200 Subject: irmd: Deliver flow re-keying MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Re-key each encrypted flow's batch root periodically so a long-lived flow never exhausts or over-uses a single root. The IRMd re-runs the OAP exchange with the peer IRMd over the flow-update relay. The per-flow re-keying state is tracked in the registry (reg_flow). A re-key delivers one root seed from the OAP exchange. keyrot immediately HKDF-expands it into 128 node keys (KR_NODES_SZ = 128 × 32 B) and wipes the root. Then each of the 128 node keys is itself a root → HKDF-expanded into 64 (2^KEY_NODE_BITS) leaf keys, forked per direction; each leaf key is the actual AEAD key, good for 2^20 packets (the low counter bits are its nonce/seq). If the number of keys runs low, a re-key will be triggered (KEY_REKEY_WATERMARK). The rekey is signalled out of band to the application. The rbuff ACL is generalized into a flags word, so an RB_REKEY bit rides alongside the access RB_RD/RB_WR and FLOWDOWN/FLOWPEER bits. The RD and WR bits are revised ditching the fcntl historical weirdness. The seed is pulled via flow_read/flow_write, installed with crypt_rekey(). TX holds the old epoch until the peer is observed on the new one (or a grace deadline elapses), promoted from both the read and write paths so a recv-mostly flow still advances. Also fix the FLOW_ACCEPT and FLOW_ALLOC handlers, which on a key-buffer allocation failure returned from inside the cleanup-push region: that leaked the reply message and skipped both the stack-key scrub and the cleanup pop. Signed-off-by: Dimitri Staessens Signed-off-by: Sander Vrijders --- src/irmd/reg/reg.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'src/irmd/reg/reg.h') diff --git a/src/irmd/reg/reg.h b/src/irmd/reg/reg.h index 6b576471..e0c64fed 100644 --- a/src/irmd/reg/reg.h +++ b/src/irmd/reg/reg.h @@ -163,6 +163,40 @@ int reg_wait_flow_direct(int flow_id, bool reg_flow_is_direct(int flow_id); +/* Per-flow snapshot for the re-key timer */ +struct rekey_info { + int flow_id; + pid_t n_pid; + pid_t n_1_pid; + char name[NAME_SIZE + 1]; + uint8_t epoch; +}; + +void reg_flow_set_rekey(int flow_id, + bool initiator); + +int reg_flow_get_epoch(int flow_id); + +bool reg_flow_rekey_pending(int flow_id); + +pid_t reg_flow_get_n_1_pid(int flow_id); + +int reg_flow_snapshot_rekey_due(struct rekey_info * snap, + int max); + +void reg_flow_clear_in_flight(int flow_id); + +int reg_flow_store_pending(int flow_id, + const uint8_t * seed, + uint8_t epoch); + +bool reg_flow_take_pending(int flow_id, + uint8_t * seed, + uint8_t * epoch); + +void reg_notify_flow(int flow_id, + int event); + void reg_dealloc_flow(struct flow_info * info); void reg_dealloc_flow_resp(struct flow_info * info); -- cgit v1.2.3