Keys That Stick to the Chip: Device‑Specific Root Key & Flash Binding
Why I Needed Both Tricks
The main purpose of deriving a device-specific root key and binding the external Flash to the microcontroller is to close off a major attack vector, direct access to the key storage. Since the external Flash holds sensitive key material and can be physically removed from the PCB and read using tools like USB programmers, it becomes a weak link if left unprotected. By encrypting all data in Flash using a key that’s tied specifically to the MCU, any dumped contents become meaningless outside that device. Of course, this only holds if Initialization Vectors (IVs) are not reused; we’ll get into that risk shortly. Normally, this kind of protection is handled using a Hardware Unique Key (HUK), but since that wasn't available, I had to build my own mechanism for device binding.
The STM32H563ZI used on the Nucleo-H563ZI development board doesn’t support a Hardware Unique Key (HUK). That feature is only available on certain STM32H5 series chips like the STM32H573 or H533. A HUK or a Derivable HUK (DHUK) would have made things easier, letting the system securely generate the same unique key every time without storing it anywhere. Without that, one fallback is to hardcode a key into the firmware, but that’s not secure since someone with access could extract it. So instead, I had to come up with my own method: I combined a constant key material with a randomly generated salt (from the TRNG) and used an HMAC-based key derivation routine to generate a Master Key. This way, the key is unique per device and never stored.
How did I derive the Master Key?
The chip’s 96‑bit UID is permanent and unique, so it’s a good starting point, but using it by itself isn’t safe, since anyone with the same MCU family could try to map UIDs to keys. To add unpredictability, I generated a 20‑byte random salt on first boot with the TRNG and stored that salt in protected (RDP Level 1) internal Flash. Each time the system requests, an HKDF‑style routine (HMAC‑SHA‑256) combines the UID and that salt to produce a 16‑byte Master Key. The key never goes into Flash and is recomputed on every request, making it much harder to extract or clone. All key blobs in external SPI Flash are encrypted with this Master Key, so if the memory is removed and read elsewhere, the data is meaningless without the original MCU.
How the Keys are stored in the External Flash with the Master Key
In the TrustX key entry structure, while each field plays an important role, the HMAC Digest and the Initialization Vector (IV) are particularly critical for correct decryption. Since only the four middle fields of each key entry are encrypted, we need a reliable way to detect tampering. After generating the ciphertext, we compute an HMAC using SHA-256 over the encrypted blob, using the same Master Key that performed the encryption. This HMAC is then stored in plaintext right after the encrypted portion. Compared to a CRC or plain hash, an HMAC is more secure because any alteration in the ciphertext or the HMAC itself can be detected, as the correct HMAC can only be recomputed with the original Master Key. As for the Initialization Vector, it is necessary for AES modes like CTR, which require a unique IV for each encryption operation. The IV itself is stored in plaintext at the end of the entry, since IVs are not meant to be secret.
How do the Initialization Vectors become an Attack Vector?
IV reuse in AES-CTR mode is a serious issue. Reusing an Initialization Vector allows an attacker to XOR two ciphertexts and recover the XOR of the original plaintexts. Although the IV is 128 bits long, offering 2¹²⁸ possible values, the Birthday Paradox makes the collisions statistically significant around 2⁶⁴ entries. In practical systems, even 2³² unique IVs (~4 billion) provide a large enough space, but precautions are still required.
To mitigate the risk of IV collisions, two strategies can be employed:
- Maintain an IV Registry – Before assigning a new IV, the system can perform a lookup to check whether it has been used before. This ensures uniqueness but may be computationally heavy at scale. To speed things up, we can use a Bloom Filter.
- Use a Monotonic Counter – This method generates IVs sequentially, ensuring uniqueness without the need for lookups. However, it must be handled carefully as the counter must only increment after a key entry is fully written to Flash (i.e., after ciphertext and HMAC are saved), to avoid reuse in case of system crashes or power loss mid-operation. If the device resets unexpectedly, the counter might roll back, leading to possible IV reuse. Extra safeguards like storing the counter persistently in Flash or backing it up after each write can help prevent this scenario.
Still, this IV-based attack is just one potential risk vector. In most real-world attacks, attackers might prefer side-channel attacks or other physical attacks. But even so, we should make sure that it is safe.
How does the System derive and use the Master Key?
How does the System derive the Master Key?




How does the System use the Master Key?
Now comes the interesting part and potentially the most vulnerable. This is where side-channel attacks might come into play. The Master Key is only brought into action during two specific events: when a new key is added to the external Flash, or when an existing key is retrieved from it.
Let’s look closer at what’s really happening during those moments, because that’s when sensitive operations occur and the key is actively used in memory.

This snippet is part of the Decryption Handler, where we deal with the key data required for decrypting the user-provided ciphertext. The user has two options: either supply their own key directly (for example, if the data was encrypted on another system), or request a stored key from the Key Manager (if the data was originally encrypted using this same device).
When adding a new key to the database, the system accepts nearly all the metadata fields we previously discussed. However, during decryption using a stored key, the user only needs to provide the Key ID, which they must have noted or preserved earlier, to retrieve and use the correct key from external Flash.
How Secure and Slow is it?
To begin with, the Master Key is never stored anywhere; it’s derived only when needed, and it exists in RAM solely for the duration of the operation that requires it. That’s a security plus. The UID used in the derivation is unique not just to the MCU family, but to that specific device. While someone could technically read the UID via BootROM access, that still leaves the salt out of reach. The salt is stored in internal Flash and protected under RDP Level 1, which means it can’t be dumped through debug interfaces or the bootloader.
Now, let’s talk about the external Flash. Even if someone removes it and reads the contents, they’re only going to see encrypted blobs. Each of these is locked using the Master Key, and since that key is derived from the unique UID + Salt pair, trying to clone the Flash to another identical chip won't work. Also, during decryption or any operation that loads a key from Flash, the firmware recomputes the HMAC using the current Master Key and compares it with the stored digest. If there's any mismatch, the operation is aborted and an error is returned. That adds another layer of checking.
All that said, this setup is a strong step forward, but it’s far from tamper-proof. The system is still exposed to physical attacks like fault injection and timing-based side-channel leaks. I could try hardening the software further to resist side channels, but ultimately, the STM32H573 series, which includes side-channel-hardened crypto IPs, would be the better fit for that. Another trade-off is performance: since encryption and HKDF are handled entirely in software, the operations aren’t as fast as they would be on chips with full hardware crypto acceleration.
The Short Version
By combining the UID + Salt Key derivation with Master‑Key‑Encrypted Flash storage, I turned an ordinary STM32 into a little hardware vault that only it can open. It isn’t a certified HSM, but for an experiment, it gives me a per‑device Root of Trust, protects keys if the Flash is cloned, and teaches the real‑world trade‑offs of Embedded Security. If your MCU has a unique ID and a TRNG, you can adapt the same pattern; no secure element required.
Checkout my GitHub repository for the complete source code of this project.