2026-03-02 7:02 AM - edited 2026-03-05 3:48 AM
Hello!
I am facing some problems with implementing TLSv1.3. I have enabled NX_SECURE_TLS_ENABLE_TLS_1_3 and NX_SECURE_TLS_TLS_1_3_ENABLED from CubeMX.
I added these into my code:
extern const NX_SECURE_TLS_CRYPTO nx_crypto_tls_ciphers_ecc;
extern const NX_CRYPTO_METHOD *nx_crypto_ecc_curves[];
extern const UINT nx_crypto_ecc_curves_size;
extern const USHORT nx_crypto_ecc_supported_groups[];
extern const UINT nx_crypto_ecc_supported_groups_size;
// ...
UINT tls_setup_callback(NXD_MQTT_CLIENT *client_pt,
NX_SECURE_TLS_SESSION *TLS_session_ptr,
NX_SECURE_X509_CERT *certificate_ptr,
NX_SECURE_X509_CERT *trusted_certificate_ptr)
{
// ...
/* Initialize TLS module */
nx_secure_tls_initialize();
/* Create a TLS session */
ret = nx_secure_tls_session_create(TLS_session_ptr, &nx_crypto_tls_ciphers_ecc,
crypto_metadata_client, sizeof(crypto_metadata_client));
if (ret != NX_SUCCESS)
{
return ret;
}
/* Force the use of TLS 1.3 */
ret = nx_secure_tls_session_protocol_version_override(TLS_session_ptr, NX_SECURE_TLS_VERSION_TLS_1_3);
if (ret != NX_SUCCESS)
{
return ret;
}
/* Enable ECC cipher suite to be used when using ECC generated keys */
ret = nx_secure_tls_ecc_initialize(TLS_session_ptr,
nx_crypto_ecc_supported_groups,
nx_crypto_ecc_supported_groups_size,
nx_crypto_ecc_curves);
if (ret != NX_SUCCESS)
{
return ret;
}
// ...
}Everything else stayed the same as it was when using TLSv1.2 (which is working).
The tls_setup_callback function finished without issues, but when trying to establish a connection, it will fail due to a handshake error. I also tried connecting with the same client key and certificate using OpenSSL command, and the connection was a success, so the key and certificate are not the issue here.
The program always goes to the NX_SECURE_TLS_ALERT case (in the nx_secure_tls_process_record.c file), where it then returns NX_SECURE_TLS_ALERT_RECEIVED (alert 0x28 (decimal value of 40), which indicates handshake failure).
Also tried to create a separate NX_SECURE_TLS_CRYPTO
const NX_SECURE_TLS_CRYPTO nx_crypto_tls_ciphers_ecc_1_3 =
{
/* Ciphersuite lookup table and size. */
_nx_crypto_ciphersuite_lookup_table_tls_1_3,
_nx_crypto_ciphersuite_lookup_table_tls_1_3_size,
/* X.509 certificate cipher table and size. */
_nx_crypto_x509_cipher_lookup_table_ecc,
_nx_crypto_x509_cipher_lookup_table_ecc_size,
/* TLS version-specific methods. */
/* For TLSv1.0 and TLSv1.1 */
// NULL,
// NULL,
// NULL,
/* For TLSv1.2 */
NULL,
NULL,
/* For TLSv1.3 */
&crypto_method_hkdf,
&crypto_method_hmac,
&crypto_method_ecdhe,
};where _nx_crypto_ciphersuite_lookup_table_tls_1_3 table is using only the TLS_AES_128_GCM_SHA256 cipher, which is definitely supported by the remote server (checked when tried to connect using the OpenSSL command and forcing it to use TLS_AES_128_GCM_SHA256). But no results, same alert level and error.
Is there anything else that needs to be done in the code in order to use TLSv1.3?
Solved! Go to Solution.
2026-03-09 9:08 AM
Alright, found a solution to the problem.
At first, when I was researching about going over to TLSv1.3, my understanding was that TLSv1.3 also supported the RSA CA (Certificate Authority) certificate, but as it turned out that in NetXDuo this is not the case, because it has limited ciphersuites available, which makes it only support ECC (ECDSA) generated (ca and client) certificates and client key.
Now, the only things needed to be done were to enable the following settings from CubeMX:
After setting the certificates up for client and the key, now needed to add them also (before that converted them into C header files just like mentioned in the above post) ->
ret = nx_secure_x509_certificate_initialize(&local_client_certificate, // Structure to initialize
(UCHAR*)ecc_client_crt_der, // Pointer to CLIENT CERTIFICATE data
ecc_client_crt_der_len, // Length of the CLIENT CERTIFICATE data
NX_NULL, 0, // No intermediate certs for client
(UCHAR*)ecc_client_key_der, // Pointer to CLIENT PRIVATE KEY data
ecc_client_key_der_len, // Length of CLIENT PRIVATE KEY data
NX_SECURE_X509_KEY_TYPE_EC_DER); // Type of private key
if (ret != NX_SUCCESS)
{
return ret;
}
/* Add the client Certificate and Key to trusted source */
ret = nx_secure_tls_local_certificate_add(TLS_session_ptr, &local_client_certificate);
if (ret != TX_SUCCESS)
{
return ret;
}and for the CA certification ->
ret = nx_secure_x509_certificate_initialize(trusted_certificate_ptr, // Structure to initialize
(UCHAR*)ecc_ca_crt_der, // Pointer to CA CERTIFICATE data
ecc_ca_crt_der_len, // Length of the CA CERTIFICATE data
NX_NULL, // Not needed
0, // Not needed
NULL, // Not needed
0, // Not needed
NX_SECURE_X509_KEY_TYPE_EC_DER); // Type of private key
if (ret != NX_SUCCESS)
{
return ret;
}
/* Add a CA Certificate to our trusted store */
ret = nx_secure_tls_trusted_certificate_add(TLS_session_ptr, trusted_certificate_ptr);
if (ret != TX_SUCCESS)
{
return ret;
}And now it is working!
2026-03-04 7:50 AM
Some more information regarding testing the TLSv1.3.
The generated ECC client key and certificate were converted into C header files using the following commands (using Git for Windows command line):
# Convert Client certificate
openssl x509 -in client.crt -outform DER -out client.crt.der
# Convert it into C header file
xxd -i client.key.der > client.key.h
# Convert Client key
openssl ec -in client.key -outform DER -out client.key.der
# Convert it into C header file
xxd -i client.crt.der > client.crt.hFrom WireShark logs I can see this:
Transport Layer Security
[Stream index: 74]
TLSv1.2 Record Layer: Alert (Level: Fatal, Description: Handshake Failure)
Content Type: Alert (21)
Version: TLS 1.2 (0x0303)
Length: 2
Alert Message
Level: Fatal (2)
Description: Handshake Failure (40)The WireShark log from "Client Hello" packet:
Transport Layer Security
[Stream index: 74]
TLSv1.2 Record Layer: Handshake Protocol: Client Hello
Content Type: Handshake (22)
Version: TLS 1.2 (0x0303)
Length: 185
Handshake Protocol: Client Hello
Handshake Type: Client Hello (1)
Length: 181
Version: TLS 1.2 (0x0303)
Random: 69a8526aa60c06225e7f03267fe28e37a21ce20588047a3e601dc45e0508f71e
Session ID Length: 0
Cipher Suites Length: 20
Cipher Suites (10 suites)
Compression Methods Length: 1
Compression Methods (1 method)
Extensions Length: 120
Extension: supported_groups (len=8)
Extension: ec_point_formats (len=2)
Extension: supported_versions (len=3) TLS 1.3
Extension: key_share (len=71) secp256r1
Extension: signature_algorithms (len=16)It seems that NetXDuo is still using TLSv1.2 although I enabled TLSv1.3 (and from the WireShark logs it seems that NetXDuo also offers TLSv1.3 support/compatibility). Also, I enabled the setting NX_SECURE_TLS_DISABLE_PROTOCOL_VERSION_DOWNGRADE in CubeMX, but this did not make anything better nor worse.
I also tried increasing the size of crypto_metadata_client and tls_packet_buffer buffer, which also did not make anything better nor worse.
Any help or guidance on what to try or do next would be highly appreciated! Anyone from ST team able to help with this as I am getting out of ideas about what to do?
2026-03-09 9:08 AM
Alright, found a solution to the problem.
At first, when I was researching about going over to TLSv1.3, my understanding was that TLSv1.3 also supported the RSA CA (Certificate Authority) certificate, but as it turned out that in NetXDuo this is not the case, because it has limited ciphersuites available, which makes it only support ECC (ECDSA) generated (ca and client) certificates and client key.
Now, the only things needed to be done were to enable the following settings from CubeMX:
After setting the certificates up for client and the key, now needed to add them also (before that converted them into C header files just like mentioned in the above post) ->
ret = nx_secure_x509_certificate_initialize(&local_client_certificate, // Structure to initialize
(UCHAR*)ecc_client_crt_der, // Pointer to CLIENT CERTIFICATE data
ecc_client_crt_der_len, // Length of the CLIENT CERTIFICATE data
NX_NULL, 0, // No intermediate certs for client
(UCHAR*)ecc_client_key_der, // Pointer to CLIENT PRIVATE KEY data
ecc_client_key_der_len, // Length of CLIENT PRIVATE KEY data
NX_SECURE_X509_KEY_TYPE_EC_DER); // Type of private key
if (ret != NX_SUCCESS)
{
return ret;
}
/* Add the client Certificate and Key to trusted source */
ret = nx_secure_tls_local_certificate_add(TLS_session_ptr, &local_client_certificate);
if (ret != TX_SUCCESS)
{
return ret;
}and for the CA certification ->
ret = nx_secure_x509_certificate_initialize(trusted_certificate_ptr, // Structure to initialize
(UCHAR*)ecc_ca_crt_der, // Pointer to CA CERTIFICATE data
ecc_ca_crt_der_len, // Length of the CA CERTIFICATE data
NX_NULL, // Not needed
0, // Not needed
NULL, // Not needed
0, // Not needed
NX_SECURE_X509_KEY_TYPE_EC_DER); // Type of private key
if (ret != NX_SUCCESS)
{
return ret;
}
/* Add a CA Certificate to our trusted store */
ret = nx_secure_tls_trusted_certificate_add(TLS_session_ptr, trusted_certificate_ptr);
if (ret != TX_SUCCESS)
{
return ret;
}And now it is working!