Arm Mbed and Pelion Device Management support forum

Using mbedTLS HTTPS in Tiva C series without RTOS

Hi,

I’m trying to implement HTTPS on Tiva c without RTOS which uses LWIP tcp/udp stack.
Since there is no RTOS, I cant use socket APIs in LWIP so I’m having issues to define mbedtls_ssl_set_bio call back functions to send and receive data.

Has anyone implemented like this which can help me? or any ideas which can be implemented in this case?

regards,
Deepak

I guess you mean that you want to use Mbed-OS bare-metal that does not support the Mbed TLS?

Something I’m looking for too and found this using Mbed 2

https://os.mbed.com/teams/ST/code/NTPClient_HelloWorld//file/c710dd7a4242/main.cpp/

I was going start to start with adapting this example using Mbed 2 then move it onto bare-metal.
Perhaps you could try this if your board is supported on Mbed 2.

Hi Paul,

I have bare-metal project on tiva c. Now i’m trying to add mbedTLS to support https post and get in that project.
Tiva C has LWIP TCP stack which does not have socket APIs as my project is bare-metal. Now, for MbedTLS I need callback functions to send and receive data for mbedtls_ssl_set_bio(). Since I cant use socket APIs, I’m looking for functions based on LWIP raw APIs so that I can use mbedTLS in my project.

Do you have any ideas for this situation?

thanks

hi @dpkrai93
You will need to supply your own bio callbacks to Mbed TLS, wrapping the send and recv functions. For example, as mentioned here, your send\recv functions should be able to call your LWIP functions withing.
Regards,
Mbed TLS Support
Ron

Hi Ron,

Thank you for your reply. i know I have to write my own callbacks for Mbed but I’m having issued to integrate LWIP raw functions with Mbed send and recv functions.
Is there any example where its been done or you have some clue how to do it?
this is the only thing I’m stuck at. Issue is happening during SSL handshake.
I’m facing similar issue as this link Mbedtls with LwIP and k64f
Nothing is available in complete threads which can help me.

Anything useful will be great.

Regards,
Deepak

Hi Deepak,
I am sorry, bu I am not aware of any examples.

What similar issue are you facing? Your receive callback returns WANT READ?
What is the specific scenario you are encountering?
Regards

Hi Ron,

The issues that i’m facing are how to integrate my tcp callback functions with my mbed callback functions.

I’m still at beginning stage of this but I have written my functions as this

static int netSend(void *ctx, const unsigned char *buf, size_t len)
{
int ret;
int sd;
err_t eError;

eError = tcp_write(mypcb, buf, len,
                       TCP_WRITE_FLAG_COPY);

//
//  Write data for sending (but does not send it immediately).
//
if(eError == ERR_OK)
{
    //
    // Find out what we can send and send it
    //
    tcp_output(mypcb);
}

return (len);

}

static int netRecv(void *ctx, unsigned char *buf, size_t len)
{

struct tcp_pcb *conn = (struct tcp_pcb *)ctx;

struct pbuf *p;
uint16_t ret;
uint16_t copy_len;
err_t err;

  p = (struct pbuf *)buf;

/* limit number of bytes again to copy from first pbuf in a chain only /
copy_len = (uint16_t)LWIP_MIN(len, p->len);
/
copy the data /
ret = pbuf_copy_partial(p, buf, copy_len, 0);
LWIP_ASSERT(“ret == copy_len”, ret == copy_len);
/
hide the copied bytes from the pbuf */
err = pbuf_header(p, -ret);
LWIP_ASSERT(“error”, err == ERR_OK);
pbuf_free§;

return ret;

}

static err_t
TCPReceive(void *pvArg, struct tcp_pcb *psPcb, struct pbuf *psBuf, err_t iErr)
{

while (psBuf->tot_len > 0) {
  uint16_t recvd_part = (uint16_t)LWIP_MIN(psBuf->tot_len, 0xFFFF);
  tcp_recved(psPcb, recvd_part);
  psBuf->tot_len -= recvd_part;
}
return (ERR_OK);

}

static err_t
TCPSent(void *pvArg, struct tcp_pcb *psPcb, uint16_t ui16Len)
{
return(ERR_OK);
}

Am I going in correct direction or is it something that I’m missing?

When I do the SSL handshake the call flow is like this

netSend -> TCPSent -> TCPReceive -> netRecv

then it goes into fault.

Any idea what needs to be changed or whats wrong in this code?

Regards,
Deepak

HI @dpkrai93

The documentation of mbedtls_ssl_send_t tells:

 * \return         The callback must return the number of bytes sent if any,
 *                 or a non-zero error code.
 *                 If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_WRITE
 *                 must be returned when the operation would block.

So if your send function returns ERR_OK, it probably returns 0 to the TLS callback, which could cause issues.
In addition, in your netSend, you shouldn’t return len in case eError != ERR_OK
Have you managed to work sith an IDE to understand where it crashes?
Regards

Hi Ron,

I understood the MBEDTLS_ERR_SSL_WANT_WRITE issue and made changes in my send function. But i’m still having issues as the handshake crashes.
I need 4 functions to work together which are send, recv callbacks of mbed and send recv callbacks to TCP.

I’m having issues in that. i receive the server hello and cert from the server in TCP receive but i dont know how to write the mbed recv function in accordance with tcp receive so it know what it received and continues the handshake.

this is my mbed send function which I think is correct now.

static int netSend(void *ctx, const unsigned char *buf, size_t len)
{
int ret;
int sd;
err_t eError;

struct tcp_pcb *conn = (struct tcp_pcb *)ctx;

eError = tcp_write(conn, buf, len,
                       TCP_WRITE_FLAG_COPY);

//
//  Write data for sending (but does not send it immediately).
//

if (eError!= ERR_OK) {
   return MBEDTLS_ERR_SSL_WANT_WRITE;
 }
else if(eError == ERR_OK)
{
    tcp_output(conn);
    return (len);
}

}

Can you help me to implement wrapper functions for the send\recv callbacks, calling the lwip API?

Any ideas or example will be great.

Regards,
Deepak

HI Deepak,
It is not clear to me why you need 4 functions.

The send\recv callbacks that you set in mbedtls_ssl_set_bio() should call the same tcp functionality in your platform.
When you send\recv data in Mbed TLS, using mbedtls_ssl_read() and mbedtls_ssl_write() it calls the callbacks, which, inside, read and send data from TCP.
Have you looked at the ssl_client2 example which uses BSD socket? You will need to replace the used bio callbacks to functions using your platfomr’s TCP API.
Regards

Hi Ron,

Currently I have the 4 functions that i was talking about are 2 for tcp call backs when a data is sent through tcp TCPSent is called and when data is received over TCP TCPRecv is called. I may write nothing in those two functions. but as I understand the flow of SSL handshake, mbed uses the netSend and netRecv to do the handshake. So I have written the function to send the data as told in the earlier reply but I dont know how to integrate mbed netRecv function to the TCP connection that is being used.

I went through the ssl_client2 example but i cant use sockets as I dont have an OS.

so, should I just write netSend and netRecv functions for mbedtls_ssl_set_bio() and it will take care of everything? and is my netSend function correct?

https://lwip.fandom.com/wiki/Raw/TCP#Sending_TCP_data this link shows the call flow of lwip tcp connection. If you follow the lwIP Session Establishment (Local lwIP client / remote server) table this is what i’m trying to achieve by also adding mbed.

-Deepak

HI Deepak,

I went through the ssl_client2 example but i cant use sockets as I don’t have an OS.

Yes, I am aware you can’t use sockets, as you don’t have an OS, but this was an example for you to see how you wrap the Transport Layer functions that are defined in the platform( socket API in this example, while in your case it should be the lwIP functionality).
Once you set these callbacks to mbedtls_ssl_set_bio(), and you setup your network functionality ( if needed). then the TLS should be seemless as shown in the example.
Have you looked in this post?
Regards

Hi Ron,

I have seen this post and I understand what you’re saying but there’s a little problem in implementing that.

I’m using LwIP so I have to define a TCP receive callback function which is called every time my tcp connection receives anything.
I used tcp_write in my mbed send function and it send fine, but I don’t have any particular function to read from tcp. After sending client hello, my TCP receive function receives the Server Hello, Certificate info etc. but that is received in TCP receive function which I defined in as TCP callback.

Now the issue is how to integrate TCP receive and Mbed Recv function because mbed recv function isnt reading the server hello and other info to respond correctly and that’s where my connection is failing.

I created my PC as a https server and used wireshark to see the handshake from my device.

Regards

Hi Deepak,
Do you mean event driven bio callbacks?
I believe that your case is similar to an asynchronous non blocking socket.

  • Perhaps have the lwip recv callback put the data in a shared buffer, and Mbed TLS will read from that buffer, when needed?
  • How about implementing the recv as non blocking, and Mbed TLS tries to read from the “socket”, it will either get the data, or the WANT_READ in case no data.
    Regards

Hi Ron,

I did think about this idea and tried to implement it but still no progress in handshake.
this is what I did

struct received_data {

struct tcp_pcb *handshakepcb;
unsigned char payload[2000];
bool recv_flag;

struct pbuf *recv_buf;
uint16_t previous_len;

};

static int netSend(void *ctx, const unsigned char *buf, size_t len)
{
int ret;
int sd;
err_t eError;

struct tcp_pcb *conn = (struct tcp_pcb *)ctx;

eError = tcp_write(conn, buf, len,
                       TCP_WRITE_FLAG_COPY);

//
//  Write data for sending (but does not send it immediately).
//

if (eError!= ERR_OK) {
   return MBEDTLS_ERR_SSL_WANT_WRITE;
 }
else if(eError == ERR_OK)
{
    tcp_output(conn);
    return (len);
}

}

static int netRecv(void *ctx, unsigned char *buf, size_t len)
{
if(handshake.recv_flag==true)
{
memcpy(buf, handshake.payload, len);
return len;
}
else
return MBEDTLS_ERR_SSL_WANT_READ;
}

static err_t
TCPReceive(void *pvArg, struct tcp_pcb *psPcb, struct pbuf *psBuf, err_t iErr)
{
memcpy(handshake.payload, psBuf->payload, psBuf->tot_len);

handshake.handshakepcb=psPcb;
handshake.recv_buf=psBuf;
handshake.recv_flag=true;

tcp_recved(psPcb, psBuf->tot_len);
pbuf_free(psBuf);

return (ERR_OK);

}

Is my netRecv function ok?
or should I be using something else?

Regards,
Deepak

Hi Ron,

I was able to solve the callback issue using a buffer to save the received data.

But now I’m facing a different issue in which when I’m trying to build my code with call to https post function, my flash data is being overwritten by mbed data.

For example I have a structure that i save in flash but the values in that structure are being modified with different values if I include the mbed functions.

Do you have any idea why that might be happening?

Regards,
Deepak