Conversation
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).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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_registertakesiterationsstraight from thepake_registerresponse (only a<= 0floor) and feeds it intohashlib.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_resultcompared the device'sdev_confirmMAC with a plain!=, which short-circuits on the first differing byte. Switched tohmac.compare_digest.Validation
Ran on this branch, with these changes applied:
tests/transports/test_tpaptransport.py+tests/test_device_factory.py→ 1411 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.)