Skip to content

Instantly share code, notes, and snippets.

@kabbi
Last active September 13, 2024 10:32
Show Gist options
  • Save kabbi/32658d7d3a086cd47d877882933a9908 to your computer and use it in GitHub Desktop.
Save kabbi/32658d7d3a086cd47d877882933a9908 to your computer and use it in GitHub Desktop.
Yeelight xiaomi mesh light bulb auth sequence dump

Service UUID 0000fe95-0000-1000-8000-00805f9b34fb

Model MJDP09UL, yeelink.light.mbulb3

Connection sequence:

  • read version
  • mtu to 247
  • write to [0010] a4
  • notified [0016] 0000040006f2
  • write to [0016] 0000050006f2 // mtu negotiation / echo test, device sends us the number repeated number times, like f2 is 242 bytes mtu
  • notified [0016] 00000401f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2 // we verify we can receive message this large
  • write to [0016] 00000501f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2 // and device verifies we can send message this large

  • write to [0010] 50000000 // mesh login step 3
  • write to [0016] 000000030100 // FlowPacket, packageType = 3, frameCount = 1
  • notified [0016] 00000101 // ACKPacket, status = 1
  • write to [0016] 0100ef4aa18195dd09baeb0600290f13d9355c9c06910f6fc52d81eab85467b8ce30761741ef29e6d327d88c2b2b657d8f6a32c12e76f6bd4d2403f6918638646831 // DataPacket, seq 1, seems to be 64 bytes of secp256r1 public key
  • notified [0016] 00000100 // ACKPacket, status = 0
  • notified [0016] 00000203b9cd02e363185ce74cec57be7cd0b83d0126908b4d306fda4ba2df8100e1cfb268289deede73b4e8f5728a99e3ec968186594eb90190fdb552a8747f07b3970e // SingleCtrPacket, type = 3, payload = ?
  • write to [0016] 00000300 SingleActPacket, status = 0
  • write to [0016] 000000050100 // FlowPacket, packageType = 5, frameCount = 1
  • notified [0016] 00000101 // ACKPacket, status = 0
  • write to [0016] 0100aac37a2bad4e0e97 // DataPacket, seq 1, aes-ccm-encrypted (using second half of sessionKey as aes key and a static 101112131415161718191a1b nonce) crc of previous received data packet
  • notified [0016] 00000100 // ACKPacket, status = 0
  • notified [0010] 51000000 // mesh login complete?

  • read version
  • read version
  • done

Crypto

  • sessionKey: HKDF(blob, 'miot-mesh-login-salt', 'miot-mesh-login-info', 64)
    • blob: 32 bytes + 32 bytes
      • 32 bytes of ECDH secret of secp256r1 session private and public keys
      • 32 bytes of gatt ltmk cloud key
  • auth packet blob: aes-ccm encrypted payload
    • payload is CRC32 of device public key?
    • nonce is static, 101112131415161718191a1b
    • key is second half of sessionKey, 128 bit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment