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
The migration guide explains that most structs are now considered private. 

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




image.png