diff --git a/components/esp-tls/esp_tls_mbedtls.c b/components/esp-tls/esp_tls_mbedtls.c index d1debabffa..4e13617ee8 100644 --- a/components/esp-tls/esp_tls_mbedtls.c +++ b/components/esp-tls/esp_tls_mbedtls.c @@ -639,7 +639,9 @@ static esp_err_t set_pki_context(esp_tls_t *tls, const esp_tls_pki_t *pki) esp_ecdsa_opaque_key_t opaque_key = { .curve = curve, .efuse_block = tls->ecdsa_efuse_blk, - .use_km_key = false, +#if SOC_KEY_MANAGER_SUPPORTED + .key_recovery_info = NULL, +#endif /* SOC_KEY_MANAGER_SUPPORTED */ }; // Import opaque key reference diff --git a/components/esp_hal_security/test_apps/crypto/main/ds/ds_types.h b/components/esp_hal_security/test_apps/crypto/main/ds/ds_types.h index 6b82bf20fe..8fb442839c 100644 --- a/components/esp_hal_security/test_apps/crypto/main/ds/ds_types.h +++ b/components/esp_hal_security/test_apps/crypto/main/ds/ds_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -24,6 +24,11 @@ + ESP_DS_SIGNATURE_M_PRIME_BIT_LEN \ + ESP_DS_SIGNATURE_L_BIT_LEN \ + ESP_DS_SIGNATURE_PADDING_BIT_LEN) / 8)) +typedef enum { + ESP_DS_KEY_HMAC, + ESP_DS_KEY_AES, + ESP_DS_KEY_MAX, +} esp_ds_key_type_t; typedef enum { ESP_DS_RSA_1024 = (1024 / 32) - 1, diff --git a/components/esp_hal_security/test_apps/crypto/main/ds/test_ds.c b/components/esp_hal_security/test_apps/crypto/main/ds/test_ds.c index b982707cce..0269309924 100644 --- a/components/esp_hal_security/test_apps/crypto/main/ds/test_ds.c +++ b/components/esp_hal_security/test_apps/crypto/main/ds/test_ds.c @@ -164,11 +164,16 @@ static esp_err_t esp_ds_sign(const void *message, return esp_ds_finish_sign(signature, data); } -static esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data, - const void *iv, - const esp_ds_p_data_t *p_data, - const void *key) +static esp_err_t esp_ds_encrypt_params_using_key_type(esp_ds_data_t *data, + const void *iv, + const esp_ds_p_data_t *p_data, + const void *key, + esp_ds_key_type_t key_type) { + if (key_type >= ESP_DS_KEY_MAX) { + return ESP_ERR_INVALID_ARG; + } + if (!p_data) { return ESP_ERR_INVALID_ARG; } @@ -188,7 +193,7 @@ static esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data, ets_ds_data_t *ds_data = (ets_ds_data_t *) data; const ets_ds_p_data_t *ds_plain_data = (const ets_ds_p_data_t *) p_data; - ets_ds_result_t ets_result = ets_ds_encrypt_params(ds_data, iv, ds_plain_data, key, ETS_DS_KEY_HMAC); + ets_ds_result_t ets_result = ets_ds_encrypt_params(ds_data, iv, ds_plain_data, key, (ets_ds_key_t) key_type); if (ets_result == ETS_DS_INVALID_PARAM) { result = ESP_ERR_INVALID_ARG; @@ -286,11 +291,16 @@ static esp_err_t esp_ds_sign(const void *message, return esp_ds_finish_sign(signature, (void *)data); } -static esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data, - const void *iv, - const esp_ds_p_data_t *p_data, - const void *key) +static esp_err_t esp_ds_encrypt_params_using_key_type(esp_ds_data_t *data, + const void *iv, + const esp_ds_p_data_t *p_data, + const void *key, + esp_ds_key_type_t key_type) { + if (key_type >= ESP_DS_KEY_MAX) { + return ESP_ERR_INVALID_ARG; + } + assert(esp_ptr_internal(p_data) && esp_ptr_word_aligned(p_data)); esp_err_t result = ESP_OK; @@ -301,7 +311,7 @@ static esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data, ets_ds_data_t *ds_data = (ets_ds_data_t *) data; const ets_ds_p_data_t *ds_plain_data = (const ets_ds_p_data_t *) p_data; - ets_ds_result_t ets_result = ets_ds_encrypt_params(ds_data, iv, ds_plain_data, key, ETS_DS_KEY_HMAC); + ets_ds_result_t ets_result = ets_ds_encrypt_params(ds_data, iv, ds_plain_data, key, (ets_ds_key_t) key_type); if (ets_result == ETS_DS_INVALID_PARAM) { result = ESP_ERR_INVALID_ARG; @@ -343,8 +353,8 @@ TEST(ds, digital_signature_parameter_encryption) p_data.M_prime = t->p_data.M_prime; p_data.length = t->p_data.length; - esp_err_t r = esp_ds_encrypt_params(&result, t->iv, &p_data, - test_hmac_keys[t->hmac_key_idx]); + esp_err_t r = esp_ds_encrypt_params_using_key_type(&result, t->iv, &p_data, + test_hmac_keys[t->hmac_key_idx], ESP_DS_KEY_HMAC); ESP_LOGI(TAG, "Encrypting test case %d done", i); TEST_ASSERT_EQUAL(ESP_OK, r); TEST_ASSERT_EQUAL(t->p_data.length, result.rsa_length); diff --git a/components/esp_security/include/esp_ds.h b/components/esp_security/include/esp_ds.h index 2ed1b7f4c6..dbc23bb44c 100644 --- a/components/esp_security/include/esp_ds.h +++ b/components/esp_security/include/esp_ds.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,6 +27,7 @@ extern "C" { #define ESP_DS_SIGNATURE_M_PRIME_BIT_LEN 32 #define ESP_DS_SIGNATURE_L_BIT_LEN 32 #define ESP_DS_SIGNATURE_PADDING_BIT_LEN 64 +#define ESP_DS_DATA_KEY_SIZE 32 /* Length of parameter 'C' stored in flash, in bytes - Operands Y, M and r_bar; each equal to maximum RSA bit length @@ -40,6 +41,12 @@ extern "C" { + ESP_DS_SIGNATURE_L_BIT_LEN \ + ESP_DS_SIGNATURE_PADDING_BIT_LEN) / 8)) +typedef enum { + ESP_DS_KEY_HMAC, + ESP_DS_KEY_AES, + ESP_DS_KEY_MAX, +} esp_ds_key_type_t; + /** * @brief Context object used for non-blocking digital signature operations * @@ -223,7 +230,7 @@ esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx); * @param p_data Pointer to input plaintext key data. The expectation is this data will be deleted after this process * is done and 'data' is stored. * @param key Pointer to 32 bytes of key data. Type determined by key_type parameter. The expectation is the - * corresponding HMAC key will be stored to efuse and then permanently erased. + * corresponding HMAC key will be stored to efuse and then permanently erased for ESP_DS_KEY_HMAC. * * @note * The numbers Y, M, Rb which are a part of esp_ds_data_t should be provided in little endian format @@ -241,6 +248,40 @@ esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data, const esp_ds_p_data_t *p_data, const void *key); +/** + * @brief Encrypt the private key parameters. + * + * The encryption is a prerequisite step before any signature operation can be done. + * It is not strictly necessary to use this encryption function, the encryption could also happen on an external + * device. + * + * @param data Output buffer to store encrypted data, suitable for later use generating signatures. + * @param iv Pointer to 16 byte IV buffer, will be copied into 'data'. Should be randomly generated bytes each time. + * @param p_data Pointer to input plaintext key data. The expectation is this data will be deleted after this process + * is done and 'data' is stored. + * @param key Pointer to 32 bytes of key data. Type determined by key_type parameter. The expectation is the + * corresponding HMAC key will be stored to efuse and then permanently erased for ESP_DS_KEY_HMAC. + * or the AES key will be used by the the DS peripheral (internally) to decrypt the encrypted RSA private key + * parameters for ESP_DS_KEY_AES. + * @param key_type The type of key parameter (either ESP_DS_KEY_HMAC or ESP_DS_KEY_AES). + * + * @note + * The numbers Y, M, Rb which are a part of esp_ds_data_t should be provided in little endian format + * and should be of length equal to the RSA private key bit length + * The message length in bits should also be equal to the RSA private key bit length. + * No padding is applied to the message automatically, Please ensure the message is appropriate padded before + * calling the API. + * + * @return + * - ESP_OK if successful, the ds operation has been finished and the result is written to signature. + * - ESP_ERR_INVALID_ARG if one of the parameters is NULL or p_data->rsa_length is too long + */ +esp_err_t esp_ds_encrypt_params_using_key_type(esp_ds_data_t *data, + const void *iv, + const esp_ds_p_data_t *p_data, + const void *key, + esp_ds_key_type_t key_type); + #ifdef __cplusplus } #endif diff --git a/components/esp_security/src/esp_ds.c b/components/esp_security/src/esp_ds.c index 0d311c610b..621f54242f 100644 --- a/components/esp_security/src/esp_ds.c +++ b/components/esp_security/src/esp_ds.c @@ -203,11 +203,16 @@ esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx) return return_value; } -esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data, - const void *iv, - const esp_ds_p_data_t *p_data, - const void *key) +static esp_err_t ds_encrypt_params_using_key_type(esp_ds_data_t *data, + const void *iv, + const esp_ds_p_data_t *p_data, + const void *key, + esp_ds_key_type_t key_type) { + if (key_type >= ESP_DS_KEY_MAX) { + return ESP_ERR_INVALID_ARG; + } + // p_data has to be valid, in internal memory and word aligned if (!p_data) { return ESP_ERR_INVALID_ARG; @@ -223,7 +228,7 @@ esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data, ets_ds_data_t *ds_data = (ets_ds_data_t *) data; const ets_ds_p_data_t *ds_plain_data = (const ets_ds_p_data_t *) p_data; - ets_ds_result_t ets_result = ets_ds_encrypt_params(ds_data, iv, ds_plain_data, key, ETS_DS_KEY_HMAC); + ets_ds_result_t ets_result = ets_ds_encrypt_params(ds_data, iv, ds_plain_data, key, (ets_ds_key_t) key_type); if (ets_result == ETS_DS_INVALID_PARAM) { result = ESP_ERR_INVALID_ARG; @@ -423,18 +428,23 @@ esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx) return return_value; } -esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data, - const void *iv, - const esp_ds_p_data_t *p_data, - const void *key) +static esp_err_t ds_encrypt_params_using_key_type(esp_ds_data_t *data, + const void *iv, + const esp_ds_p_data_t *p_data, + const void *key, + esp_ds_key_type_t key_type) { + if (key_type >= ESP_DS_KEY_MAX) { + return ESP_ERR_INVALID_ARG; + } + if (!p_data) { return ESP_ERR_INVALID_ARG; } esp_err_t result = ESP_OK; - // The `esp_ds_encrypt_params` operation does not use the Digital Signature peripheral, + // The `esp_ds_encrypt_params_using_key_type` operation does not use the Digital Signature peripheral, // but just the AES and SHA peripherals, so acquiring locks just for these peripherals // would be enough rather than acquiring a lock for the Digital Signature peripheral. esp_crypto_sha_aes_lock_acquire(); @@ -446,7 +456,7 @@ esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data, ets_ds_data_t *ds_data = (ets_ds_data_t *) data; const ets_ds_p_data_t *ds_plain_data = (const ets_ds_p_data_t *) p_data; - ets_ds_result_t ets_result = ets_ds_encrypt_params(ds_data, iv, ds_plain_data, key, ETS_DS_KEY_HMAC); + ets_ds_result_t ets_result = ets_ds_encrypt_params(ds_data, iv, ds_plain_data, key, (ets_ds_key_t) key_type); if (ets_result == ETS_DS_INVALID_PARAM) { result = ESP_ERR_INVALID_ARG; @@ -461,3 +471,20 @@ esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data, return result; } #endif + +esp_err_t esp_ds_encrypt_params_using_key_type(esp_ds_data_t *data, + const void *iv, + const esp_ds_p_data_t *p_data, + const void *key, + esp_ds_key_type_t key_type) +{ + return ds_encrypt_params_using_key_type(data, iv, p_data, key, key_type); +} + +esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data, + const void *iv, + const esp_ds_p_data_t *p_data, + const void *key) +{ + return ds_encrypt_params_using_key_type(data, iv, p_data, key, ESP_DS_KEY_HMAC); +} diff --git a/components/esp_security/src/esp_key_mgr.c b/components/esp_security/src/esp_key_mgr.c index 28bcfbedba..786050cad6 100644 --- a/components/esp_security/src/esp_key_mgr.c +++ b/components/esp_security/src/esp_key_mgr.c @@ -561,6 +561,11 @@ esp_err_t esp_key_mgr_activate_key(esp_key_mgr_key_recovery_info_t *key_recovery return ESP_ERR_INVALID_ARG; } + if (key_recovery_info->magic != KEY_HUK_SECTOR_MAGIC) { + ESP_LOGE(TAG, "Invalid key recovery info magic"); + return ESP_ERR_INVALID_ARG; + } + esp_key_mgr_key_type_t key_type = key_recovery_info->key_type; ESP_LOGD(TAG, "Activating key of type %d", key_type); diff --git a/components/esp_security/test_apps/crypto_drivers/main/test_ds.c b/components/esp_security/test_apps/crypto_drivers/main/test_ds.c index 6a7629d80c..13c8c877d9 100644 --- a/components/esp_security/test_apps/crypto_drivers/main/test_ds.c +++ b/components/esp_security/test_apps/crypto_drivers/main/test_ds.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -79,7 +79,7 @@ TEST_CASE("Digital Signature Parameter Encryption data NULL", "[hw_crypto] [ds]" esp_ds_p_data_t p_data = {0}; const char key [32] = {0}; - TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params(NULL, iv, &p_data, key)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params_using_key_type(NULL, iv, &p_data, key, ESP_DS_KEY_HMAC)); } TEST_CASE("Digital Signature Parameter Encryption iv NULL", "[hw_crypto] [ds]") @@ -88,7 +88,7 @@ TEST_CASE("Digital Signature Parameter Encryption iv NULL", "[hw_crypto] [ds]") esp_ds_p_data_t p_data = {0}; const char key [32] = {0}; - TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params(&data, NULL, &p_data, key)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params_using_key_type(&data, NULL, &p_data, key, ESP_DS_KEY_HMAC)); } TEST_CASE("Digital Signature Parameter Encryption p_data NULL", "[hw_crypto] [ds]") @@ -97,7 +97,7 @@ TEST_CASE("Digital Signature Parameter Encryption p_data NULL", "[hw_crypto] [ds const char iv [32] = {0}; const char key [32] = {0}; - TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params(&data, iv, NULL, key)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params_using_key_type(&data, iv, NULL, key, ESP_DS_KEY_HMAC)); } TEST_CASE("Digital Signature Parameter Encryption key NULL", "[hw_crypto] [ds]") @@ -106,7 +106,7 @@ TEST_CASE("Digital Signature Parameter Encryption key NULL", "[hw_crypto] [ds]") const char iv [32] = {0}; esp_ds_p_data_t p_data = {0}; - TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params(&data, iv, &p_data, NULL)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params_using_key_type(&data, iv, &p_data, NULL, ESP_DS_KEY_HMAC)); } TEST_CASE("Digital Signature Parameter Encryption", "[hw_crypto] [ds]") @@ -123,8 +123,8 @@ TEST_CASE("Digital Signature Parameter Encryption", "[hw_crypto] [ds]") p_data.M_prime = t->p_data.M_prime; p_data.length = t->p_data.length; - esp_err_t r = esp_ds_encrypt_params(&result, t->iv, &p_data, - test_hmac_keys[t->hmac_key_idx]); + esp_err_t r = esp_ds_encrypt_params_using_key_type(&result, t->iv, &p_data, + test_hmac_keys[t->hmac_key_idx], ESP_DS_KEY_HMAC); printf("Encrypting test case %d done\n", i); TEST_ASSERT_EQUAL(ESP_OK, r); TEST_ASSERT_EQUAL(t->p_data.length, result.rsa_length); diff --git a/components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml b/components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml index 4ff99e0e2a..79b062cc90 100644 --- a/components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml +++ b/components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml @@ -301,6 +301,10 @@ secure_services: type: IDF function: esp_sha_512_t_init_hash args: 1 + - id: 113 + type: IDF + function: esp_ds_encrypt_params_using_key_type + args: 5 # ID: 134-169 (36) - Reserved for future use - family: attestation entries: diff --git a/components/esp_tee/scripts/esp32c6/sec_srv_tbl_default.yml b/components/esp_tee/scripts/esp32c6/sec_srv_tbl_default.yml index 16fa321453..2d864bc106 100644 --- a/components/esp_tee/scripts/esp32c6/sec_srv_tbl_default.yml +++ b/components/esp_tee/scripts/esp32c6/sec_srv_tbl_default.yml @@ -241,6 +241,10 @@ secure_services: type: IDF function: esp_sha_set_mode args: 1 + - id: 111 + type: IDF + function: esp_ds_encrypt_params_using_key_type + args: 5 # ID: 134-169 (36) - Reserved for future use - family: attestation entries: diff --git a/components/esp_tee/scripts/esp32h2/sec_srv_tbl_default.yml b/components/esp_tee/scripts/esp32h2/sec_srv_tbl_default.yml index 0a5321f6e2..567f143692 100644 --- a/components/esp_tee/scripts/esp32h2/sec_srv_tbl_default.yml +++ b/components/esp_tee/scripts/esp32h2/sec_srv_tbl_default.yml @@ -245,6 +245,10 @@ secure_services: type: IDF function: esp_sha_set_mode args: 1 + - id: 112 + type: IDF + function: esp_ds_encrypt_params_using_key_type + args: 5 # ID: 134-169 (36) - Reserved for future use - family: attestation entries: diff --git a/components/esp_tee/src/esp_secure_service_wrapper.c b/components/esp_tee/src/esp_secure_service_wrapper.c index d5abd001ec..655ba201f7 100644 --- a/components/esp_tee/src/esp_secure_service_wrapper.c +++ b/components/esp_tee/src/esp_secure_service_wrapper.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -287,6 +287,18 @@ esp_err_t __wrap_esp_ds_encrypt_params(esp_ds_data_t *data, esp_crypto_sha_aes_lock_release(); return err; } + +esp_err_t __wrap_esp_ds_encrypt_params_using_key_type(esp_ds_data_t *data, + const void *iv, + const esp_ds_p_data_t *p_data, + const void *key, + esp_ds_key_type_t key_type) +{ + esp_crypto_sha_aes_lock_acquire(); + esp_err_t err = esp_tee_service_call(6, SS_ESP_DS_ENCRYPT_PARAMS_USING_KEY_TYPE, data, iv, p_data, key, key_type); + esp_crypto_sha_aes_lock_release(); + return err; +} #endif /* ---------------------------------------------- MPI ------------------------------------------------- */ diff --git a/components/esp_tee/subproject/main/core/esp_secure_services.c b/components/esp_tee/subproject/main/core/esp_secure_services.c index 757b30931f..13d53db7ad 100644 --- a/components/esp_tee/subproject/main/core/esp_secure_services.c +++ b/components/esp_tee/subproject/main/core/esp_secure_services.c @@ -347,6 +347,8 @@ esp_err_t _ss_esp_ds_encrypt_params(esp_ds_data_t *data, (esp_tee_ptr_in_ree((void *)iv) && esp_tee_ptr_in_ree((void *)key))); valid_addr &= esp_tee_ptr_in_ree((void *)((char *)data + sizeof(esp_ds_data_t))); + valid_addr &= esp_tee_ptr_in_ree((void *)((char *)p_data + sizeof(esp_ds_p_data_t))); + valid_addr &= esp_tee_ptr_in_ree((void *)((char *)key + ESP_DS_DATA_KEY_SIZE)); if (!valid_addr) { return ESP_ERR_INVALID_ARG; @@ -355,6 +357,27 @@ esp_err_t _ss_esp_ds_encrypt_params(esp_ds_data_t *data, return esp_ds_encrypt_params(data, iv, p_data, key); } + +esp_err_t _ss_esp_ds_encrypt_params_using_key_type(esp_ds_data_t *data, + const void *iv, + const esp_ds_p_data_t *p_data, + const void *key, + esp_ds_key_type_t key_type) +{ + bool valid_addr = ((esp_tee_ptr_in_ree((void *)data) && esp_tee_ptr_in_ree((void *)p_data)) && + (esp_tee_ptr_in_ree((void *)iv) && esp_tee_ptr_in_ree((void *)key))); + + valid_addr &= esp_tee_ptr_in_ree((void *)((char *)data + sizeof(esp_ds_data_t))); + valid_addr &= esp_tee_ptr_in_ree((void *)((char *)p_data + sizeof(esp_ds_p_data_t))); + valid_addr &= esp_tee_ptr_in_ree((void *)((char *)key + ESP_DS_DATA_KEY_SIZE)); + + if (!valid_addr) { + return ESP_ERR_INVALID_ARG; + } + ESP_FAULT_ASSERT(valid_addr); + + return esp_ds_encrypt_params_using_key_type(data, iv, p_data, key, key_type); +} #endif /* ---------------------------------------------- MPI ------------------------------------------------- */