Merge branch 'feat/ecdsa_perph_while_mutual_auth_v5.1' into 'release/v5.1'

Feat/ecdsa perph while mutual auth v5.1

See merge request espressif/esp-idf!27245
This commit is contained in:
Mahavir Jain 2023-11-20 18:03:19 +08:00
commit ecd485be87
13 changed files with 296 additions and 8 deletions

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -150,6 +150,10 @@ typedef struct esp_tls_cfg {
unsigned int clientkey_password_len; /*!< String length of the password pointed to by
clientkey_password */
bool use_ecdsa_peripheral; /*!< Use the ECDSA peripheral for the private key operations */
uint8_t ecdsa_key_efuse_blk; /*!< The efuse block where the ECDSA key is stored */
bool non_block; /*!< Configure non-blocking mode. If set to true the
underneath socket will be configured in non
blocking mode after tls session is established */
@ -273,6 +277,10 @@ typedef struct esp_tls_cfg_server {
unsigned int serverkey_password_len; /*!< String length of the password pointed to by
serverkey_password */
bool use_ecdsa_peripheral; /*!< Use ECDSA peripheral to use private key */
uint8_t ecdsa_key_efuse_blk; /*!< The efuse block where ECDSA key is stored */
bool use_secure_element; /*!< Enable this option to use secure element or
atecc608a chip ( Integrated with ESP32-WROOM-32SE ) */

View File

@ -20,6 +20,10 @@
#include "esp_log.h"
#include "esp_check.h"
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
#include "ecdsa/ecdsa_alt.h"
#endif
#ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
#include "esp_crt_bundle.h"
#endif
@ -385,6 +389,21 @@ static esp_err_t set_pki_context(esp_tls_t *tls, const esp_tls_pki_t *pki)
return ret;
}
} else
#endif
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
if (tls->use_ecdsa_peripheral) {
ret = esp_ecdsa_privkey_load_pk_context(pki->pk_key, tls->ecdsa_efuse_blk);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize pk context for ecdsa peripheral with the key stored in efuse block %d", tls->ecdsa_efuse_blk);
return ret;
}
mbedtls_ecp_keypair *keypair = mbedtls_pk_ec(*pki->pk_key);
ret = mbedtls_ecp_group_load(&keypair->MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1);
if (ret != 0) {
ESP_LOGE(TAG, "Failed to set up an ECP group context with the key stored in efuse block %d", tls->ecdsa_efuse_blk);
return ret;
}
} else
#endif
if (pki->privkey_pem_buf != NULL) {
ret = mbedtls_pk_parse_key(pki->pk_key, pki->privkey_pem_buf, pki->privkey_pem_bytes,
@ -561,6 +580,29 @@ esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls)
ESP_LOGE(TAG, "Please enable secure element support for ESP-TLS in menuconfig");
return ESP_FAIL;
#endif /* CONFIG_ESP_TLS_USE_SECURE_ELEMENT */
} else if (cfg->use_ecdsa_peripheral) {
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
tls->use_ecdsa_peripheral = cfg->use_ecdsa_peripheral;
tls->ecdsa_efuse_blk = cfg->ecdsa_key_efuse_blk;
esp_tls_pki_t pki = {
.public_cert = &tls->servercert,
.pk_key = &tls->serverkey,
.publiccert_pem_buf = cfg->servercert_buf,
.publiccert_pem_bytes = cfg->servercert_bytes,
.privkey_pem_buf = NULL,
.privkey_pem_bytes = 0,
.privkey_password = NULL,
.privkey_password_len = 0,
};
esp_err_t esp_ret = set_pki_context(tls, &pki);
if (esp_ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to set client pki context");
return esp_ret;
}
#else
ESP_LOGE(TAG, "Please enable the support for signing using ECDSA peripheral in menuconfig.");
return ESP_FAIL;
#endif
} else if (cfg->servercert_buf != NULL && cfg->serverkey_buf != NULL) {
esp_tls_pki_t pki = {
.public_cert = &tls->servercert,
@ -767,6 +809,39 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t
#else
ESP_LOGE(TAG, "Please enable the DS peripheral support for the ESP-TLS in menuconfig. (only supported for the ESP32-S2 chip)");
return ESP_FAIL;
#endif
} else if (cfg->use_ecdsa_peripheral) {
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
tls->use_ecdsa_peripheral = cfg->use_ecdsa_peripheral;
tls->ecdsa_efuse_blk = cfg->ecdsa_key_efuse_blk;
esp_tls_pki_t pki = {
.public_cert = &tls->clientcert,
.pk_key = &tls->clientkey,
.publiccert_pem_buf = cfg->clientcert_buf,
.publiccert_pem_bytes = cfg->clientcert_bytes,
.privkey_pem_buf = NULL,
.privkey_pem_bytes = 0,
.privkey_password = NULL,
.privkey_password_len = 0,
};
esp_err_t esp_ret = set_pki_context(tls, &pki);
if (esp_ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to set client pki context");
return esp_ret;
}
static const int ecdsa_peripheral_supported_ciphersuites[] = {
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
#if CONFIG_MBEDTLS_SSL_PROTO_TLS1_3
MBEDTLS_TLS1_3_AES_128_GCM_SHA256,
#endif
0
};
ESP_LOGD(TAG, "Set the ciphersuites list");
mbedtls_ssl_conf_ciphersuites(&tls->conf, ecdsa_peripheral_supported_ciphersuites);
#else
ESP_LOGE(TAG, "Please enable the support for signing using ECDSA peripheral in menuconfig.");
return ESP_FAIL;
#endif
} else if (cfg->clientcert_pem_buf != NULL && cfg->clientkey_pem_buf != NULL) {
esp_tls_pki_t pki = {

View File

@ -55,6 +55,10 @@ struct esp_tls {
mbedtls_pk_context clientkey; /*!< Container for the private key of the client
certificate */
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
bool use_ecdsa_peripheral; /*!< Use the ECDSA peripheral for the private key operations. */
uint8_t ecdsa_efuse_blk; /*!< The efuse block number where the ECDSA key is stored. */
#endif
#ifdef CONFIG_ESP_TLS_SERVER
mbedtls_x509_crt servercert; /*!< Container for the X.509 server certificate */

View File

@ -743,7 +743,11 @@ esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *co
esp_transport_ssl_set_client_key_data_der(ssl, config->client_key_pem, config->client_key_len);
}
}
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
if (config->use_ecdsa_peripheral) {
esp_transport_ssl_set_client_key_ecdsa_peripheral(ssl, config->ecdsa_key_efuse_blk);
}
#endif
if (config->client_key_password && config->client_key_password_len > 0) {
esp_transport_ssl_set_client_key_password(ssl, config->client_key_password, config->client_key_password_len);
}

View File

@ -133,6 +133,10 @@ typedef struct {
size_t client_key_len; /*!< Length of the buffer pointed to by client_key_pem. May be 0 for null-terminated pem */
const char *client_key_password; /*!< Client key decryption password string */
size_t client_key_password_len; /*!< String length of the password pointed to by client_key_password */
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
bool use_ecdsa_peripheral; /*!< Use ECDSA peripheral to use private key. */
uint8_t ecdsa_key_efuse_blk; /*!< The efuse block where ECDSA key is stored. */
#endif
const char *user_agent; /*!< The User Agent string to send with HTTP requests */
esp_http_client_method_t method; /*!< HTTP Method */
int timeout_ms; /*!< Network timeout in milliseconds */

View File

@ -313,7 +313,7 @@ typedef struct httpd_config {
* - ESP_ERR_HTTPD_ALLOC_MEM : Failed to allocate memory for instance
* - ESP_ERR_HTTPD_TASK : Failed to launch server task
*/
esp_err_t httpd_start(httpd_handle_t *handle, const httpd_config_t *config);
esp_err_t httpd_start(httpd_handle_t *handle, const httpd_config_t *config);
/**
* @brief Stops the web server

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -79,6 +79,12 @@ struct httpd_ssl_config {
/** Private key byte length */
size_t prvtkey_len;
/** Use ECDSA peripheral to use private key */
bool use_ecdsa_peripheral;
/** The efuse block where ECDSA key is stored */
uint8_t ecdsa_key_efuse_blk;
/** Transport Mode (default secure) */
httpd_ssl_transport_mode_t transport_mode;
@ -150,6 +156,8 @@ typedef struct httpd_ssl_config httpd_ssl_config_t;
.cacert_len = 0, \
.prvtkey_pem = NULL, \
.prvtkey_len = 0, \
.use_ecdsa_peripheral = false, \
.ecdsa_key_efuse_blk = 0, \
.transport_mode = HTTPD_SSL_TRANSPORT_SECURE, \
.port_secure = 443, \
.port_insecure = 80, \

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -262,7 +262,15 @@ static httpd_ssl_ctx_t *create_secure_context(const struct httpd_ssl_config *con
/* Pass on secure element boolean */
cfg->use_secure_element = config->use_secure_element;
if (!cfg->use_secure_element) {
if (config->prvtkey_pem != NULL && config->prvtkey_len > 0) {
if (config->use_ecdsa_peripheral) {
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
ssl_ctx->tls_cfg->use_ecdsa_peripheral = config->use_ecdsa_peripheral;
ssl_ctx->tls_cfg->ecdsa_key_efuse_blk = config->ecdsa_key_efuse_blk;
#else
ESP_LOGE(TAG, "Please enable the support for signing using ECDSA peripheral in menuconfig.");
goto exit;
#endif
} else if (config->prvtkey_pem != NULL && config->prvtkey_len > 0) {
cfg->serverkey_buf = malloc(config->prvtkey_len);
if (cfg->serverkey_buf) {

View File

@ -250,6 +250,9 @@ if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN OR CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY)
if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_sign")
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_sign_restartable")
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_write_signature")
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_write_signature_restartable")
endif()
if(CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY)

View File

@ -8,7 +8,9 @@
#include "esp_crypto_lock.h"
#include "esp_efuse.h"
#include "mbedtls/ecp.h"
#include "mbedtls/error.h"
#include "mbedtls/ecdsa.h"
#include "mbedtls/asn1write.h"
#include "mbedtls/platform_util.h"
#include "esp_private/periph_ctrl.h"
#include "ecdsa/ecdsa_alt.h"
@ -178,6 +180,137 @@ int __wrap_mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mp
return __real_mbedtls_ecdsa_sign(grp, r, s, d, buf, blen, f_rng, p_rng);
}
}
extern int __real_mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
int (*f_rng_blind)(void *, unsigned char *, size_t), void *p_rng_blind,
mbedtls_ecdsa_restart_ctx *rs_ctx);
int __wrap_mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
int (*f_rng_blind)(void *, unsigned char *, size_t), void *p_rng_blind,
mbedtls_ecdsa_restart_ctx *rs_ctx);
int __wrap_mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
int (*f_rng_blind)(void *, unsigned char *, size_t), void *p_rng_blind,
mbedtls_ecdsa_restart_ctx *rs_ctx)
{
/*
* Check `d` whether it contains the hardware key
*/
if (d->MBEDTLS_PRIVATE(s) == ECDSA_KEY_MAGIC) {
// Use hardware ECDSA peripheral
return esp_ecdsa_sign(grp, r, s, d, buf, blen);
} else {
return __real_mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen, f_rng, p_rng, f_rng_blind, p_rng_blind, rs_ctx);
}
}
int __real_mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hlen,
unsigned char *sig, size_t sig_size, size_t *slen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
mbedtls_ecdsa_restart_ctx *rs_ctx);
int __wrap_mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hlen,
unsigned char *sig, size_t sig_size, size_t *slen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
mbedtls_ecdsa_restart_ctx *rs_ctx);
/*
* Convert a signature (given by context) to ASN.1
*/
static int ecdsa_signature_to_asn1(const mbedtls_mpi *r, const mbedtls_mpi *s,
unsigned char *sig, size_t sig_size,
size_t *slen)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char buf[MBEDTLS_ECDSA_MAX_LEN] = { 0 };
// Setting the pointer p to the end of the buffer as the functions used afterwards write in backwards manner in the given buffer.
unsigned char *p = buf + sizeof(buf);
size_t len = 0;
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, s));
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, r));
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, buf, len));
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, buf,
MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE));
if (len > sig_size) {
return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
}
memcpy(sig, p, len);
*slen = len;
return 0;
}
int __wrap_mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hlen,
unsigned char *sig, size_t sig_size, size_t *slen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
mbedtls_ecdsa_restart_ctx *rs_ctx)
{
if (ctx->MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(s) != ECDSA_KEY_MAGIC) {
return __real_mbedtls_ecdsa_write_signature_restartable(ctx, md_alg, hash, hlen, sig, sig_size, slen, f_rng, p_rng, rs_ctx);
}
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi r, s;
mbedtls_mpi_init(&r);
mbedtls_mpi_init(&s);
/*
* Check `d` whether it contains the hardware key
*/
if (ctx->MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(s) == ECDSA_KEY_MAGIC) {
// Use hardware ECDSA peripheral
MBEDTLS_MPI_CHK(esp_ecdsa_sign(&ctx->MBEDTLS_PRIVATE(grp), &r, &s, &ctx->MBEDTLS_PRIVATE(d), hash, hlen));
}
MBEDTLS_MPI_CHK(ecdsa_signature_to_asn1(&r, &s, sig, sig_size, slen));
cleanup:
mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s);
return ret;
}
int __wrap_mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hlen,
unsigned char *sig, size_t sig_size, size_t *slen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng);
int __wrap_mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hlen,
unsigned char *sig, size_t sig_size, size_t *slen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng)
{
return __wrap_mbedtls_ecdsa_write_signature_restartable(
ctx, md_alg, hash, hlen, sig, sig_size, slen,
f_rng, p_rng, NULL);
}
#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN */
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -72,6 +72,16 @@ void esp_transport_ssl_enable_global_ca_store(esp_transport_handle_t t);
*/
void esp_transport_ssl_set_client_cert_data(esp_transport_handle_t t, const char *data, int len);
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
/**
* @brief Set SSL client key data for mutual authentication when using ECDSA peripheral.
*
* @param t ssl transport
* @param[in] efuse_blk Efuse block where ECDSA private key is stored
*/
void esp_transport_ssl_set_client_key_ecdsa_peripheral(esp_transport_handle_t t, uint8_t ecdsa_efuse_blk);
#endif
/**
* @brief Set SSL client certificate data for mutual authentication (as DER format).
* Note that, this function stores the pointer to data, rather than making a copy.

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -370,6 +370,15 @@ void esp_transport_ssl_set_client_cert_data(esp_transport_handle_t t, const char
ssl->cfg.clientcert_pem_bytes = len + 1;
}
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
void esp_transport_ssl_set_client_key_ecdsa_peripheral(esp_transport_handle_t t, uint8_t ecdsa_efuse_blk)
{
GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t);
ssl->cfg.use_ecdsa_peripheral = true;
ssl->cfg.ecdsa_key_efuse_blk = ecdsa_efuse_blk;
}
#endif
void esp_transport_ssl_set_client_cert_data_der(esp_transport_handle_t t, const char *data, int len)
{
GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t);

View File

@ -192,6 +192,28 @@ SSL/TLS libraries and with all respective configurations set to default.
* An example of mutual authentication with the DS peripheral can be found at :example:`ssl mutual auth<protocols/mqtt/ssl_mutual_auth>` which internally uses (ESP-TLS) for the TLS connection.
.. only:: SOC_ECDSA_SUPPORTED
ECDSA Peripheral with ESP-TLS
-----------------------------
ESP-TLS provides support for using the ECDSA peripheral with {IDF_TARGET_NAME}. The use of ECDSA peripheral is supported only when ESP-TLS is used with MbedTLS as its underlying SSL/TLS stack. The ECDSA private key should be present in the efuse for using the ECDSA peripheral. Please refer to `espefuse.py <https://docs.espressif.com/projects/esptool/en/latest/esp32/espefuse/index.html>`_ documentation for programming the ECDSA key in the efuse.
To use ECDSA peripheral with ESP-TLS, set ``use_ecdsa_peripheral`` to `true` and set ``ecdsa_key_efuse_blk`` to the efuse block id in which ECDSA private key is stored in the :cpp:type:`esp_tls_cfg_t` config structure.
This will enable the use of ECDSA peripheral for private key operations. As the client private key is already present in the eFuse, it need not be supplied to the :cpp:type:`esp_tls_cfg_t` structure.
.. code-block:: c
#include "esp_tls.h"
esp_tls_cfg_t cfg = {
.use_ecdsa_peripheral = true,
.ecdsa_key_efuse_blk = /* efuse block with ecdsa private key */,
};
.. note::
When using ECDSA peripheral with TLS, only ``MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256`` ciphersuite is supported. If using TLS v1.3, ``MBEDTLS_TLS1_3_AES_128_GCM_SHA256`` ciphersuite is supported.
API Reference
-------------