ARMmbed / mbed-os

Arm Mbed OS is a platform operating system designed for the internet of things
https://mbed.com
Other
4.67k stars 2.98k forks source link

TCPSocket setup as server faults when recv() is called during TLS handshake #15105

Open blackwiz4rd opened 3 years ago

blackwiz4rd commented 3 years ago

Description of defect

I am trying to build a TLS server for an embedded device (nucleo-144 stm32f429). I took as a guideline this example from mbedos (https://github.com/ARMmbed/mbed-os-example-tls/blob/master/tls-client/HelloHttpsClient.cpp) and readapted it with this example from mbedtls (https://github.com/ARMmbed/mbedtls/blob/development/programs/ssl/ssl_server.c). The TCPSocket is established and works fine. However, during the handshake procedure, the device produces an error. I have ensured that the client is sending the "Client Hello" correctly and that the embedded device does not answer anymore after that.

I also ensured that if the embedded device works as a Client the device produces no faults.

++ MbedOS Fault Handler ++

FaultType: HardFault

Context:
R   0: 20008EB0
R   1: 2000D198
R   2: 00000005
R   3: FFFFFFFF
R   4: 2000D198
R   5: 00000000
R   6: 00000005
R   7: 00000005
R   8: 08041BB5
R   9: 08041C70
R  10: FFFF9800
R  11: 08041A40
R  12: 00000001
SP   : 20005598
LR   : 08007D9F
PC   : FFFFFFFE
xPSR : 61000000
PSP  : 20005530
MSP  : 2002FFD0
CPUID: 410FC241
HFSR : 40000000
MMFSR: 00000001
BFSR : 00000000
UFSR : 00000000
DFSR : 00000000
AFSR : 00000000
Mode : Thread
Priv : Privileged
Stack: PSP

-- MbedOS Fault Handler --

++ MbedOS Error Info ++
Error Status: 0x80FF013D Code: 317 Module: 255
Error Message: Fault exception
Location: 0xFFFFFFFE
Error Value: 0x200001B0
Current Thread: main Id: 0x20008190 Entry: 0x80175D1 StackSize: 0x1000 StackMem: 0x200046D0 SP: 0x20005598 
For more info, visit: https://mbed.com/s/error?error=0x80FF013D&tgt=NUCLEO_F439ZI
-- MbedOS Error Info --

= System will be rebooted due to a fatal error =
= Reboot count(=15) reached maximum, system will halt after rebooting =

Target(s) affected by this defect ?

Embedded device

Toolchain(s) (name and version) displaying this defect ?

n/a

What version of Mbed-os are you using (tag or sha) ?

mbed-os-6.14.0

What version(s) of tools are you using. List all that apply (E.g. mbed-cli)

n/a

How is this defect reproduced ?

int Server::run()
{
    int ret;

    /* Configure the TCPSocket */
    if ((ret = configureTCPSocket()) != 0)
        return ret;
    /* Configure Mbed TLS structures */
    if ((ret = configureTlsContexts()) != 0)
         return ret;

    /* Starts a server on a specific port */
    SocketAddress saddr = SocketAddress("0.0.0.0");
    saddr.set_port(4433);

    mbedtls_printf("Bind on %s at port %u\n",
        saddr.get_ip_address(), saddr.get_port());
    if ((ret = socket.bind(saddr)) != NSAPI_ERROR_OK) {
        mbedtls_printf("socket.bind() returned %d\n", ret);
        return ret;
    }

    if ((ret = socket.listen()) != NSAPI_ERROR_OK) {
        mbedtls_printf("socket.listen() returned %d\n", ret);
        return ret;
    }

    accepted_socket = socket.accept();

    SocketAddress test;
    accepted_socket->getpeername(&test);

    mbedtls_printf("getpeername: ip %s on port %u", test.get_ip_address(), test.get_port());

    /* Start the TLS handshake */
    mbedtls_printf("Starting the TLS handshake...\n");
    do {
         mbedtls_printf("handshake start\n");
         ret = mbedtls_ssl_handshake(&ssl);
         mbedtls_printf("handshake end %i\n",ret);
    } while(ret != 0 &&
             (ret == MBEDTLS_ERR_SSL_WANT_READ ||
             ret == MBEDTLS_ERR_SSL_WANT_WRITE));
     if (ret < 0) {
         mbedtls_printf("mbedtls_ssl_handshake() returned -0x%04X\n", -ret);
         return ret;
    }
     mbedtls_printf("Successfully completed the TLS handshake\n");

    return 0;
}

int Server::configureTCPSocket()
{
    int ret;
    EthernetInterface eth;
    eth.disconnect();
    const SocketAddress eth_ip = SocketAddress("192.168.0.3");
    const SocketAddress eth_netmask = SocketAddress("255.255.255.0");
    const SocketAddress eth_gateway = SocketAddress("0.0.0.0");
    eth.set_network(eth_ip, eth_netmask, eth_gateway);
    ret = eth.connect();

    SocketAddress a;
    eth.get_ip_address(&a);
    mbedtls_printf("eth address: %s\n", a.get_ip_address() ? a.get_ip_address() : "None");

    if ((ret = socket.open(&eth)) != NSAPI_ERROR_OK) {
        mbedtls_printf("socket.open() returned %d\n", ret);
        return ret;
    }

    return 0;
}

int Server::configureTlsContexts()
{
    int ret;

    ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
            reinterpret_cast<const unsigned char *>(DRBG_PERSONALIZED_STR),
            strlen(DRBG_PERSONALIZED_STR) + 1);
    if (ret != 0) {
        mbedtls_printf("mbedtls_ctr_drbg_seed() returned -0x%04X\n", -ret);
        return ret;
    }

    ret = mbedtls_x509_crt_parse(&srvcert,
                        reinterpret_cast<const unsigned char *>(SRV_CERT),
                        strlen(SRV_CERT) + 1);
    if (ret != 0) {
        mbedtls_printf("mbedtls_x509_crt_parse() returned -0x%04X\n", -ret);
        return ret;
    }

    ret = mbedtls_x509_crt_parse(&srvcert,
                        reinterpret_cast<const unsigned char *>(CA_CERT),
                        strlen(CA_CERT) + 1);
    if (ret != 0) {
        mbedtls_printf("mbedtls_x509_crt_parse() returned -0x%04X\n", -ret);
        return ret;
    }

    ret = mbedtls_x509_crt_parse(&cacert,
                        reinterpret_cast<const unsigned char *>(CA_CERT),
                        strlen(CA_CERT) + 1);
    if (ret != 0) {
        mbedtls_printf("mbedtls_x509_crt_parse() returned -0x%04X\n", -ret);
        return ret;
    }

    ret =  mbedtls_pk_parse_key(&pvtkey,
                        reinterpret_cast<const unsigned char *>(SRV_PVT_KEY),
                        strlen(SRV_PVT_KEY) + 1, NULL, -1 );
    if (ret != 0) {
        mbedtls_printf("mbedtls_pk_parse_key() returned -0x%04X\n", -ret);
        return ret;
    }

    ret = mbedtls_ssl_config_defaults(&ssl_conf, MBEDTLS_SSL_IS_SERVER,
                                      MBEDTLS_SSL_TRANSPORT_STREAM,
                                      MBEDTLS_SSL_PRESET_DEFAULT);
    if (ret != 0) {
        mbedtls_printf("mbedtls_ssl_config_defaults() returned -0x%04X\n",
                       -ret);
        return ret;
    }

    mbedtls_ssl_conf_ca_chain(&ssl_conf, &cacert, NULL);

    if( ( ret = mbedtls_ssl_conf_own_cert( &ssl_conf, &srvcert, &pvtkey ) ) != 0 )
    {
        mbedtls_printf( "mbedtls_ssl_conf_own_cert() returned %d\n", ret );
        return ret;
    }
    mbedtls_ssl_conf_rng(&ssl_conf, mbedtls_ctr_drbg_random, &ctr_drbg);

    /*
     * It is possible to disable authentication by passing
     * MBEDTLS_SSL_VERIFY_NONE in the call to mbedtls_ssl_conf_authmode()
     */
    mbedtls_ssl_conf_authmode(&ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED);

    /* Configure certificate verification function to clear time/date flags */
    mbedtls_ssl_conf_verify(&ssl_conf, sslVerify, this);

#if HELLO_HTTPS_CLIENT_DEBUG_LEVEL > 0
    mbedtls_ssl_conf_dbg(&ssl_conf, sslDebug, NULL);
    mbedtls_debug_set_threshold(HELLO_HTTPS_CLIENT_DEBUG_LEVEL);
#endif /* HELLO_HTTPS_CLIENT_DEBUG_LEVEL > 0 */

    if ((ret = mbedtls_ssl_setup( &ssl, &ssl_conf)) != 0) {
        mbedtls_printf("mbedtls_ssl_setup() returned -0x%04X\n", -ret);
        return ret;
    }

    mbedtls_ssl_set_bio(&ssl, static_cast<void *>(&accepted_socket), sslSend, sslRecv,
                        NULL);

    return 0;
}

int Server::sslRecv(void *ctx, unsigned char *buf, size_t len)
{
    int ret;
    TCPSocket *s = static_cast<TCPSocket *>(ctx);
    ret = s->recv(buf, len);
    printf("buf recv %s\n", buf);

    return ret;
}

int Server::sslSend(void *ctx, const unsigned char *buf, size_t len)
{
    int ret;
    TCPSocket *s = static_cast<TCPSocket *>(ctx);
    ret = s->send(buf, len);
    printf("buf send %s\n", buf);

    return ret;
}
mbedmain commented 3 years ago

@blackwiz4rd thank you for raising this issue.Please take a look at the following comments:

What toolchain(s) are you using? It would help if you could also specify the versions of any tools you are using?

NOTE: If there are fields which are not applicable then please just add 'n/a' or 'None'. This indicates to us that at least all the fields have been considered. Please update the issue header with the missing information.