The intensity of attacks targeting IoT devices increases with year over year. New threats require a complex approach; as a result, security became the top priority for both software developers and hardware manufacturers. This article addresses the primary vectors of attacks against smart gadgets and describes some firmware and data protection techniques using a Nucleo development board equipped with an STM32H743 microcontroller as an example.
Breaking into smart devices may bring devastating consequences. Take, for instance, the accidental hacking of Xiaomi pet feeders by a Russian IT researcher.
Over-the-air (OTA) updates and numerous debug interfaces present in such gadgets may be used as security holes enabling the attacker to replace their firmware and steal intellectual property.
Secure Boot framework
Developers willing to protect their creations have to solve two key issues.
- Implement a firmware authenticity verification (i.e. authentication) mechanism using a cryptographic algorithm (e.g. SHA-256 or NIST P256). This ensures that only the trusted code can be executed on the device; and
- Protect the device memory against external attacks and prevent attackers from accessing critical regions. In theory, this can be done through the exploitation of software vulnerabilities, use of debugging interfaces (e.g. JTAG), and application of logical analyzers.
These two protection approaches are different and serve different purposes; only their combined use allows to effectively counter the threats. In other words, even the most sophisticated cryptographic algorithm would be useless if a hacker dumps and decrypts the firmware. The opposite is also true; the memory protected from reading won’t prevent the execution of a program containing malicious code.
How it works
OTA updates are the easiest way to update the device’s firmware (i.e. perform a Secure Firmware Update (SFU)). The developer stores the encrypted binary file on a server, while the client downloads the file, confirms its integrity, authenticates it, decrypts, and installs.
The following measures ensure the basic security during this process: (1) the verified Secure Boot prevents alternative download methods and forms the root of trust in the system; and (2) private encryption keys must be stored in the device’s firmware and must be individual.
In addition, the implementation of the cryptographic algorithm must be checked for resistance against side-channel attacks (SCA) and fault injection attacks (FIA). These attack types will be addressed in more detail below.
Finally, the device must be protected against unauthorized external access. For instance, many developers disable the JTAG interface frequently used by hackers. Additional intrusion detection mechanisms include, among other things, anti-tampering measures that, unfortunately, aren’t used as frequently as they should.
Now it is time to see how the above recommendations are implemented in STM32 microcontrollers.
The choice of available protection mechanisms depends on the microcontroller family (F, G, L, or H). Examples provided in the X-CUBE-SBSFU (Secure Boot and Secure Firmware Update) solution cover the most part of this assortment, but to get the full information, one has to research the official documentation as well. In this article, I am going to refer to the following sources:
- AN5156 – the key document on the STM32 microcontroller security;
- UM2262 – a user manual on the SBSFU framework in the X-CUBE package;
- AN4838 – an application note on the MPU (Memory Protection Unit);
- PM0253 – a programming manual on defense mechanisms for the Cortex-M7 processor;
- DS12110 – a datasheet for the H743 microcontroller; and
- RM0443 – a reference manual for the H743 microcontroller
All documents are in the PDF format.
ReaDout Protection (RDP)
This is a basic security mechanism preventing various debugging interfaces (JTAG, SWV, and ETM) from accessing the microcontroller’s memory. Its implementation is strongly recommended for all mass devices. The RDP can be disabled only at the Level 1 protection, and this operation erases the contents of the flash memory. The user may also enable Level 2 RDP (RDP2) after loading the binary code to the embedded flash memory; this operation is irreversible for the microchip.
In theory, this may complicate technical support and searching for a defect in case the device is sent in for repair. However, the application still can write information to flash memory and edit it; therefore, firmware updates, including SFU, still remain possible. If RDP is enabled, an attempt to access the protected memory region generates an error on the AHB bus.
In H743 microcontrollers, this function is implemented by RDP bits
[15:8] in registers
FLASH_OPTSR_PRG located in the Option Bytes area. The
0xAA corresponds to Level 0 protection (the default variant),
0xCC to Level 1, while any other value corresponds to Level 2 (the maximum).
According to the STMicroelectronics diagrams, Option Bytes belong to the internal flash memory, but direct access to them is impossible. To make any changes, the user must address the respective registers and follow a certain procedure (for more detail, see chapter 3.4.3. Option Byte Modification in RM0433).
Write Protection (WRP)
This security mechanism supplements RDP; not only does it protect the flash memory contents against external threats (i.e. injections of malicious code with its subsequent execution), but also guards against going beyond the array bounds and buffer overflows in user functions as well. The WPR feature is easy to use, and the vendor strongly recommends using it.
The flexibility of this mechanism makes it possible to protect from writing both individual pages and entire memory sectors (for more detail, see the documentation). In addition, prior to enabling the WRP, you can fill the free space with NOP or WFI instructions; this measure definitely won’t do any harm.
In H743 microcontrollers, the user has access to 2 MB of flash memory divided into two banks (at the addresses
0x0800 0000 –
0x080F FFFF and
0x0810 0000 –
0x081F FFFF, respectively). Each bank, in turn, is divided into eight sectors 128 KB each. Bits
[7:0] in the registers
FLASH_WPSN_XX are responsible for the WRP function.
Proprietary Code ReadOut Protection (PCROP)
The name of this protection feature may confuse a novice hacker: its first part makes you think of a Program Counter, while the second one, ReadOut Protection, has already been addressed.
In fact, the PCROP and RDP perform similar functions: the RDP blocks unauthorized access to the memory via debug interfaces of the microcontroller, while the PCROP protects against more sophisticated attacks performed to steal the device’s firmware and exploiting vulnerabilities and errors in its software.
To protect the corporate intellectual property (libraries and pieces of code) from copying and reverse engineering, the developers may mark a certain range of addresses in the flash memory by the “execution only” flag using the registers
FLASH_PRAR_PRGX. The flash memory contents stored in that area will be sent only to the microcontroller instruction bus.
Unfortunately, the practical application of this technology may result in the internal memory granulation: for instance, in the H743 microchip, only one area can be allocated for PCROP in each memory bank (i.e. no more than two per microchip). This area must be a multiple of the block size (256 bytes) and aligned by the respective bound.
Secure Access Only (SAO)
This is one of the most exciting memory protection functions in STM32. The developers cannot even agree about its name: in one document (AN5156), it is called Secure User Memory; in the other (RM0443), it’s Secure Access Only; while for the G0/G4 series, it is referred to as Securable Area!
The secure access only memory area is used to create a unified boot method immediately after the reset signal. This code has exclusive reading, writing, and execution rights within the set range of addresses. Its isolation from the rest of the program is implemented at the hardware level.
In STM32, SAO is primarily used to store Secure Boot and create the trust chain in the system. The keys and encryption algorithms for integrity checks and authentication of the main firmware image prior to the transfer of control to the main program should be stored there, too. Similar to other protection mechanisms, certain registers in the Option Bytes (
FLASH_SCAR_PRGX) are responsible for the SAO placement in the flash memory.
It is important not to confuse the secure access flash memory (Secure) with the system memory (System) in the H7 series. The latter one is always located slightly ‘alongside’ of the main memory array (addresses from
0x1FF0 0000 to
0x1FF5 0000). In all STMicroelectronics chips, the system memory area in the first bank (the one used to store the DFU bootloader code) is marked as Secure. However, the respective free sector in the second bank belongs to the system memory but is not secure (by default)! This sector contains additional 128 KB that you can use at your full discretion.
Memory Protection Unit (MPU)
All the above protection mechanisms have a common feature: they are static, i.e. hardcoded at the time of the program execution. This is not a disadvantage in itself; however, the use of an OS with several processes in a complex project makes necessary to dynamically configure the access right settings to various memory areas. The Memory Protection Unit is responsible for this: it divides the memory map into several regions and defines the location, size, access permissions, and memory attributes of each region.
The MPU is a component of the processor (in this particular case, a Cortex-M7). In the entire ARM Cortex-M model range, only the M0 family is not equipped with an MPU. In other words, the MPU can control the access to any component mapped in the processor’s address space. Therefore, this unit can be used not only for its direct purposes (e.g. RAM and flash memory protection), but also to restrict the rights to peripherals, including interfaces, registers, etc.
Another important thing: the MPU controls the CPU, but not the DMA (Direct Memory Access) units that may also have access to the internal memory over the internal buses of the microcontroller! Fortunately, the possibilities of DMA units are limited in comparison with the CPU, except for the specialized DMA2D (Chrom-ART). Can the DMA2D be used to bypass the MPU and compromise a real device? I had never encountered such examples and would really love to see one! 🙂
The MPU-related documentation is contained in the processor programming manual. This is bad news for those too lazy to read such materials and considering them intended only for system programmers and compiler developers. And of course, you have to thoroughly review the application note AN4838, too.
This protection mechanism also works dynamically, although not at the microcontroller or processor level but at the finished device level. The developers can use special microchip pins and low-power peripherals (e.g. the real-time clock or backup SRAM) to detect unauthorized access to the device (e.g. an attempt to open its case or inflict “a blunt impact damage”).
As you can see, H743 microcontrollers have three domains divided by their performance and power consumption level. The D1 contains the Cortex-M7, the most part of the internal SRAM, and the fastest peripherals: FMC, LTDC, QSPI, etc. The D2 accommodates the standard interfaces: ETH, USB, and MMC. Finally, the D3 accommodates the above-mentioned low-power peripherals that continue operating even when the device is powered only by its internal battery.
Therefore, by using Anti-Tamper pins on the microcontroller, the developer can detect an attempt to break into it and clear, at the hardware level, the RTC registers and backup RAM in the D3 thus, erasing all commercial secrets stored there – even if the attacker has disconnected the device from the main power supply! This guarantees that the confidential information won’t be stolen, while the technical support will easily determine what has happened with the device.
Independent Watchdog (IWDG)
Last but not least is the independent watchdog (IWDG). By default, it triggers a reset sequence when the program encounters a critical error or gets trapped in an infinite loop.
As you are aware, the IWDG clock is an independent low-speed internal oscillator (LSI). Therefore, it is possible to check with it during the execution of critical code regions (that might become the primary targets for attackers implementing various side-channel and fault injection attacks against the power source, clock etc.). In addition, IWDG can forcibly reset the main processor if it was not promptly initialized (e.g. the bootloader was not executed or an update installed).
The IWDG belongs to the basic peripherals and exists on all modern microcontrollers, including Н743.
External flash memory
The vendor strongly recommends enabling the microcontroller protection features described above; with the modern threats to the IoT, their importance is beyond doubt. However, the Secure Boot and Secure Firmware Update concept becomes essential if an external flash memory microchip is used to store the firmware and user data. Taking their capacity, such microcontrollers are pretty cheap; for instance, the STM32H750, with its frequency of up to 480 MHz and 128 KB of flash memory, costs some $7. Its Quad-SPI memory interface makes it possible not only to map the external flash memory in the processor’s address space, but also execute the code stored in it with minimum performance losses.
Now that you have become familiar with the hardware protection mechanisms, let’s see how the Secure Boot firmware image is created. UM2262 user manual will be of great assistance.
On the server side, the process looks as follows. First, the firmware hash code is computed in accordance with the SHA-256 algorithm and placed in the header. Then two keys (a private and a public ones) are generated based on NIST P-256 elliptic curves, and the binary file is signed using the Elliptic Curve Digital Signature Algorithm (ECDSA). At the final stage, the header and firmware are encrypted using the AES CBC algorithm, and the resultant file is sent to the user together with the initialization vector (IV).
On the device side, the same sequence of events is implemented in the reverse order and with minimum changes. Out of the box, Secure Boot supports the following schemes:
SECBOOT_ECCDSA_WITHOUT_ENCRYPT_SHA256(image without encryption; authentication with an ECCDSA key);
SECBOOT_ECCDSA_WITH_AES128_CBC_SHA256(AES encryption; authentication with an ECCDSA key);
SECBOOT_AES128_GCM_AES128_GCM_AES128_GCM(AES encryption, authentication with a symmetric key).
Interestingly, all encryption algorithms in the Secure Boot package are implemented at the software level, even for microcontrollers equipped with cryptographic accelerators (the CRYP and HASH blocks). Apparently, STMicroelectronics engineers leave the decision whether to use these specific peripherals to the customers.
User encryption scheme
If necessary, the developers may implement the Secure Boot feature using their own algorithms. To do so, it is necessary to set a definition for the cryptographic scheme in
SECoreBin/Inc/se_crypto_config.h. Next, the user firmware header description is modified in
SECoreBin/Inc/se_def_metadata.h. Then the functions have to be implemented in accordance with the bootloader interface (see
And finally, the developers have to modify the scripts
translate_key.py accordingly and integrate them with their development environment. The easiest way to do so is generate the file
SECBOOT_CUSTOM.bat together with
Implementation for H743
Now you have an idea of the main Secure Boot components, and it is time to port the basic ST project to a Nucleo H743 debugging board. There are no implementation examples specifically designed for this model, but there is one for its ‘older brother’, the Н753. These microchips are similar in many ways except for a hardware cryptographic accelerator installed on the Н753. This difference is important but not critical for our purposes; so, I will use the H743 as the basis for my project.
The package contains two implementations for this platform; they differ by the number of slots in the microcontroller’s memory allocated for the actual firmware (configurations with one or two slots). Each implementation contains three projects.
It is recommended to replace the macro definition
STM32H743xx and then compile the projects in the following order:
This project contains the implementation of the basic cryptographic functions. It is necessary to specify the scheme in the definition
SECBOOT_CRYPTO_SCHEME: either select a premade example provided by the vendor or use a custom encryption. It is also necessary to set a private key in the files
OEM_KEY_COMPANY1_key_AES_XXX.bin. After the execution of the
prebuild.sh script, they will be saved in binary representation in the file
This is the SBSFU bootloader responsible for secure firmware updates and providing the transport layer (in the basic examples, it is the Y-MODEM protocol). In addition, the bootloader activates all the implemented cryptographic algorithms. The Secure Boot core can be integrated in the project in the form of a precompiled library. Then the compiled file can be flashed into the microcontroller memory using STlink Utility or STM32CubeProgrammer.
This is a basic user app example. A simple text interface makes it possible to verify the protection, display service information, and reflash the device. The
UserApp.sfb digital signature is formed on the basis of the compiled file using
postbuild.sh. Then it has to be transmitted to the bootloader via the Y-MODEM protocol. The SBSFU verifies the signature authenticity and saves it in the allocated SAO (Secure Access Only) memory.
Important: in the ‘full functionality’ mode, the SBSFU project requires to disable the microcontroller debugging aids. To reset the PCROP and reconfigure the RDP level on the debug board, it is necessary to press the Reset button and connect to it in the “Connect Under Reset” mode using the STM32CubeProgrammer utility. To remind again: if you change the RDP, the internal flash memory containing, among other things, the encryption keys will be erased.
Flashing and configuring Option Bytes
Finally, it is necessary to set the required mode for the Option Bytes. First, I switch RDP to the Level 1 protection (see the detailed description above). Then I set the values for the PCROP and WRP based on the respective memory addresses. Everything is ready! Now it is possible to reset the microcontroller, connect to it using the terminal (the debug board provides it as a VCP), and read the Secure Boot greetings. All standard STMicroelectronics security features are now enabled and function properly.
If you are looking for more specific solutions, you may try, for instance, STSAFE-A100 or a Nucleo expansion board. For built-in systems, this is like a TPM for the PC. Please note however that this item is protected under a nondisclosure agreement (NDA), and ST won’t part with it easily. But you can always invent something, right? 🙂
As you can see, the Secure Boot is a pretty simple framework; it is convenient for porting and allows to implement the boot-up sequence and firmware updates for a device with minimal effort. Needless to say, the Secure Boot significantly raises the security of the device and may even thwart a hacker’s attack.
Unfortunately, there are no 100% secure solutions in this world, and even following the developers’ recommendations to the letter does not guarantee you won’t have any vulnerabilities left. Physical devices, being real-world objects, offer much more information and means of communication than might seem at the first glance.
A dedicated hacker can bypass even the multilayered defense by subjecting the microchip to UV rays, analyzing its power delivery buses, or generating electromagnetic interference using sophisticated equipment. However, such exotic methods go beyond the scope of this article. May the security be with you!