mirror of
https://github.com/esphome/esphome.git
synced 2026-09-26 14:30:23 +00:00
Trim the noise glue and drive the source filter from the define
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user