mirror of
https://github.com/espressif/esp-idf.git
synced 2026-05-28 16:46:31 +03:00
fix(esp_wifi): Skip allocation of new buffers during EAP processing
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -21,7 +21,7 @@
|
||||
*/
|
||||
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
|
||||
|
||||
// located at mbedtls/library/ssl_misc.h
|
||||
// Located in mbedtls/library/ssl_misc.h
|
||||
#include "ssl_misc.h"
|
||||
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
@@ -59,8 +59,9 @@
|
||||
|
||||
uint32_t tls_instance_count;
|
||||
struct tls_data {
|
||||
/* Data for mbedlts */
|
||||
/* Data for mbedtls */
|
||||
struct wpabuf *in_data;
|
||||
size_t in_data_off;
|
||||
/* Data from mbedtls */
|
||||
struct wpabuf *out_data;
|
||||
};
|
||||
@@ -69,7 +70,7 @@ typedef struct tls_context {
|
||||
mbedtls_ssl_context ssl; /*!< TLS/SSL context */
|
||||
mbedtls_entropy_context entropy; /*!< mbedTLS entropy context structure */
|
||||
mbedtls_ctr_drbg_context ctr_drbg; /*!< mbedTLS ctr drbg context structure */
|
||||
mbedtls_ssl_config conf; /*!< TLS/SSL config to be shared structures */
|
||||
mbedtls_ssl_config conf; /*!< TLS/SSL config shared across structures */
|
||||
mbedtls_x509_crt cacert; /*!< Container for X.509 CA certificate */
|
||||
mbedtls_x509_crt *cacert_ptr; /*!< Pointer to the cacert being used. */
|
||||
mbedtls_x509_crt clientcert; /*!< Container for X.509 client certificate */
|
||||
@@ -108,6 +109,54 @@ static void tls_mbedtls_conn_delete(tls_context_t *tls)
|
||||
}
|
||||
}
|
||||
|
||||
static void tls_mbedtls_reset_in_data(struct tls_data *data)
|
||||
{
|
||||
if (data->in_data) {
|
||||
wpabuf_free(data->in_data);
|
||||
}
|
||||
|
||||
data->in_data = NULL;
|
||||
data->in_data_off = 0;
|
||||
}
|
||||
|
||||
static void tls_mbedtls_reset_out_data(struct tls_data *data)
|
||||
{
|
||||
if (data->out_data) {
|
||||
wpabuf_free(data->out_data);
|
||||
}
|
||||
|
||||
data->out_data = NULL;
|
||||
}
|
||||
|
||||
static int tls_mbedtls_append_in_data(struct tls_data *data,
|
||||
const struct wpabuf *in_data)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (in_data == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = wpabuf_len(in_data);
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (data->in_data == NULL ||
|
||||
data->in_data_off == wpabuf_len(data->in_data)) {
|
||||
tls_mbedtls_reset_in_data(data);
|
||||
data->in_data = wpabuf_dup(in_data);
|
||||
return data->in_data ? 0 : -1;
|
||||
}
|
||||
|
||||
if (wpabuf_resize(&data->in_data, len) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpabuf_put_data(data->in_data, wpabuf_head(in_data), len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tls_mbedtls_write(void *ctx, const unsigned char *buf, size_t len)
|
||||
{
|
||||
struct tls_connection *conn = (struct tls_connection *)ctx;
|
||||
@@ -125,25 +174,27 @@ static int tls_mbedtls_read(void *ctx, unsigned char *buf, size_t len)
|
||||
{
|
||||
struct tls_connection *conn = (struct tls_connection *)ctx;
|
||||
struct tls_data *data = &conn->tls_io_data;
|
||||
struct wpabuf *local_buf;
|
||||
size_t remaining;
|
||||
|
||||
if (data->in_data == NULL || len > wpabuf_len(data->in_data)) {
|
||||
/* We don't have suffient buffer available for read */
|
||||
if (data->in_data == NULL ||
|
||||
data->in_data_off > wpabuf_len(data->in_data)) {
|
||||
/* We don't have sufficient buffer available for read */
|
||||
wpa_printf(MSG_INFO, "len=%zu not available in input", len);
|
||||
return MBEDTLS_ERR_SSL_WANT_READ;
|
||||
}
|
||||
|
||||
os_memcpy(buf, wpabuf_head(data->in_data), len);
|
||||
/* adjust buffer */
|
||||
if (len < wpabuf_len(data->in_data)) {
|
||||
/* TODO optimize this operation */
|
||||
local_buf = wpabuf_alloc_copy(wpabuf_mhead_u8(data->in_data) + len,
|
||||
wpabuf_len(data->in_data) - len);
|
||||
wpabuf_free(data->in_data);
|
||||
data->in_data = local_buf;
|
||||
} else {
|
||||
wpabuf_free(data->in_data);
|
||||
data->in_data = NULL;
|
||||
remaining = wpabuf_len(data->in_data) - data->in_data_off;
|
||||
if (len > remaining) {
|
||||
/* We don't have sufficient buffer available for read */
|
||||
wpa_printf(MSG_INFO, "len=%zu not available in input", len);
|
||||
return MBEDTLS_ERR_SSL_WANT_READ;
|
||||
}
|
||||
|
||||
os_memcpy(buf, wpabuf_head_u8(data->in_data) + data->in_data_off, len);
|
||||
data->in_data_off += len;
|
||||
|
||||
if (data->in_data_off == wpabuf_len(data->in_data)) {
|
||||
tls_mbedtls_reset_in_data(data);
|
||||
}
|
||||
|
||||
return len;
|
||||
@@ -154,7 +205,7 @@ static int set_pki_context(tls_context_t *tls, const struct tls_connection_param
|
||||
int ret;
|
||||
|
||||
if (cfg->client_cert_blob == NULL || cfg->private_key_blob == NULL) {
|
||||
wpa_printf(MSG_ERROR, "%s: config not correct", __func__);
|
||||
wpa_printf(MSG_ERROR, "%s: invalid configuration", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -454,7 +505,7 @@ static const int suiteb_ciphersuite_preference[] =
|
||||
|
||||
static void tls_set_ciphersuite(const struct tls_connection_params *cfg, tls_context_t *tls)
|
||||
{
|
||||
/* Only set ciphersuite if cert's key length is high or ciphersuites are set by user */
|
||||
/* Only set ciphersuite if cert key length is high or ciphersuites are set by user. */
|
||||
#ifdef CONFIG_SUITEB192
|
||||
if (cfg->flags & TLS_CONN_SUITEB) {
|
||||
/* cipher suites will be set based on certificate */
|
||||
@@ -473,6 +524,8 @@ static void tls_set_ciphersuite(const struct tls_connection_params *cfg, tls_con
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
/* Set cipher suites if user has explicitly set them.
|
||||
* TODO: public API to set EAP ciphers */
|
||||
if (tls->ciphersuite[0]) {
|
||||
mbedtls_ssl_conf_ciphersuites(&tls->conf, tls->ciphersuite);
|
||||
} else if (mbedtls_pk_get_bitlen(&tls->clientkey) > 2048 ||
|
||||
@@ -614,7 +667,7 @@ static int tls_create_mbedtls_handle(struct tls_connection *conn,
|
||||
mbedtls_ssl_conf_cbc_record_splitting(&tls->conf, MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED);
|
||||
#endif
|
||||
|
||||
/* Enable debug prints in case supplicant's prints are enabled */
|
||||
/* Enable debug prints if supplicant logging is enabled. */
|
||||
#if defined(CONFIG_MBEDTLS_DEBUG) && defined(ESPRESSIF_USE)
|
||||
mbedtls_esp_enable_debug_log(&tls->conf, 2);
|
||||
#endif
|
||||
@@ -649,15 +702,18 @@ struct tls_connection * tls_connection_init(void *tls_ctx)
|
||||
|
||||
void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
/* case: tls init failed */
|
||||
/* Case: TLS init failed. */
|
||||
if (!conn) {
|
||||
return;
|
||||
}
|
||||
/* Free ssl ctx and data */
|
||||
tls_mbedtls_reset_in_data(&conn->tls_io_data);
|
||||
/* Output buffer ownership is transferred to caller before return. */
|
||||
conn->tls_io_data.out_data = NULL;
|
||||
/* Free SSL context and data. */
|
||||
tls_mbedtls_conn_delete((tls_context_t *) conn->tls);
|
||||
os_free(conn->tls);
|
||||
conn->tls = NULL;
|
||||
/* Data in in ssl ctx, free connection */
|
||||
/* SSL context data is freed above; free connection. */
|
||||
os_free(conn);
|
||||
}
|
||||
|
||||
@@ -750,10 +806,12 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx,
|
||||
struct wpabuf *resp;
|
||||
int cli_state;
|
||||
|
||||
/* data freed by sender */
|
||||
/* Data is freed by sender. */
|
||||
conn->tls_io_data.out_data = NULL;
|
||||
if (wpabuf_len(in_data)) {
|
||||
conn->tls_io_data.in_data = wpabuf_dup(in_data);
|
||||
if (tls_mbedtls_append_in_data(&conn->tls_io_data, in_data) < 0) {
|
||||
wpa_printf(MSG_ERROR, "%s: failed to queue TLS input", __func__);
|
||||
tls_mbedtls_reset_in_data(&conn->tls_io_data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Multiple reads */
|
||||
@@ -790,9 +848,18 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx,
|
||||
}
|
||||
|
||||
if (!conn->tls_io_data.out_data) {
|
||||
wpa_printf(MSG_INFO, "application data is null, adding one byte for ack");
|
||||
wpa_printf(MSG_INFO, "Application data is NULL; adding one byte for ACK");
|
||||
u8 *dummy = os_zalloc(1);
|
||||
if (dummy == NULL) {
|
||||
wpa_printf(MSG_INFO, "%s: memory allocation failure. line:%d", __func__, __LINE__);
|
||||
goto end;
|
||||
}
|
||||
conn->tls_io_data.out_data = wpabuf_alloc_ext_data(dummy, 0);
|
||||
if (conn->tls_io_data.out_data == NULL) {
|
||||
wpa_printf(MSG_INFO, "%s: memory allocation failure. line:%d", __func__, __LINE__);
|
||||
os_free(dummy);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
@@ -818,13 +885,13 @@ struct wpabuf * tls_connection_encrypt(void *tls_ctx,
|
||||
struct wpabuf *resp;
|
||||
size_t ret;
|
||||
|
||||
/* Reset dangling pointer */
|
||||
/* Clear dangling pointer. */
|
||||
conn->tls_io_data.out_data = NULL;
|
||||
ret = mbedtls_ssl_write(&conn->tls->ssl,
|
||||
(unsigned char*) wpabuf_head(in_data), wpabuf_len(in_data));
|
||||
|
||||
if (ret < wpabuf_len(in_data)) {
|
||||
wpa_printf(MSG_ERROR, "%s:%d, not able to write whole data",
|
||||
wpa_printf(MSG_ERROR, "%s:%d, unable to write all data",
|
||||
__func__, __LINE__);
|
||||
}
|
||||
|
||||
@@ -846,26 +913,25 @@ struct wpabuf *tls_connection_decrypt(void *tls_ctx,
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
}
|
||||
/* Reset dangling output buffer before setting data, data was freed by caller */
|
||||
/* Clear dangling output buffer before setting data; it was freed by caller. */
|
||||
conn->tls_io_data.out_data = NULL;
|
||||
|
||||
conn->tls_io_data.in_data = wpabuf_dup(in_data);
|
||||
|
||||
if (!conn->tls_io_data.in_data) {
|
||||
if (tls_mbedtls_append_in_data(&conn->tls_io_data, in_data) < 0) {
|
||||
wpa_printf(MSG_ERROR, "%s: failed to queue TLS input", __func__);
|
||||
tls_mbedtls_reset_in_data(&conn->tls_io_data);
|
||||
goto cleanup;
|
||||
}
|
||||
ret = mbedtls_ssl_read(&conn->tls->ssl, buf, MAX_PHASE2_BUFFER);
|
||||
if (ret < 0) {
|
||||
wpa_printf(MSG_ERROR, "%s:%d, not able to read data",
|
||||
wpa_printf(MSG_ERROR, "%s:%d, unable to read data",
|
||||
__func__, __LINE__);
|
||||
goto cleanup;
|
||||
}
|
||||
out = wpabuf_alloc_copy(buf, ret);
|
||||
cleanup:
|
||||
/* there may be some error written in output buffer */
|
||||
/* There may be an error written to output buffer. */
|
||||
if (conn->tls_io_data.out_data) {
|
||||
os_free(conn->tls_io_data.out_data);
|
||||
conn->tls_io_data.out_data = NULL;
|
||||
tls_mbedtls_reset_out_data(&conn->tls_io_data);
|
||||
}
|
||||
|
||||
os_free(buf);
|
||||
@@ -884,8 +950,8 @@ int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* cipher array should contain cipher number in mbedtls num as per IANA
|
||||
* Please see cipherlist is u8, therefore only initial ones are supported */
|
||||
/* Cipher array should contain cipher numbers in mbedtls format, based on IANA values.
|
||||
* Since cipherlist is u8, only the initial values are supported. */
|
||||
int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
|
||||
u8 *ciphers)
|
||||
{
|
||||
@@ -967,7 +1033,7 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
|
||||
tls_context_t *tls = (tls_context_t *)os_zalloc(sizeof(tls_context_t));
|
||||
|
||||
if (!tls) {
|
||||
wpa_printf(MSG_ERROR, "failed to allocate tls context");
|
||||
wpa_printf(MSG_ERROR, "failed to allocate TLS context");
|
||||
return -1;
|
||||
}
|
||||
if (!params) {
|
||||
@@ -978,7 +1044,7 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
|
||||
|
||||
ret = tls_create_mbedtls_handle(conn, params, tls);
|
||||
if (ret < 0) {
|
||||
wpa_printf(MSG_ERROR, "failed to create ssl handle");
|
||||
wpa_printf(MSG_ERROR, "failed to create SSL handle");
|
||||
goto err;
|
||||
}
|
||||
mbedtls_ssl_set_bio(&tls->ssl, conn, tls_mbedtls_write, tls_mbedtls_read, NULL);
|
||||
@@ -1015,7 +1081,7 @@ static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
|
||||
mbedtls_ssl_context *ssl = &conn->tls->ssl;
|
||||
|
||||
if (!ssl) {
|
||||
wpa_printf(MSG_ERROR, "TLS: %s, session ingo is null", __func__);
|
||||
wpa_printf(MSG_ERROR, "TLS: %s, session info is null", __func__);
|
||||
return -1;
|
||||
}
|
||||
if (!mbedtls_ssl_is_handshake_over(ssl)) {
|
||||
@@ -1030,9 +1096,6 @@ static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
|
||||
os_memcpy(seed, conn->randbytes, 2 * TLS_RANDOM_LEN);
|
||||
}
|
||||
|
||||
wpa_hexdump_key(MSG_MSGDUMP, "random", seed, 2 * TLS_RANDOM_LEN);
|
||||
wpa_hexdump_key(MSG_MSGDUMP, "master", ssl->MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(master), TLS_MASTER_SECRET_LEN);
|
||||
|
||||
ret = mbedtls_ssl_tls_prf(conn->tls_prf_type, conn->master_secret, TLS_MASTER_SECRET_LEN,
|
||||
label, seed, 2 * TLS_RANDOM_LEN, out, out_len);
|
||||
|
||||
@@ -1068,12 +1131,9 @@ int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn,
|
||||
|
||||
int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
if (conn->tls_io_data.in_data) {
|
||||
wpabuf_free(conn->tls_io_data.in_data);
|
||||
}
|
||||
conn->tls_io_data.in_data = NULL;
|
||||
tls_mbedtls_reset_in_data(&conn->tls_io_data);
|
||||
|
||||
/* outdata may have dangling pointer */
|
||||
/* Output buffer ownership is transferred to caller before return. */
|
||||
conn->tls_io_data.out_data = NULL;
|
||||
|
||||
return mbedtls_ssl_session_reset(&conn->tls->ssl);
|
||||
|
||||
Reference in New Issue
Block a user