Mbedtls Maybe Running Out of Memory

Hello, I am having trouble making a TLS connection using the mbedtls library. Currently I am getting the error code 0x8100 from the function mbedtls_ssl_setup. However, I have tested an extremely large amount of stack memory and heap memory and I still get this error, which leads me to believe that the problem is elsewhere.

Below is how far I have gotten in the code. I am working my way from the TLS Demo project. I feel like I must have missed something in my setup, but it seems to match the demo. I do not need mutual authentication with the server that I am trying to reach.

static void MQTT_Task( void * pvParameters ) 

{
    LOG_printf( ( "MQTT Task\n" ) );

    uint32_t ulPublishCount = 0U, ulTopicCount = 0U;
    const uint32_t ulMaxPublishCount = 5UL;
    NetworkContext_t xNetworkContext = { 0 };
    TlsTransportParams_t xTlsTransportParams = { 0 };
    NetworkCredentials_t xNetworkCredentials = { 0 };
    MQTTContext_t xMQTTContext = { 0 };
    MQTTStatus_t xMQTTStatus;
    TlsTransportStatus_t xNetworkStatus;

    /* Remove compiler warnings about unused parameters. */
    ( void ) pvParameters;

    /* Set the pParams member of the network context with desired transport. */
    xNetworkContext.pParams = &xTlsTransportParams;

    while(1) {

        LOG_printf( ( "Starting Network Connection\n" ) );

         prvInitializeTopicBuffers();

        if( FreeRTOS_IsNetworkUp() == pdFALSE )
        {
            while( FreeRTOS_IsNetworkUp() == pdFALSE )
            {
                vTaskDelay( pdMS_TO_TICKS( 1000U ) );
                LOG_printf( ( "Waiting for the network link up event...\n" ) );
            }
        }

        xNetworkStatus = TLS_connectToServer( &xNetworkCredentials,
                                                &xNetworkContext );


        Status.TLS = xNetworkStatus;
        LOG_printf( ( "Network = %d...\n", xNetworkStatus) );


    }

}

static TlsTransportStatus_t TLS_connectToServer( NetworkCredentials_t * pxNetworkCredentials,
                                                                  NetworkContext_t * pxNetworkContext )

{
    LOG_printf( ( "TLS Connection to Server\n" ) );

    TlsTransportStatus_t xNetworkStatus;
    BackoffAlgorithmStatus_t xBackoffAlgStatus = BackoffAlgorithmSuccess;
    BackoffAlgorithmContext_t xReconnectParams;
    uint16_t usNextRetryBackOff = 0U;

    TlsTransportParams_t * pTlsTransportParams = NULL;
    //TlsTransportStatus_t returnStatus = TLS_TRANSPORT_SUCCESS;
    BaseType_t socketStatus = 0;
    BaseType_t isSocketConnected = pdFALSE, isTlsSetup = pdFALSE;

    /* Set the credentials for establishing a TLS connection. */
    pxNetworkCredentials->pRootCa = ( const unsigned char * ) democonfigROOT_CA_PEM;
    pxNetworkCredentials->rootCaSize = sizeof( democonfigROOT_CA_PEM );
    pxNetworkCredentials->disableSni = democonfigDISABLE_SNI;

    BackoffAlgorithm_InitializeParams( &xReconnectParams,
                                       mqttexampleRETRY_BACKOFF_BASE_MS,
                                       mqttexampleRETRY_MAX_BACKOFF_DELAY_MS,
                                       mqttexampleRETRY_MAX_ATTEMPTS );

    do 
    {
        LOG_printf( ( "TLS Loop Started\n" ) );

        // ---- Error Checks ----

        if( ( pxNetworkContext == NULL ) ||
            ( pxNetworkContext->pParams == NULL ) ||
            ( democonfigMQTT_BROKER_ENDPOINT == NULL ) ||
            ( pxNetworkCredentials == NULL ) )
            return TLS_TRANSPORT_INVALID_PARAMETER;

        if( ( pxNetworkCredentials->pRootCa == NULL ) )
            return TLS_TRANSPORT_INVALID_PARAMETER;
    
        // ---- Socket Connection ----

        LOG_printf( ( "Connecting to Remote Socket\n" ) );

        pTlsTransportParams = pxNetworkContext->pParams;
        pTlsTransportParams->tcpSocket = NULL;

        socketStatus = Sockets_Connect( &( pTlsTransportParams->tcpSocket ),
                                            democonfigMQTT_BROKER_ENDPOINT,
                                            democonfigMQTT_BROKER_PORT,
                                            mqttexampleTRANSPORT_SEND_RECV_TIMEOUT_MS,
                                            mqttexampleTRANSPORT_SEND_RECV_TIMEOUT_MS );

        if( socketStatus != 0 )
        {
            LOG_printf( ( "Failed to connect to %s with error %d.",
                        democonfigMQTT_BROKER_ENDPOINT,
                        socketStatus ) );
            return TLS_TRANSPORT_CONNECT_FAILURE;
        }
				
				LOG_printf( ( "Connected to Remote Socket\n" ) );

        // ---- TLS Connection MbedTLS ----

        TlsTransportStatus_t TLS_Status = TLS_TRANSPORT_SUCCESS;

        mbedtls_threading_set_alt( mbedtls_platform_mutex_init,
                               mbedtls_platform_mutex_free,
                               mbedtls_platform_mutex_lock,
                               mbedtls_platform_mutex_unlock );

        if(TLS_Status != TLS_TRANSPORT_SUCCESS) {
           LOG_printf( ( "mbedTLS not initalized...\n" ) );
           return TLS_TRANSPORT_CONNECT_FAILURE;
        }

        // ---- SSL ----

        LOG_printf( ( "SSL Connection\n" ) );

        TlsTransportParams_t * pTlsTransportParams = NULL;
        TlsTransportStatus_t returnStatus = TLS_TRANSPORT_SUCCESS;
        int32_t mbedtlsError = 0;

        configASSERT( pxNetworkContext != NULL );
        configASSERT( pxNetworkContext->pParams != NULL );
        configASSERT( democonfigMQTT_BROKER_ENDPOINT != NULL );
        configASSERT( pxNetworkCredentials != NULL );
        configASSERT( pxNetworkCredentials->pRootCa != NULL );

        pTlsTransportParams = pxNetworkContext->pParams;
        SSL_contextInit( &( pTlsTransportParams->sslContext ) );

        mbedtlsError = mbedtls_ssl_config_defaults( &( pTlsTransportParams->sslContext.config ),
                                                MBEDTLS_SSL_IS_CLIENT,
                                                MBEDTLS_SSL_TRANSPORT_STREAM,
                                                MBEDTLS_SSL_PRESET_DEFAULT );

        if( mbedtlsError != 0 )
        {
            LOG_printf( ( "Failed to set default SSL configuration: mbedTLSError...") );

            /* Per mbed TLS docs, mbedtls_ssl_config_defaults only fails on memory allocation. */
            return TLS_TRANSPORT_INSUFFICIENT_MEMORY;
        }                                        

        /* Set up the certificate security profile, starting from the default value. */
        pTlsTransportParams->sslContext.certProfile = mbedtls_x509_crt_profile_default;

        /* Set SSL authmode and the RNG context. */
        mbedtls_ssl_conf_authmode( &( pTlsTransportParams->sslContext.config ),
                                   MBEDTLS_SSL_VERIFY_REQUIRED );
        mbedtls_ssl_conf_rng( &( pTlsTransportParams->sslContext.config ),
                                generateRandomBytes,
                                &pTlsTransportParams->sslContext );
        mbedtls_ssl_conf_cert_profile( &( pTlsTransportParams->sslContext.config ),
                                       &( pTlsTransportParams->sslContext.certProfile ) );

        /* Parse the server root CA certificate into the SSL context. */
        mbedtlsError = mbedtls_x509_crt_parse( &( pTlsTransportParams->sslContext.rootCa ),
                                               pxNetworkCredentials->pRootCa,
                                               pxNetworkCredentials->rootCaSize );
        
        mbedtls_ssl_conf_ca_chain( &( pTlsTransportParams->sslContext.config ),
                                    &( pTlsTransportParams->sslContext.rootCa ),
                                    NULL );
                                               

        if( mbedtlsError != 0 )
        {
            LogError( ( "Failed to parse server root CA certificate.\n" ) );
            return TLS_TRANSPORT_INVALID_CREDENTIALS;
        }

        /* Enable SNI if requested. */
        if( pxNetworkCredentials->disableSni == pdFALSE )
        {
            mbedtlsError = mbedtls_ssl_set_hostname( &( pTlsTransportParams->sslContext.context ),
                                                     democonfigMQTT_BROKER_ENDPOINT );

            if( mbedtlsError != 0 )
            {
                LogError( ( "Failed to set server name: mbedTLSError= %s : %s.",
                            mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
                            mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );

                return  TLS_TRANSPORT_INTERNAL_ERROR;
            }
        }

        /* Set Maximum Fragment Length if enabled. */
        #ifdef MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
            if( returnStatus == TLS_TRANSPORT_SUCCESS )
            {
                /* Enable the max fragment extension. 4096 bytes is currently the largest fragment size permitted.
                * See RFC 8449 https://tools.ietf.org/html/rfc8449 for more information.
                *
                * Smaller values can be found in "mbedtls/include/ssl.h".
                */
                mbedtlsError = mbedtls_ssl_conf_max_frag_len( &( pTlsTransportParams->sslContext.config ), MBEDTLS_SSL_MAX_FRAG_LEN_4096 );

                if( mbedtlsError != 0 )
                {
                    LogError( ( "Failed to maximum fragment length extension...\n") );
                    return TLS_TRANSPORT_INTERNAL_ERROR;
                }
            }
        #endif /* ifdef MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */

        // ---- TLS Handshake ----

        LOG_printf( ( "TLS Handshake\n" ) );

        configASSERT( pxNetworkContext != NULL );
        configASSERT( pxNetworkContext->pParams != NULL );
        configASSERT( pxNetworkCredentials != NULL );

        pTlsTransportParams = pxNetworkContext->pParams;

        mbedtlsError = mbedtls_ssl_setup( &( pTlsTransportParams->sslContext.context ),
                                      &( pTlsTransportParams->sslContext.config ) );

        if( mbedtlsError != 0 )
        {

            return mbedtlsError;
        }     

        /* These two macros MBEDTLS_SSL_SEND and MBEDTLS_SSL_RECV need to be
         * defined in mbedtls_config.h according to which implementation you use.
         */
        mbedtls_ssl_set_bio( &( pTlsTransportParams->sslContext.context ),
                                 ( void * ) pTlsTransportParams->tcpSocket,
                                 mbedtls_platform_send,
                                 mbedtls_platform_recv,
                                 NULL );

         /* Perform the TLS handshake. */
        do
        {
            mbedtlsError = mbedtls_ssl_handshake( &( pTlsTransportParams->sslContext.context ) );
        } while( ( mbedtlsError == MBEDTLS_ERR_SSL_WANT_READ ) ||
                 ( mbedtlsError == MBEDTLS_ERR_SSL_WANT_WRITE ) );

        if( mbedtlsError != 0 )
        {
            return TLS_TRANSPORT_HANDSHAKE_FAILED;
        }
                               
        LOG_printf( ( "Reached end of loop\n" ) );
				
		xNetworkStatus = TLS_TRANSPORT_SUCCESS;

    } while( ( xNetworkStatus != TLS_TRANSPORT_SUCCESS ) && ( xBackoffAlgStatus == BackoffAlgorithmSuccess ) );

    return TLS_TRANSPORT_SUCCESS;

} 

static int generateRandomBytes( void * pvCtx,
                                    unsigned char * pucRandom,
                                    size_t xRandomLength )
{
    /* Must cast from void pointer to conform to mbed TLS API. */
    SSLContext_t * pxCtx = ( SSLContext_t * ) pvCtx;
    CK_RV xResult;

    xResult = pxCtx->pxP11FunctionList->C_GenerateRandom( pxCtx->xP11Session, pucRandom, xRandomLength );

    if( xResult != CKR_OK )
    {
        LogError( ( "Failed to generate random bytes from the PKCS #11 module." ) );
    }

    return (int) xResult;
}

static void SSL_contextInit( SSLContext_t * pSslContext )
{
    configASSERT( pSslContext != NULL );

    mbedtls_ssl_config_init( &( pSslContext->config ) );
    mbedtls_x509_crt_init( &( pSslContext->rootCa ) );
    mbedtls_pk_init( &( pSslContext->privKey ) );
    // mbedtls_x509_crt_init( &( pSslContext->clientCert ) );
    mbedtls_ssl_init( &( pSslContext->context ) );
}

Can you share the logs that you are getting? Also, can you enable debug logging for mbedTLS?

Are you able to use the demo as it is successfully?

Thanks.

Hi,

Yes my demo project was working. I found out the issue. I needed to port the Calloc function for this to work on my hardware and additionally increase my heap size.

Thank you for reporting back your solution.