Open Sesame. Sesame is a smart door lock from the
CandyHouse. It uses Bluetooth Low Energy to communicate wirelessly with
smartphone apps. We are going to explain its BLE protocol and how we can write a
script to control it. The protocol is reverse engineered from its Android app.
This is not a full protocol documentation. I only reversed it just enough to
lock/unlock the door.
BLE Services
The device exposes two BLE services that we can discover:
Operations: Normal operation service 00001523-1212-EFDE-1523-785FEABCD123
DFU: Device Firmware Upgrade service
DFU service is for upgrading firmwares while the operations service is where all
the fun happens and it exposes a few characteristic that we can use to read /
write data.
Command: 00001524-1212-EFDE-1523-785FEABCD123
Status: 00001526-1212-EFDE-1523-785FEABCD123
The packet format
Before we can send anything to the lock, we need to first understand the format
of its packet.
HMAC
macData
md5(userID)
S/N
OP
payload
32
6
16
4
1
optional
Where:
macData is the manufacturerData you can read from the BLE advertisement
packet: it is the Sesame’s MAC address with 3 bytes of zeroes prepending it,
which you will need to strip
userID is your email address
S/N is a number read from the Status characteristic
OP is a number indicating operations: LOCK = 1, UNLOCK = 2
payload is not needed for locking and unlocking
The HMAC
HMAC is
a standard way to authenticate the authenticity of a message. Sesame used
SHA-256 as the hash function. The password can be a bit hard to extract. I
believe (which means I traced the reversed code, but I have not verified if my
assumption is correct) it came from a password which can be retrieved by
logging into their XMPP server and chat with the server for user profile.
However, it will need to be decrypt with a hard-coded key from the app. I was
lazy to going through this so I wrote a
Xposed module
to extract it from the app. I hooked on to the SecretKeySpec constructor and
wait for it to be initialized with the HMAC password.
Reading the Status
The serialNumber is an incrementing, rollover counter that we need to read
from the device and include in the packet. It is located at bytes 6 ~ 10 of the
response of the Status characteristic. You will need to plus one before you
use it. Byte 14 is somewhat interesting as well, it is the error code for last
command. You can find a list of error codes in the example code.
Wrapping it up
Pun intended. Before you can send out the constructed packet, you will need to
break it down to a series of 20 bytes-sized packets. The first bytes is PT,
indicating which part is the packet and then 19-bytes of the original payload.
PT indicates a series of packets: 01 for the first one, 02 for the rest and 04
to finalize it
With that ready, you can simply write the wrapped packet to the Command
characteristic. It’s a write-and-ack endpoint.
Notes & Trivia
The reversing was done with apktool, JADX and Android Studio
Interestingly, the Sesame app use XMPP protocol to talk to its cloud
counterparts
The early version app contains a lot of Taiwanese internet memes in it.
#TaiwanNo156不能亡
Example Code
Here’s an example snippet for unlocking a Sesame. Have fun!