Phone-based door opening: Code and 3D parts for the device https://christophhagen.de/projects/software/sesame.html
Go to file
2024-04-22 12:58:18 +02:00
include New state machine, local UDP route 2024-04-22 12:58:18 +02:00
src New state machine, local UDP route 2024-04-22 12:58:18 +02:00
.gitignore Make example config explicit 2022-07-15 15:03:32 +02:00
LICENSE Initial commit 2022-01-23 09:24:48 +01:00
platformio.ini Use local UDP messages instead of web server 2024-04-20 17:47:44 +02:00
README.md Add readme 2022-05-01 20:57:11 +02:00

Sesame

This repository is part of the Sesame system to remotely unlock a door using a phone. A high-level description can be found here, and the code for the server and the remote are also available.

Requirements

The following Arduino libraries are required:

Hardware

The device is based on an ESP32, which has a servo attached. The ESP (the Sesame device) connects to Wifi, and then opens a Websocket to a Sesame server to listen for requests. The Sesame remote (e.g. an iPhone with the Sesame App) preshares an authentication key with the Sesame device to ensure that only a valid remote may issue unlock commands. The Sesame remote sends an unlock command to the server via a normal HTTPS request, which relays the command to the Sesame device. The server is only needed to establish a bidirectional communication channel between the device and the remote. The device verifies received commands with the pre-shared key and controls the servo, which pushes the physical button to open the door.

Security

The security goal of the system is to prevent an attacker from opening the door by compromising the system.

The security of the system is based on a few assumptions:

  1. The physical security of the device is ensured. Since the device is located within the house it unlocks, anyone with physical access to the device has already achieved the task which the system is supposed to prevent. This assumption reduces the risk of side-channel attacks significantly.
  2. The authentication key is protected on the remote. Compromise of the authentication key is prevented by storing the key within the iOS keychain, which must be suitably protected.
  3. The cryptographic primitives of the system are secure. Sesame uses authentication based on HMAC-SHA256 with a 256-bit random key for fixed-size messages. Freshness is ensured using counters and timestamps. According to the current state of cryptography, this can be considered secure. The biggest source of vulnerabilities are improper implementations, but this one relies mostly on existing and mature software and is very simplistic in its design.
  4. There are no software errors that allow the extraction of the key from the device. This one is the most critical aspect with regard to the security of the system. If an attacker can exploit some flaws in the software used to get priviliged access to the device or the remote, then it may find ways to circumvent the security checks, either by extracting the symmetric key, or by directly accessing the servo. The device sits behind a router, and opens only a secure websocket to the server, plus a connection to an NTP server. The NTP connection is possibly the easiest to compromise, which would allow an attacker to change the time on the device. This would lead to old messages becoming valid again, but for the additional counter included in each of them. Thus, an attacker would also need to prevent any newer messages from reaching the device, in order for old messages to remain valid. To transmit messages to the device an attacker would need to compromise the websocket connection, either by compromising the server, or by getting the device to connect to a fake server. A fake server is difficult to achieve, since the connection is protected by SSL, thus an attacker would require a valid certificate for the server domain. Compromising the Sesame server would probably be easier, but I've taken all steps known to me to protect it from compromise. It has the latest updates, strict security settings for all applications, and strong passwords. Overall, the effort of breaching the system is likely to be much larger than to simply break the door open. This implies that the system is not the weakest link, and does not decrease the overall security of the house.

Privacy

No special provisions (apart from using standard encryption techniques) are in place to provide privacy or anonymity of the users with regard to door unlocks. The system itself does not log access times or other sensitive information.

Operation

The operation of the system can be summarized as follows:

Setup

  1. The remote generates a two symmetric keys (for device and remote messages)
  2. The keys are programmed into the device by flashing the software
  3. The device connects to the server

Unlocking

  1. The remote creates a message with time and counter and signs it with the remote key
  2. The remote transmits the message to the server
  3. The server sends the message to the device
  4. The device checks the message and unlocks the door
  5. The device signs a response message with the new counter with its own key
  6. The device transmits the response to the server
  7. The remote checks the server for a device response
  8. The remote validates the message and checks counter and time for discrepancies.

FAQ

Why not use asymmetric keys?

It would certainly be nice to only store a public key of the remote on the device, and the verify signed messages. Unfortunately I didn't find suitable libraries for the ESP32 and Swift, which are:

  • efficient enough to run on embedded hardware in reasonable time.
  • compatible with each other
  • easy enough to understand and use correctly
  • allow exchange of keys in an interoperable format

I've tested several options, most notably mbed TLS and micro-ECC. But I had problems selecting algorithms I could use on both platforms, couldn't get signatures to verify correctly, or had problems loading and transmitting keys. I've mostly tried to use the secp256r1 curve, but I couldn't find/use any Swift libraries in a compatible way. The issues involved big/little endian conversion, hash-before-sign and key formats. If you have any suggestions, feel free to let me know.

What are the plans for the future?

The next feature I would like to implement is to share one-time keys for the lock with other people. This requires some additional work regarding the code, and also some more thoughts about the security of the system.

Other than that, the system fulfills its purpose, and doesn't need more upgrades at the moment.