Trim the noise glue and drive the source filter from the define

This commit is contained in:
J. Nick Koston
2026-09-05 11:28:00 +02:00
parent 029f6d4bc3
commit 8d60f03ff3
9 changed files with 119 additions and 258 deletions
+14 -23
View File
@@ -110,17 +110,19 @@ class FakeEncryptedDevice(threading.Thread):
return
server_flags = espota2.SERVER_FEATURE_SUPPORTS_NOISE if self.offer_noise else 0
sock.sendall(bytes([espota2.RESPONSE_FEATURE_FLAGS, server_flags]))
if noise_negotiated and not self.offer_noise:
return # the client fails closed; nothing further arrives
if not noise_negotiated:
# A device that does not require encryption lets a plaintext
# client through
self._transfer(
lambda byte: sock.sendall(bytes([byte])),
lambda length: _recv_exact(sock, length),
lambda remaining: sock.recv(min(remaining, 4096)),
lambda remaining: _recv_exact(
sock, min(remaining, espota2.UPLOAD_BLOCK_SIZE)
),
)
return
if not self.offer_noise:
return # the client fails closed; nothing further arrives
from cryptography.exceptions import InvalidTag
from noise.connection import NoiseConnection
@@ -159,7 +161,7 @@ class FakeEncryptedDevice(threading.Thread):
assert len(plaintext) == length, "control units must be one per frame"
return plaintext
def recv_data(remaining: int) -> bytes:
def recv_data(_remaining: int) -> bytes:
plaintext = proto.decrypt(_recv_frame(sock))
assert 0 < len(plaintext) <= espota2.NOISE_MAX_PLAINTEXT
return plaintext
@@ -183,9 +185,7 @@ class FakeEncryptedDevice(threading.Thread):
received = b""
acked = 0
while len(received) < size:
chunk = recv_data(size - len(received))
assert chunk, "client closed mid-transfer"
received += chunk
received += recv_data(size - len(received))
if self.version >= espota2.OTA_VERSION_2_0:
while acked + espota2.UPLOAD_BLOCK_SIZE <= len(received) or (
len(received) == size and acked < size
@@ -264,25 +264,16 @@ def test_client_fails_closed_when_device_lacks_encryption() -> None:
device.join_and_check()
def test_plaintext_client_accepted_by_offering_device() -> None:
"""A device that offers but does not require encryption still takes a
plaintext upload from a client with no key configured."""
@pytest.mark.parametrize("noise_psk", [None, PSK], ids=["plaintext", "encrypted"])
def test_offering_device_accepts_either_transport(noise_psk: str | None) -> None:
"""A device that offers but does not require encryption takes a plaintext
upload from a keyless client and an encrypted one from a keyed client."""
if noise_psk:
pytest.importorskip("aioesphomeapi.noise")
firmware = bytes(range(256)) * 40
device = FakeEncryptedDevice(offer_noise=True, require_noise=False)
with patch("time.sleep"):
_upload(device, firmware, None)
device.join_and_check()
assert device.received == firmware
def test_keyed_client_encrypts_with_offering_device() -> None:
"""The upload that turns on `ota: encryption:` is already encrypted when
the running firmware offers it."""
pytest.importorskip("aioesphomeapi.noise")
firmware = bytes(range(256)) * 40
device = FakeEncryptedDevice(offer_noise=True, require_noise=False)
with patch("time.sleep"):
_upload(device, firmware, PSK)
_upload(device, firmware, noise_psk)
device.join_and_check()
assert device.received == firmware