Merge branch 'feat/psram_enc_exempt_v5.5' into 'release/v5.5'

feat(esp_psram): add option to carve unencrypted PSRAM region (v5.5)

See merge request espressif/esp-idf!49931
This commit is contained in:
Jiang Jiang Jian
2026-07-16 17:04:28 +08:00
11 changed files with 312 additions and 9 deletions
+24
View File
@@ -252,6 +252,30 @@ By default, failure to initialize external RAM will cause the ESP-IDF startup to
On {IDF_TARGET_NAME}, PSRAM encryption can be controlled on a per-MMU-page basis, allowing individual PSRAM pages to be selectively encrypted or left unencrypted. However, in the default configuration, all PSRAM pages are encrypted when flash encryption is enabled.
Reserving an Unencrypted PSRAM Region
-------------------------------------
Enabling :ref:`CONFIG_SPIRAM_ENC_EXEMPT` reserves a region at the upper end of PSRAM (highest physical addresses; sized by :ref:`CONFIG_SPIRAM_ENC_EXEMPT_SIZE`, in KB, rounded up to the MMU page size) that is mapped without encryption. This region is registered as a separate heap pool reachable only via the ``MALLOC_CAP_SPIRAM_NO_ENC`` capability. The rest of PSRAM (and flash) remains encrypted.
.. warning::
Memory allocated with ``MALLOC_CAP_SPIRAM_NO_ENC`` is stored as plaintext in PSRAM and can be observed by an attacker with physical access to the PSRAM interface. Never place TLS state, keys, or other secrets in this region.
Typical use case: PSRAM encryption imposes alignment constraints on buffers that some DMA engines (for example, 2D-DMA) cannot satisfy. Buffers that need to be DMA-accessed from such engines can be allocated from this unencrypted region:
.. code-block:: c
#if CONFIG_SPIRAM_ENC_EXEMPT
uint32_t caps = MALLOC_CAP_SPIRAM_NO_ENC;
#else
uint32_t caps = MALLOC_CAP_SPIRAM;
#endif
uint8_t *buf = heap_caps_malloc(buf_size, caps);
``MALLOC_CAP_SPIRAM_NO_ENC`` must be requested explicitly. It is intentionally not combined with ``MALLOC_CAP_SPIRAM`` or ``MALLOC_CAP_DEFAULT``, so ordinary SPIRAM/heap allocations cannot accidentally land in the unencrypted region.
To verify after the fact that a buffer was allocated from the unencrypted carve-out (for example after a ``heap_caps_malloc_prefer()`` call that may have fallen back to encrypted PSRAM), use ``esp_psram_ptr_is_no_enc()``.
.. only:: SOC_PSRAM_ENCRYPTION_SEPARATE_KEY
On {IDF_TARGET_NAME}, PSRAM encryption can use an independent encryption key. If the PSRAM encryption key is not programmed, the flash encryption key will be used as the PSRAM encryption key.
+24
View File
@@ -252,6 +252,30 @@ ESP-IDF 启动过程中,片外 RAM 被映射到数据虚拟地址空间,该
在 {IDF_TARGET_NAME} 上,PSRAM 加密可以按 MMU 页面粒度进行控制,允许对单个 PSRAM 页面选择性地加密或不加密。但在默认配置下,启用 flash 加密时所有 PSRAM 页面都会被加密。
预留未加密的 PSRAM 区域
-----------------------
启用 :ref:`CONFIG_SPIRAM_ENC_EXEMPT` 会在 PSRAM 上端(最高物理地址区,大小由 :ref:`CONFIG_SPIRAM_ENC_EXEMPT_SIZE` 指定,单位为 KB,向上取整到 MMU 页面大小)预留一段区域,该区域在映射时不启用加密。此区域被注册为一个独立的堆池,仅可通过 ``MALLOC_CAP_SPIRAM_NO_ENC`` 能力位访问。其余 PSRAM(以及 flash)仍然保持加密。
.. warning::
通过 ``MALLOC_CAP_SPIRAM_NO_ENC`` 分配的内存以明文形式存储在 PSRAM 中,攻击者若能物理接触 PSRAM 接口即可读取其内容。切勿将 TLS 状态、密钥或其他敏感数据放入该区域。
典型使用场景:PSRAM 加密会对缓冲区施加对齐约束,部分 DMA 引擎(如 2D-DMA)无法满足这些约束。需要被此类引擎进行 DMA 访问的缓冲区可以从该未加密区域分配:
.. code-block:: c
#if CONFIG_SPIRAM_ENC_EXEMPT
uint32_t caps = MALLOC_CAP_SPIRAM_NO_ENC;
#else
uint32_t caps = MALLOC_CAP_SPIRAM;
#endif
uint8_t *buf = heap_caps_malloc(buf_size, caps);
必须显式请求 ``MALLOC_CAP_SPIRAM_NO_ENC``。该能力位有意未与 ``MALLOC_CAP_SPIRAM`` 或 ``MALLOC_CAP_DEFAULT`` 组合,因此普通 SPIRAM/堆分配不会意外落入该未加密区域。
如需在分配后验证缓冲区是否确实位于未加密的预留区域(例如调用 ``heap_caps_malloc_prefer()`` 后可能回退到加密的 PSRAM),可使用 ``esp_psram_ptr_is_no_enc()``。
.. only:: SOC_PSRAM_ENCRYPTION_SEPARATE_KEY
在 {IDF_TARGET_NAME} 上,PSRAM 加密可以使用独立的加密密钥。如果未烧录 PSRAM 加密密钥,则会使用 flash 加密密钥作为 PSRAM 加密密钥。