mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 18:50:34 +03:00
fix(esp_security): Enable ECC clock while using the Key Manager's ECDH key deployment mode
This commit is contained in:
@@ -23,6 +23,7 @@ endif()
|
||||
|
||||
if(CONFIG_CRYPTO_IS_KEY_MANAGER_SUPPORTED)
|
||||
list(APPEND srcs "key_manager/test_key_manager.c"
|
||||
"key_manager/km_ecdh0_verify.c"
|
||||
"$ENV{IDF_PATH}/components/esp_security/src/esp_key_mgr.c")
|
||||
list(APPEND priv_include_dirs "$ENV{IDF_PATH}/components/esp_security/include")
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "unity.h"
|
||||
|
||||
#include "ecc_impl.h"
|
||||
#include "psa/crypto.h"
|
||||
|
||||
#include "mbedtls/private/aes.h"
|
||||
#include "mbedtls/ecp.h"
|
||||
#include "mbedtls/bignum.h"
|
||||
|
||||
#include "km_ecdh0_verify.h"
|
||||
|
||||
/* P-192 generator hardcoded in esp_ecc's little-endian layout. We don't pull
|
||||
* P-192 from mbedtls because support for ECDSA P-192 is disabled by default in mbedtls.
|
||||
* P-256 and P-384 are loaded from mbedtls at use time -- see load_curve_generator_le below. */
|
||||
static const uint8_t p192_G_x_le[P192_LEN] = {
|
||||
0x12, 0x10, 0xff, 0x82, 0xfd, 0x0a, 0xff, 0xf4, 0x00, 0x88, 0xa1, 0x43,
|
||||
0xeb, 0x20, 0xbf, 0x7c, 0xf6, 0x90, 0x30, 0xb0, 0x0e, 0xa8, 0x8d, 0x18,
|
||||
};
|
||||
static const uint8_t p192_G_y_le[P192_LEN] = {
|
||||
0x11, 0x48, 0x79, 0x1e, 0xa1, 0x77, 0xf9, 0x73, 0xd5, 0xcd, 0x24, 0x6b,
|
||||
0xed, 0x11, 0x10, 0x63, 0x78, 0xda, 0xc8, 0xff, 0x95, 0x2b, 0x19, 0x07,
|
||||
};
|
||||
|
||||
static void load_curve_generator_le(mbedtls_ecp_group_id grp_id,
|
||||
uint8_t *gx_le, uint8_t *gy_le,
|
||||
size_t coord_len)
|
||||
{
|
||||
mbedtls_ecp_group grp;
|
||||
mbedtls_ecp_group_init(&grp);
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_ecp_group_load(&grp, grp_id));
|
||||
|
||||
/* mbedtls_ecp_point_write_binary in uncompressed form gives
|
||||
* 0x04 || X_BE || Y_BE. Reverse each coord into the LE byte order
|
||||
* esp_ecc expects. */
|
||||
uint8_t buf[1 + 2 * P384_LEN];
|
||||
size_t olen = 0;
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_ecp_point_write_binary(&grp, &grp.G,
|
||||
MBEDTLS_ECP_PF_UNCOMPRESSED,
|
||||
&olen, buf, sizeof(buf)));
|
||||
TEST_ASSERT_EQUAL(1 + 2 * coord_len, olen);
|
||||
for (size_t i = 0; i < coord_len; ++i) {
|
||||
gx_le[i] = buf[1 + coord_len - 1 - i];
|
||||
gy_le[i] = buf[1 + 2 * coord_len - 1 - i];
|
||||
}
|
||||
|
||||
mbedtls_ecp_group_free(&grp);
|
||||
}
|
||||
|
||||
void km_verify_compute_x_be(const uint8_t *k1_be, size_t k1_len,
|
||||
const uint8_t *k2_G_km, uint8_t x_be_out[32])
|
||||
{
|
||||
uint8_t k1_le[P256_LEN] = { 0 };
|
||||
TEST_ASSERT_LESS_OR_EQUAL(P256_LEN, k1_len);
|
||||
for (size_t i = 0; i < k1_len; ++i) {
|
||||
k1_le[i] = k1_be[k1_len - 1 - i];
|
||||
}
|
||||
|
||||
ecc_point_t k2_G = { .len = P256_LEN };
|
||||
memcpy(k2_G.x, k2_G_km, P256_LEN);
|
||||
memcpy(k2_G.y, k2_G_km + P256_LEN, P256_LEN);
|
||||
|
||||
ecc_point_t result = { 0 };
|
||||
TEST_ASSERT_EQUAL(0, esp_ecc_point_multiply(&k2_G, k1_le, &result, true));
|
||||
|
||||
for (int i = 0; i < P256_LEN; ++i) {
|
||||
x_be_out[i] = result.x[P256_LEN - 1 - i];
|
||||
}
|
||||
}
|
||||
|
||||
void km_verify_ecdsa_pubkey_from_scalar(unsigned curve_len,
|
||||
const uint8_t *scalar_be,
|
||||
size_t scalar_len,
|
||||
uint8_t *pub_x_le_out,
|
||||
uint8_t *pub_y_le_out)
|
||||
{
|
||||
uint8_t scalar_le[P384_LEN] = { 0 };
|
||||
TEST_ASSERT_LESS_OR_EQUAL(curve_len, scalar_len);
|
||||
for (size_t i = 0; i < scalar_len; ++i) {
|
||||
scalar_le[i] = scalar_be[scalar_len - 1 - i];
|
||||
}
|
||||
|
||||
ecc_point_t G = { .len = curve_len };
|
||||
switch (curve_len) {
|
||||
case P192_LEN:
|
||||
memcpy(G.x, p192_G_x_le, P192_LEN);
|
||||
memcpy(G.y, p192_G_y_le, P192_LEN);
|
||||
break;
|
||||
case P256_LEN:
|
||||
load_curve_generator_le(MBEDTLS_ECP_DP_SECP256R1, G.x, G.y, P256_LEN);
|
||||
break;
|
||||
#if SOC_ECC_SUPPORT_CURVE_P384
|
||||
case P384_LEN:
|
||||
load_curve_generator_le(MBEDTLS_ECP_DP_SECP384R1, G.x, G.y, P384_LEN);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
TEST_FAIL_MESSAGE("Unsupported curve length for ECDSA pubkey reconstruction");
|
||||
}
|
||||
|
||||
ecc_point_t pub = { 0 };
|
||||
/* G is always a valid curve point, so verify_first=false. */
|
||||
TEST_ASSERT_EQUAL(0, esp_ecc_point_multiply(&G, scalar_le, &pub, false));
|
||||
|
||||
memcpy(pub_x_le_out, pub.x, curve_len);
|
||||
memcpy(pub_y_le_out, pub.y, curve_len);
|
||||
}
|
||||
|
||||
void km_verify_flash_xts_encrypt(const uint8_t *key, size_t key_bits,
|
||||
uint32_t flash_address,
|
||||
const uint8_t *pt, size_t pt_len,
|
||||
uint8_t *ct_out)
|
||||
{
|
||||
TEST_ASSERT_LESS_OR_EQUAL(128, pt_len);
|
||||
TEST_ASSERT_EQUAL(0, flash_address & 0x7F);
|
||||
|
||||
mbedtls_aes_xts_context ctx;
|
||||
mbedtls_aes_xts_init(&ctx);
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_aes_xts_setkey_enc(&ctx, key, key_bits));
|
||||
|
||||
uint8_t block_in[128] = { 0 };
|
||||
uint8_t block_rev[128] = { 0 };
|
||||
uint8_t block_cipher_rev[128];
|
||||
uint8_t block_cipher[128];
|
||||
memcpy(block_in, pt, pt_len);
|
||||
for (int i = 0; i < 128; ++i) {
|
||||
block_rev[i] = block_in[127 - i];
|
||||
}
|
||||
|
||||
uint8_t data_unit[16] = { 0 };
|
||||
uint32_t tweak_addr = flash_address & ~0x7FU;
|
||||
data_unit[0] = (uint8_t)(tweak_addr);
|
||||
data_unit[1] = (uint8_t)(tweak_addr >> 8);
|
||||
data_unit[2] = (uint8_t)(tweak_addr >> 16);
|
||||
data_unit[3] = (uint8_t)(tweak_addr >> 24);
|
||||
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_aes_crypt_xts(&ctx, MBEDTLS_AES_ENCRYPT, 128,
|
||||
data_unit, block_rev, block_cipher_rev));
|
||||
for (int i = 0; i < 128; ++i) {
|
||||
block_cipher[i] = block_cipher_rev[127 - i];
|
||||
}
|
||||
memcpy(ct_out, block_cipher, pt_len);
|
||||
|
||||
mbedtls_aes_xts_free(&ctx);
|
||||
}
|
||||
|
||||
void km_verify_hmac_sha256(const uint8_t *key, size_t key_len,
|
||||
const uint8_t *msg, size_t msg_len,
|
||||
uint8_t mac_out[32])
|
||||
{
|
||||
psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
|
||||
psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_MESSAGE);
|
||||
psa_set_key_algorithm(&attr, PSA_ALG_HMAC(PSA_ALG_SHA_256));
|
||||
psa_set_key_type(&attr, PSA_KEY_TYPE_HMAC);
|
||||
psa_set_key_bits(&attr, key_len * 8);
|
||||
|
||||
psa_key_id_t key_id = 0;
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attr, key, key_len, &key_id));
|
||||
|
||||
size_t mac_len = 0;
|
||||
psa_status_t status = psa_mac_compute(key_id,
|
||||
PSA_ALG_HMAC(PSA_ALG_SHA_256),
|
||||
msg, msg_len,
|
||||
mac_out, 32, &mac_len);
|
||||
psa_destroy_key(key_id);
|
||||
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
|
||||
TEST_ASSERT_EQUAL(32, mac_len);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*
|
||||
* Runtime verification helpers for Key-Manager ECDH0 deployments.
|
||||
*
|
||||
* After an ECDH0 deploy the KM exports k2*G in `ecdh0_info`. The host side
|
||||
* knows k1, so it can reconstruct x(k1*k2*G) on P-256 (via the ECC
|
||||
* peripheral), derive the expected per-peripheral effective key, and
|
||||
* assert the hardware output (HMAC / ECDSA pubkey / XTS ciphertext)
|
||||
* matches bit-for-bit.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Compute x(k1 * k2_G) on NIST P-256 using the ECC peripheral and return it
|
||||
* as 32 big-endian bytes.
|
||||
*
|
||||
* k1_be: big-endian scalar bytes (24 or 32).
|
||||
* k1_len: length of k1_be in bytes.
|
||||
* k2_G_km: 64-byte KM-format public point exported in ecdh0_info: the
|
||||
* peripheral's native LE-x || LE-y layout.
|
||||
* x_be_out: 32 big-endian bytes of the result's x-coordinate.
|
||||
*/
|
||||
void km_verify_compute_x_be(const uint8_t *k1_be, size_t k1_len,
|
||||
const uint8_t *k2_G_km, uint8_t x_be_out[32]);
|
||||
|
||||
/* Given an ECDSA scalar (big-endian) and an ECC curve length
|
||||
* (P192_LEN / P256_LEN / P384_LEN, from ecc_impl.h), compute scalar*G on
|
||||
* that curve via the ECC peripheral and write pub_x / pub_y in the
|
||||
* little-endian byte order the ECDSA peripheral exports.
|
||||
*/
|
||||
void km_verify_ecdsa_pubkey_from_scalar(unsigned curve_len,
|
||||
const uint8_t *scalar_be,
|
||||
size_t scalar_len,
|
||||
uint8_t *pub_x_le_out,
|
||||
uint8_t *pub_y_le_out);
|
||||
|
||||
/* ESP32 flash-encryption XTS-AES in software (block-reversal wrapper around
|
||||
* standard XTS, flash-address-based tweak). Encrypts `pt_len` <= 128 bytes
|
||||
* at a 128-byte-aligned `flash_address`.
|
||||
*/
|
||||
void km_verify_flash_xts_encrypt(const uint8_t *key, size_t key_bits,
|
||||
uint32_t flash_address,
|
||||
const uint8_t *pt, size_t pt_len,
|
||||
uint8_t *ct_out);
|
||||
|
||||
/* HMAC-SHA256 one-shot via PSA */
|
||||
void km_verify_hmac_sha256(const uint8_t *key, size_t key_len,
|
||||
const uint8_t *msg, size_t msg_len,
|
||||
uint8_t mac_out[32]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -24,6 +24,13 @@
|
||||
#include "esp_flash.h"
|
||||
#include "key_manager_test_cases.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_crypto_periph_clk.h"
|
||||
|
||||
/* Runtime-verification helpers for ECDH0 deployments (ecc_point_multiply
|
||||
* wrapper, ECDSA pubkey reconstruction, flash-XTS reference, HMAC).
|
||||
* See km_ecdh0_verify.h for details. */
|
||||
#include "km_ecdh0_verify.h"
|
||||
#include "ecc_impl.h" /* for P192_LEN / P256_LEN / P384_LEN */
|
||||
|
||||
#if SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY
|
||||
#include "hal/ecdsa_types.h"
|
||||
@@ -48,8 +55,14 @@ const esp_partition_t *get_test_storage_partition(void)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif /* SOC_KEY_MANAGER_FE_KEY_DEPLOY */
|
||||
|
||||
static void test_xts_aes_key_aes_mode(test_data_aes_mode_t *test_data)
|
||||
#if SOC_KEY_MANAGER_FE_KEY_DEPLOY
|
||||
/* Common XTS-AES verify body. Used by both the AES-mode and ECDH1-mode XTS
|
||||
* tests, which carry their own struct types but share the same plaintext +
|
||||
* expected-ciphertext layout. */
|
||||
static void verify_xts_aes_test_data(const uint8_t *plaintext_data,
|
||||
const test_xts_data_t *xts_test_data)
|
||||
{
|
||||
const esp_partition_t *partition = get_test_storage_partition();
|
||||
ESP_ERROR_CHECK(esp_partition_erase_range(partition, 0, partition->size));
|
||||
@@ -57,17 +70,27 @@ static void test_xts_aes_key_aes_mode(test_data_aes_mode_t *test_data)
|
||||
uint8_t read_data[128];
|
||||
for (int i = 0; i < TEST_COUNT; i++) {
|
||||
memset(read_data, 0, sizeof(read_data));
|
||||
uint32_t address = test_data->xts_test_data[i].data_offset;
|
||||
uint32_t data_size = test_data->xts_test_data[i].data_size;
|
||||
uint32_t address = xts_test_data[i].data_offset;
|
||||
uint32_t data_size = xts_test_data[i].data_size;
|
||||
|
||||
ESP_ERROR_CHECK(esp_flash_write_encrypted(NULL, address, test_data->plaintext_data, data_size));
|
||||
ESP_ERROR_CHECK(esp_flash_write_encrypted(NULL, address, plaintext_data, data_size));
|
||||
ESP_ERROR_CHECK(esp_flash_read(NULL, read_data, address, data_size));
|
||||
|
||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(test_data->xts_test_data[i].ciphertext, read_data, data_size);
|
||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(xts_test_data[i].ciphertext, read_data, data_size);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_xts_aes_key_ecdh0_mode(test_data_ecdh0_mode_t *test_data)
|
||||
static void test_xts_aes_key_aes_mode(test_data_aes_mode_t *test_data)
|
||||
{
|
||||
verify_xts_aes_test_data(test_data->plaintext_data, test_data->xts_test_data);
|
||||
}
|
||||
|
||||
/* Verify the ECDH0-deployed XTS key by writing plaintext through the HW
|
||||
* flash-encrypt path and comparing the readback against the ciphertext we
|
||||
* compute in software with mbedtls_xts under the derived key material.
|
||||
*/
|
||||
static void test_xts_aes_key_ecdh0_mode(test_data_ecdh0_mode_t *test_data,
|
||||
const uint8_t *derived_key, size_t key_bits)
|
||||
{
|
||||
const esp_partition_t *partition = get_test_storage_partition();
|
||||
ESP_ERROR_CHECK(esp_partition_erase_range(partition, 0, partition->size));
|
||||
@@ -76,12 +99,13 @@ static void test_xts_aes_key_ecdh0_mode(test_data_ecdh0_mode_t *test_data)
|
||||
uint32_t address = partition->address;
|
||||
uint32_t data_size = 32;
|
||||
|
||||
ESP_LOG_BUFFER_HEXDUMP("Plaintext data", test_data->plaintext_data, data_size, ESP_LOG_DEBUG);
|
||||
|
||||
ESP_ERROR_CHECK(esp_flash_write_encrypted(NULL, address, test_data->plaintext_data, data_size));
|
||||
ESP_ERROR_CHECK(esp_flash_read(NULL, read_data, address, data_size));
|
||||
|
||||
ESP_LOG_BUFFER_HEXDUMP("Encrypted data", read_data, data_size, ESP_LOG_DEBUG);
|
||||
uint8_t expected[32];
|
||||
km_verify_flash_xts_encrypt(derived_key, key_bits, address,
|
||||
test_data->plaintext_data, data_size, expected);
|
||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, read_data, data_size);
|
||||
}
|
||||
|
||||
#if SOC_KEY_MANAGER_FE_KEY_DEPLOY_XTS_AES_128 || SOC_KEY_MANAGER_FE_KEY_DEPLOY_XTS_AES_256
|
||||
@@ -135,7 +159,24 @@ static void key_mgr_test_xts_aes_key_ecdh0_mode(esp_key_mgr_key_len_t key_len)
|
||||
#endif /* SOC_KEY_MANAGER_FE_KEY_DEPLOY_XTS_AES_256 */
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, esp_key_mgr_activate_key(&key_recovery_info));
|
||||
test_xts_aes_key_ecdh0_mode(&test_data_ecdh0);
|
||||
|
||||
/* Reconstruct the deployed XTS key from k1 and the exported k2*G, then
|
||||
* assert the HW flash ciphertext matches what mbedtls_xts produces with
|
||||
* that key.
|
||||
*/
|
||||
uint8_t derived_key[64];
|
||||
size_t key_bits = 256;
|
||||
km_verify_compute_x_be(test_data_ecdh0.k1[0], sizeof(test_data_ecdh0.k1[0]),
|
||||
ecdh0_info.k2_G[0], derived_key);
|
||||
#if SOC_KEY_MANAGER_FE_KEY_DEPLOY_XTS_AES_256
|
||||
if (key_len == ESP_KEY_MGR_XTS_AES_LEN_256) {
|
||||
km_verify_compute_x_be(test_data_ecdh0.k1[1], sizeof(test_data_ecdh0.k1[1]),
|
||||
ecdh0_info.k2_G[1], derived_key + 32);
|
||||
key_bits = 512;
|
||||
}
|
||||
#endif
|
||||
test_xts_aes_key_ecdh0_mode(&test_data_ecdh0, derived_key, key_bits);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, esp_key_mgr_deactivate_key(key_recovery_info.key_type));
|
||||
}
|
||||
#endif /* SOC_KEY_MANAGER_FE_KEY_DEPLOY_XTS_AES_128 || SOC_KEY_MANAGER_FE_KEY_DEPLOY_XTS_AES_256 */
|
||||
@@ -354,6 +395,39 @@ static void key_mgr_test_ecdsa_key_ecdh0_mode(esp_key_mgr_key_len_t key_len)
|
||||
#endif
|
||||
TEST_ASSERT_EQUAL(ESP_OK, esp_key_mgr_activate_key(&key_recovery_info));
|
||||
|
||||
#if SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
|
||||
/* Reconstruct the scalar the KM should have deployed from k1 and the
|
||||
* exported k2*G, then compute scalar*G on the target curve in software
|
||||
* and assert the ECDSA peripheral's exported pubkey matches byte-for-byte.
|
||||
*/
|
||||
uint8_t x_be_stage0[32];
|
||||
km_verify_compute_x_be(test_data_ecdh0.k1[0], sizeof(test_data_ecdh0.k1[0]),
|
||||
ecdh0_info.k2_G[0], x_be_stage0);
|
||||
|
||||
if (key_len == ESP_KEY_MGR_ECDSA_LEN_256) {
|
||||
uint8_t pub_x_le[32], pub_y_le[32];
|
||||
km_verify_ecdsa_pubkey_from_scalar(P256_LEN, x_be_stage0, 32, pub_x_le, pub_y_le);
|
||||
test_ecdsa_export_pubkey(ECDSA_CURVE_SECP256R1, pub_x_le, pub_y_le, 1);
|
||||
} else if (key_len == ESP_KEY_MGR_ECDSA_LEN_192) {
|
||||
uint8_t pub_x_le[24], pub_y_le[24];
|
||||
km_verify_ecdsa_pubkey_from_scalar(P192_LEN, x_be_stage0 + 8, 24, pub_x_le, pub_y_le);
|
||||
test_ecdsa_export_pubkey(ECDSA_CURVE_SECP192R1, pub_x_le, pub_y_le, 1);
|
||||
}
|
||||
#if SOC_ECDSA_SUPPORT_CURVE_P384
|
||||
else if (key_len == ESP_KEY_MGR_ECDSA_LEN_384) {
|
||||
uint8_t x_be_stage1[32];
|
||||
km_verify_compute_x_be(test_data_ecdh0.k1[1], sizeof(test_data_ecdh0.k1[1]),
|
||||
ecdh0_info.k2_G[1], x_be_stage1);
|
||||
uint8_t scalar_be[48];
|
||||
memcpy(scalar_be, x_be_stage0 + 16, 16);
|
||||
memcpy(scalar_be + 16, x_be_stage1, 32);
|
||||
uint8_t pub_x_le[48], pub_y_le[48];
|
||||
km_verify_ecdsa_pubkey_from_scalar(P384_LEN, scalar_be, 48, pub_x_le, pub_y_le);
|
||||
test_ecdsa_export_pubkey(ECDSA_CURVE_SECP384R1, pub_x_le, pub_y_le, 1);
|
||||
}
|
||||
#endif
|
||||
#endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */
|
||||
|
||||
#if SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
|
||||
key_mgr_test_ecdsa_key(key_len, ECDSA_K_TYPE_DETERMINISITIC);
|
||||
#endif
|
||||
@@ -402,11 +476,28 @@ static void key_mgr_test_hmac_key_aes_mode(test_data_aes_mode_t *test_data)
|
||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(test_data->hmac_test_data.hmac_result, hmac, sizeof(test_data->hmac_test_data.hmac_result));
|
||||
}
|
||||
|
||||
static void key_mgr_test_hmac_key_ecdh0_mode(const uint8_t *message, size_t message_len)
|
||||
/* Verify the ECDH0-deployed HMAC output. k2*G is exported via ecdh0_info, so
|
||||
* the test can reconstruct x(k1 * k2*G) using the ECC peripheral, then compute
|
||||
* HMAC(x_le, message) in software and compare against the hardware HMAC. */
|
||||
static void key_mgr_test_hmac_key_ecdh0_mode(const uint8_t *k1_be, size_t k1_len,
|
||||
const uint8_t *k2_G_km,
|
||||
const uint8_t *message, size_t message_len)
|
||||
{
|
||||
uint8_t hmac[32] = {0};
|
||||
TEST_ASSERT_EQUAL(ESP_OK, hmac_calculate(HMAC_KEY_KM, message, message_len, hmac));
|
||||
// We cannot verify the result here as the HMAC key deployed is unknown.
|
||||
uint8_t x_be[32];
|
||||
km_verify_compute_x_be(k1_be, k1_len, k2_G_km, x_be);
|
||||
|
||||
/* HMAC peripheral reads the key slot in LE order, whereas the mbedtls needs it in BE.*/
|
||||
uint8_t x_le[32];
|
||||
for (int i = 0; i < 32; ++i) {
|
||||
x_le[i] = x_be[31 - i];
|
||||
}
|
||||
|
||||
uint8_t expected_mac[32];
|
||||
km_verify_hmac_sha256(x_le, sizeof(x_le), message, message_len, expected_mac);
|
||||
|
||||
uint8_t hw_mac[32] = { 0 };
|
||||
TEST_ASSERT_EQUAL(ESP_OK, hmac_calculate(HMAC_KEY_KM, message, message_len, hw_mac));
|
||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_mac, hw_mac, sizeof(hw_mac));
|
||||
}
|
||||
|
||||
static void key_mgr_test_hmac_key_aes_random_mode(const uint8_t *message, size_t message_len)
|
||||
@@ -447,7 +538,10 @@ static void key_mgr_test_hmac_ecdh0_mode(void)
|
||||
ESP_LOG_BUFFER_HEXDUMP("K2_G", ecdh0_info.k2_G[0], KEY_MGR_ECDH0_INFO_SIZE, ESP_LOG_DEBUG);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, esp_key_mgr_activate_key(&key_recovery_info));
|
||||
key_mgr_test_hmac_key_ecdh0_mode(test_data_hmac.hmac_test_data.message, sizeof(test_data_hmac.hmac_test_data.message));
|
||||
key_mgr_test_hmac_key_ecdh0_mode(test_data_ecdh0.k1[0], sizeof(test_data_ecdh0.k1[0]),
|
||||
ecdh0_info.k2_G[0],
|
||||
test_data_hmac.hmac_test_data.message,
|
||||
sizeof(test_data_hmac.hmac_test_data.message));
|
||||
TEST_ASSERT_EQUAL(ESP_OK, esp_key_mgr_deactivate_key(key_recovery_info.key_type));
|
||||
}
|
||||
|
||||
@@ -514,7 +608,7 @@ TEST_SETUP(key_manager)
|
||||
TEST_IGNORE_MESSAGE("Key Manager not supported on this chip");
|
||||
}
|
||||
test_utils_record_free_mem();
|
||||
TEST_ESP_OK(test_utils_set_leak_level(800, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL));
|
||||
TEST_ESP_OK(test_utils_set_leak_level(900, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL));
|
||||
}
|
||||
|
||||
TEST_TEAR_DOWN(key_manager)
|
||||
|
||||
@@ -126,6 +126,12 @@ static void esp_key_mgr_acquire_hardware(bool deployment_mode)
|
||||
esp_crypto_ecc_lock_acquire();
|
||||
esp_crypto_sha_aes_lock_acquire();
|
||||
esp_crypto_key_manager_lock_acquire();
|
||||
// The KM peripheral uses the external ECC block for the ECDH0/ECDH1
|
||||
// scalar multiplications; its bus clock must be on, otherwise the KM
|
||||
// deploys an incorrect key.
|
||||
#if SOC_ECC_SUPPORTED
|
||||
esp_crypto_ecc_enable_periph_clk(true);
|
||||
#endif
|
||||
}
|
||||
// Reset the Key Manager Clock
|
||||
esp_crypto_key_mgr_enable_periph_clk(true);
|
||||
@@ -134,6 +140,9 @@ static void esp_key_mgr_acquire_hardware(bool deployment_mode)
|
||||
static void esp_key_mgr_release_hardware(bool deployment_mode)
|
||||
{
|
||||
if (deployment_mode) {
|
||||
#if SOC_ECC_SUPPORTED
|
||||
esp_crypto_ecc_enable_periph_clk(false);
|
||||
#endif
|
||||
esp_crypto_key_manager_lock_release();
|
||||
esp_crypto_sha_aes_lock_release();
|
||||
esp_crypto_ecc_lock_release();
|
||||
|
||||
Reference in New Issue
Block a user