Ever wondered why your brand-new Philips Hue suddenly starts blinking SOS?
And didn’t you wear an Apple Watch a few minutes ago, and why did you buy 2 TVs in that time?
Security of smart and embedded devices is one of those topics everyone heard about – might it be good or (more likely) bad.
Let us take a journey down the rabbit hole and find out how such devices handle security today and how we can improve that. On that journey, we will visit 5 points which, in all fairness, are going to be quite technical.
Security today
As hinted by the introduction, security doesn’t seem to be the focus of most manufacturers. This can be harmless like the Philips Hue prank but can also be rather problematic. A lack of security can enable an attacker to gain access to sensitive data like your banking information or even some very private stuff like the camera of your Smart Vibrator.
But, a lack of security might be a blessing for some people. If you try to incorporate hardware from an arbitrary manufacturer into your Smart Home and they do not provide a convenient API, the only option might be to reverse engineer one for yourself. This is the basis of quite some nice “Hacks” in the Maker scene.
Security Challenges
One of the main problems implementing security in embedded devices is the fact, that they are usually very resource constraint. This includes power consumption, CPU and Memory limitations and most of the time no embedded security hardware support.
The last point is especially important if someone has physical access to the device. The best encryption during transmission is completely useless if someone read out the whole memory beforehand with the key stored in plain text. This also includes stored SSID and Passkey if the device is included into a WiFi Network.
Now for the other constraints since all of them are tied together.
If you have a Microcontroller like the ATmega328 (used in the Arduino Nano) with 16 MHz, one can instantly see that there is not a lot of room to implement fancy encryption algorithms. Most of the time the actual firmware (like for example a LED Controller) is already using every available CPU cycle and most of the memory.
Using more powerful Microcontroller alleviates this problem at the cost of using a bunch more power. This might not be as important for Microcontroller with a constant power supply, but a lot of them are connected to a tiny battery which should run for years.
All in all, it’s not that hard to see why most people try to avoid the whole security issue altogether.
Possible Solutions
First of all, it’s important to assess the actual security risk. This depends on the intended location of use and the application of the device itself.
It might not be that important to secure a device against physical access if you build it yourself and use it in your own home to control your kitchen lighting via your mobile phone.
If a thief gets access to it, you already have way bigger problems than a stolen WiFi password. And fair chance to find a normal thief capable of cloning the memory of an embedded device just to get your WiFi password.
Now for the more interesting and probably way scarier part.
Let’s see what can happen if someone gets physical access to a device which is not encrypted.
In December 2015 on the annual CCC Alexander Graf had a talk about accessing his cable modem and with that around 3 Mio. Modems in Germany. All he had to do was buy the same modem for cheap and start poking. If you have 50 minutes to spare, watch the video which is very entertaining and frightening at the same time.
Now let’s imagine there is an embedded device inside a huge company which is connected to the WiFi network. It’s just a small environment monitor in some office.
Now let’s further imagine there is a nice technician there to fix something and he happens to find this device in his pocket a bit later.
Sadly this is one of those nice unencrypted devices and he is capable of reading out all the information necessary to access the WiFi with another device of his choosing. With that, he circumvented quite a big part of the security already.
Now that we have established that some physical encryption might be nice, let’s look at the communication itself.
That unencrypted communication is a bad idea should come as no surprise to anyone.
Using conventional encryption is very resource intensive most of the time. To improve that and keep the needed CPU cycles to a minimum one can use other, more lightweight encryption algorithms.
Some Microcontrollers have actual hardware support for encryption built-in. This enables the usage of established secure communication standards like SSL. The ESP32 used later on in the practical example is such a candidate.
Unfortunately only a very small amount of currently available Microcontrollers support such features out of the box without sacrificing too much resource efficiency.
With this, it should be possible to create a firmware with an acceptable amount of security. Assuming you use common sense for your normal code and don’t leave huge holes in your security through the way you design software. In that case, no amount of physical or software based encryption can help you.
Let’s get physical
So let’s see what we can do to get an IoT devices using an ESP32 (like this one) decently secure.
Let’s assume the ESP should be connected to your WiFi and within the ESP we get some kind of data via I²C. This data should now be transmitted via MQTT to a Smart Home Middleware.
Furthermore, you’re a bit paranoid that someone might read out the memory to get to your WiFi and MQTT credentials because the device sits somewhere in your small garden shack.
Now we need a list of stuff we need to secure the device as much as possible:
- secure method to connect to your WiFi
- encrypted communication via MQTT
- physical encryption to prevent copying of the memory
The first point is rather easy to achieve. If you are sure you don’t change your WiFi very often, you can bake the credentials into your firmware. Just make sure you don’t commit them to a public repository.
The second option would be to use Push-Button WPS (never use PIN based WPS, that’s as insecure as it gets!). Support for both options is already part of the standard esp-idf (the SDK provided by espressif, the creators of the ESP Platform).
On to the second point.
That’s actually easy as well. Support for OpenSSL is part of the esp-idf and can be used in combination with an MQTT Library of your choosing to encrypt the MQTT traffic to your MQTT Server (e.g. mosquitto). One of the prominent ones I used on a few projects is maintained by tuanpmt on GitHub (https://github.com/tuanpmt/esp32-mqtt).
Now for the actual fun part since up until now, this can be done with most Microcontroller on the market. So how do we enable memory encryption on the ESP32?
The encryption is handled by the bootloader and is done automatically if the “Enable flash encryption on boot” option is set in the menuconfig. The key is stored in efuse key block 1 and read/write protected against software access. The encryption itself uses AES-256. Every two 16 byte blocks a unique key is used which is derived from the flash encryption key. Encryption or decryption via the UART bootloader is disabled by default and only 3 subsequent flashes via serial reflashing are possible. After 4 serial flash update cycles, the FLASH_CRYPT_CNT efuse has the maximum value of 0xFF and encryption is permanently DISABLED. To prevent this from happening, flashing via Over-the-air (OTA) Updates is the recommended way. There is no limit on flashing via OTAs.
One additional feature is to use pre-generated keys, which might be useful for development purposes. It’s not the recommended way for production systems since it’s not ensured that the generated keys are as good as the internally generated ones.
Memory encryption is all nice and well, but what about Secure Boot?
Luckily that’s also supported by the ESP32.
The good news is that all critical data is stored internally in the chip inaccessible in efuses (BLOCK2 to be more precise). To enable secure boot one needs an ECDSA public/private key pair (AES 256-bit). On first boot, a device secure bootloader is created using hardware RNG and stored R/W protected in efuses. Additionally, a security digest is created. The digest is composed of the key, an IV, and the bootloader contents. JTAG and ROM BASIC interpreter should be disabled via burning the corresponding efuses. Secure boot is then permanently enabled by burning the ABS_DONE_0 efuse.
From now on, only bootloader images will be booted if the security digest matches. On every boot, a newly calculated security digest will be compared. The whole digest and comparison is done by the hardware and is not readable by software.
A few more tips on creating the key:
Use an industry standard like OpenSSL to create the keys and don’t try to do your own stuff. That’s usually not a good idea.
Keep the private key as secure as possible, if it gets out you are screwed.
Use the “Secure Boot: One-Time Flash” option for production devices. This way each device gets a unique key which is never stored outside the device itself.
Conclusion
Creating a device which is secure regarding readout of flash and making sure only a signed firmware is bootable, is not that complicated. This, of course, is only true if you are using something like the ESP32. As far as I know, the popular Arduino Platform, for example, doesn’t support features like that.
If you are using the ESP32 in combination with the esp-idf you’re able to use most C++ features, so the security of the rest of your firmware is completely up to you and your ability to write secure software. Since the chip sports a 240MHz Dual Core for around 5-10€ you get quite a lot of power for your money and the ability to secure your inventions better and easier.
Leave a Reply
You must be logged in to post a comment.