From 942e4c64ad03e537a77366c6bf1309241b71f1e8 Mon Sep 17 00:00:00 2001 From: Dimitri Staessens Date: Thu, 2 Jul 2026 19:05:25 +0200 Subject: lib: Separate rekey replay from epoch conflict keyrot_rekey() treated any re-key attempt against a live epoch (current or previous) the same way, whether the offered root key matched the live one (a replay) or was genuinely different (a conflict). Compare the offered key against the live batch's root and return -EREPLAY for a match, keeping -1/-ECRYPT for an actual conflict, so callers can handle replayed re-keys distinctly from real ones. Signed-off-by: Dimitri Staessens Signed-off-by: Sander Vrijders --- src/lib/crypt/keyrot.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'src/lib/crypt') diff --git a/src/lib/crypt/keyrot.c b/src/lib/crypt/keyrot.c index def29297..e98df356 100644 --- a/src/lib/crypt/keyrot.c +++ b/src/lib/crypt/keyrot.c @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -470,17 +471,17 @@ void keyrot_destroy(struct keyrot * kr) } /* A dup live epoch shadows straggler RX; epoch is peer-driven. */ -static bool kr_epoch_live(const struct kr_batch * cur, - const struct kr_batch * prev, - uint8_t epoch) +static struct kr_batch * kr_live_batch(struct kr_batch * cur, + struct kr_batch * prev, + uint8_t epoch) { if (epoch == cur->epoch) - return true; + return cur; - if (prev == NULL) - return false; + if (prev != NULL && epoch == prev->epoch) + return prev; - return epoch == prev->epoch; + return NULL; } int keyrot_rekey(struct keyrot * kr, @@ -491,6 +492,8 @@ int keyrot_rekey(struct keyrot * kr, struct kr_batch * old_prev; struct kr_batch * cur; struct kr_batch * prev; + struct kr_batch * live; + int ret; assert(kr != NULL); assert(root != NULL); @@ -507,10 +510,16 @@ int keyrot_rekey(struct keyrot * kr, cur = rcu_deref(kr->cur); prev = rcu_deref(kr->prev); - if (kr_epoch_live(cur, prev, epoch)) { + live = kr_live_batch(cur, prev, epoch); + if (live != NULL) { + /* The first node key identifies the root. */ + if (crypt_ct_cmp(live->nodes, nb->nodes, SYMMKEYSZ) == 0) + ret = -EREPLAY; + else + ret = -1; rcu_wrunlock(&kr->guard); kr_batch_free(nb); - return -1; + return ret; } old_prev = kr->prev; -- cgit v1.2.3