mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
feat(mbedtls): Add PSA Crypto driver for external secure elements
Add generic secure element PSA driver with runtime callback registration.
Consolidate Kconfig into single MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED option.
Closes https://github.com/espressif/esp-idf/issues/18388
(cherry picked from commit 1c20f525b4)
This commit is contained in:
@@ -477,6 +477,14 @@ if(CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u mbedtls_rom_osi_functions_init")
|
||||
endif()
|
||||
|
||||
if(CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED)
|
||||
target_sources(tfpsacrypto PRIVATE
|
||||
"${COMPONENT_DIR}/port/psa_driver/secure_element/psa_crypto_driver_secure_element.c")
|
||||
target_include_directories(tfpsacrypto PUBLIC "${COMPONENT_DIR}/port/psa_driver/include")
|
||||
target_compile_definitions(tfpsacrypto PRIVATE
|
||||
SECURE_ELEMENT_DRIVER_ENABLED)
|
||||
endif()
|
||||
|
||||
if(CONFIG_COMPILER_STATIC_ANALYZER AND CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-fno-analyzer")
|
||||
target_compile_options(tfpsacrypto PRIVATE "-fno-analyzer")
|
||||
@@ -544,11 +552,6 @@ if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM)
|
||||
target_link_libraries(tfpsacrypto PRIVATE idf::esp_timer)
|
||||
endif()
|
||||
|
||||
# # Link esp-cryptoauthlib to mbedtls
|
||||
# if(CONFIG_ATCA_MBEDTLS_ECDSA)
|
||||
# mbedcrypto_optional_deps(espressif__esp-cryptoauthlib esp-cryptoauthlib)
|
||||
# endif()
|
||||
|
||||
# Apply -fno-analyzer to ALL mbedTLS targets at the very end when all targets are created
|
||||
if(CONFIG_COMPILER_STATIC_ANALYZER AND CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
||||
message(STATUS "Applying -fno-analyzer to all mbedTLS targets...")
|
||||
|
||||
@@ -1000,49 +1000,49 @@ menu "mbedTLS"
|
||||
config MBEDTLS_ECP_DP_SECP384R1_ENABLED
|
||||
bool "Enable SECP384R1 curve"
|
||||
depends on MBEDTLS_ECP_C
|
||||
default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY)
|
||||
default y
|
||||
help
|
||||
Enable support for SECP384R1 Elliptic Curve.
|
||||
|
||||
config MBEDTLS_ECP_DP_SECP521R1_ENABLED
|
||||
bool "Enable SECP521R1 curve"
|
||||
depends on MBEDTLS_ECP_C
|
||||
default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY)
|
||||
default y
|
||||
help
|
||||
Enable support for SECP521R1 Elliptic Curve.
|
||||
|
||||
config MBEDTLS_ECP_DP_SECP256K1_ENABLED
|
||||
bool "Enable SECP256K1 curve"
|
||||
depends on MBEDTLS_ECP_C
|
||||
default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY)
|
||||
default y
|
||||
help
|
||||
Enable support for SECP256K1 Elliptic Curve.
|
||||
|
||||
config MBEDTLS_ECP_DP_BP256R1_ENABLED
|
||||
bool "Enable BP256R1 curve"
|
||||
depends on MBEDTLS_ECP_C
|
||||
default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY)
|
||||
default y
|
||||
help
|
||||
support for DP Elliptic Curve.
|
||||
|
||||
config MBEDTLS_ECP_DP_BP384R1_ENABLED
|
||||
bool "Enable BP384R1 curve"
|
||||
depends on MBEDTLS_ECP_C
|
||||
default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY)
|
||||
default y
|
||||
help
|
||||
support for DP Elliptic Curve.
|
||||
|
||||
config MBEDTLS_ECP_DP_BP512R1_ENABLED
|
||||
bool "Enable BP512R1 curve"
|
||||
depends on MBEDTLS_ECP_C
|
||||
default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY)
|
||||
default y
|
||||
help
|
||||
support for DP Elliptic Curve.
|
||||
|
||||
config MBEDTLS_ECP_DP_CURVE25519_ENABLED
|
||||
bool "Enable CURVE25519 curve"
|
||||
depends on MBEDTLS_ECP_C
|
||||
default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY)
|
||||
default y
|
||||
help
|
||||
Enable support for CURVE25519 Elliptic Curve.
|
||||
endmenu
|
||||
@@ -1510,19 +1510,14 @@ menu "mbedTLS"
|
||||
it also increases the binary size by ~1.2 KB as it pulls in the peripheral's block
|
||||
mode code as well.
|
||||
|
||||
config MBEDTLS_ATCA_HW_ECDSA_SIGN
|
||||
bool "Enable hardware ECDSA sign acceleration when using ATECC608A"
|
||||
config MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED
|
||||
bool "Enable secure element hardware support (e.g., ATECC608A)"
|
||||
default n
|
||||
help
|
||||
This option enables hardware acceleration for ECDSA sign function, only
|
||||
when using ATECC608A cryptoauth chip.
|
||||
|
||||
config MBEDTLS_ATCA_HW_ECDSA_VERIFY
|
||||
bool "Enable hardware ECDSA verify acceleration when using ATECC608A"
|
||||
default n
|
||||
help
|
||||
This option enables hardware acceleration for ECDSA sign function, only
|
||||
when using ATECC608A cryptoauth chip.
|
||||
Enable PSA Crypto driver support for external secure elements.
|
||||
This enables sign, verify, and key export operations via runtime-registered
|
||||
callbacks from the secure element component (e.g., esp-cryptoauthlib).
|
||||
The private key never leaves the secure element.
|
||||
|
||||
config MBEDTLS_HARDWARE_RSA_DS_PERIPHERAL
|
||||
bool "Enable hardware RSA digital signature peripheral acceleration"
|
||||
|
||||
@@ -153,8 +153,7 @@ CONFIG_MBEDTLS_HARDWARE_ECC=y
|
||||
CONFIG_MBEDTLS_ECC_OTHER_CURVES_SOFT_FALLBACK=y
|
||||
CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN=n
|
||||
CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY=y
|
||||
CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN=n
|
||||
CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY=n
|
||||
CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED=n
|
||||
|
||||
CONFIG_MBEDTLS_PKCS7_C=y
|
||||
CONFIG_MBEDTLS_PKCS1_V15=y
|
||||
|
||||
@@ -267,13 +267,8 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN
|
||||
#define MBEDTLS_ECDSA_SIGN_ALT
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY
|
||||
#define MBEDTLS_ECDSA_VERIFY_ALT
|
||||
#endif
|
||||
/* SECURE_ELEMENT_DRIVER_ENABLED is set via target_compile_definitions in
|
||||
* CMakeLists.txt when CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED is set. */
|
||||
|
||||
#ifdef CONFIG_MBEDTLS_HARDWARE_ECC
|
||||
#ifdef CONFIG_MBEDTLS_ECC_OTHER_CURVES_SOFT_FALLBACK
|
||||
|
||||
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "psa/crypto.h"
|
||||
#include "psa/crypto_types.h"
|
||||
|
||||
#include "psa_crypto_driver_secure_element_contexts.h"
|
||||
|
||||
#if defined(SECURE_ELEMENT_DRIVER_ENABLED) || defined(CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED)
|
||||
#ifndef PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT
|
||||
#define PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Secure element PSA driver location
|
||||
*
|
||||
* Vendor-specific location for secure element keys.
|
||||
* Bits 8-31 are location, using vendor flag (0x800000) + SE vendor ID.
|
||||
*/
|
||||
#define PSA_KEY_LOCATION_SECURE_ELEMENT ((psa_key_location_t) 0x800004)
|
||||
|
||||
/**
|
||||
* @brief Construct a lifetime for secure element keys with default persistence
|
||||
*/
|
||||
#define PSA_KEY_LIFETIME_SECURE_ELEMENT \
|
||||
PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( \
|
||||
PSA_KEY_PERSISTENCE_DEFAULT, \
|
||||
PSA_KEY_LOCATION_SECURE_ELEMENT)
|
||||
|
||||
/**
|
||||
* @brief Construct a volatile lifetime for secure element keys
|
||||
*/
|
||||
#define PSA_KEY_LIFETIME_SECURE_ELEMENT_VOLATILE \
|
||||
PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( \
|
||||
PSA_KEY_PERSISTENCE_VOLATILE, \
|
||||
PSA_KEY_LOCATION_SECURE_ELEMENT)
|
||||
|
||||
/*
|
||||
* Callback typedefs for secure element operations.
|
||||
*
|
||||
* These allow the SE-specific backend (e.g. esp-cryptoauthlib for ATECC608A)
|
||||
* to register its implementation at runtime without any build-time dependency.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Callback to sign a hash using the secure element
|
||||
*
|
||||
* @param slot_id Slot containing the private key
|
||||
* @param hash Hash to sign
|
||||
* @param hash_len Length of hash (e.g. 32 for SHA-256)
|
||||
* @param sig Output buffer for raw signature (R || S)
|
||||
* @param sig_size Size of sig buffer
|
||||
* @param sig_len Actual signature length written
|
||||
* @return psa_status_t
|
||||
*/
|
||||
typedef psa_status_t (*secure_element_sign_cb_t)(uint8_t slot_id, const uint8_t *hash, size_t hash_len,
|
||||
uint8_t *sig, size_t sig_size, size_t *sig_len);
|
||||
|
||||
/**
|
||||
* @brief Callback to export the public key from a secure element slot
|
||||
*
|
||||
* @param slot_id Slot containing the key pair
|
||||
* @param pubkey Output buffer for raw public key (X || Y)
|
||||
* @param pubkey_size Size of pubkey buffer
|
||||
* @param pubkey_len Actual public key length written
|
||||
* @return psa_status_t
|
||||
*/
|
||||
typedef psa_status_t (*secure_element_export_pubkey_cb_t)(uint8_t slot_id, uint8_t *pubkey,
|
||||
size_t pubkey_size, size_t *pubkey_len);
|
||||
|
||||
/**
|
||||
* @brief Callback to verify a hash signature using the secure element
|
||||
*
|
||||
* @param hash Hash that was signed
|
||||
* @param hash_len Length of hash
|
||||
* @param sig Raw signature (R || S)
|
||||
* @param sig_len Length of signature
|
||||
* @param pubkey Raw public key (X || Y)
|
||||
* @param pubkey_len Length of public key
|
||||
* @param is_verified Output: true if signature is valid
|
||||
* @return psa_status_t
|
||||
*/
|
||||
typedef psa_status_t (*secure_element_verify_cb_t)(const uint8_t *hash, size_t hash_len,
|
||||
const uint8_t *sig, size_t sig_len, const uint8_t *pubkey, size_t pubkey_len, bool *is_verified);
|
||||
|
||||
/**
|
||||
* @brief Secure element callback table
|
||||
*
|
||||
* The algorithm, key_type, and key_bits fields declare what the SE supports.
|
||||
* The driver validates incoming requests against these and returns
|
||||
* PSA_ERROR_NOT_SUPPORTED for anything that doesn't match, allowing the
|
||||
* PSA framework to fall back to software.
|
||||
*/
|
||||
typedef struct {
|
||||
secure_element_sign_cb_t sign; /**< Sign hash callback (NULL if not supported) */
|
||||
secure_element_export_pubkey_cb_t export_pubkey; /**< Export public key callback (NULL if not supported) */
|
||||
secure_element_verify_cb_t verify; /**< Verify hash callback (NULL if not supported) */
|
||||
psa_algorithm_t algorithm; /**< Supported algorithm, e.g. PSA_ALG_ECDSA(PSA_ALG_SHA_256) */
|
||||
psa_key_type_t key_type; /**< Supported key type, e.g. PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1) */
|
||||
size_t key_bits; /**< Supported key size in bits, e.g. 256 */
|
||||
} secure_element_callbacks_t;
|
||||
|
||||
/**
|
||||
* @brief Register secure element callbacks
|
||||
*
|
||||
* Must be called once during application initialization, before any PSA
|
||||
* operations targeting PSA_KEY_LOCATION_SECURE_ELEMENT. Uses atomic
|
||||
* compare-and-swap so only the first call succeeds.
|
||||
*
|
||||
* @param callbacks Pointer to callback table (must remain valid for program lifetime)
|
||||
* @return PSA_SUCCESS on success
|
||||
* @return PSA_ERROR_BAD_STATE if callbacks were already registered
|
||||
* @return PSA_ERROR_INVALID_ARGUMENT if callbacks is NULL
|
||||
*/
|
||||
psa_status_t secure_element_register_callbacks(const secure_element_callbacks_t *callbacks);
|
||||
|
||||
/**
|
||||
* @brief Sign a hash using secure element opaque driver
|
||||
*/
|
||||
psa_status_t secure_element_opaque_sign_hash(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t *hash,
|
||||
size_t hash_length,
|
||||
uint8_t *signature,
|
||||
size_t signature_size,
|
||||
size_t *signature_length);
|
||||
|
||||
/**
|
||||
* @brief Import a secure element key reference (not actual key material)
|
||||
*/
|
||||
psa_status_t secure_element_opaque_import_key(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *data,
|
||||
size_t data_length,
|
||||
uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
size_t *key_buffer_length,
|
||||
size_t *bits);
|
||||
|
||||
/**
|
||||
* @brief Export the public key from a secure element opaque key
|
||||
*/
|
||||
psa_status_t secure_element_opaque_export_public_key(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
uint8_t *data,
|
||||
size_t data_size,
|
||||
size_t *data_length);
|
||||
|
||||
/**
|
||||
* @brief Get the key buffer size for a secure element opaque key
|
||||
*/
|
||||
size_t secure_element_opaque_size_function(
|
||||
psa_key_type_t key_type,
|
||||
size_t key_bits);
|
||||
|
||||
/**
|
||||
* @brief Verify a hash using secure element transparent driver
|
||||
*/
|
||||
psa_status_t secure_element_transparent_verify_hash(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t *hash,
|
||||
size_t hash_length,
|
||||
const uint8_t *signature,
|
||||
size_t signature_length);
|
||||
|
||||
/**
|
||||
* @brief Start a hash verification operation
|
||||
*/
|
||||
psa_status_t secure_element_transparent_verify_hash_start(
|
||||
secure_element_transparent_verify_hash_operation_t *operation,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t *hash,
|
||||
size_t hash_length,
|
||||
const uint8_t *signature,
|
||||
size_t signature_length);
|
||||
|
||||
/**
|
||||
* @brief Complete a hash verification operation
|
||||
*/
|
||||
psa_status_t secure_element_transparent_verify_hash_complete(
|
||||
secure_element_transparent_verify_hash_operation_t *operation);
|
||||
|
||||
/**
|
||||
* @brief Abort a hash verification operation
|
||||
*/
|
||||
psa_status_t secure_element_transparent_verify_hash_abort(
|
||||
secure_element_transparent_verify_hash_operation_t *operation);
|
||||
|
||||
/**
|
||||
* @brief Start a hash signing operation using opaque driver
|
||||
*/
|
||||
psa_status_t secure_element_opaque_sign_hash_start(
|
||||
secure_element_opaque_sign_hash_operation_t *operation,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t *hash,
|
||||
size_t hash_length);
|
||||
|
||||
/**
|
||||
* @brief Complete a hash signing operation using opaque driver
|
||||
*/
|
||||
psa_status_t secure_element_opaque_sign_hash_complete(
|
||||
secure_element_opaque_sign_hash_operation_t *operation,
|
||||
uint8_t *signature, size_t signature_size,
|
||||
size_t *signature_length);
|
||||
|
||||
/**
|
||||
* @brief Abort a hash signing operation using opaque driver
|
||||
*/
|
||||
psa_status_t secure_element_opaque_sign_hash_abort(
|
||||
secure_element_opaque_sign_hash_operation_t *operation);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SECURE_ELEMENT_DRIVER_ENABLED || CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED */
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Maximum key component length in bytes.
|
||||
* Supports up to P-384 (48 bytes). Increase to 66 for P-521 if needed.
|
||||
*/
|
||||
#define SECURE_ELEMENT_MAX_KEY_BYTES 48
|
||||
|
||||
/**
|
||||
* @brief Opaque key structure for secure element import
|
||||
*
|
||||
* This struct is passed as the "key material" to psa_import_key().
|
||||
* It identifies which SE slot the key refers to.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t slot_id; /**< Slot index on the secure element */
|
||||
} secure_element_opaque_key_t;
|
||||
|
||||
/**
|
||||
* @brief Operation context for transparent verify_hash
|
||||
*
|
||||
* Used by the interruptible verify API to store intermediate state
|
||||
* between start / complete / abort calls.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t sha[SECURE_ELEMENT_MAX_KEY_BYTES];
|
||||
uint8_t r[SECURE_ELEMENT_MAX_KEY_BYTES];
|
||||
uint8_t s[SECURE_ELEMENT_MAX_KEY_BYTES];
|
||||
uint8_t qx[SECURE_ELEMENT_MAX_KEY_BYTES];
|
||||
uint8_t qy[SECURE_ELEMENT_MAX_KEY_BYTES];
|
||||
size_t key_len;
|
||||
size_t sha_len;
|
||||
} secure_element_transparent_verify_hash_operation_t;
|
||||
|
||||
/**
|
||||
* @brief Operation context for opaque sign_hash
|
||||
*
|
||||
* Used by the interruptible sign API to store intermediate state
|
||||
* between start / complete / abort calls.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t sha[SECURE_ELEMENT_MAX_KEY_BYTES];
|
||||
size_t key_len;
|
||||
size_t sha_len;
|
||||
secure_element_opaque_key_t *opaque_key;
|
||||
unsigned int alg;
|
||||
} secure_element_opaque_sign_hash_operation_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,487 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Generic Secure Element PSA Crypto Driver
|
||||
*
|
||||
* This driver provides PSA Crypto API integration for external secure elements
|
||||
* (e.g., ATECC608A). The SE-specific operations are dispatched through
|
||||
* runtime-registered callbacks, removing any build-time dependency on a
|
||||
* particular SE library.
|
||||
*
|
||||
* The callbacks struct declares which algorithm/key_type/key_bits the SE
|
||||
* supports. The driver validates each request against these and returns
|
||||
* PSA_ERROR_NOT_SUPPORTED for mismatches, letting PSA fall back to software.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdatomic.h>
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef SECURE_ELEMENT_DRIVER_ENABLED
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "psa_crypto_driver_secure_element.h"
|
||||
|
||||
static const char *TAG = "psa_crypto_driver_secure_element";
|
||||
|
||||
#define UNCOMPRESSED_POINT_FORMAT 0x04
|
||||
|
||||
/* Runtime-registered SE callbacks (set once via secure_element_register_callbacks) */
|
||||
static const secure_element_callbacks_t *s_se_callbacks = NULL;
|
||||
|
||||
psa_status_t secure_element_register_callbacks(const secure_element_callbacks_t *callbacks)
|
||||
{
|
||||
if (callbacks == NULL) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (callbacks->key_bits == 0) {
|
||||
ESP_LOGE(TAG, "key_bits must be set in callbacks");
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
/* Atomic compare-and-swap: only the first registration succeeds */
|
||||
const secure_element_callbacks_t *expected = NULL;
|
||||
if (!atomic_compare_exchange_strong((volatile _Atomic(const secure_element_callbacks_t *) *)&s_se_callbacks,
|
||||
&expected, callbacks)) {
|
||||
ESP_LOGE(TAG, "Secure element callbacks already registered");
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the registered callbacks, or NULL if not yet registered
|
||||
*/
|
||||
static inline const secure_element_callbacks_t *se_get_callbacks(void)
|
||||
{
|
||||
return s_se_callbacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if a request matches the registered SE capabilities
|
||||
*
|
||||
* Compares the algorithm and key type from the request against what the SE
|
||||
* declared at registration time. Returns PSA_ERROR_NOT_SUPPORTED on mismatch.
|
||||
*/
|
||||
static psa_status_t validate_request(psa_algorithm_t alg, const psa_key_attributes_t *attributes)
|
||||
{
|
||||
const secure_element_callbacks_t *cbs = se_get_callbacks();
|
||||
if (!cbs) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/* Check algorithm family matches (e.g., both are ECDSA) */
|
||||
psa_algorithm_t registered_alg = cbs->algorithm;
|
||||
|
||||
/* Use PSA_ALG_SIGN_GET_HASH to compare base algorithm ignoring hash */
|
||||
if (PSA_ALG_IS_ECDSA(registered_alg)) {
|
||||
if (!PSA_ALG_IS_ECDSA(alg)) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
/* If registered with a specific hash, check it matches */
|
||||
psa_algorithm_t reg_hash = PSA_ALG_SIGN_GET_HASH(registered_alg);
|
||||
if (reg_hash != PSA_ALG_ANY_HASH && reg_hash != PSA_ALG_SIGN_GET_HASH(alg)) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
} else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(registered_alg)) {
|
||||
if (!PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
} else if (registered_alg != alg) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/* Check key type matches */
|
||||
if (attributes) {
|
||||
psa_key_type_t req_type = psa_get_key_type(attributes);
|
||||
/* Accept both key pair and public key for the same family */
|
||||
psa_key_type_t reg_base = PSA_KEY_TYPE_IS_KEY_PAIR(cbs->key_type)
|
||||
? PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(cbs->key_type))
|
||||
: cbs->key_type;
|
||||
psa_key_type_t req_base = PSA_KEY_TYPE_IS_KEY_PAIR(req_type)
|
||||
? PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(req_type))
|
||||
: req_type;
|
||||
if (reg_base != req_base) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/* Check key size matches */
|
||||
size_t req_bits = psa_get_key_bits(attributes);
|
||||
if (req_bits != 0 && req_bits != cbs->key_bits) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
/* Transparent verify operations */
|
||||
psa_status_t secure_element_transparent_verify_hash_start(
|
||||
secure_element_transparent_verify_hash_operation_t *operation,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t *hash,
|
||||
size_t hash_length,
|
||||
const uint8_t *signature,
|
||||
size_t signature_length)
|
||||
{
|
||||
if (!operation || !attributes || !key_buffer || !hash || !signature) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
/* Validate against registered SE capabilities */
|
||||
psa_status_t status = validate_request(alg, attributes);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
size_t key_len = PSA_BITS_TO_BYTES(psa_get_key_bits(attributes));
|
||||
if (key_len == 0 || key_len > SECURE_ELEMENT_MAX_KEY_BYTES) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
/* Verify key buffer can hold the uncompressed public key (0x04 || X || Y) */
|
||||
if (key_buffer_size < 1 + 2 * key_len) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
/* Validate hash length matches key component length */
|
||||
if (hash_length != key_len) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (signature_length != 2 * key_len) {
|
||||
return PSA_ERROR_INVALID_SIGNATURE;
|
||||
}
|
||||
|
||||
/* Handle public key format - must be uncompressed (0x04 || X || Y) */
|
||||
if (key_buffer[0] != UNCOMPRESSED_POINT_FORMAT) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (key_buffer_size != 2 * key_len + 1) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
memset(operation, 0, sizeof(secure_element_transparent_verify_hash_operation_t));
|
||||
operation->key_len = key_len;
|
||||
operation->sha_len = hash_length;
|
||||
|
||||
/* Big-endian format, matching PSA format */
|
||||
memcpy(operation->sha, hash, key_len);
|
||||
memcpy(operation->r, signature, key_len);
|
||||
memcpy(operation->s, signature + key_len, key_len);
|
||||
|
||||
/* Extract public key coordinates (skip 0x04 format byte) */
|
||||
memcpy(operation->qx, key_buffer + 1, key_len);
|
||||
memcpy(operation->qy, key_buffer + 1 + key_len, key_len);
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_status_t secure_element_transparent_verify_hash_complete(secure_element_transparent_verify_hash_operation_t *operation)
|
||||
{
|
||||
if (!operation) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
const secure_element_callbacks_t *cbs = se_get_callbacks();
|
||||
if (!cbs || !cbs->verify) {
|
||||
ESP_LOGE(TAG, "Secure element verify callback not registered");
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
size_t key_len = operation->key_len;
|
||||
|
||||
/* Construct public key (X || Y) */
|
||||
uint8_t pubkey[2 * SECURE_ELEMENT_MAX_KEY_BYTES];
|
||||
memcpy(pubkey, operation->qx, key_len);
|
||||
memcpy(pubkey + key_len, operation->qy, key_len);
|
||||
|
||||
/* Construct signature (R || S) */
|
||||
uint8_t sig[2 * SECURE_ELEMENT_MAX_KEY_BYTES];
|
||||
memcpy(sig, operation->r, key_len);
|
||||
memcpy(sig + key_len, operation->s, key_len);
|
||||
|
||||
/* Verify using registered SE callback */
|
||||
bool is_verified = false;
|
||||
psa_status_t status = cbs->verify(operation->sha, operation->sha_len,
|
||||
sig, 2 * key_len,
|
||||
pubkey, 2 * key_len,
|
||||
&is_verified);
|
||||
|
||||
if (status != PSA_SUCCESS) {
|
||||
ESP_LOGE(TAG, "SE verify callback failed: 0x%04x", (unsigned)status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (!is_verified) {
|
||||
return PSA_ERROR_INVALID_SIGNATURE;
|
||||
}
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_status_t secure_element_transparent_verify_hash_abort(secure_element_transparent_verify_hash_operation_t *operation)
|
||||
{
|
||||
if (operation) {
|
||||
memset(operation, 0, sizeof(secure_element_transparent_verify_hash_operation_t));
|
||||
}
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_status_t secure_element_transparent_verify_hash(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t *hash,
|
||||
size_t hash_length,
|
||||
const uint8_t *signature,
|
||||
size_t signature_length)
|
||||
{
|
||||
secure_element_transparent_verify_hash_operation_t operation;
|
||||
|
||||
psa_status_t status = secure_element_transparent_verify_hash_start(
|
||||
&operation, attributes, key_buffer, key_buffer_size,
|
||||
alg, hash, hash_length, signature, signature_length);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = secure_element_transparent_verify_hash_complete(&operation);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
return secure_element_transparent_verify_hash_abort(&operation);
|
||||
}
|
||||
|
||||
/* Opaque sign operations */
|
||||
psa_status_t secure_element_opaque_import_key(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *data,
|
||||
size_t data_length,
|
||||
uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
size_t *key_buffer_length,
|
||||
size_t *bits)
|
||||
{
|
||||
if (!attributes || !data || data_length < 1 || !key_buffer || !key_buffer_length || !bits) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (key_buffer_size < sizeof(secure_element_opaque_key_t) || data_length < sizeof(secure_element_opaque_key_t)) {
|
||||
return PSA_ERROR_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
/* Validate the key attributes match what the SE supports */
|
||||
const secure_element_callbacks_t *cbs = se_get_callbacks();
|
||||
if (!cbs) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
psa_status_t status = validate_request(psa_get_key_algorithm(attributes), attributes);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
memcpy(key_buffer, data, sizeof(secure_element_opaque_key_t));
|
||||
*key_buffer_length = sizeof(secure_element_opaque_key_t);
|
||||
*bits = psa_get_key_bits(attributes);
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_status_t secure_element_opaque_sign_hash_start(
|
||||
secure_element_opaque_sign_hash_operation_t *operation,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t *hash,
|
||||
size_t hash_length)
|
||||
{
|
||||
if (!operation || !attributes || !key_buffer || !hash) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (key_buffer_size < sizeof(secure_element_opaque_key_t)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
/* Validate against registered SE capabilities */
|
||||
psa_status_t status = validate_request(alg, attributes);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
size_t component_len = PSA_BITS_TO_BYTES(psa_get_key_bits(attributes));
|
||||
if (component_len == 0 || component_len > SECURE_ELEMENT_MAX_KEY_BYTES) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
/* Validate hash length matches key component length */
|
||||
if (hash_length != component_len) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
memset(operation, 0, sizeof(secure_element_opaque_sign_hash_operation_t));
|
||||
operation->key_len = component_len;
|
||||
memcpy(operation->sha, hash, component_len);
|
||||
operation->opaque_key = (secure_element_opaque_key_t *) key_buffer;
|
||||
operation->alg = alg;
|
||||
operation->sha_len = hash_length;
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_status_t secure_element_opaque_sign_hash_complete(
|
||||
secure_element_opaque_sign_hash_operation_t *operation,
|
||||
uint8_t *signature, size_t signature_size,
|
||||
size_t *signature_length)
|
||||
{
|
||||
if (!operation || !signature || !signature_length) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
size_t component_len = operation->key_len;
|
||||
|
||||
if (signature_size < 2 * component_len) {
|
||||
return PSA_ERROR_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
const secure_element_callbacks_t *cbs = se_get_callbacks();
|
||||
if (!cbs || !cbs->sign) {
|
||||
ESP_LOGE(TAG, "Secure element sign callback not registered");
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/* Sign using registered SE callback */
|
||||
uint8_t sig[2 * SECURE_ELEMENT_MAX_KEY_BYTES];
|
||||
size_t sig_len = 0;
|
||||
psa_status_t status = cbs->sign(operation->opaque_key->slot_id,
|
||||
operation->sha, operation->sha_len,
|
||||
sig, sizeof(sig), &sig_len);
|
||||
|
||||
if (status != PSA_SUCCESS) {
|
||||
ESP_LOGE(TAG, "SE sign callback failed: 0x%04x", (unsigned)status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Copy signature to output (R || S format, big-endian - matches PSA) */
|
||||
memcpy(signature, sig, 2 * component_len);
|
||||
*signature_length = 2 * component_len;
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_status_t secure_element_opaque_sign_hash_abort(secure_element_opaque_sign_hash_operation_t *operation)
|
||||
{
|
||||
if (operation) {
|
||||
memset(operation, 0, sizeof(secure_element_opaque_sign_hash_operation_t));
|
||||
}
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_status_t secure_element_opaque_sign_hash(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t *hash,
|
||||
size_t hash_length,
|
||||
uint8_t *signature,
|
||||
size_t signature_size,
|
||||
size_t *signature_length)
|
||||
{
|
||||
secure_element_opaque_sign_hash_operation_t operation;
|
||||
|
||||
psa_status_t status = secure_element_opaque_sign_hash_start(
|
||||
&operation, attributes, key_buffer, key_buffer_size, alg, hash, hash_length);
|
||||
if (status != PSA_SUCCESS) {
|
||||
secure_element_opaque_sign_hash_abort(&operation);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = secure_element_opaque_sign_hash_complete(&operation, signature, signature_size, signature_length);
|
||||
if (status != PSA_SUCCESS) {
|
||||
secure_element_opaque_sign_hash_abort(&operation);
|
||||
return status;
|
||||
}
|
||||
|
||||
return secure_element_opaque_sign_hash_abort(&operation);
|
||||
}
|
||||
|
||||
psa_status_t secure_element_opaque_export_public_key(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
uint8_t *data,
|
||||
size_t data_size,
|
||||
size_t *data_length)
|
||||
{
|
||||
if (!attributes || !key_buffer || !data || !data_length) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (key_buffer_size < sizeof(secure_element_opaque_key_t)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
const secure_element_opaque_key_t *opaque_key = (const secure_element_opaque_key_t *) key_buffer;
|
||||
|
||||
const secure_element_callbacks_t *cbs = se_get_callbacks();
|
||||
if (!cbs || !cbs->export_pubkey) {
|
||||
ESP_LOGE(TAG, "Secure element export_pubkey callback not registered");
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/* Get key length from registered capabilities */
|
||||
size_t key_len = PSA_BITS_TO_BYTES(cbs->key_bits);
|
||||
|
||||
/* Need 1 byte for format + key_len bytes for x + key_len bytes for y */
|
||||
size_t required_size = 1 + (2 * key_len);
|
||||
if (data_size < required_size) {
|
||||
return PSA_ERROR_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
/* Export public key using registered SE callback */
|
||||
uint8_t pubkey[2 * SECURE_ELEMENT_MAX_KEY_BYTES];
|
||||
size_t pubkey_len = 0;
|
||||
psa_status_t status = cbs->export_pubkey(opaque_key->slot_id, pubkey, sizeof(pubkey), &pubkey_len);
|
||||
|
||||
if (status != PSA_SUCCESS) {
|
||||
ESP_LOGE(TAG, "SE export_pubkey callback failed: 0x%04x", (unsigned)status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Format: uncompressed point (0x04 followed by x and y coordinates) */
|
||||
data[0] = UNCOMPRESSED_POINT_FORMAT;
|
||||
memcpy(data + 1, pubkey, key_len); /* X coordinate */
|
||||
memcpy(data + 1 + key_len, pubkey + key_len, key_len); /* Y coordinate */
|
||||
|
||||
*data_length = required_size;
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
size_t secure_element_opaque_size_function(
|
||||
psa_key_type_t key_type,
|
||||
size_t key_bits)
|
||||
{
|
||||
(void)key_type;
|
||||
(void)key_bits;
|
||||
|
||||
/* Opaque keys always use the same size structure */
|
||||
return sizeof(secure_element_opaque_key_t);
|
||||
}
|
||||
|
||||
#endif /* SECURE_ELEMENT_DRIVER_ENABLED */
|
||||
5
components/mbedtls/sdkconfig.rename
Normal file
5
components/mbedtls/sdkconfig.rename
Normal file
@@ -0,0 +1,5 @@
|
||||
# Renamed ATCA/SE ECDSA options to generic secure element (v6.0)
|
||||
CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED
|
||||
CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED
|
||||
CONFIG_MBEDTLS_SE_HW_ECDSA_SIGN CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED
|
||||
CONFIG_MBEDTLS_SE_HW_ECDSA_VERIFY CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED
|
||||
@@ -207,23 +207,23 @@ To use a custom TLS stack in your project, follow these steps:
|
||||
ATECC608A (Secure Element) with ESP-TLS
|
||||
--------------------------------------------------
|
||||
|
||||
ESP-TLS provides support for using ATECC608A cryptoauth chip with ESP32 series of SoCs. The use of ATECC608A is supported only when ESP-TLS is used with MbedTLS as its underlying SSL/TLS stack. ESP-TLS uses MbedTLS as its underlying TLS/SSL stack by default unless changed manually.
|
||||
ESP-TLS provides support for using ATECC608A cryptoauth chip with ESP32 series of SoCs via the PSA Crypto opaque driver interface. The use of ATECC608A is supported only when ESP-TLS is used with MbedTLS as its underlying SSL/TLS stack. ESP-TLS uses MbedTLS as its underlying TLS/SSL stack by default unless changed manually.
|
||||
|
||||
.. note::
|
||||
|
||||
ATECC608A chip interfaced to ESP32 series must be already configured. For details, please refer to `esp_cryptoauth_utility <https://github.com/espressif/esp-cryptoauthlib/blob/master/esp_cryptoauth_utility/README.md#esp_cryptoauth_utility>`_.
|
||||
|
||||
To enable the secure element support, and use it in your project for TLS connection, you have to follow the below steps:
|
||||
To enable the secure element support, and use it in your project for TLS connection, follow the steps below:
|
||||
|
||||
1) Add `esp-cryptoauthlib <https://github.com/espressif/esp-cryptoauthlib>`_ in your project, for details please refer `how to use esp-cryptoauthlib with ESP-IDF <https://github.com/espressif/esp-cryptoauthlib#how-to-use-esp-cryptoauthlib-with-esp-idf>`_.
|
||||
1) Add `esp-cryptoauthlib <https://github.com/espressif/esp-cryptoauthlib>`_ as a dependency in your project. For details, please refer to `how to use esp-cryptoauthlib with ESP-IDF <https://github.com/espressif/esp-cryptoauthlib#how-to-use-esp-cryptoauthlib-with-esp-idf>`_.
|
||||
|
||||
2) Enable the menuconfig option :ref:`CONFIG_ESP_TLS_USE_SECURE_ELEMENT`:
|
||||
2) Enable the menuconfig option :ref:`CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED`:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
menuconfig > Component config > ESP-TLS > Use Secure Element (ATECC608A) with ESP-TLS
|
||||
menuconfig > Component config > mbedTLS > Enable secure element hardware support
|
||||
|
||||
3) Select type of ATECC608A chip with following option:
|
||||
3) Select the type of ATECC608A chip:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
@@ -231,13 +231,40 @@ To enable the secure element support, and use it in your project for TLS connect
|
||||
|
||||
To know more about different types of ATECC608A chips and how to obtain the type of ATECC608A connected to your ESP module, please visit `ATECC608A chip type <https://github.com/espressif/esp-cryptoauthlib/blob/master/esp_cryptoauth_utility/README.md#find-type-of-atecc608a-chip-connected-to-esp32-wroom32-se>`_.
|
||||
|
||||
4) Enable the use of ATECC608A in ESP-TLS by providing the following config option in :cpp:type:`esp_tls_cfg_t`:
|
||||
4) Import the ATECC608A key and configure ESP-TLS to use it via :cpp:type:`esp_key_config_t`:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include "psa/crypto.h"
|
||||
#include "psa_crypto_driver_secure_element.h"
|
||||
#include "psa_crypto_driver_secure_element_contexts.h"
|
||||
#include "esp_key_config.h"
|
||||
|
||||
/* Import ATECC608A key reference into PSA */
|
||||
psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
|
||||
psa_set_key_lifetime(&key_attr, PSA_KEY_LIFETIME_SECURE_ELEMENT_VOLATILE);
|
||||
psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_HASH);
|
||||
psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
|
||||
psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
|
||||
psa_set_key_bits(&key_attr, 256);
|
||||
|
||||
secure_element_opaque_key_t opaque_key = {
|
||||
.slot_id = 0, /* Private key slot on ATECC608A */
|
||||
};
|
||||
|
||||
psa_key_id_t psa_key_id;
|
||||
psa_import_key(&key_attr, (const uint8_t *)&opaque_key,
|
||||
sizeof(opaque_key), &psa_key_id);
|
||||
|
||||
/* Configure ESP-TLS to use the PSA key */
|
||||
esp_key_config_t key_config = {
|
||||
.source = ESP_KEY_SOURCE_PSA,
|
||||
.psa.key_id = psa_key_id,
|
||||
};
|
||||
|
||||
esp_tls_cfg_t cfg = {
|
||||
/* other configurations options */
|
||||
.use_secure_element = true,
|
||||
/* other configuration options */
|
||||
.client_key = &key_config,
|
||||
};
|
||||
|
||||
.. only:: SOC_DIG_SIGN_SUPPORTED
|
||||
|
||||
@@ -207,7 +207,7 @@ ESP-TLS 组件支持通过 :cpp:func:`esp_tls_register_stack` API 注册自定
|
||||
ESP-TLS 中的 ATECC608A(安全元件)
|
||||
-----------------------------------------
|
||||
|
||||
ESP-TLS 支持在 ESP32 系列芯片上使用 ATECC608A 加密芯片,但必须将 MbedTLS 作为 ESP-TLS 的底层 SSL/TLS 协议栈。未经手动更改,ESP-TLS 默认以 MbedTLS 为其底层 TLS/SSL 协议栈。
|
||||
ESP-TLS 支持通过 PSA Crypto 不透明驱动接口在 ESP32 系列芯片上使用 ATECC608A 加密芯片。使用 ATECC608A 时必须将 MbedTLS 作为 ESP-TLS 的底层 SSL/TLS 协议栈。未经手动更改,ESP-TLS 默认以 MbedTLS 为其底层 TLS/SSL 协议栈。
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -215,13 +215,13 @@ ESP-TLS 支持在 ESP32 系列芯片上使用 ATECC608A 加密芯片,但必须
|
||||
|
||||
要启用安全元件支持,并将其应用于工程 TLS 连接,请遵循以下步骤:
|
||||
|
||||
1) 在工程中添加 `esp-cryptoauthlib <https://github.com/espressif/esp-cryptoauthlib>`_,详情请参阅 `如何在 ESP-IDF 中使用 esp-cryptoauthlib <https://github.com/espressif/esp-cryptoauthlib#how-to-use-esp-cryptoauthlib-with-esp-idf>`_。
|
||||
1) 在工程中添加 `esp-cryptoauthlib <https://github.com/espressif/esp-cryptoauthlib>`_ 作为依赖,详情请参阅 `如何在 ESP-IDF 中使用 esp-cryptoauthlib <https://github.com/espressif/esp-cryptoauthlib#how-to-use-esp-cryptoauthlib-with-esp-idf>`_。
|
||||
|
||||
2) 启用 menuconfig 选项 :ref:`CONFIG_ESP_TLS_USE_SECURE_ELEMENT`:
|
||||
2) 启用 menuconfig 选项 :ref:`CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED`:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
menuconfig > Component config > ESP-TLS > Use Secure Element (ATECC608A) with ESP-TLS
|
||||
menuconfig > Component config > mbedTLS > Enable secure element hardware support
|
||||
|
||||
3) 选择 ATECC608A 芯片类型:
|
||||
|
||||
@@ -231,13 +231,40 @@ ESP-TLS 支持在 ESP32 系列芯片上使用 ATECC608A 加密芯片,但必须
|
||||
|
||||
如需了解更多 ATECC608A 芯片类型,或需了解如何获取连接到特定 ESP 模块的 ATECC608A 芯片类型,请参阅 `ATECC608A 芯片类型 <https://github.com/espressif/esp-cryptoauthlib/blob/master/esp_cryptoauth_utility/README.md#find-type-of-atecc608a-chip-connected-to-esp32-wroom32-se>`_。
|
||||
|
||||
4) 在 :cpp:type:`esp_tls_cfg_t` 中提供以下配置,在 ESP-TLS 中启用 ATECC608A:
|
||||
4) 初始化 PSA Crypto,导入 ATECC608A 密钥,并通过 :cpp:type:`esp_key_config_t` 配置 ESP-TLS 使用:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include "psa/crypto.h"
|
||||
#include "psa_crypto_driver_secure_element.h"
|
||||
#include "psa_crypto_driver_secure_element_contexts.h"
|
||||
#include "esp_key_config.h"
|
||||
|
||||
/* 将 ATECC608A 密钥引用导入 PSA */
|
||||
psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
|
||||
psa_set_key_lifetime(&key_attr, PSA_KEY_LIFETIME_SECURE_ELEMENT_VOLATILE);
|
||||
psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_HASH);
|
||||
psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
|
||||
psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
|
||||
psa_set_key_bits(&key_attr, 256);
|
||||
|
||||
secure_element_opaque_key_t opaque_key = {
|
||||
.slot_id = 0, /* ATECC608A 上的私钥槽位 */
|
||||
};
|
||||
|
||||
psa_key_id_t psa_key_id;
|
||||
psa_import_key(&key_attr, (const uint8_t *)&opaque_key,
|
||||
sizeof(opaque_key), &psa_key_id);
|
||||
|
||||
/* 配置 ESP-TLS 使用 PSA 密钥 */
|
||||
esp_key_config_t key_config = {
|
||||
.source = ESP_KEY_SOURCE_PSA,
|
||||
.psa.key_id = psa_key_id,
|
||||
};
|
||||
|
||||
esp_tls_cfg_t cfg = {
|
||||
/* 其他配置选项 */
|
||||
.use_secure_element = true,
|
||||
.client_key = &key_config,
|
||||
};
|
||||
|
||||
.. only:: SOC_DIG_SIGN_SUPPORTED
|
||||
|
||||
Reference in New Issue
Block a user