diff options
| author | Dimitri Staessens <dimitri@ouroboros.rocks> | 2026-07-02 19:05:25 +0200 |
|---|---|---|
| committer | Sander Vrijders <sander@ouroboros.rocks> | 2026-07-08 11:02:24 +0200 |
| commit | 942e4c64ad03e537a77366c6bf1309241b71f1e8 (patch) | |
| tree | 18f34aa34befd23673ecc1638919349821fa791f /src/lib/crypt/keyrot.c | |
| parent | fca717aba18850d2e32a069905f03314cd836c17 (diff) | |
| download | ouroboros-942e4c64ad03e537a77366c6bf1309241b71f1e8.tar.gz ouroboros-942e4c64ad03e537a77366c6bf1309241b71f1e8.zip | |
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 <dimitri@ouroboros.rocks>
Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
Diffstat (limited to 'src/lib/crypt/keyrot.c')
| -rw-r--r-- | src/lib/crypt/keyrot.c | 27 |
1 files changed, 18 insertions, 9 deletions
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 <ouroboros/atomics.h> #include <ouroboros/crypt.h> +#include <ouroboros/errno.h> #include <ouroboros/pthread.h> #include <ouroboros/rcu.h> @@ -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; |
