cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H563 MQTT establishing a connection to a remote server

Sander_UP
Associate III

Hello!

I am facing a problem when trying to connect to a remote server using NetXDuo and MQTT. We have a cloud service with which we want to establish a connection so we can send some data. I am basing my project on the example from the STMH573 MQTT Client. The exact problem I am facing is that when trying to establish the connection using the username and password, and the certificates an error occurs, when trying to secure connect. I get these two TSL alerts - alert level is 0x2 and alert value 0x28 (secure connection failed to be established). Using TLSv1.2.

What I did:

  • Converting CA certificate to the header file format 
openssl x509 -in ca.crt -outform DER -out ca.der
# Then convert into the header file format using xxd.exe
xxd.exe -i ca.der > ca.cert.h​
  • Converting client certificate to the header file format 
openssl x509 -in client.crt -outform DER -out client.der
# Then converting it into the header file format
xxd.exe -i client.der > client.cert.h​
  • Converting client key to the header file format 
openssl rsa -outform der -in client.key -traditional -out client.key.der
# Then converting it into the header file format
xxd.exe -i client.key.der > client.key.h​
  • Added username and password (those are correct, checked). After the secure connection, error is returned - 0x10005 (NXD_MQTT_CONNECT_FAILURE).
/* Before connecting, send the username and password to log in */
ret = nxd_mqtt_client_login_set(&MqttClient, MQTT_USERNAME, MQTT_USERNAME_LEN, MQTT_PASSWORD, MQTT_PASSWORD_LEN);
if (ret != NX_SUCCESS)
{
  Error_Handler();
}

/* Start a secure connection to the server. */
ret = nxd_mqtt_client_secure_connect(&MqttClient, &mqtt_server_ip, MQTT_PORT, tls_setup_callback,
                                       MQTT_KEEP_ALIVE_TIMER, CLEAN_SESSION, NX_WAIT_FOREVER);​
  • From the client example project we have the nx_secure_x509_certificate_initialize function that I used to initialize the CA certificate 
ret = nx_secure_x509_certificate_initialize(trusted_certificate_ptr, 
                                              (UCHAR*)ca_der,                               // Pointer to CLIENT CERTIFICATE data
                                              ca_der_len,                                   // Length of the CLIENT CERTIFICATE data
                                              NX_NULL, 
                                              0, 
                                              NULL,                                         // Pointer to CLIENT PRIVATE KEY data
                                              0,                                            // Length of CLIENT PRIVATE KEY data
                                              NX_SECURE_X509_KEY_TYPE_NONE);                // Type of private key

ret = nx_secure_tls_trusted_certificate_add(TLS_session_ptr, trusted_certificate_ptr);
if (ret != TX_SUCCESS)
{
  Error_Handler();
}​
  • Then I added another nx_secure_x509_certificate_initialize function to initialize the client certificate and the client key 
ret = nx_secure_x509_certificate_initialize(&local_client_certificate, 
                                              (UCHAR*)client_der,                       // Pointer to CLIENT CERTIFICATE data
                                              client_der_len,                           // Length of the CLIENT CERTIFICATE data
                                              NX_NULL, 0, 
                                              (UCHAR*)client_key_der,                   // Pointer to CLIENT PRIVATE KEY data
                                              client_key_der_len,                       // Length of CLIENT PRIVATE KEY data
                                              NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER);   // Type of private key​

ret = nx_secure_tls_trusted_certificate_add(TLS_session_ptr, &local_client_certificate);
if (ret != TX_SUCCESS)
{
  Error_Handler();
}
  • Also, enabled the NX_SECURE_ENABLE_ECC_CIPHERSUITE, NX_SECURE_TLS_TLS_1_2_ENABLED, NX_SECURE_TLS_USE_SCSV_CIPHPERSUITE (enabled for testing purposes, did not see anything different) and NX_SECURE_ENABLE_AEAD_CIPHER flags from CubeMX.
  • Checked with OpenSSL what kind of cipher is needed - TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384.
  • Still getting the same alert. Then, if I understood correctly, I need to initialize also the ciphers and the curves 
extern const USHORT           nx_crypto_ecc_supported_groups[];
extern const UINT             nx_crypto_ecc_supported_groups_size;
extern const NX_CRYPTO_METHOD *nx_crypto_ecc_curves[];

ret = nx_secure_tls_ecc_initialize(TLS_session_ptr,
                                    nx_crypto_ecc_supported_groups,
                                    nx_crypto_ecc_supported_groups_size,
                                    nx_crypto_ecc_curves);​

After all that I am still facing the same problem - unable to establish a connection. What else have I done:

  • Checked DNS - working.
  • Checked SNTP - working/correct.
  • Checked DHCP - working/correct.
  • Using openssl to try to establish a connection to the remote server using TSLv1.2 - connection was correctly established, which means that the CA and client certificate, and the client key are correct.
  • Using PAHO (Python) to establish the connection with the same credentials - working.
  • Converting the credentials to PEM format and then into the header file format - did not work.
  • Tried enabling and using TLSv1.3 - same problems/alerts.

Where the program fails is here - 

if (client_ptr -> nxd_mqtt_client_use_tls)
    {

        status = nx_secure_tls_session_start(&(client_ptr -> nxd_mqtt_tls_session), &(client_ptr -> nxd_mqtt_client_socket), wait_option);

        if (status != NX_SUCCESS)
        {

            /* Revert thread priority. */
            tx_thread_priority_change(tx_thread_identify(), old_priority, &old_priority);

            /* End connection. */
            _nxd_mqtt_client_connection_end(client_ptr, NX_NO_WAIT);

            return(NXD_MQTT_CONNECT_FAILURE);
        }
    }

returning error code 0x114 (NX_SECURE_TLS_ALERT_RECEIVED) - The remote host sent an alert, indicating an error and closing the connection. This from the nxd_mqtt_client.c file.

 

I am not sure what else to do and to test. Any help or guidance is appreciated!

2 REPLIES 2
Sander_UP
Associate III

I managed to fix one of the issues, which is related to adding the client certificate and the client key. The solution was using the nx_secure_tls_local_certificate_add instead of the nx_secure_tls_trusted_certificate_add.

ret = nx_secure_x509_certificate_initialize(&local_client_certificate, 
                                              (UCHAR*)client_der,                       // Pointer to CLIENT CERTIFICATE data
                                              client_der_len,                           // Length of the CLIENT CERTIFICATE data
                                              NX_NULL, 0, 
                                              (UCHAR*)client_key_der,                   // Pointer to CLIENT PRIVATE KEY data
                                              client_key_der_len,                       // Length of CLIENT PRIVATE KEY data
                                              NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER);   // Type of private key​

ret = nx_secure_tls_local_certificate_add(TLS_session_ptr, &local_client_certificate);
if (ret != TX_SUCCESS)
{
  Error_Handler();
}

 

Now, there is the issue when publishing the message, and the program gets stuck here:

/* Wait for the broker to publish the message. */
tx_event_flags_get(&mqtt_app_flag, DEMO_ALL_EVENTS, TX_OR_CLEAR, &events, TX_WAIT_FOREVER);

It seems that the message has been published, but not sure why the program gets stuck here. Is it because there is still some settings missing or wrong configuration on NetXDuo side? Or is it that the remote server, that did receive the published message, did not respond for some reason?

Sander_UP
Associate III

Hello!

The previous problem came from the fact that in my code I tried to subscribe to a topic that did not exist. Now, I uncommented all the code that deals with the subscribing. After that, I can send/publish messages to the remote server.

But at random times, the program just hangs and does not send anymore. When this happens I usually get the NXD_MQTT_PACKET_POOL_FAILURE (0x10006 code) error. My packet size pool is set to 20 packets. Does it mean that the packet pool will be filled at some point, due to which the system cannot handle anymore packets? If I understood NetXDuo correctly, then every time I receive the PUBACK from the remote server, the packet pool is emptied, in which case my previous assumption is incorrect.

Also, at some points the connection is dropped (I strongly believe that is caused by NetXDuo as we have another system sending MQTT packets, which does not loose the connection). But I tried to create a function that tries to reconnect, but the second time DNS function nx_dns_host_by_name_get is called, it returns an error - NX_DNS_QUERY_FAILED (0xA3).

In summary, program gets stuck at some point and not sending anymore packets or when the connection drops, and when trying to reconnect, I am unable to do so. Are these problems connected somehow or are these separate issues in my code?

 

All the ideas and help would be much appreciated!

 

Edit 1: I also noticed that in the NetXDuo section, some priorities seem to be a little off. What I mean by this is for example the NX_APP_THREAD_PRIORITY is set to 10, but MQTT_PRIORITY and SNTP_PRIORITY have these priorities - 3 and 5, respectively. Should not NX_APP_THREAD_PRIORITY have the highest priority of them all, because it deals with IP level things?