Sesame-Device/README.md
Christoph Hagen eb982b3287 Add readme
2022-05-01 20:57:11 +02:00

70 lines
6.4 KiB
Markdown

# 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](https://christophhagen.de/projects/software/sesame.html), and the code for the [server](https://christophhagen.de/git/ch/Sesame-Server) and the [remote](https://christophhagen.de/git/ch/Sesame-iOS) are also available.
## Requirements
The following Arduino libraries are required:
- [ESP32 Arduino Core](https://github.com/espressif/arduino-esp32)
- [ESP32Servo](https://github.com/madhephaestus/ESP32Servo)
- [Websockets](https://github.com/Links2004/arduinoWebSockets)
# 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
4. The *remote* creates a message with time and counter and signs it with the remote key
5. The *remote* transmits the message to the *server*
6. The *server* sends the message to the *device*
7. The *device* checks the message and unlocks the door
8. The *device* signs a response message with the new counter with its own key
9. The *device* transmits the response to the *server*
10. The *remote* checks the *server* for a *device* response
11. 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](https://tls.mbed.org) and [micro-ECC](https://github.com/kmackay/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.