mirror of
https://github.com/esphome/esphome.git
synced 2026-10-05 10:31:29 +00:00
[noise] Document the resume constraints, bound the KDF inputs, and test PSK rotation
This commit is contained in:
@@ -167,6 +167,28 @@ TEST(NoiseResumeCache, BadMacOrMalformedOfferLeavesTicketIntact) {
|
||||
noise_cipherstate_free(recv);
|
||||
}
|
||||
|
||||
TEST(NoiseResumeCache, SetPskForgetsTickets) {
|
||||
NoiseContext ctx;
|
||||
ResumeTicket ticket;
|
||||
ASSERT_TRUE(ctx.resume_cache().issue(ticket));
|
||||
|
||||
psk_t psk{};
|
||||
psk[0] = 1;
|
||||
ctx.set_psk(psk);
|
||||
|
||||
uint8_t offer[RESUME_OFFER_SIZE];
|
||||
build_offer_for_ticket(offer, ticket, KAT_CLIENT_NONCE);
|
||||
uint8_t prologue[KAT_PROLOGUE_SIZE];
|
||||
build_prologue(prologue, offer);
|
||||
uint8_t ext[RESUME_ACCEPT_SIZE];
|
||||
NoiseCipherState *send = nullptr, *recv = nullptr;
|
||||
EXPECT_EQ(
|
||||
ctx.resume_cache().try_accept(offer, sizeof(offer), prologue, sizeof(prologue), ext, sizeof(ext), send, recv),
|
||||
0u);
|
||||
EXPECT_EQ(send, nullptr);
|
||||
EXPECT_EQ(recv, nullptr);
|
||||
}
|
||||
|
||||
TEST(NoiseResumeCache, IssueRotatesSlotsAndClearForgetsAll) {
|
||||
ResumeTicketCache cache;
|
||||
ResumeTicket tickets[ResumeTicketCache::SLOTS + 1];
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
|
||||
import aioesphomeapi.core
|
||||
import pytest
|
||||
|
||||
@@ -20,27 +22,37 @@ async def test_api_noise_resume(
|
||||
if not hasattr(aioesphomeapi.core, "ResumeAPIError"):
|
||||
pytest.skip("aioesphomeapi without noise session resume")
|
||||
|
||||
device_lines: list[str] = []
|
||||
resumed = asyncio.Event()
|
||||
resumed_count = 0
|
||||
|
||||
def on_line(line: str) -> None:
|
||||
nonlocal resumed_count
|
||||
if "Session resumed" in line:
|
||||
resumed_count += 1
|
||||
resumed.set()
|
||||
|
||||
async with (
|
||||
run_compiled(yaml_config, line_callback=device_lines.append),
|
||||
run_compiled(yaml_config, line_callback=on_line),
|
||||
api_client_connected(noise_psk=NOISE_KEY) as client,
|
||||
):
|
||||
# First connection: full handshake, the device issues a ticket
|
||||
info = await client.device_info()
|
||||
assert info.name == "host-noise-resume"
|
||||
assert not any("Session resumed" in line for line in device_lines)
|
||||
assert resumed_count == 0
|
||||
|
||||
# Same client reconnects and offers the ticket
|
||||
await client.disconnect()
|
||||
await client.connect(login=True)
|
||||
info = await client.device_info()
|
||||
assert info.name == "host-noise-resume"
|
||||
assert any("Session resumed" in line for line in device_lines)
|
||||
await asyncio.wait_for(resumed.wait(), timeout=10.0)
|
||||
assert resumed_count == 1
|
||||
resumed.clear()
|
||||
|
||||
# The resumed session issued a fresh ticket, so it resumes again
|
||||
await client.disconnect()
|
||||
await client.connect(login=True)
|
||||
info = await client.device_info()
|
||||
assert info.name == "host-noise-resume"
|
||||
assert sum("Session resumed" in line for line in device_lines) == 2
|
||||
await asyncio.wait_for(resumed.wait(), timeout=10.0)
|
||||
assert resumed_count == 2
|
||||
|
||||
Reference in New Issue
Block a user