Is my garage door control with Shelly hardware reasonably safe ? Let’s find it out !

Stuff needed

Here is what you need if you want to try it by yourself:

Understanding BTHome protocol

The BTHome protocol is a well documented open standard that everyone can use for free.

Below is the BTHome service data (BLE payload) for the BLU Button.

FieldBytesDescriptionExample values
UUID2BTHome messages start with 0xFCD2. Bytes are reversed.0xD2FC must be used to generate payloads.
BTHome device information1Flags indicating device capabilities.0x44 for unencrypted payloads, 0x41 when using encryption.
Object type1Indicates what value follows in next byte(s)0x00 for packet ID, 0x01 for battery level, 0x3A for a button event
Object data1-2Data length depends on the object type0x01 for a button (0x3A) press, 0x64 for battery (0x01) at 100%
Object type1Next object type ..…
Object data1-2Next object data ……

Objects are chained together, up to the maximal possible payload size. In this experiment with the seeed studio XIAO-nRF52840-Plus, it wasn’t possible to exceed 29 bytes.

Sample button push at 100% battery payloads : D2FC 44 00EC 0164 3A01 and D2FC 44 00AB 0164 3A01

When not using encryption, the Packet ID (0x00) object is used to determine if a received packet belongs to the same transmission, as the BLE message is sent several times to ensure proper reception by the receiver. This can be observed when doing a raw packet capture with the nRF52840 dongle.

Encryption

The optional, but strongly recommended, BTHome encryption is done using AES-CCM, which is a reputed cryptographic algorithm.

The encryption key is generated on the remote. It must be retrieved with the Shelly BLE Debug app, after pairing the remote with a smartphone. This encryption key is installed manually on the receiver through its web interface. Key exchange is done out-of-band, which is reasonably safe. The only weak point may be the pairing process between the smartphone running the app and the remote. This risk can be reduced by pairing in an isolated environment.

Replay attacks are avoided by incrementing a counter value, which is included in the nonce. Proper checks against this counter value must be done on the receiving side (counter value must be greather than the last one for the message to be accepted).

The counter is a 32 bits value, which allows 4294967296 payloads before it overflows. If an event is generated every second, it would take 136 years before overflow happens. In the case of a garage door, this may never happen. Nonetheless I’m curious to see what happens when the counter overflows.

The encryption design is solid on paper.

Simulating the BLU Button

To simulate the BLU Button, I use my DIY advertiser built with a XIAO-nRF52840-Plus. Unencrypted payloads from above were used to confirm that advertisement are working correctly and are straightforward to test. Encryption is done using the bthome example script.

As there already is a counter with AES-CCM, the Packet ID (0x00) field must not be included in encrypted data. Only Battery (0x01) and Button (0x3A) are kept : 0164 3A01 is our cleartext payload.

FieldBytesDescriptionExample values
UUID2BTHome messages start with 0xFCD2. Bytes are reversed.0xD2FC must be used to generate payloads.
BTHome device information1Flags indicating device capabilities.0x41 when using encryption.
CiphertextDepends on dataEncrypted payload0xD890C2B1
Counter4Little endian (like UUID)0x0A000000
MIC4Message Integrity Check0xA522591A

Sample encrypted payload with 0x0000000A in the counter : D2FC 41 D890C2B1 0A000000 A522591A

Below is the ordered test sequence.

Counter value (little endian)DescriptionAdvertised payloadResult
0x0000000AFunctional test. Must work.D2FC41D890C2B10A000000A522591APass : relay did switch
0x0000000BFunctional test. Must workD2FC419FACE9970B0000000693EFA3Pass : relay did switch
0x00000005Counter value decreased. Must not work.D2FC41F92213B9050000002C3B30EFPass: relay did not switch
0x0000000CValid counter value. Must work again.D2FC41F08CB92E0C000000A31A1C90Pass : relay did switch
0x0000000CReplay attack. Must not work.D2FC41F08CB92E0C000000A31A1C90Pass : relay did not switch
0xF0000000Big counter jump forward. Must work.D2FC41557712F8000000F04A101E93Pass : relay did switch
0xFFFFFFFFBiggest counter value possible. Must work.D2FC41CEB140D8FFFFFFFF6343DC0CPass : relay did switch
0x00000000Counter overflow. Does it still work ?D2FC4104A875E5000000002E36D095Relay did not switch. AES key must be replaced. As you would have to do it after 136 years when pushing the button every second, this is not an issue.

Conclusion

The table below summarizes the observations and tests done above.

Control pointExplanationResult
Standard encryptionUsed encryption protocols are well-recognized standards. No home-brew encryption algorithms are used.Pass : AES-CCM is used
Key exchange securityIs the key exchange secure ?Pass : out-of-band key exchange can be considered as safe, if done properly
Unencrypted payloadReceiving an unencrypted payload must not trigger the output relayPass : unencrypted frames are ignored when encryption is enabled.
Replay attack mitigationReplaying a frame must not trigger the output relayPass : replay attack did not work.

The security of the BTHome protocol seems solid and this installation will definitely stay to control my garage door. Thumbs up for Allterco (Shelly) for providing a free-of-charge BLE implementation that is actually safe to use!