TPAP Implementation#1592
Conversation
There was a problem hiding this comment.
Pull Request Overview
Implements the new TPAP (TP-Link Adaptive Protocol) encryption type with SPAKE2+ HTTPS transport for TP-Link devices. This is an initial implementation to test handshake functionality with new firmware that uses TPAP encryption.
- Added complete TPAP transport implementation using SPAKE2+ P-256 handshake and AEAD data channel
- Updated device factory to support TPAP encryption type routing
- Added ecdsa dependency for elliptic curve operations
Reviewed Changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| pyproject.toml | Added ecdsa dependency and mypy overrides for the new package |
| kasa/transports/tpaptransport.py | New TPAP transport implementation with SPAKE2+ handshake and secure channel |
| kasa/transports/init.py | Added TpapTransport to module exports |
| kasa/deviceconfig.py | Added Tpap enum value to DeviceEncryptionType |
| kasa/device_factory.py | Added SMART.TPAP.HTTPS protocol mapping and fixed typo |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1592 +/- ##
==========================================
+ Coverage 93.21% 93.73% +0.52%
==========================================
Files 157 158 +1
Lines 9819 10637 +818
Branches 1005 1110 +105
==========================================
+ Hits 9153 9971 +818
Misses 472 472
Partials 194 194 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
@rytilahti Ok, I think this is a good first pass. I just need someone with a RV device to test it. The CodeQL Security flags, from my understanding, will always come up with md5 and sha1 hashing in the code, but it's required for the device communication, just like with the other transports. |
|
Sanitized discovery, logs, and TLS observations for the RV30 Max Plus(EU)-Firmware:1.3.0 Build 250909 Rel.135514 using TPAP. Personally identifying values are redacted. Hope this help.
uv run kasa --username '' --password '' --debug --host 192.168.68.63 discover config uv run kasa --username '' --password '' --debug --host 192.168.68.63 discover raw SSL: Wireshark: |
|
@danieyal Pull the latest commit and try giving it a shot again. |
|
unfortunately, still the same error. |
|
I think i have got the TLS working now but stuck on the authentication now.
The device is returning a JSON response with 'error_code': -2402 along with authentication failure details like failedAttempts and remainAttempts. The device is rejecting the authentication attempt at the pake_register stage returning error code -2402. My theory is the device is actively rejecting our credentials/authentication attempt before we even get to the SPAKE2+ cryptographic exchange. This suggests the device needs something we're not providing, most likely DAC support. |
|
I have been working on this today without much movement, still trying to figure out the authentication pieces. Looks like I will have to implement NOC but having issues getting the information and URLs for the certificate registration with the Tapo cloud. There is an API rate limit which causes problems as well. So, I'm still working on this, but nothing yet. |
|
@danieyal Are you able to use the Tapo app on your computer with Wireshark? I'm trying to reverse engineer the url for the certificates and the requests are not working. I am looking for something to do with: This is what points to where to apply for the certificates, but I can't get the communication to work correctly on my end. I'm trying to get the signature correct with the app to the cloud so I can pull the url, but I can't get that either. Until I have the URL to work with the serviceId: nbu.cvm-server-v2, then I can't get the library to handle the noc certificates. |
|
@danieyal try pulling again and let me know. I updated the ciphers like you found and I also corrected the last error you posted, it went to the stok field in the register parameters, it needed to be sessionId instead. Let me know what you get with this. |
|
@ZeliardM Thanks for the updates, and to clarify my side:
Re: NOC/
I also pulled the latest branch:
Frida Log for device commissioning, I reset my device to see if pake_register appear at all, but it seems like nope, it just communicates over cloud regardless, other Tapo devices (plug, bulb, hub, camera) that I own still communicates locally (so probably not local network issue), I can 'see' the local endpoint for other devices but only vacuum just straight to cloud endpoint. Sorry, if it takes too long, setting up Frida took longer than expected. |
|
@danieyal That's great, I do see something in your logs about nbu, that may help point me where I need to go. Yea, Frida is a pain. I've used it in the past but lost my devices to do so, so it's been rough lately. I appreciate your work so far. I am going through the encryption pieces again. Yea, the pake_register phase is essentially handshake1 and I still need to see what is going on. |
|
@danieyal Ok, I've spent most of the day going over things, and I think I'm at an impasse. I can't get the URLs to communicate with the cloud for the NOC certificates. I've gotten close, but what happens is that the APK uses a call, gets a cloud token, then pulls the URLs from the cloud. I can get the cloud token, but the I cannot get the signature matches for the calls out that have 'signature-required' set to true. I need to see if there is a way to reverse engineer these signatures so we can get them to match from my code based on how everything is supposed to be. I have some scripts and code that I've got for testing if you would be able to take it along with some of the Frida work you've done and possibly see if you can get the URL? I can send them via Discord if that works? |
|
@ZeliardM yeah sure, I will try but since I am working during the day, I might not have enough time to dedicate to it, but I'll try. Discord works for me. |
|
@danieyal All good, give it a shot and let me know and we will go from there. Thanks! |
|
@danieyal What I have been able to pull apart today is that the checkpassword call that is used in the frida logs you posted earlier, this has the same signature requirements that I am looking for. If you can get me some wireshark pulls of this actual communication so I can see the actual headers and packet information, then I might be able to reverse engineer this from there. If you want, we can keep going on Discord, my username is the same there. |
|
@danieyal nevermind, I finally got the matching signature and figured out how to get the right url for getting the certificates! |
|
Ok, now that I have all of this, my plan is as follows:
It's going to take quite some time for me to get through all of this, I want to put it together cleanly. I'm headed out of town with my family for the weekend so I may not work on it much right now, but will keep everyone updated as I keep working on it. |
|
I am still slowly working on this. I have the NOC capabilities set up, now I'm working on testing the code. Having issues with the CSR formatting so I'll keep plugging away at it and keep you in the loop. |
|
@tuck-ski Thaks for this feedback. I haven't had anyone test this path yet so it's good to see. I'll take this information and see if I can work on getting the issues resolved and let you know. Thanks! |
|
If anyone with a Tapo RV30 or RV20 is tired of waiting (and - after about 7 months of "I've almost got it" - no longer believes a solution is coming, like I did)... There is an alternative solution using the HA integration by epg-pers: Using this, I got my TAPO RV20 Max Plus up and running again in just a few minutes. Maybe this helps someone out there. |
Tested this branch working end-to-end on a P125M, no KLAP regressionBuilt Background / why this matters now: TP-Link has been pushing firmware auto-updates that migrate plugs from KLAP to TPAP. Once a device updates, it stops speaking the old auth entirely. It still works in the Tapo app, but silently drops off Home Assistant (shows Repro of the pre-PR failureA P125M that auto-updated to firmware 1.4.2 Build 251204 now advertises: On stock 0.10.2, With this PR
Useful finding for the migration/re-auth pathThe existing KLAP KLAP regression check (since this touches shared protocol code)Same build, against devices still on KLAP:
Thanks for the work on this. I'm happy to run additional tests on P125M / firmware 1.4.2 hardware if it'd help. |
RV30 Max TPAP test resultsI tested this PR branch against a Tapo RV30 Max and the TPAP transport works for read-only operations when the protocol/device family is explicitly forced. Test environment
Discovery result
Commands tested successfullyThe following commands completed successfully when forcing the device family and TPAP connection parameters: Observed working featuresstate and feature expose the following successfully: Specific read-only feature checks also worked: feature vacuum_status -> 5 vacuum records list also returned valid historical cleaning records and total statistics. Matter warningThe device reports UNKNOWN_METHOD_ERROR for Matter setup info: get_matter_setup_info for Matter (error_code=UNKNOWN_METHOD_ERROR) This does not block the TPAP transport, state, feature, consumables, or cleaning records. Important observationIf I run commands without forcing the connection parameters, some commands may fail with: TPAP pake_share failed: INTERNAL_UNKNOWN_ERROR(-100000) Forcing the following parameters made the read-only commands work reliably: I also avoided running multiple commands in parallel. Sequential execution with a short delay between commands was more stable. Not tested yetI intentionally did not run commands that modify the real robot state, such as: vacuum_start I can run those write/action tests if maintainers want additional validation on RV30 Max hardware. |
|
Wanted to share a real-world validation of this PR. I have a 36-device Tapo smart home running Home Assistant on a Synology NAS via Docker. After the 1.4.2 firmware update rolled out across my P125M plugs, KL125 bulbs, and KL400L5 strips, everything broke — both Home Assistant and my H500 hub automations stopped working entirely. I manually patched the python-kasa 0.10.2 installation inside my HA Docker container tonight using the files from this PR:
After patching and re-adding the affected P125M devices through the HA UI, everything came back online. Full control restored over all TPAP devices on firmware 1.4.2. Tested against: P125M (firmware 1.4.2 Build 251204 Rel.103056) This PR works. Please merge. |
|
I understand this PR is not fully functional on some devices like the rv30 vacuum. However, right now basic things on Home Assistant like smart plugs are completely broken. Two testers have validated smart plugs work with the new code and there is no regression on KLAP. There are currently likely thousands of users with broken smart homes. I would propose you merge this PR and open a second for advanced device support. |
|
This PR should handle read and write functionality. This is just a communication piece, nothing with the actual commands has changed. If the communication is there and the existing commands worked before, they should work now. Again, I don't have a device to test so someone would need to confirm but it should work. The authentication regression is the fact that some devices respond to discovery calls on both UDP and TDP and if UDP wins out before the new TDP it will fail back to KLAP, that's a discovery regression, not an issue with this PR and is to be handled separately in several other PRs I have also started. I appreciate everyone commenting and validating information for this PR, it's good to know for most everyone it is working as intended. What everyone needs to understand is, the work is here, it's in place, there are just other things in life that have come up for the maintainers and myself and this is a personal side, helping the community project. We all understand the importance of this in everyone's smart home designs and functionality and not trying to belittle that in any way. The fixes will come full circle, just not sure when yet. |
Tapo RV30 Max TPAP Validation ReportI ran additional validation against a Tapo RV30 Max using this PR branch. Context
The goal was to validate both reversible write operations and supervised motion controls without requiring any cloud/app interaction. Test Results
Observed Status Mapping
SummaryFrom these tests, the TPAP implementation in this PR is working for the main practical control paths on the RV30 Max: connection, status reads, reversible setting writes, start, pause, resume and return-home. UDP discovery was also validated. The device was correctly identified as an RV30 Max using the I can run more targeted tests if maintainers need additional coverage, but from a user-impact perspective this already enables a meaningful and currently missing feature set for RV-series vacuums. My recommendation would be to move this PR forward rather than waiting for every possible edge case to be perfect. The perfect is the enemy of the good, and this version already provides working TPAP support for real hardware while leaving room for follow-up improvements. |
|
Tested on L900-5(EU) — pake_share fails with -100000 Device discovery: Steps that succeed: discover (via /), pake_register (device returns valid extra_crypt, dev_salt, dev_share, cipher_suites: 1, iterations: 3000). pake_register response: pake_share fails: INTERNAL_UNKNOWN_ERROR(-100000) — the device rejects our proof. I tried the following credential candidates (all fail):
The Tapo account ownership is confirmed (MD5(email) matches the device owner field). The same dev_salt appears on both L900-5 strips on the network, which may be relevant. The RV30 Max that was successfully tested has dac: 1, noc: 1. This device has dac: 0, noc: 0. Worth checking whether the _use_dac_certification() or credential derivation paths differ for those flags. |
|
Running this PR against 9x TP-Link P125M smart plugs (fw 1.4.2 Build 251204) and all nine authenticate successfully. I instrumented The only difference is the
Two things worth noting: 1. The 2. The bug is in the non-DAC if self._use_dac_certification():
self._dac_nonce_base64 = self._base64(secrets.token_bytes(16))
share_params["dac_nonce"] = self._dac_nonce_base64All the working devices seem to have All my hardware is |
I tested with a shim - possible because the pinned version is the same = 0.10.2. Custom component which is effectively a no-op, with I can finally add my sets of P110 plugs that I just heavily invested in with this PR. Firmware 1.4.3 Build 251223 Rel. 100616. One oddity is that I need to re-authenticate with my Tapo credentials on each restart. Otherwise works like a charm. |
# Conflicts: # pyproject.toml # uv.lock
|
@realugbun @awood-ops Thanks for the reports. I have re-investigated the APK code and it seems that there are not changes from the APK side for TPAP handling lately. When dac = 0, the entire dac_nonce is completely gated and left out and not used. If dac = 1, then it is created according to the specifications and passed to the pake_register and then the pake_result is handled in that respect. dac, or Device Attestation Certificate, is a local certificate that is registered on the device, then verified by the connection to make sure that the certificate was issues by TPLink correctly and that it matches the device it's registered to and the user account. I have made some recent changes to the code. If you could check the devices again that do not have dac and then, if possible, get me full debug logs if it fails again and let me know. You can send them via Discord as well, my handle there is the same. Another thing you could try and do is completely remove the device that is failing from your account and re-add it using the device selection method instead of auto-discovery method. Also, if you have Third-Party Compatibility turned on, you can try disabling it. Or disabling and re-enabling it. Sometimes this will work and let the older devices use their older authentication instead of TPAP, but if you want TPAP, then I would turn it on and then turn it back off and see if that kind of resets the devices communication on their end. The new commit will be out shortly and you can try then. |
|
Ok, everyone. The new commits are out here, let's give them a shot and let's see if everything is still functioning like it should. The hub handling should be back instead of forcing camera auth. We've also cleaned up a lot of other pieces and hopefully getting really close to a release. I know it's been a really long time and it's very close to coming out. |
|
Ok, a couple more credential handling things as well were just pushed. Please test the changes and let me know how things work everyone! |
|
@ZeliardM tested on my end with my RV30 and P110, and it still works great |
Retest on latest commit (
|
@ZeliardM credentials recalled on reboots, and P110 plugs working perfectly. Thanks! |
RV30 Max validation update for PR #1592Tested against the current Device under test: Static checks
Relevant feature IDs confirmed in the PR code: Runtime results on RV30 Max
Reversible write details
Motion command detailsThe robot accepted and executed the motion commands, confirmed by status reads:
However, each action command returned this CLI error after the robot had already accepted the command: This looks like a CLI formatting issue for action responses, not a TPAP transport/device-control failure. The likely code path is ConclusionFor RV30 Max, the current PR works for the practical TPAP paths:
The only issue found is the CLI action-response formatting error above. I would not consider that a blocker for the TPAP implementation itself; it can be handled as a small CLI follow-up fix. |
Discovered with new firmware for devices, TP-Link is implementing a new Encryption Type, TPAP. This is an initial implementation to see if the coding works for the handshake. Testing of the code coverage still has to be worked on. The initial implementation includes the new transport, changes to the device_factory to allow devices to select the new transport, and a change to the project to include ecdsa as a new dependency along with cryptography for the new tpaptransport.py.