Session is not ressuming MbedTLS handshake problem

int net_sock_open_mbedtls(net_sockhnd_t sockhnd, const char * hostname, int dstport, int localport)
{
int rc = NET_ERR;
net_sock_ctxt_t *sock = (net_sock_ctxt_t * ) sockhnd;
net_tls_data_t * tlsData = sock->tlsData;

/* mbedTLS instance */
int ret = 0;
const unsigned char *pers = (unsigned char *)“net_tls”;

mbedtls_platform_set_calloc_free(heap_alloc, heap_free); /* Common to all sockets. */
mbedtls_ssl_config_init(&tlsData->conf);
mbedtls_ssl_conf_dbg(&tlsData->conf, my_debug, stdout);
mbedtls_ctr_drbg_init(&tlsData->ctr_drbg);
mbedtls_x509_crt_init(&tlsData->cacert);
if (tlsData->tls_dev_cert != NULL)
{
mbedtls_x509_crt_init(&tlsData->clicert);
}
if (tlsData->tls_dev_key != NULL)
{
mbedtls_pk_init(&tlsData->pkey);
}
//0 to 5
mbedtls_debug_set_threshold(2);

mbedtls_entropy_init(&tlsData->entropy);
if( (ret = mbedtls_entropy_add_source(&tlsData->entropy, mbedtls_hardware_poll, (void*)&hrng, 1, MBEDTLS_ENTROPY_SOURCE_STRONG)) != 0 )
{
msg_error( " failed\n ! mbedtls_entropy_add_source returned -0x%x\n", -ret );
internal_close(sock);
return NET_ERR;
}
if( (ret = mbedtls_ctr_drbg_seed(&tlsData->ctr_drbg, mbedtls_entropy_func, &tlsData->entropy, pers, strlen((char const *)pers))) != 0 )
{
msg_error(" failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n", -ret);
internal_close(sock);
return NET_ERR;
}

/* Root CA */
if (tlsData->tls_ca_certs != NULL)
{
if( (ret = mbedtls_x509_crt_parse(&tlsData->cacert, (unsigned char const *)tlsData->tls_ca_certs, strlen((char const *) tlsData->tls_ca_certs) + 1)) != 0 )
{
msg_error(" failed\n ! mbedtls_x509_crt_parse returned -0x%x while parsing root cert\n", -ret);
internal_close(sock);
return NET_ERR;
}
}

if (tlsData->tls_ca_crl != NULL)
{
if( (ret = mbedtls_x509_crl_parse(&tlsData->cacrl, (unsigned char const *)tlsData->tls_ca_crl, strlen((char const *) tlsData->tls_ca_crl) + 1)) != 0 )
{
msg_error(" failed\n ! mbedtls_x509_crt_parse returned -0x%x while parsing the cert revocation list\n", -ret);
internal_close(sock);
return NET_ERR;
}
}

/* Client cert. and key */
if( (tlsData->tls_dev_cert != NULL) && (tlsData->tls_dev_key != NULL) )
{
if( (ret = mbedtls_x509_crt_parse(&tlsData->clicert, (unsigned char const *)tlsData->tls_dev_cert, strlen((char const )tlsData->tls_dev_cert) + 1)) != 0 )
{
msg_error(" failed\n ! mbedtls_x509_crt_parse returned -0x%x while parsing device cert\n", -ret);
internal_close(sock);
return NET_ERR;
}
#ifdef FIREWALL_MBEDLIB
/
Note: The firewall mbedTLS protection does not allow to protect the device private key with a password. /
if( (ret = mbedtls_firewall_pk_parse_key(&tlsData->pkey, (unsigned char const )tlsData->tls_dev_key, (size_t)0 ,
(unsigned char const )"", 0)) != 0 )
{
msg_error(" failed\n ! mbedtls_pk_parse_key returned -0x%x while parsing private key\n\n", -ret);
internal_close(sock);
return NET_ERR;
}
/
the key is converted to an RSA structure here : pk_parse_key_pkcs1_der
the info pointer are changed in pk_wrap.c
/
extern mbedtls_pk_info_t mbedtls_firewall_info;
tlsData->pkey.pk_info = &mbedtls_firewall_info;
#else /
FIREWALL_MBEDLIB */
if( (ret = mbedtls_pk_parse_key(&tlsData->pkey, (unsigned char const *)tlsData->tls_dev_key, strlen((char const *)tlsData->tls_dev_key) + 1,
(unsigned char const )tlsData->tls_dev_pwd, tlsData->tls_dev_pwd_len)) != 0 )
{
msg_error(" failed\n ! mbedtls_pk_parse_key returned -0x%x while parsing private key\n\n", -ret);
internal_close(sock);
return NET_ERR;
}
#endif /
FIREWALL_MBEDLIB */
}

/* TCP Connection */
msg_debug(" . Connecting to %s:%d…", hostname, dstport);
if( (ret = net_sock_create(hnet, &sock->underlying_sock_ctxt, NET_PROTO_TCP)) != NET_OK )
{
msg_error(" failed to create a TCP socket ! net_sock_create returned %d\n", ret);
internal_close(sock);
return NET_ERR;
}

if( (ret = net_sock_setopt(sock->underlying_sock_ctxt, (sock->blocking == true) ? “sock_blocking” : “sock_noblocking”, NULL, 0)) != NET_OK )
{
msg_error(" failed setting the %s option.\n", (sock->blocking == true) ? “sock_blocking” : “sock_noblocking”);
if (net_sock_destroy(sock->underlying_sock_ctxt) != NET_OK )
{
msg_error(“Failed destroying the socket.\n”);
}
internal_close(sock);
return NET_ERR;
}

/* TLS Connection */
if( (ret = mbedtls_ssl_config_defaults(&tlsData->conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
{
msg_error(" failed\n ! mbedtls_ssl_config_defaults returned -0x%x\n\n", -ret);
internal_close(sock);
return NET_ERR;
}

#if 0
mbedtls_ssl_conf_cert_profile(&sock->conf, &mbedtls_x509_crt_XXX_suite);
// TODO: Allow the user to select a TLS profile?
#endif
/* Only for debug

  • mbedtls_ssl_conf_verify(&(tlsDataParams->conf), _iot_tls_verify_cert, NULL); */
    if(tlsData->tls_srv_verification == true)
    {
    mbedtls_ssl_conf_authmode(&tlsData->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
    }
    else
    {
    mbedtls_ssl_conf_authmode(&tlsData->conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
    }

mbedtls_ssl_conf_rng(&tlsData->conf, mbedtls_ctr_drbg_random, &tlsData->ctr_drbg);
mbedtls_ssl_conf_ca_chain(&tlsData->conf, &tlsData->cacert, (tlsData->tls_ca_crl != NULL) ? &tlsData->cacrl : NULL);

if( (tlsData->tls_dev_cert != NULL) && (tlsData->tls_dev_key != NULL) )
{
if( (ret = mbedtls_ssl_conf_own_cert(&tlsData->conf, &tlsData->clicert, &tlsData->pkey)) != 0)
{
msg_error(" failed\n ! mbedtls_ssl_conf_own_cert returned -0x%x\n\n", -ret);
internal_close(sock);
return NET_ERR;
}
}

if( (ret = mbedtls_ssl_setup(&tlsData->ssl, &tlsData->conf)) != 0 )
{
msg_error(" failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", -ret);

if (net_sock_destroy(sock->underlying_sock_ctxt) != NET_OK )
{
  msg_error("Failed destroying the socket.\n");
}
internal_close(sock);
return NET_ERR;

}
if(tlsData->tls_srv_name != NULL)
{
if( (ret = mbedtls_ssl_set_hostname(&tlsData->ssl, tlsData->tls_srv_name)) != 0 )
{
msg_error(" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret);
internal_close(sock);
return NET_ERR;
}
}

if (sock->blocking == true)
{
mbedtls_ssl_conf_read_timeout(&tlsData->conf, sock->read_timeout);
mbedtls_ssl_set_bio(&tlsData->ssl, (void *) sock->underlying_sock_ctxt, mbedtls_net_send, NULL, mbedtls_net_recv_blocking);
}
else
{
mbedtls_ssl_set_bio(&tlsData->ssl, (void *) sock->underlying_sock_ctxt, mbedtls_net_send, mbedtls_net_recv, NULL);
}

msg_debug("\n\nSSL state connect : %d ", sock->tlsData->ssl.state);

if( (ret = net_sock_open(sock->underlying_sock_ctxt, hostname, dstport, localport)) != NET_OK )
{
msg_error(" failed to connect to %s:%d ! net_sock_open returned %d\n", hostname, dstport, ret);
if (net_sock_destroy(sock->underlying_sock_ctxt) != NET_OK )
{
msg_error(“Failed destroying the socket.\n”);
}
internal_close(sock);
return NET_ERR;
}

msg_debug("\n\nSSL state connect : %d “, sock->tlsData->ssl.state);
msg_debug(” . Performing the SSL/TLS handshake…");

while( (ret = mbedtls_ssl_handshake(&tlsData->ssl)) != 0 )
{
if( (ret != MBEDTLS_ERR_SSL_WANT_READ) && (ret != MBEDTLS_ERR_SSL_WANT_WRITE) )
{
if( (tlsData->flags = mbedtls_ssl_get_verify_result(&tlsData->ssl)) != 0 )
{
char vrfy_buf[512];
mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), " ! “, tlsData->flags);
if (tlsData->tls_srv_verification == true)
{
msg_error(“Server verification:\n%s\n”, vrfy_buf);
}
else
{
msg_info(“Server verification:\n%s\n”, vrfy_buf);
}
}
msg_error(” failed\n ! mbedtls_ssl_handshake returned -0x%x\n", -ret);

  if (net_sock_close(sock->underlying_sock_ctxt) != NET_OK )
  {
    msg_error("Failed closing the socket.\n");
  }
  if (net_sock_destroy(sock->underlying_sock_ctxt) != NET_OK )
  {
    msg_error("Failed destroying the socket.\n");
  }
  internal_close(sock);
  
  return (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) ? NET_AUTH : NET_ERR;
}

}

msg_debug(" ok\n [ Protocol is %s ]\n [ Ciphersuite is %s ]\n",
mbedtls_ssl_get_version(&sock->tlsData->ssl),
mbedtls_ssl_get_ciphersuite(&sock->tlsData->ssl));

if( (ret = mbedtls_ssl_get_record_expansion(&tlsData->ssl)) >= 0)
{
msg_debug(" [ Record expansion is %d ]\n", ret);
}
else
{
msg_debug(" [ Record expansion is unknown (compression) ]\n");
}

msg_debug(" . Verifying peer X.509 certificate…");

rc = NET_OK;

return rc;
}

The session is not ressuming. The full handshake is happening at all the time.
Please help me.

Hi @ajmal_interaxis
I am missing in your code the session resumption part.
Where are the calls for mbedtls_ssl_session_save() , mbedtls_ssl_session_reset(), mbedtls_ssl_session_load() and mbedtls_ssl_set_session() in your code?
Please follow the session resumption path in the client example
Regards,
Mbed TLS Support
Ron

1 Like

Hi @roneld01,
Thanks for your reply.
In that code ssl_client2.c they are not updating the variable “opt.reconnect”, I couldn’t find that.

if( opt.reconnect != 0 )
{
mbedtls_printf(" . Saving session for reuse…" );
fflush( stdout );

    if( opt.reco_mode == 1 )
    {
        /* free any previously saved data */
        if( session_data != NULL )
        {
            mbedtls_platform_zeroize( session_data, session_data_len );
            mbedtls_free( session_data );
            session_data = NULL;
        }

        /* get size of the buffer needed */
        mbedtls_ssl_session_save( mbedtls_ssl_get_session_pointer( &ssl ),
                                  NULL, 0, &session_data_len );
        session_data = mbedtls_calloc( 1, session_data_len );
        if( session_data == NULL )
        {
            mbedtls_printf( " failed\n  ! alloc %u bytes for session data\n",
                            (unsigned) session_data_len );
            ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
            goto exit;
        }

        /* actually save session data */
        if( ( ret = mbedtls_ssl_session_save( mbedtls_ssl_get_session_pointer( &ssl ),
                                              session_data, session_data_len,
                                              &session_data_len ) ) != 0 )
        {
            mbedtls_printf( " failed\n  ! mbedtls_ssl_session_saved returned -0x%04x\n\n",
                            -ret );
            goto exit;
        }
    }
    else
    {
        if( ( ret = mbedtls_ssl_get_session( &ssl, &saved_session ) ) != 0 )
        {
            mbedtls_printf( " failed\n  ! mbedtls_ssl_get_session returned -0x%x\n\n",
                            -ret );
            goto exit;
        }
    }

    mbedtls_printf( " ok\n" );

Then how can we save the session?
Please tell me where is the exact place of updating that variable in the code??

HI @ajmal_interaxis

The ssl_client2 is a sample application to be used as an example. it is not a fully functions ssl client.
The opt.reconnect is a parameter given to the application on execution.
If you run the application with reconnect=1, then you will see that when handshake is over, the client savers the session, and the tries to reconnect and resume.
Please follow this example on your client application.(You can simply remove the opt.reconnect option in your code)
Regards,
Ron