The Internet of Broken Protocols: Showcase #3

(complete list of showcases:

Administrative note: I'm going to post my solution for showcase #1 soon. The answers that I got from readers are great, I've already learned something new. Thank you and please keep them coming!

Updated: solution posted! Sorry for the delay :)


Bob bought a smart lock. The lock has a small screen, supports Bluetooth, and once paired with a phone it automatically unlocks itself when the phone is nearby. The manufacturer doesn't rely on Bluetooth for security, but designed their own protocol. You'll find the description of the protocol below, please identify any weaknesses. You can comment or email me at with your solution. I'll update this post with my solution in 48 hours.

The protocol consists of two sub protocols: pairing and unlocking. Bob needs an app made by the lock manufacturer.

# Pairing

1/ The lock and the app perform an unauthenticated Curve25519 key exchange. Let K denote the 32-byte shared secret.

2/ The lock calculates HMAC-SHA256(K, "SMARTLOCK"), converts the MAC to a number and displays on its screen the last 6 digits.

3/ The app calculates HMAC-SHA256(K, "SMARTLOCK"), converts the MAC to a number and displays on the phone screen the last 6 digits.

4/ Bob compares the two numbers and presses OK on the app to proceed if they match; otherwise he presses CANCEL to close the connection. This step helps prevent man-in-the-middle attacks.

5/ If Bob pressed OK in step 4, the pairing is considered successful.

# Unlocking

1/ The app and the lock initialize a counter which starts with 0. This counter helps prevent replay attacks.

1/ Every 20 seconds, the lock broadcasts over Bluetooth HMAC-SHA256(K, "PLEASE UNLOCK ME").

2/ If the phone is nearby it would see the broadcast and the app would verify the HMAC and send counter || HMAC-SHA256(K, counter || "OK UNLOCK YOURSELF"). The app increases its counter.

3/ The lock verifies the HMAC, extracts the counter and checks that it is larger than or equal to its local counter. If the HMAC is invalid or the counter is smaller, the lock does nothing. Otherwise it overwrites its local counter with the new value and unlocks itself.


I got answers from the usual suspects, i.e., Andrew L., Thắng N., Carl M. and Alex B. Andrew L. provided the most comprehensive answer, so I'm going to use that as my answer :). Note that none rather than Andrew actually discovered the attack in the second paragraph.

"The pairing protocol doesn't seem to use short authentication codes right.  A strong protocol would cause both devices to commit to showing a code before either device learns what the code is.  Since nothing appears to do this, a MITM could force ~1M key exchanges with each side until it gets lucky and gets the same code on both sides.

That attack can be strengthened by trying ~1M DH secrets internally until the right code occurs.  Since DH is usually fast, this allows a MITM to be undetected in a single try.

If the DH exchange has small subgroups, then a MITM can probably even force the same full key on both sides by replacing the DH public keys with generators of a small subgroup.

(Hey, protocol designers: after doing DH, you still have the public keys you exhanged.  Use them!)

Unlocking is weak, too.  The lock sends the same challenge every time.  An attacker can send the challenge to the phone even if the phone is nowhere near the lock and then relay the response to the lock.

(Hey protocol designer: you have bidirectional communication.  Have the lock send a unique challenge and have the phone send a MAC or similar response to the challenge.  And then have the lock enforce a short time limit on the whole exchange to make long-distance relaying harder.)"

Now a new challenge: how do you fix this protocol?