Every IoT device has a different hardware design. Each has different capabilities and makes different security tradeoffs. It’s helpful to describe broad ‘hardware classes’ or ‘technology levels’ of devices.
These classes let us classify the capabilities and cost of devices and help us to understand why particular tradeoffs are made in a device’s design.
These are 32 or 64-bit CPUs, usually ARM, with an MMU and external RAM. They can run Linux. Implicit in this is that they can also run OpenSSL and perform cryptographic operations (particularly public key operations) quickly.
Power envelope is the largest of anything discussed here, with minimum continuous power draw typically in the 10mW range and very large peak power consumption (watts). Raspberry Pi and BeagleBone are common development boards that fall into this class.
These are easy to develop for – you can use an off-the-shelf Linux distribution in most cases. Your chip vendor will probably supply one for you.
Because you’ve got lots of RAM and can afford dynamic allocation, you can use higher-level languages than C or C++. Your development will be faster and cheaper if you use something like Python or Go for non-real-time parts of the application.
The hardware requires a CPU, external RAM (sometimes on-package, but always separate die), external flash and relatively complex power supplies. The increase in COGS is typically $15 or more, which translates to a $30-$100 difference in the final retail price of the device.
Linux is a big, heavy operating system for an embedded system. It has longer boot times, unpredictable real-time behaviour and a large, complex software stack that is difficult to reason about. You gain fast firmware development, easy access to third-party software and flexible filesystems.
Linux can take a long time to boot – often longer than users will tolerate. Typical boot time is 30-60 seconds. Sub-20 seconds is achievable without much work. There are research efforts to bring this down to under five seconds. Five seconds is still too long for many applications (control systems – medical, industrial, drones) but they will usually use separate microcontrollers for the time-critical functions.
The possibility that a Linux system might not boot reliably or in a predictable amount of time (e.g. failed
fsck, down network) can be enough to eliminate it from many applications. Without a UI or human to power-cycle it, you may not be able to bring it up again.
Lots of Linux systems ship with an extra microcontroller (like IPMI) that can reset the machine if it doesn’t respond in a fixed period of time. Often this micro will need to talk over the network – with all of the associated security risks. Now you have two embedded systems to worry about!
Embedded Linux devices are vulnerable to all of the same problems that a Linux machine on the Internet has. You’ll need to ship regular security updates, which will probably require a longish period of downtime to apply.
You can get the same CPU power as a Huge device (32-bit ARM clocked at anything you like) but bundled with on-chip RAM and flash. This is a great compromise for many devices. COGS is significantly lower due to the integrated storage and the device will have more built-in peripherals.
These can have megabytes of flash and RAM or as little as kilobytes. Power consumption can be very low, but you must go smaller for the lowest-power devices (microwatt and lower).
You can’t (as of 2016) run Linux on these as they do not have enough RAM or an MMU. You need to select an RTOS or ucLinux. You can’t just pull software components from the Internet; you must consider how they will be integrated into your firmware. As a result, firmware development time will be longer.
As you’re using an RTOS from a third-party vendor, you probably have all of the vulnerabilities that a Linux system does, but without the intense scrutiny that Linux has. In other words, you’re just as vulnerable, but you don’t know it.
These devices are capable of the whole range of cryptographic operations, but because you’re using a custom software stack, you can’t just drop in OpenSSL. You need to be very careful to ensure that any cryptographic libraries you include are correct, secure, and legal for you to bundle with your product (in the export controls sense). Supporting the full range of certificate operations (expirations, revocations, updates) requires flexibility in your use of flash, and that is challenging as you don’t have a general-purpose filesystem to rely on.
Increase in COGS is $1-$5.
Sometimes these are embedded into other SoCs, such as WiFi modules.
16-bit with integrated RAM and flash. There is no dominant architecture at this time. You’ve probably got 16-1024kb of onboard RAM. Clock rates range from 4-80MHz.
You can use C++ but the storage and runtime overheads may be burdensome. You might be restricted to plain C. You could use dynamic memory allocation, but you probably don’t have enough RAM to do so safely.
To save power there are provisions for switching the CPU and peripherals off. You usually won’t see sub-1MHz clock rates.
Public key crypto is doable but takes significant development effort. The CPU time required might be noticeable by the user. You should consider using an external cryptoprocessor.
These are often embedded in BLE and Bluetooth chipsets.
8-bit CPUs e.g. AVR8, 8-bit PIC, 8051.
Often Harvard architecture (split instruction/data memories). Often the instruction memory is mapped directly to flash. This is interesting for security as buffer overflows will trash data RAM but not affect instructions.
These are often embedded in smaller RF chips such as the Nordic nRF series.
They can have tiny power consumption if programmed appropriately; they can run for years on a coin cell.
You technically can run C++ code on these, but there’s no point. You can’t fit much code on them in the first place, C++ gets poor compiled code density, and you’d only use C++ if you have complex software anyway. So just stick with C.
Because quiescent power consumption is so low, some applications stop thinking in terms of continuous power consumption (e.g. 10$\mu$A continuous) and start thinking in terms of number of power-consuming operations (e.g. 400 door strike activations on a single primary cell). You don’t use rechargeable cells in these applications because self-discharge is too high. This saves further on BOM cost.
Symmetric crypto is usually OK on these, but key setup time can be noticeable. Public key crypto is generally impossible as they don’t have enough RAM to hold the key. Of course, any cryptography is going to run the CPU hard for a long time, and this is going to hurt your battery life.
If you’re using coin cells to run your device, the peak power consumption can pull their voltage low enough that the CPU will brown out (or worse, latch up). This is problematic for boot-time firmware verification; a device will be fine if you leave it on, but if you turn it off it won’t be able to start again.
8-bit, under 128 bytes of static RAM and maybe a kilobyte of flash – tinyAVR, for example.
There’s probably not enough RAM to store a symmetric key, so any crypto is challenging here. Some algorithms have smaller working set sizes, but you’re in desperate territory. The vast majority of designs that need cryptography will select a large CPU or have a dedicated cryptoprocessor to do the heavy lifting.
Typical clock rates are 128kHz or 4-16MHz. If you’re in the MHz range and have enough RAM, you can run some symmetric algorithms. kHz-range designs will incur noticeable delays.
You can use C. You might use assembler if you’re counting pennies.