Skip to content

feat: Add Protocol 3.5 Support (AES-GCM) #285

@damacus

Description

@damacus

feat: Add Protocol 3.5 Support (AES-GCM)

Summary

Protocol 3.5 is a major protocol revision that uses AES-GCM encryption and a
completely different packet format. This is required for the newest Eufy vacuum
models.

Technical Details

Based on tinytuya protocol notes:

Packet Format Changes

Old format (3.2-3.4): 0x000055AA prefix

000055aaSSSSSSSSMMMMMMMMLLLLLLLL[RRRRRRRR]DD..DDCC..CC0000aa55

New format (3.5): 0x00006699 prefix

00006699VVRRSSSSSSSSMMMMMMMMLLLLLLLL(II*12)DD..DD(TT*16)00009966

Where:

  • 00006699 - New prefix
  • VV - 8-bit version field (always 0x00)
  • RR - 8-bit reserved field (always 0x00)
  • SSSSSSSS - 32-bit sequence number
  • MMMMMMMM - 32-bit Command ID
  • LLLLLLLL - 32-bit packet length (IV through Tag, excluding footer)
  • (II*12) - 96-bit (12-byte) per-packet AES-GCM IV/nonce
  • DD..DD - Variable length encrypted payload (NOT padded)
  • (TT*16) - 128-bit (16-byte) GCM authentication tag
  • 00009966 - New footer

Encryption Changes

Aspect Protocol 3.3/3.4 Protocol 3.5
Algorithm AES-128-ECB AES-128-GCM
Padding PKCS7 (multiple of 16) None
Integrity CRC32 or HMAC-SHA256 GCM Tag
IV/Nonce None (ECB mode) 12-byte per-packet

Device Discovery Changes

Protocol 3.5 devices do NOT send unsolicited discovery broadcasts. Instead:

  1. Client broadcasts {"from":"app","ip":"192.168.1.42"} to port 7000
  2. Device responds directly to the specified IP
  3. Discovery packets use GCM encryption with key = MD5(yGAdlopoPVldABfn)

Session Key Negotiation

Protocol 3.5 also requires session key negotiation (same as 3.4), but uses the
GCM IV from the client nonce for key derivation.

Current State

  • ❌ New packet format not implemented
  • ❌ AES-GCM encryption not implemented
  • ❌ Active device discovery not implemented
  • ❌ Session key negotiation with GCM not implemented

Affected Models (Suspected)

Models that likely use Protocol 3.5:

Implementation Plan

Phase 1: Packet Format

  1. Add new magic prefix/suffix constants for 6699 format
  2. Create Message35 class or extend Message to handle new format
  3. Update Message.from_bytes() to detect and parse 3.5 packets

Phase 2: AES-GCM Encryption

  1. Add GCM cipher support to TuyaCipher
  2. Implement per-packet IV generation
  3. Implement GCM tag verification

Phase 3: Session Keys

  1. Implement 3-way handshake with GCM encryption
  2. Handle session key derivation with GCM IV

Phase 4: Device Discovery

  1. Implement active broadcast for device discovery
  2. Handle direct responses from devices

Code Changes Required

tuyalocalapi.py

# New constants
MAGIC_PREFIX_35 = 0x00006699
MAGIC_SUFFIX_35 = 0x00009966

# New cipher mode
from cryptography.hazmat.primitives.ciphers.aead import AESGCM

class TuyaCipher:
    def encrypt_gcm(self, data: bytes, iv: bytes) -> tuple[bytes, bytes]:
        """Encrypt using AES-GCM, returns (ciphertext, tag)"""
        ...
    
    def decrypt_gcm(self, data: bytes, iv: bytes, tag: bytes) -> bytes:
        """Decrypt using AES-GCM with tag verification"""
        ...

References

Related Issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions