Skip to content

tpap: harden pre-auth DoS + constant-time confirm-MAC compare - #9

Open
Austin519 wants to merge 1 commit into
ZeliardM:feature/tpapfrom
Austin519:tpap-hardening
Open

Austin519 wants to merge 1 commit into
ZeliardM:feature/tpapfrom
Austin519:tpap-hardening

Conversation

@Austin519

Copy link
Copy Markdown

Two small defense-in-depth hardenings for the TPAP transport in python-kasa#1592, found while validating the branch against real KP125M(US) hardware. Both target TpapEncryptionSession; neither changes behavior for real devices.

1. Pre-auth DoS: unbounded PBKDF2 work factor from an unauthenticated response

_build_share_params_from_register takes iterations straight from the pake_register response (only a <= 0 floor) and feeds it into hashlib.pbkdf2_hmac("sha256", …, iterations, …) synchronously, before SPAKE2+ confirmation authenticates the peer. A malicious or on-path device can return a huge iteration count and stall the entire asyncio event loop (in a shared-loop host like Home Assistant, that's the whole integration process, not just one device).

Fix: cap at MAX_PAKE_ITERATIONS = 100_000 — generously above any realistic PAKE configuration (fixtures use ≤ 100), rejecting absurd values with the existing "invalid iterations" error.

2. Timing side-channel on the confirmation MAC compare

_establish_session_from_share_result compared the device's dev_confirm MAC with a plain !=, which short-circuits on the first differing byte. Switched to hmac.compare_digest.

Validation

Ran on this branch, with these changes applied: tests/transports/test_tpaptransport.py + tests/test_device_factory.py1411 passed (116 + 1295), ruff check (incl. flake8-bandit) → all checks passed, mypy → no issues. Functional operation also confirmed against a live KP125M(US) (fw 1.2.5 Build 241213) on the port-80 path.

(Separately, I left a note on python-kasa#1592 about a possible AEAD nonce-reuse between request and response observed on the same hardware — that one looks protocol-level and isn't addressed here.)

Two defense-in-depth fixes to TpapEncryptionSession:

- Cap PBKDF2-HMAC-SHA256 iterations from the unauthenticated pake_register
  response (MAX_PAKE_ITERATIONS = 100_000). The count was previously unbounded
  and hashed synchronously on the event loop, so a malicious/on-path device
  could stall the whole asyncio process (e.g. all of Home Assistant) before
  SPAKE2+ confirmation ever authenticates the peer.
- Compare the device confirmation MAC with hmac.compare_digest instead of a
  short-circuiting '!=', removing a timing side-channel on MAC verification.

No behavioral change for real devices (fixtures use iterations <= 100).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant