You can chat about native SDK questions and issues here.

User avatar
By rith87
#81547 Hello folks,

I am running into an issue with getting HTTPS to work on NONOS v3.0. I've tried the stock libssl and libmbedtls but both of them get stuck after calling espconn_secure_connect(), which in turn fires the following message:

Code: Select allclient handshake start.


I tried building my own version of mbedtls using the source provided by Espressif and still ran into the same failure as above. Tried running at 160 MHz and still the same failure.

It looks like my code is getting stuck in the mbedtls library here:

Code: Select all         if (TLSmsg->ssl.state == MBEDTLS_SSL_HELLO_REQUEST){
            if (Threadmsg->preverse != NULL){
               struct espconn *accept_conn = NULL;
               struct espconn *espconn = Threadmsg->preverse;
               struct sockaddr_in name;
               socklen_t name_len = sizeof(name);
               remot_info *pinfo = NULL;
               espconn_get_connection_info(espconn, &pinfo , ESPCONN_SSL);
               if (espconn->link_cnt == 0x01)
                  return ERR_ISCONN;

               ret = mbedtls_net_accept(&TLSmsg->listen_fd, &TLSmsg->fd, NULL, 0, NULL);
               lwIP_REQUIRE_NOERROR(ret, exit);
               accept_conn = mbedtls_espconn_new();
               lwIP_REQUIRE_ACTION(accept_conn, exit, ret = ERR_MEM);
               Threadmsg->pespconn = accept_conn;
               /*get the remote information*/
               getpeername(TLSmsg->fd.fd, (struct sockaddr*)&name, &name_len);
               Threadmsg->pcommon.remote_port = htons(name.sin_port);
               os_memcpy(Threadmsg->pcommon.remote_ip, &name.sin_addr.s_addr, 4);
               
               espconn->proto.tcp->remote_port = htons(name.sin_port);
               os_memcpy(espconn->proto.tcp->remote_ip, &name.sin_addr.s_addr, 4);
               
               espconn_copy_partial(accept_conn, espconn);               

               /*insert the node to the active connection list*/
               espconn_list_creat(&plink_active, Threadmsg);
               os_printf("server handshake start.\n");
            } else{
               os_printf("client handshake start.\n");
            }
            config_flag = mbedtls_msg_config(TLSmsg);
            if (config_flag){
//               mbedtls_keep_alive(TLSmsg->fd.fd, 1, SSL_KEEP_IDLE, SSL_KEEP_INTVL, SSL_KEEP_CNT);
               system_overclock();
            } else{
               ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
               lwIP_REQUIRE_NOERROR(ret, exit);
            }
         }
         
         system_soft_wdt_stop();
         while ((ret = mbedtls_ssl_handshake(&TLSmsg->ssl)) != 0) {

            if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
               ret = ESPCONN_OK;
               break;
            } else{
               break;
            }
         }
         system_soft_wdt_restart();


While the mbedtls_ssl_handshake loop has disabled the software watchdog, it seems like the handshake process is so slow that it triggers the hardware watchdog. So, after a several seconds, the HW WDT triggers and the ESP reboots.

The same API endpoint works great on the Arduino stack. Both BearSSL and axTLS work fine. However, when digging into the Arduino stack, it looks like they have some magic. The yield() function allows background processes to run and prevents the HW WDT from triggering.

Code: Select allsize_t WiFiClientSecure::write(Stream& stream)
{
    size_t totalSent = 0;
    size_t countRead;
    size_t countSent;
    if (!_ssl)
    {
        return 0;
    }
    do {
        uint8_t temp[256]; // Temporary chunk size same as ClientContext
        countSent = 0;
        countRead = stream.readBytes(temp, sizeof(temp));
        if (countRead) {
            countSent = write(temp, countRead);
            totalSent += countSent;
        }
        yield(); // Feed the WDT
    } while ( (countSent == countRead) && (countSent > 0) );
    return totalSent;
}


So, it seems like I have the following options. Anyone else have better ideas?

    - Port the magic yield() function into NONOS.. Not sure if it is possible?
    - Find the easiest cipher suite that my server supports and pray that the ESP is quick enough to handle it

FYI, here is the list of cipher suites that my server supports. I would guess that AES128-SHA is the most lightweight cipher suite? Anyone knows what that corresponds to in the mbedtls library?

    - ECDHE-ECDSA-AES128-GCM-SHA256
    - ECDHE-RSA-AES128-GCM-SHA256
    - ECDHE-ECDSA-AES128-SHA256
    - ECDHE-RSA-AES128-SHA256
    - ECDHE-ECDSA-AES128-SHA
    - ECDHE-RSA-AES128-SHA
    - ECDHE-ECDSA-AES256-GCM-SHA384
    - ECDHE-RSA-AES256-GCM-SHA384
    - ECDHE-ECDSA-AES256-SHA384
    - ECDHE-RSA-AES256-SHA384
    - ECDHE-RSA-AES256-SHA
    - ECDHE-ECDSA-AES256-SHA
    - AES128-GCM-SHA256
    - AES128-SHA256
    - AES128-SHA
    - AES256-GCM-SHA384
    - AES256-SHA256
    - AES256-SHA
User avatar
By rith87
#81560 Ok, managed to enable logging for the mbedtls library:

Code: Select allclient handshake start.
=> handshake
client state: 0
=> flush output
<= flush output
client state: 1
=> flush output
<= flush output
=> write client hello
client hello, max version: [3:1]
client hello, session id len.: 0
client hello, add ciphersuite: 0035
client hello, add ciphersuite: 002f
client hello, add ciphersuite: 00b7
client hello, add ciphersuite: 0095
client hello, add ciphersuite: 00b6
client hello, add ciphersuite: 0094
client hello, got 7 ciphersuites
client hello, compress len.: 1
client hello, compress alg.: 0
client hello, total extension length: 0
=> write record
output record: msgtype = 22, version = [3:1], msglen = 57
=> flush output
message length: 62, out_left: 62
<= flush output
<= write record
<= write client hello
client state: 2
=> flush output
<= flush output
=> parse server hello
=> read record
=> fetch input
in_left: 0, nb_want: 5
in_left: 0, nb_want: 5
<= handshake
=> handshake
client state: 2
=> flush output
<= flush output
=> parse server hello
=> read record
=> fetch input
in_left: 0, nb_want: 5
in_left: 0, nb_want: 5
<= fetch input
input record: msgtype = 22, version = [3:1], msglen = 81
=> fetch input
in_left: 5, nb_want: 86
in_left: 5, nb_want: 86
<= fetch input
handshake message: msglen = 81, type = 2, hslen = 81
<= read record
server hello, session id len.: 32
no session has been resumed
server hello, chosen ciphersuite: 002f
server hello, compress alg.: 0
server hello, chosen ciphersuite: TLS-RSA-WITH-AES-128-CBC-SHA
server hello, total extension length: 5
found renegotiation extension
<= parse server hello
client state: 3
=> flush output
<= flush output
=> parse certificate
=> read record
=> fetch input
in_left: 0, nb_want: 5
in_left: 0, nb_want: 5
<= fetch input
input record: msgtype = 22, version = [3:1], msglen = 4815
=> fetch input
in_left: 5, nb_want: 4820
in_left: 5, nb_want: 4820
in_left: 1296, nb_want: 4820
<= handshake
=> handshake
client state: 3
=> flush output
<= flush output
=> parse certificate
=> read record
=> fetch input
in_left: 1296, nb_want: 5
<= fetch input
input record: msgtype = 22, version = [3:1], msglen = 4815
=> fetch input
in_left: 1296, nb_want: 4820
in_left: 1296, nb_want: 4820
in_left: 2678, nb_want: 4820
<= handshake
=> handshake
client state: 3
=> flush output
<= flush output
=> parse certificate
=> read record
=> fetch input
in_left: 2678, nb_want: 5
<= fetch input
input record: msgtype = 22, version = [3:1], msglen = 4815
=> fetch input
in_left: 2678, nb_want: 4820
in_left: 2678, nb_want: 4820
in_left: 4060, nb_want: 4820
<= handshake
=> handshake
client state: 3
=> flush output
<= flush output
=> parse certificate
=> read record
=> fetch input
in_left: 4060, nb_want: 5
<= fetch input
input record: msgtype = 22, version = [3:1], msglen = 4815
=> fetch input
in_left: 4060, nb_want: 4820
in_left: 4060, nb_want: 4820
<= fetch input
handshake message: msglen = 4815, type = 11, hslen = 4815
<= read record
<= parse certificate
client state: 4
=> flush output
<= flush output
=> parse server key exchange
<= skip parse server key exchange
client state: 5
=> flush output
<= flush output
=> parse certificate request
=> read record
=> fetch input
in_left: 0, nb_want: 5
in_left: 0, nb_want: 5
<= fetch input
input record: msgtype = 22, version = [3:1], msglen = 4
=> fetch input
in_left: 5, nb_want: 9
in_left: 5, nb_want: 9
<= fetch input
handshake message: msglen = 4, type = 14, hslen = 4
<= read record
got no certificate request
<= parse certificate request
client state: 6
=> flush output
<= flush output
=> parse server hello done
<= parse server hello done
client state: 7
=> flush output
<= flush output
=> write certificate
<= skip write certificate
client state: 8
=> flush output
<= flush output
=> write client key exchange

 ets Jan  8 2013,rst cause:4, boot mode:(3,6)

wdt reset
load 0x40100000, len 1328, room 16
tail 0
chksum 0x38
load 0x3ffe8000, len 632, room 8
tail 0
chksum 0x5c
csum 0x5c
User avatar
By rith87
#81564 Looks like it was a memory related issue. I removed this huge malloc statement and now the handshake completes. Unfortunately, looks like connection still fails:

Code: Select allclient handshake ok!
Connected
=> write
=> write record
=> encrypt buf
before encrypt: msglen = 256, including 16 bytes of IV and 12 bytes of padding
<= encrypt buf
output record: msgtype = 23, version = [3:3], msglen = 256
=> flush output
message length: 261, out_left: 261
ssl->f_send
<= flush output
<= write record
<= write
Sending request header
Feed WDTSending request body
Send ESP=> write
=> write record
=> encrypt buf
before encrypt: msglen = 208, including 16 bytes of IV and 5 bytes of padding
<= encrypt buf
output record: msgtype = 23, version = [3:3], msglen = 208
=> flush output
message length: 213, out_left: 213
ssl->f_send
<= flush output
<= write record
<= write
Sent ESPAll sent
=> read
=> read record
=> fetch input
in_left: 0, nb_want: 5
in_left: 0, nb_want: 5
ssl->f_recv(_timeout)
<= fetch input
input record: msgtype = 23, version = [3:3], msglen = 256
=> fetch input
in_left: 5, nb_want: 261
in_left: 5, nb_want: 261
ssl->f_recv(_timeout)
<= fetch input
=> decrypt buf
<= decrypt buf
<= read record
<= read
=> read
=> read record
=> fetch input
in_left: 0, nb_want: 5
in_left: 0, nb_want: 5
ssl->f_recv(_timeout)
mbedtls_ssl_fetch_input
mbedtls_ssl_read_record
=> read
=> read record
=> fetch input
in_left: 0, nb_want: 5
in_left: 0, nb_want: 5
ssl->f_recv(_timeout)
<= fetch input
input record: msgtype = 23, version = [3:3], msglen = 192
=> fetch input
in_left: 5, nb_want: 197
in_left: 5, nb_want: 197
ssl->f_recv(_timeout)
<= fetch input
=> decrypt buf
<= decrypt buf
<= read record
<= read
=> read
=> read record
=> fetch input
in_left: 0, nb_want: 5
in_left: 0, nb_want: 5
ssl->f_recv(_timeout)
mbedtls_ssl_fetch_input
mbedtls_ssl_read_record
client's data invalid protocol
=> write close notify
=> send alert message
=> write record
=> encrypt buf
before encrypt: msglen = 64, including 16 bytes of IV and 14 bytes of padding
<= encrypt buf
output record: msgtype = 21, version = [3:3], msglen = 64
=> flush output
message length: 69, out_left: 69
ssl->f_send
<= flush output
<= write record
<= send alert message
<= write close notify
Reason:[-0x7880]
=> free
<= free
Disconnected with error
Disconnected