In today’s technology environment customers rightfully expect device software capability to include software update. Software feature or bug updates need to be delivered seamlessly, transparently, securely, and reliably. As embedded product designers, our focus is typically on implementing core product features. In some cases, our hardware platform board support package (BSP) may not contain the features necessary to implement secure software download in our application environment.
Bridging the gaps in the default platform support package is essential to meeting customer expectations and providing responsible and effective device security. The challenge as product developers is to minimize the effort required to implement device software updates without sacrificing capabilities or security.
The stakes are high with embedded device software updates, and mistakes could result in a dreaded “brick” scenario, with your product no longer functional and needing to be returned for repair or replacement. This article describes some best practices engineers may use when implementing a software update framework for sensing devices, including those connected via Bluetooth BLE.
New cases of hacker attacks on IoT devices are publicized almost daily. One of the first considerations in development of a device update framework should be security. Your software update mechanism needs to be designed in a way that ensures a hacker cannot use your update scheme as a way to install or modify software on your devices.
Fortunately, the combination of relatively powerful embedded processors capable of cryptography algorithms and open source licensed software libraries for cryptography mean that most any device is capable of securing communication of device software updates with peer reviewed and standards laboratory approved algorithms. One strategy for protecting device updates from unauthorized use is the use of public key or asymmetric cryptography.
The public key or asymmetric cryptography scheme is the same one used today to secure the world wide web via the ubiquitous HTTPS protocol. Two keys are used which are represented by massively large numbers, typically 128 to 256 bits in length. To put this in perspective, a 256 bit number represents approximately 1x1077 possible combinations, which is approximately the number of digits required to assign a unique number to every atom in the universe. The fastest supercomputer in the word would take multiple universe lifetimes to brute force try every possible combination of a 256-bit number in any simple math operation, making any brute force attempt at key determination impractical.
Public key or asymmetric cryptography uses mathematical relationships between two keys, a public key and private key. The cryptographic algorithms are used to guarantee a mathematical translation of a message or signature must have been performed with access to the private key. However, the value of the public key does not provide any useful clues about the content of the private key. In practice this means we can create a private key which never leaves our development environment, and public key which is saved to each device in unencrypted format, as shown in figure 1.
Figure 2 describes the process used in the development environment to create a signed device update package using the private key. The device update file is hashed using a hashing algorithm like the Secure Hash Algorithm or SHA. Any change to the device update file would result in a change to the hash. This hash is used along with the private key to generate a signature.
See figure 3 for the operation used to validate this device update package within device firmware. The device verifies the signature on the hash with its public key, recovering the signed hash for this file. The device can compute its own hash using an algorithm like SHA. If the signed hash and the computed hash are equal, the device can be certain the device update package was signed using the private key.
Neither the device update file nor the signed hash needs to be encrypted in this scheme, and the public key does not need to be transferred or stored in an encrypted format. The public key algorithm in this example is used for authentication purposes only, to ensure the update was authorized by the holder of the private key.
The algorithms used to operate on these massively large numbers are well documented but not trivial to implement in an efficient way on low resource platforms such as embedded devices. Fortunately there are open source options available for fast, peer reviewed, and efficient public key cryptography libraries on embedded devices.
- The micro-ecc library implements a type of public key cryptography known as Elliptic Curve Cryptography (ECC), includes curves defined by standards bodies including NIST, and is available under a permissive BSD license. This library can be combined with a hashing algorithm such as SHA-256 to support a public key encryption scheme like the one mentioned above.
- The wolfSSL wolfCrypt library includes several options for asymmetric cryptography using ECC or RSA, as well as several hashing algorithms, has been previously validated with NIST FIPS-140-2. The library full source is available with a GPLv2 license for open source projects or a paid commercial license.
Making Updates “Brick-Proof”
The worst nightmare of any product developer or engineer is a scenario where your device is turned into an inoperable “brick” which must be returned by the customer for service or replacement. The security best practices discussed in the previous section help ensure your device update mechanism won’t accept a device update from a hacker which bricks your device. However, there are still cases like power loss during update, corruption of packets or other communication issues during transfer which need to be handled correctly by your device update algorithm.
A common way to support brick proof updates on devices is via an A/B update scheme. The details of the implementation of an A/B update scheme typically depend on the support and customization options for the device bootloader used by the platform. However, the basic idea is to keep multiple copies of the device software or firmware in flash. One copy is dedicated to the known good software currently running on the device when an update starts. A second area of flash is reserved for a staging area where a software update can be written. An intelligent bootloader can select between the two images based on image validity and update sequence.
Figure 4 describes a typical A/B flash layout. The bootloader begins at the reset vector. Immediately following the bootloader area is a header describing the first image. This header will contain information like the hash, checksum, size, and update sequence of the first firmware image, Firmware Image A. A reserved space is placed after firmware image A to reserve space for future updates and align the start address for a second Firmware Image B. Following this reserved area is a header and image payload for Firmware Image B.
The bootloader uses logic such as the logic described in the flowchart in figure 5 to determine which image to boot at startup. Cyclic Redundancy Check (CRC) or hash and signature algorithms can be used to verify the image payload is complete and correct based on the contents of the image header.
The image header could also contain a sequence number to identify the most recent image written. The bootloader uses this information to decide which image to boot. A shared memory section can be used by the bootloader to indicate the image source for use in the update algorithm (discussed in the next section).
If neither image is valid, the bootloader would ideally fallback to wait for a device update. However, the mechanisms supported by the bootloader for update may be limited. For instance, the bootloader might not support connectivity via Bluetooth or Wi-Fi. Therefore it’s important to avoid a scenario where neither image is valid. This responsibility rests largely on the update algorithm, as discussed in the next section.
The logic used for the update algorithm in an A/B update scheme is illustrated in figure 6. The update algorithm uses the information provided by the bootloader to determine which image is currently in use. The destination image is chosen to ensure the current booting and known good image is not modified. In other words, if the bootloader selected Image A for the current image boot, the area corresponding to Image B will be used as the destination staging area in flash. This means the update algorithm should never corrupt the last bootable area of flash.
The first step in the update process invalidates the flash header, indicating to the bootloader that this area of flash no longer contains a valid image. The image can then be streamed into flash in partial blocks, avoiding the need to buffer an entire image in memory. After the update has been completely written to flash, the device can read the flash area and validate the image through the security mechanisms described at the beginning of the article.
Only when the image has been completely written, re-read, and validated will the image header be updated to show this image location is valid. A counter value contained in the header will be incremented to show the new image is the latest image written. The device can now be rebooted to boot to the newly updated firmware, using the previous firmware image location the next time an update is requested.
Streaming Update Files
The process of streaming an update file to the device varies by connectivity scenario. For sensors which are connected through Bluetooth BLE, special considerations for the capabilities of Bluetooth BLE transport must be considered. For instance, the default BLE ATT packet size contains only 20 bytes of payload. Not all Bluetooth devices support increasing this value. This is especially important when your update needs to be performed across multiple mobile platforms (iOS and Android for instance).
Using acknowledgements with attribute writes and small attribute sizes may result in unacceptable transfer time for update file transfer. One solution for this problem is to write relatively small packet sizes without acknowledgement and periodically check CRC on the host side to ensure transfers have completed successfully.
Open source projects exist to implement this Bluetooth BLE handshake mechanism on multiple platforms including iOS and Android. The Secure Device Update (SDU) available at www.securedeviceupdate.com implements device firmware capable of supporting Bluetooth BLE update scenarios using public key cryptography as described in this article and open source iOS and Android libraries.
Designing your device software update for security and reliability is critical for delivering the functionality and capabilities your customers expect. With the right planning and design, open source projects can be leveraged to minimize the development effort required and ensure peer reviewed security algorithms are a part of your device update strategy.
About the author
Dan Walkes is a software/firmware engineer with a background in embedded and IoT software and hardware development, and is the author of the Secure Device Update (SDU) library for embedded devices. He owns Trellis-Logic, which provides Embedded and IoT project development services.