From 4e2ff94588b48c8994f60607023aad6fc64a5a19 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 24 Aug 2026 14:39:15 -0500 Subject: [PATCH] [noise] Keep two resume tickets --- esphome/components/noise/noise_resume.h | 5 ++++- tests/components/noise/test_noise_resume.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/esphome/components/noise/noise_resume.h b/esphome/components/noise/noise_resume.h index 6de53a3295..a2dd6ca8b6 100644 --- a/esphome/components/noise/noise_resume.h +++ b/esphome/components/noise/noise_resume.h @@ -63,10 +63,13 @@ class ResumeTicketCache { /// Forget every ticket (PSK change). void clear(); + // Realistically one or two controllers hold a ticket at a time; a third + // just evicts the oldest and that client does one full handshake. + static constexpr uint8_t SLOTS = 2; + protected: bool take_verified_(const uint8_t *offer, uint8_t *secret_out); - static constexpr uint8_t SLOTS = 4; ResumeTicket slots_[SLOTS]; bool used_[SLOTS]{}; uint8_t next_{0}; diff --git a/tests/components/noise/test_noise_resume.cpp b/tests/components/noise/test_noise_resume.cpp index 4c4b8ac44f..692e16239b 100644 --- a/tests/components/noise/test_noise_resume.cpp +++ b/tests/components/noise/test_noise_resume.cpp @@ -160,7 +160,7 @@ TEST(NoiseResumeCache, BadMacOrMalformedOfferLeavesTicketIntact) { TEST(NoiseResumeCache, IssueRotatesSlotsAndClearForgetsAll) { ResumeTicketCache cache; - ResumeTicket tickets[5]; + ResumeTicket tickets[ResumeTicketCache::SLOTS + 1]; for (auto &ticket : tickets) { ASSERT_TRUE(cache.issue(ticket)); } @@ -168,12 +168,12 @@ TEST(NoiseResumeCache, IssueRotatesSlotsAndClearForgetsAll) { uint8_t prologue[1] = {0}; uint8_t ext[RESUME_ACCEPT_SIZE]; - // Slot 0 was evicted by the fifth issue + // The oldest ticket was evicted by the one-past-capacity issue build_offer_for_ticket(offer, tickets[0], KAT_CLIENT_NONCE); NoiseCipherState *send = nullptr, *recv = nullptr; EXPECT_FALSE(cache.try_accept(offer, sizeof(offer), prologue, sizeof(prologue), ext, send, recv)); - // Tickets 1..4 remain redeemable - for (int i = 1; i < 5; i++) { + // The rest remain redeemable + for (int i = 1; i <= ResumeTicketCache::SLOTS; i++) { build_offer_for_ticket(offer, tickets[i], KAT_CLIENT_NONCE); EXPECT_TRUE(cache.try_accept(offer, sizeof(offer), prologue, sizeof(prologue), ext, send, recv)); noise_cipherstate_free(send);