Skip to content

Commit

Permalink
Merge branch 'feature/use_ecdsa_perph_while_mutual_auth' into 'master'
Browse files Browse the repository at this point in the history
feat: ECDSA peripheral while performing http connection with mutual auth

Closes IDF-7390

See merge request espressif/esp-idf!25052
  • Loading branch information
mahavirj committed Sep 11, 2023
2 parents bd0eac7 + 692e1a9 commit 2b3418b
Show file tree
Hide file tree
Showing 12 changed files with 272 additions and 8 deletions.
10 changes: 9 additions & 1 deletion components/esp-tls/esp_tls.h
Original file line number Diff line number Diff line change
@@ -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
*/
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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 ) */

Expand Down
73 changes: 73 additions & 0 deletions components/esp-tls/esp_tls_mbedtls.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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 = {
Expand Down
4 changes: 4 additions & 0 deletions components/esp-tls/private_include/esp_tls_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down
6 changes: 5 additions & 1 deletion components/esp_http_client/esp_http_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
4 changes: 4 additions & 0 deletions components/esp_http_client/include/esp_http_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
2 changes: 1 addition & 1 deletion components/esp_http_server/include/esp_http_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 9 additions & 1 deletion components/esp_https_server/include/esp_https_server.h
Original file line number Diff line number Diff line change
@@ -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
*/
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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, \
Expand Down
12 changes: 10 additions & 2 deletions components/esp_https_server/src/https_server.c
Original file line number Diff line number Diff line change
@@ -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
*/
Expand Down Expand Up @@ -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) {
Expand Down
3 changes: 3 additions & 0 deletions components/mbedtls/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
133 changes: 133 additions & 0 deletions components/mbedtls/port/ecdsa/ecdsa_alt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit 2b3418b

Please sign in to comment.