Skip to content

Collaboration document for PSK Identity 02

Colin Kuebler edited this page Aug 14, 2020 · 279 revisions

Here we will share and organize our findings and data from #483

Findings

  • firmware OS SDK version did not change, but the hash and build time did
    • OS SDK ver: 2.0.0(e8c5810) compiled @ Jan 25 2019 14:26:04
    • OS SDK ver: 2.0.0(29f7e05) compiled @ Sep 30 2019 11:19:12
      • interesting that this build date corresponds with the release of tuya-convert 2.0, coincidence?
  • psk begins with 02 rather than 01
    • guessing this will tell us the psk algorithm version
  • disabled most of the serial debugging output
    • unfortunate as this was a useful reverse engineering resource
  • did not respond to our smartconfig procedure
    • it may use a new mechanism or additional restrictions have been imposed
  • MAC address in flash appears to be compared with actual device MAC
    • likely to foil reverse engineering attempts by running firmware on a dev board
  • new factory written key found in flash, "pskKey"
    • this may mean the encryption key will no longer be derived deterministically, big bummer
    • only found in @rsbob's backup, looks like @Farfar's was updated to this firmware and thus lacks this factory written key
      • this may mean there is still hope for devices that came with a lower firmware, since updating to this firmware would require fetching the key
      • this is a very interesting new endpoint: tuya.device.uuid.pskkey.get

It appears a unique preshared key is programmed into each device at the factory. Unlike before where the key could be derived from the TLS identity, now the identity is a hash of the device's id and MAC address. For those following along, the new identity derivation is:

'\x02' + 'BAohbmd6aG91IFR1' + sha256(prod_idx + mac_addr)

where prod_idx is the ASCII of the 8 digit product ID, and mac_addr is the MAC address of the device in hex, all lowercase, no punctuation. These parameters are all stored in the flash in a JSON blob at 0xfb000.


What changed was before the PSK was derived directly from the hint. Now it seems the key is preprogrammed at the factory, not computed on the device, and no information about it is ever sent to the server. The device sends its unique ID (basically MAC address) and the server figures out (presumably from a database) what the key should be. The device can request the server downgrade to the old authentication, but the server cannot ask the device to downgrade. Since we emulate the server, the downgrade path doesn't help us.

I tried to load the firmware backup onto a Node-MCU-like board, but I got this error

Yeah, they worked pretty hard on that. There a ton of checks and countermeasures to make running the firmware on anything other than the Tuya device very difficult. I'd assume the concern was counterfeit devices mooching off their cloud services. But as a result, getting this firmware running under a debugger is probably a real challenge. I relied on static analysis personally, so I didn't try it. They do many checks against the MAC address and hardware identifiers and each device is given a unique (?) API key, so if one was cloned, they could easily blacklist all of the cloned devices.

Curious constant (in tuya_tls.c, perhaps?)

Yes. It seems Tuya copied the xkcd getRandomNumber function (https://xkcd.com/221/). The "randomness" comes from a small fixed pool (the string you see there). There's a computation I don't fully understand at the beginning, but it effectively memcpys a substring of that pool to use as the random data for the TLS connection. Now I have no background in cryptography, but as far as I can tell, that is not actually exploitable for us because of the pre-shared key.


Procedures

The missing part is how to compute the PSK from the PSK identity, if that is possible with the information we have.

As @iracigt has said, the prod_idx is used to compute the PSK identity. This is handed to the server by the client during the handshake, so it is not secret information.

prod_idx is not secret information either, it is the first part of the gwId as you have noticed, @CHAZICLE. In fact the gwId is what is being hashed here, which is prod_idx + mac.

The point is that the previous implementation did leak secret information through the PSK identity, which we could use to compute the PSK. Now that it does not, our job is harder.

In order to solve this, we will need samples of actual communications between the client (smart device) and the server (Tuya cloud), along with a copy of that device's firmware. If anyone is able to provide both we may be able to crack this.

One possible procedure to accomplish this would be:

  1. Start with a new device
  2. Create a bridged hotspot using create_ap
  3. Start recording the network interface with tcpdump or WireShark
  4. Connect smart phone
  5. Use the vendor app to connect the smart device to the hotspot
  6. Disconnect and stop recording
  7. Open the device and read the firmware over serial using esptool.py

  1. Install create_ap
git clone https://github.com/oblique/create_ap
cd create_ap
sudo make install
cd ..
  1. Setup a pass through AP (assuming your interface is wlan0)
sudo create_ap wlan0 wlan0 MyAccessPoint MyPassPhrase
  1. Start recording
tcpdump -i wlan0 -w capture.pcap
  1. Connect your phone to MyAccessPoint (or whatever you decide to call it)
  2. Use the app (SmartLife or vendor branded app) to pair the device
  3. Wait for registration to complete
  4. Disconnect the device
  5. Go back to tcpdump and press Ctrl + C
  6. Disassemble the device and connect to the serial port of the ESP
  7. Download the firmware using esptool
esptool.py read_flash 0 0x100000 firmware.bin
  1. Upload both capture.pcap and firmware.bin

Get: https://github.com/espressif/esptool Issue command: esptool.py read_flash 0 0x100000 firmware-backup.bin


Data

Known Affected Devices

  • BSD34 smart socket
  • BSD29
  • Deltaco SH-P01E
  • Bakibo TB95
  • Bakibo TP22Y
  • MoesHouse Smart Downlight
  • loratap sc500w curtain switch
  • Teckin SB50
  • Gosund 800l bulb
  • Merkury MI-EW003-999W LED Light strip
  • DETA Quad Smart Switch (6904HA)
  • DETA Triple Smart Switch
  • Arlec GLD060HA lamp
  • AOFO Smart Power Strip (ZLD-44EU-W)
  • Gosund SP 112
  • Arlec PC399HA

Firmware

Network Captures

Strings

OS SDK ver: 2.0.0(29f7e05) compiled @ Sep 30 2019 11:19:12 [N]%s:%d metedata is without encryption, cover this partition with encrypted data [N]%s:%d var block [%d] last version is without encryption,now need to encrypt data and cover this partition [ERR]%s:%d flash_aes128_ecb_encrypt err [ERR]%s:%d !!!!!!CHIP_MAC:%s FLASH_MAC:%s!!!!!! aes-internal-dec.c aes-internal-enc.c lhttps://a3.tuyacn.com/gw.json https://a3.tuyaeu.com/gw.json https://a3-ueaz.tuyaus.com/gw.json https://a3.tuyaus.com/gw.json {"mac_addr":"500291e8f141","prod_idx":"26636676","auz_key":"wg7xdxUcsi7W0EmnPUlEtuwoyZwcF2W2","pskKey":"GUKgTWzsxGCn8UR5tIFFluuKD2qA8FYmaZwY2","prod_test":false} {"ap_ssid":"SmartLife","ap_pwd":null} {"CC":"CN"} vtrust-flash ESP_E8F141 vtrust-flash


Clone this wiki locally