Merge branch 'feature/use_ecdsa_perph_while_mutual_auth' into 'master'

feat: ECDSA peripheral while performing http connection with mutual auth

Closes IDF-7390

See merge request espressif/esp-idf!25052
This commit is contained in:
Mahavir Jain 2023-09-11 19:41:21 +08:00
commit 2b3418b4a0
12 changed files with 272 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
*/
@ -151,6 +151,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 */
@ -276,6 +280,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
@ -404,6 +408,19 @@ 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) {
esp_ecdsa_pk_conf_t conf = {
.grp_id = MBEDTLS_ECP_DP_SECP256R1,
.efuse_block = tls->ecdsa_efuse_blk,
};
ret = esp_ecdsa_set_pk_context(pki->pk_key, &conf);
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;
}
} else
#endif
if (pki->privkey_pem_buf != NULL) {
ret = mbedtls_pk_parse_key(pki->pk_key, pki->privkey_pem_buf, pki->privkey_pem_bytes,
@ -580,6 +597,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,
@ -786,6 +826,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

@ -58,6 +58,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

@ -245,6 +245,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

@ -6,7 +6,9 @@
#include <string.h>
#include "hal/ecdsa_hal.h"
#include "esp_efuse.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"
@ -279,6 +281,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);