Fix 5 protocol 3.5 (6699) packet bugs causing v3.5 devices to stay unavailable#1
Open
aimaaaimaa wants to merge 1 commit into
Open
Conversation
…able Tested against a Mirabella Genio A60 RGB bulb (bf5a70c8c88945ac62lhk1). Before these fixes the device never connected; after it connects and reports status correctly. Bug 1 — pack_message_6699: length field incorrectly included the 4-byte trailing suffix (+4), making it 48 instead of 44. The length field is part of the GCM AAD; a wrong value produces a wrong GCM tag, so the device silently rejects SESS_KEY_NEG_START and never responds. Fix: remove the +4 from the length calculation. Bug 2 — unpack_message_6699: payload_end was calculated as header_len + header.length - 4, cutting 4 bytes short and placing the ciphertext/tag boundaries incorrectly, causing GCM decryption to fail on all device responses. Fix: payload_end = header_len + header.length (suffix is outside plen). Bug 3 — unpack_message_6699 + add_data: the data-length check and buffer-advance in the 6699 branch of add_data did not account for the 4-byte trailing suffix that sits outside the plen-bounded region. Fix: +4 on both the length check and the buffer advance. Bug 4 (retcode) — unpack_message_6699: all responses from v3.5 devices include a 4-byte return code at the start of the GCM-encrypted payload (0x00000000 = success), matching the 55AA convention. This was not stripped, so _negotiate_session_key used the wrong nonce (deriving a wrong session key) and DP_QUERY responses started with \x00\x00\x00\x00 causing JSON parsing to fail. Fix: strip the 4-byte retcode from decrypted payload and surface it in the TuyaMessage retcode field, consistent with unpack_message (55AA). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.
Summary
This fixes 5 bugs in the 6699 protocol implementation that prevented protocol 3.5 devices from ever connecting. Tested against a Mirabella Genio A60 RGB bulb.
Bug 1 —
pack_message_6699: length field too largeThe length field included the 4-byte trailing suffix (
+4), making it 48 instead of 44. Since the length field is part of the GCM AAD, a wrong value produces a wrong GCM tag — the device silently rejectsSESS_KEY_NEG_STARTand never responds. Fix: remove+4from the length calculation.Bug 2 —
unpack_message_6699: wrongpayload_endpayload_endwas calculated asheader_len + header.length - 4, cutting 4 bytes short, placing ciphertext/tag boundaries incorrectly and causing GCM decryption to fail on all device responses. Fix:payload_end = header_len + header.length(suffix lives outside plen).Bug 3 —
unpack_message_6699+add_data: buffer handling missing +4The data-length check and buffer-advance in the 6699 branch of
add_datadid not account for the 4-byte trailing suffix outside the plen region. Fix:+4on both the length check and buffer advance.Bug 4 —
unpack_message_6699: 4-byte retcode not stripped from responsesAll responses from v3.5 devices include a 4-byte return code at the start of the GCM-encrypted payload (
0x00000000= success), matching the 55AA convention. This was not stripped, so:_negotiate_session_keyused the wrong nonce → wrong session key derivedDP_QUERYresponses started with\x00\x00\x00\x00→ JSON parsing failedFix: strip the 4-byte retcode from the decrypted payload and surface it in the
TuyaMessageretcode field, consistent with howunpack_message(55AA) handles retcodes.How it was diagnosed
logger/set_level)Test plan
DP_QUERYresponse decrypts and JSON-parses correctlyunpack_messagepath is unchanged)🤖 Generated with Claude Code