diff options
| author | Dimitri Staessens <dimitri@ouroboros.rocks> | 2026-07-02 01:03:45 +0200 |
|---|---|---|
| committer | Sander Vrijders <sander@ouroboros.rocks> | 2026-07-08 11:02:23 +0200 |
| commit | a16482e4d85394314553c27afcc37c0036b6d506 (patch) | |
| tree | d563c3a2130a6c669085d1c86a9757c32cabbc23 /src/lib/crypt/keyrot.c | |
| parent | 2f9fdfa5ae2749f10d9ebc805e388ab9962d9faa (diff) | |
| download | ouroboros-a16482e4d85394314553c27afcc37c0036b6d506.tar.gz ouroboros-a16482e4d85394314553c27afcc37c0036b6d506.zip | |
lib: Reject re-key to a live epoch
A re-key epoch arrives from the peer, so we need to reject duplicates
to avoid two batches sharing a wire epoch with different keys.
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 | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/src/lib/crypt/keyrot.c b/src/lib/crypt/keyrot.c index 8b0d9429..def29297 100644 --- a/src/lib/crypt/keyrot.c +++ b/src/lib/crypt/keyrot.c @@ -469,12 +469,28 @@ void keyrot_destroy(struct keyrot * kr) free(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) +{ + if (epoch == cur->epoch) + return true; + + if (prev == NULL) + return false; + + return epoch == prev->epoch; +} + int keyrot_rekey(struct keyrot * kr, const uint8_t * root, uint8_t epoch) { struct kr_batch * nb; struct kr_batch * old_prev; + struct kr_batch * cur; + struct kr_batch * prev; assert(kr != NULL); assert(root != NULL); @@ -488,6 +504,15 @@ int keyrot_rekey(struct keyrot * kr, rcu_wrlock(&kr->guard); + cur = rcu_deref(kr->cur); + prev = rcu_deref(kr->prev); + + if (kr_epoch_live(cur, prev, epoch)) { + rcu_wrunlock(&kr->guard); + kr_batch_free(nb); + return -1; + } + old_prev = kr->prev; rcu_assign(kr->prev, kr->cur); rcu_publish(nb); |
