-
Notifications
You must be signed in to change notification settings - Fork 12
feat(key_mgr): Add Key Manager HAL for ESP32-C5 and ESP32-P4 (IDFGH-17725) #113
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
hrushikesh430
wants to merge
6
commits into
espressif:master
Choose a base branch
from
hrushikesh430:feat/keymanager-approach-3
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
bc8c71c
feat(key_mgr): Add Key Manager HAL for ESP32-C5 and ESP32-P4
hrushikesh430 7e65fa1
Apply automatic fixes from pre-commit hooks
pre-commit-ci[bot] c8dffbd
refactor(key_mgr): Align HAL with esp-stub-lib contribution guide
hrushikesh430 58d95c1
Apply automatic fixes from pre-commit hooks
pre-commit-ci[bot] 51b32d1
fix(key_mgr): Address review feedback and restrict P4 KM to v3.0+
hrushikesh430 4ae32cb
Apply automatic fixes from pre-commit hooks
pre-commit-ci[bot] File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,218 @@ | ||
| /* | ||
| * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 OR MIT | ||
| * | ||
| * Internal target HAL interface for the Key Manager peripheral on | ||
| * ESP32-P4 (>= v3.0) and ESP32-C5 (any revision). This is a target-private | ||
| * interface, not part of the library's public API under include/esp-stub-lib/. | ||
| * | ||
| * This header is the contract between the keymanager stub plugin and the | ||
| * chip-specific HAL implementation. The plugin uses these accessors to | ||
| * drive the Key Manager + HUK Generator state machines and to move bytes | ||
| * between host RAM and the KM's internal memory blocks. | ||
| * | ||
| * The API intentionally mirrors the names used in ESP-IDF's | ||
| * `components/esp_security/src/esp_key_mgr.c` so that the plugin can be | ||
| * line-by-line compared against the reference driver. Locks, logging, | ||
| * eFuse helpers, and OS plumbing from the IDF version are dropped — the | ||
| * stub runs single-threaded with no RTOS. | ||
| */ | ||
| #pragma once | ||
|
|
||
| #include <stdbool.h> | ||
| #include <stddef.h> | ||
| #include <stdint.h> | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| /* ---------- Constants ---------------------------------------------------- */ | ||
|
|
||
| #define STUB_KM_K2_INFO_SIZE 64 | ||
| #define STUB_KM_K1_ENCRYPTED_SIZE 32 | ||
| #define STUB_KM_ECDH0_INFO_SIZE 64 /* k1*G or k2*G as LE-x || LE-y */ | ||
| #define STUB_KM_KEY_RECOVERY_INFO_SIZE 64 /* per slot, before CRC */ | ||
| #define STUB_KM_HUK_INFO_SIZE 660 /* Matches IDF HUK_INFO_LEN in rom/km.h */ | ||
| #define STUB_KM_SW_INIT_KEY_SIZE 32 | ||
| #define STUB_KM_HUK_RISK_ALERT_LEVEL 4 | ||
|
|
||
| /* Magic for the on-flash key_recovery_info partition (matches IDF). */ | ||
| #define STUB_KM_KEY_HUK_SECTOR_MAGIC 0xDEA5CE5AU | ||
|
|
||
| /* ---------- Enums (match IDF wire types) -------------------------------- */ | ||
|
|
||
| typedef enum { | ||
| STUB_KM_STATE_IDLE = 0, | ||
| STUB_KM_STATE_LOAD = 1, | ||
| STUB_KM_STATE_GAIN = 2, | ||
| STUB_KM_STATE_BUSY = 3, | ||
| } stub_km_state_t; | ||
|
|
||
| typedef enum { | ||
| STUB_KM_KEYGEN_MODE_RANDOM = 0, | ||
| STUB_KM_KEYGEN_MODE_AES = 1, | ||
| STUB_KM_KEYGEN_MODE_ECDH0 = 2, | ||
| STUB_KM_KEYGEN_MODE_ECDH1 = 3, | ||
| STUB_KM_KEYGEN_MODE_RECOVER = 4, | ||
| STUB_KM_KEYGEN_MODE_EXPORT = 5, | ||
| } stub_km_keygen_mode_t; | ||
|
|
||
| typedef enum { | ||
| STUB_KM_KEY_PURPOSE_INVALID = 0, | ||
| STUB_KM_KEY_PURPOSE_ECDSA_192 = 1, | ||
| STUB_KM_KEY_PURPOSE_ECDSA_256 = 2, | ||
| STUB_KM_KEY_PURPOSE_FLASH_256_1 = 3, | ||
| STUB_KM_KEY_PURPOSE_FLASH_256_2 = 4, | ||
| STUB_KM_KEY_PURPOSE_FLASH_128 = 5, | ||
| STUB_KM_KEY_PURPOSE_HMAC = 6, | ||
| STUB_KM_KEY_PURPOSE_DS = 7, | ||
| STUB_KM_KEY_PURPOSE_PSRAM_256_1 = 8, | ||
| STUB_KM_KEY_PURPOSE_PSRAM_256_2 = 9, | ||
| STUB_KM_KEY_PURPOSE_PSRAM_128 = 10, | ||
| STUB_KM_KEY_PURPOSE_ECDSA_384_L = 11, | ||
| STUB_KM_KEY_PURPOSE_ECDSA_384_H = 12, | ||
| } stub_km_key_purpose_t; | ||
|
|
||
| typedef enum { | ||
| STUB_KM_KEY_TYPE_ECDSA = 0, | ||
| STUB_KM_KEY_TYPE_FLASH_XTS_AES = 1, | ||
| STUB_KM_KEY_TYPE_HMAC = 2, | ||
| STUB_KM_KEY_TYPE_DS = 3, | ||
| STUB_KM_KEY_TYPE_PSRAM_XTS_AES = 4, | ||
| } stub_km_key_type_t; | ||
|
|
||
| typedef enum { | ||
| STUB_KM_KEY_LEN_INVALID = 0, | ||
| STUB_KM_KEY_LEN_ECDSA_192, | ||
| STUB_KM_KEY_LEN_ECDSA_256, | ||
| STUB_KM_KEY_LEN_ECDSA_384, | ||
| STUB_KM_KEY_LEN_XTS_AES_128, | ||
| STUB_KM_KEY_LEN_XTS_AES_256, | ||
| } stub_km_key_len_t; | ||
|
|
||
| typedef enum { | ||
| STUB_HUK_MODE_RECOVER = 0, | ||
| STUB_HUK_MODE_GENERATE = 1, | ||
| } stub_huk_mode_t; | ||
|
|
||
| /* ---------- HUK Generator ----------------------------------------------- */ | ||
|
|
||
| /** | ||
| * @brief Read HUK_STATUS_REG. | ||
| * | ||
| * @param[out] gen_status 0=not generated, 1=valid, 2=invalid, 3=reserved | ||
| * @param[out] risk_level 0..7 (higher = more PUF-SRAM error bits; 7 = invalid) | ||
| */ | ||
| void stub_target_huk_get_status(uint8_t *gen_status, uint8_t *risk_level); | ||
|
|
||
| /** | ||
| * @brief Drive the HUK Generator state machine through one cycle. | ||
| * | ||
| * In GENERATE mode, populates @p huk_info_buf with the freshly generated | ||
| * huk_info. In RECOVER mode, @p huk_info_buf is loaded into the HUK and the | ||
| * function returns 0 once the HUK is valid. | ||
| * | ||
| * @p huk_info_buf must be STUB_KM_HUK_INFO_SIZE (660) bytes. The 660-byte | ||
| * blob is the caller-facing huk_info (IDF HUK_INFO_LEN); esp_rom_km_huk_conf | ||
| * fills/consumes it by iterating the HUK state machine over the 384-byte | ||
| * HUK_INFO_MEM MMIO window across multiple passes. (384 = hardware window, | ||
| * 660 = persisted blob — not the same thing.) | ||
| * | ||
| * @return 0 on success; negative if HUK could not be brought to a valid | ||
| * state (for RECOVER) or if HUK generation failed (for GENERATE). | ||
| */ | ||
| int stub_target_huk_configure(stub_huk_mode_t mode, uint8_t *huk_info_buf); | ||
|
|
||
| /* ---------- Capability -------------------------------------------------- */ | ||
|
|
||
| /** | ||
| * @brief Whether this chip/revision supports the Key Manager flow this HAL | ||
| * implements (the 660-byte HUK_INFO generation/recovery). | ||
| * | ||
| * ESP32-C5: true on all revisions. ESP32-P4: true only for >= v3.0 (ROM | ||
| * ECO >= 5); earlier P4 silicon used a 384-byte HUK and is not supported. | ||
| * Callers must check this before driving any other stub_target_km_* / | ||
| * stub_target_huk_* operation. | ||
| */ | ||
| bool stub_target_km_is_supported(void); | ||
|
|
||
| /* ---------- Key Manager bring-up ---------------------------------------- */ | ||
|
|
||
| /** | ||
| * @brief Enable the KM bus clock, release reset, and power up KM memory. | ||
| * | ||
| * Must be called once before any other stub_target_km_* call. Idempotent. | ||
| * Without it, KM register writes silently no-op (peripheral held in reset) | ||
| * and KEYMNG_*_MEM reads return zero (memory power gate off). | ||
| */ | ||
| void stub_target_km_bringup(void); | ||
|
|
||
| /* ---------- Key Manager state machine ----------------------------------- */ | ||
|
|
||
| stub_km_state_t stub_target_km_get_state(void); | ||
| void stub_target_km_wait_for_state(stub_km_state_t state); | ||
|
|
||
| void stub_target_km_set_keygen_mode(stub_km_keygen_mode_t mode); | ||
| void stub_target_km_set_key_purpose(stub_km_key_purpose_t purpose); | ||
| void stub_target_km_use_sw_init_key(void); | ||
| /* @p use_256: false = XTS-AES-128, true = XTS-AES-256. Only meaningful for | ||
| * XTS-AES key types; no-op for ECDSA / HMAC / DS. */ | ||
| void stub_target_km_set_xts_aes_key_len(stub_km_key_type_t key_type, bool use_256); | ||
|
|
||
| void stub_target_km_start(void); | ||
| void stub_target_km_continue(void); | ||
|
|
||
| /* ---------- KM memory I/O (LOAD / GAIN phases) -------------------------- */ | ||
|
|
||
| /* @p len must not exceed the destination MMIO window: 32 bytes for the | ||
| * SW_INIT_KEY block, 64 bytes for ASSIST_INFO / PUBLIC_INFO. The | ||
| * implementations clamp @p len to the window size as a safety net so an | ||
| * oversized len can never spill into adjacent KM registers. */ | ||
| void stub_target_km_write_sw_init_key(const uint8_t *buf, size_t len); | ||
| void stub_target_km_write_assist_info(const uint8_t *buf, size_t len); | ||
| void stub_target_km_write_public_info(const uint8_t *buf, size_t len); | ||
| void stub_target_km_read_assist_info(uint8_t *buf, size_t len); | ||
| void stub_target_km_read_public_info(uint8_t *buf, size_t len); | ||
|
|
||
|
hrushikesh430 marked this conversation as resolved.
|
||
| /* ---------- Result checks ----------------------------------------------- */ | ||
|
|
||
| /* Reads KEYMNG_HUK_VLD_REG. */ | ||
| bool stub_target_km_is_huk_valid(void); | ||
|
|
||
| /* Reads KEYMNG_KEY_VLD_REG bit corresponding to the given (key_type, key_len). | ||
| * The KEY_VLD encoding is split by ECDSA length — pass the same key_len | ||
| * the deploy operation used. */ | ||
| bool stub_target_km_is_key_deployment_valid(stub_km_key_type_t key_type, stub_km_key_len_t key_len); | ||
|
|
||
| /** | ||
| * @brief Configure KEYMNG_USE_EFUSE_KEY for a given key type. | ||
| * | ||
| * After a successful deploy/recovery, the static register must direct the | ||
| * peripheral to use the KM-deployed key (`use_own_key=true`) rather than | ||
| * an eFuse-burned key. This is the very last step in every deploy / recover | ||
| * sequence and matches `key_mgr_hal_set_key_usage(...USE_OWN_KEY)` in IDF. | ||
| */ | ||
| void stub_target_km_set_key_usage(stub_km_key_type_t key_type, bool use_own_key); | ||
|
|
||
| /** | ||
| * @brief Check whether any eFuse key block has KM_INIT_KEY (purpose 12) | ||
| * burned. | ||
| * | ||
| * Used by AES / ECDH1 deploy handlers before the chip is told to use the | ||
| * eFuse init_key (USE_SW_INIT_KEY=0). If no key block has the right | ||
| * purpose, the chip would silently decrypt k2_info with an all-zero key | ||
| * and produce an invalid deployment — surfacing this as an explicit error | ||
| * up-front saves debugging the resulting KEY_VLD=0 mystery. | ||
| * | ||
| * @return true if at least one block has purpose == KM_INIT_KEY; false | ||
| * otherwise. Implementations iterate over all 6 KEY block purpose | ||
| * fields; chip-specific because the field width and packing | ||
| * differ between targets (C5 uses 5-bit purposes, P4 4-bit). | ||
| */ | ||
| bool stub_target_km_is_efuse_init_key_burned(void); | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,138 @@ | ||
| /* | ||
| * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 OR MIT | ||
| */ | ||
|
|
||
| #include <stdbool.h> | ||
| #include <stddef.h> | ||
| #include <stdint.h> | ||
|
|
||
| #include <err.h> | ||
|
|
||
| #include <target/key_mgr.h> | ||
|
|
||
| /* | ||
| * Weak defaults for the Key Manager HAL. Chips that ship a Key Manager | ||
| * (ESP32-C5, ESP32-P4 >= v3.0) provide strong overrides under | ||
| * src/target/<chip>/src/key_mgr.c; chips without KM keep these no-op / | ||
| * safe-default versions so the library always links. | ||
| */ | ||
|
|
||
| void __attribute__((weak)) stub_target_huk_get_status(uint8_t *gen_status, uint8_t *risk_level) | ||
| { | ||
| if (gen_status != NULL) { | ||
| *gen_status = 0U; | ||
| } | ||
| if (risk_level != NULL) { | ||
| *risk_level = STUB_KM_HUK_RISK_ALERT_LEVEL; | ||
| } | ||
| } | ||
|
|
||
| int __attribute__((weak)) stub_target_huk_configure(stub_huk_mode_t mode, uint8_t *huk_info_buf) | ||
| { | ||
| (void)mode; | ||
| (void)huk_info_buf; | ||
| return STUB_LIB_FAIL; | ||
| } | ||
|
|
||
| bool __attribute__((weak)) stub_target_km_is_supported(void) | ||
| { | ||
| return false; /* no Key Manager on this chip/revision by default */ | ||
| } | ||
|
|
||
| void __attribute__((weak)) stub_target_km_bringup(void) | ||
| { | ||
| } | ||
|
|
||
| stub_km_state_t __attribute__((weak)) stub_target_km_get_state(void) | ||
| { | ||
| return STUB_KM_STATE_IDLE; | ||
| } | ||
|
|
||
| void __attribute__((weak)) stub_target_km_wait_for_state(stub_km_state_t state) | ||
| { | ||
| (void)state; | ||
| } | ||
|
|
||
| void __attribute__((weak)) stub_target_km_set_keygen_mode(stub_km_keygen_mode_t mode) | ||
| { | ||
| (void)mode; | ||
| } | ||
|
|
||
| void __attribute__((weak)) stub_target_km_set_key_purpose(stub_km_key_purpose_t purpose) | ||
| { | ||
| (void)purpose; | ||
| } | ||
|
|
||
| void __attribute__((weak)) stub_target_km_use_sw_init_key(void) | ||
| { | ||
| } | ||
|
|
||
| void __attribute__((weak)) stub_target_km_set_xts_aes_key_len(stub_km_key_type_t key_type, bool use_256) | ||
| { | ||
| (void)key_type; | ||
| (void)use_256; | ||
| } | ||
|
|
||
| void __attribute__((weak)) stub_target_km_start(void) | ||
| { | ||
| } | ||
|
|
||
| void __attribute__((weak)) stub_target_km_continue(void) | ||
| { | ||
| } | ||
|
|
||
| void __attribute__((weak)) stub_target_km_write_sw_init_key(const uint8_t *buf, size_t len) | ||
| { | ||
| (void)buf; | ||
| (void)len; | ||
| } | ||
|
|
||
| void __attribute__((weak)) stub_target_km_write_assist_info(const uint8_t *buf, size_t len) | ||
| { | ||
| (void)buf; | ||
| (void)len; | ||
| } | ||
|
|
||
| void __attribute__((weak)) stub_target_km_write_public_info(const uint8_t *buf, size_t len) | ||
| { | ||
| (void)buf; | ||
| (void)len; | ||
| } | ||
|
|
||
| void __attribute__((weak)) stub_target_km_read_assist_info(uint8_t *buf, size_t len) | ||
| { | ||
| (void)buf; | ||
| (void)len; | ||
| } | ||
|
|
||
| void __attribute__((weak)) stub_target_km_read_public_info(uint8_t *buf, size_t len) | ||
| { | ||
| (void)buf; | ||
| (void)len; | ||
| } | ||
|
|
||
| bool __attribute__((weak)) stub_target_km_is_huk_valid(void) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| bool __attribute__((weak)) stub_target_km_is_key_deployment_valid(stub_km_key_type_t key_type, | ||
| stub_km_key_len_t key_len) | ||
| { | ||
| (void)key_type; | ||
| (void)key_len; | ||
| return false; | ||
| } | ||
|
|
||
| void __attribute__((weak)) stub_target_km_set_key_usage(stub_km_key_type_t key_type, bool use_own_key) | ||
| { | ||
| (void)key_type; | ||
| (void)use_own_key; | ||
| } | ||
|
|
||
| bool __attribute__((weak)) stub_target_km_is_efuse_init_key_burned(void) | ||
| { | ||
| return false; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| /* | ||
| * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 OR MIT | ||
| */ | ||
|
|
||
| #pragma once | ||
|
|
||
| #include "reg_base.h" | ||
|
|
||
| #define EFUSE_RD_REPEAT_DATA1_REG (DR_REG_EFUSE_BASE + 0x34) | ||
| #define EFUSE_RD_REPEAT_DATA2_REG (DR_REG_EFUSE_BASE + 0x38) | ||
|
|
||
| /* | ||
| * Per-block KEY_PURPOSE field positions (5-bit purpose values, one block per | ||
| * eFuse KEY[0..5]). Used by the Key Manager HAL to scan for KM_INIT_KEY. | ||
| */ | ||
| #define EFUSE_C5_KEY_PURPOSE_M 0x1FU | ||
| #define EFUSE_C5_KEY0_PURPOSE_IN_DATA1_S 22 | ||
| #define EFUSE_C5_KEY1_PURPOSE_IN_DATA1_S 27 | ||
| #define EFUSE_C5_KEY2_PURPOSE_IN_DATA2_S 0 | ||
| #define EFUSE_C5_KEY3_PURPOSE_IN_DATA2_S 5 | ||
| #define EFUSE_C5_KEY4_PURPOSE_IN_DATA2_S 10 | ||
| #define EFUSE_C5_KEY5_PURPOSE_IN_DATA2_S 15 |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.