Dear Mbed TLS team,
I am trying to integrate Mbed TLS in our platform:
- nxp imx rt 1024 CPU (arm based)
- FreeRTOS (10.6)
- Lwip (2.2)
- Mbed TLS (3.6.2)
LWIP supports Mbed TLS when adding defines in their configuration:
/* ---------- TLS ------------------------- */
#define LWIP_ALTCP 1
#define LWIP_ALTCP_TLS 1
#define LWIP_ALTCP_TLS_MBEDTLS 1
But, unfortunately this supports an older version of Mbed TLS (I believe 2.2.x).
When I try to compile against the Mbed TLS 3.6.2 libraries, I get a bunch of compiler warnings / errors. Most of them are mentioned in the migration guide, but even then, I have a hard time figuring out how to resolve them "the right way".
1. Private fields
1.1: The altcp_mbed module in LWIP relies on the out_left field of the ssl context struct.
/* calculate TLS overhead part to not send it to application */
overhead = state->overhead_bytes_adjust + state->ssl_context.out_left;
I am correct that this field is simply not exposed through accessor functions? I can find functions like mbedtls_ssl_get_avail, so I would expect something like mbedtls_ssl_get_bytes_to_write or something like that?
1.2: The altcp_mbed module in LWIP relies on the start field of the ssl session struct.
err_t
altcp_tls_set_session(struct altcp_pcb *conn, struct altcp_tls_session *session)
{
if (session && conn && conn->state) {
altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
int ret = -1;
if (session->data.start)
ret = mbedtls_ssl_set_session(&state->ssl_context, &session->data);
return ret < 0 ? ERR_VAL : ERR_OK;
}
return ERR_ARG;
}
I also don't know how to obtain this field "the right way". I know this is a bad idea, but it's all I got
if (session->data.private_start) ...
2. parse key expects a RNG function
This is also explained in the migration guide:
Some functions gained an RNG parameter
This affects users of the following functions: `mbedtls_ecp_check_pub_priv()`,
`mbedtls_pk_check_pair()`, `mbedtls_pk_parse_key()`, and
`mbedtls_pk_parse_keyfile()`.
You now need to pass a properly seeded, cryptographically secure RNG when
calling these functions. It is used for blinding, a countermeasure against
side-channel attacks.
Can you please give me some guidance here? I looked for examples in Mbed TLS repo and ended up with this (bold parts are added, using the key_app.c in your repo as leading example):
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_entropy_init(&entropy);
mbedtls_ctr_drbg_init(&ctr_drbg);
if ((ret = mbedtls_ctr_drbg_seed(
&ctr_drbg,
mbedtls_entropy_func,
&entropy,
privkey,
privkey_len)) != 0) {
// TODO: handle error
}
ret = mbedtls_pk_parse_key(
conf->pkey, privkey,
privkey_len,
privkey_pass,
privkey_pass_len,
mbedtls_ctr_drbg_random,
&ctr_drbg);
3. The altcp_mbed module in LWIP relies on mbedtls_ssl_flush_output
The altcp_mbed module had an include on ssl internal.
#include "mbedtls/ssl_internal.h" /* to call mbedtls_flush_output after ERR_MEM */
This header seems no longer part of the library. But the prototype of the function is now part of ssl_misc.h, but I don't think I am supposed to rely on this header either.
I have a couple of options:
- ignore the compiler warning
/home/dev_container/app/thirdparty/lwip/src/apps/altcp_tls/altcp_tls_mbedtls.c:535:5: warning: implicit declaration of function 'mbedtls_ssl_flush_output'; did you mean 'mbedtls_ssl_tls_prf'? [-Wimplicit-function-declaration]
535 | mbedtls_ssl_flush_output(&state->ssl_context);
- copy paste the declaration in the LWIP source file
- Or.... don't flush any buffers managed by Mbed TLS in the first place?
For the last one, I could really use your input. Can you say anything meaningful about the flush (line in bold) In the below function, Is it mandatory? Or can I trust the Mbed TLS will flush the output buffer whenever it needs to get flushed?
/** Sent callback from lower connection (i.e. TCP)
* This only informs the upper layer the number of ACKed bytes.
* This now take care of TLS added bytes so application receive
* correct ACKed bytes.
*/
static err_t
altcp_mbedtls_lower_sent(void *arg, struct altcp_pcb *inner_conn, u16_t len)
{
struct altcp_pcb *conn = (struct altcp_pcb *)arg;
LWIP_UNUSED_ARG(inner_conn); /* for LWIP_NOASSERT */
if (conn) {
int overhead;
u16_t app_len;
altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
LWIP_ASSERT("state", state != NULL);
LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn);
/* calculate TLS overhead part to not send it to application */
mbedtls_ssl_get_bytes_avail(&state->ssl_context);
overhead = state->overhead_bytes_adjust + state->ssl_context.private_out_left;
if ((unsigned)overhead > len) {
overhead = len;
}
/* remove ACKed bytes from overhead adjust counter */
state->overhead_bytes_adjust -= len;
/* try to send more if we failed before (may increase overhead adjust counter) */
mbedtls_ssl_flush_output(&state->ssl_context); // Does it make sense this LWIP port is responsible for flushing here??
/* remove calculated overhead from ACKed bytes len */
app_len = len - (u16_t)overhead;
/* update application write counter and inform application */
if (app_len) {
state->overhead_bytes_adjust += app_len;
if (conn->sent)
return conn->sent(conn->arg, conn, app_len);
}
}
return ERR_OK;
}
After applying the changes I mentioned above, the software compiles against Mbed TLS. I haven't dared to run anything, I just want to enjoy this short moment where I have the feeling I achieved something before runtime errors ruin my day :).
Many thanks in advance for any reply!
Best regards, Bas