GHSA-hqmg-jwp9-8cf8: AES image key left on the stack after serial-recovery encrypted-image handling in MCUboot
In MCUboot's serial-recovery encrypted-image support (boot/bootserial/src/bootserialencryption.c), decryptimageinplace() and bootimagevalidateencrypted() each keep a stack-local struct bootstatus. bootencload() writes the plaintext per-image AES key into its enckey[] field. Neither function cleared this structure before returning. In addition, a decrypt failure inside the per-sector loop of decryptimageinplace() returned early and skipped the totalout: cleanup, which left the expanded AES key context (encdata) on the stack as well. The error paths of bootimagevalidateencrypted() similarly skipped bootenczeroize().
The affected code is built when encrypted images (MCUBOOTENCIMAGES, Zephyr CONFIGBOOTENCRYPTIMAGE) are combined with serial recovery. It runs when an encrypted image is uploaded to the primary slot over the recovery protocol, and when the image list or state is queried while an encrypted image is in the secondary slot. After these functions return, the image's AES content key remains in dead stack memory. An attacker who can later read device RAM, for example through a debug port or retained RAM, can recover it.
This weakens the confidentiality of image-encryption keys within the bootloader trust boundary. A recovered key exposes the plaintext of the encrypted firmware image it protects. The device's long-term private decryption key is not exposed. No remote or recovery-protocol channel that returns this memory is known, so exploitation requires a separate memory-read capability.
Affected Software
Event History
Frequently Asked Questions
Which deployments are exposed to this issue?
The affected code is built only when encrypted-image support is combined with serial recovery, specifically MCUBOOT_ENC_IMAGES or Zephyr CONFIG_BOOT_ENCRYPT_IMAGE with serial recovery enabled. The vulnerable paths run during recovery uploads of encrypted images to the primary slot and when listing or querying state with an encrypted image in the secondary slot.
What would an attacker need to recover the key?
An attacker must be able to read device RAM after the affected function returns, such as through a debug port or retained RAM. The issue leaves the plaintext per-image AES key in dead stack memory; one decrypt-failure path can also leave the expanded AES key context there.
Are successful recovery uploads required for exposure?
No. A decrypt failure during the per-sector loop in decrypt_image_inplace() takes an early return path that skips cleanup and can leave the expanded AES key context on the stack. Error paths in boot_image_validate_encrypted() also skip key zeroization.