cancel
Showing results for 
Search instead for 
Did you mean: 

[STM32H563] Problems getting MQTT with TLSv1.3 to work using NetXDuo

Sander_UP
Associate III

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?

1 ACCEPTED SOLUTION

Accepted Solutions
Sander_UP
Associate III

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:

  • NX_SECURE_ENABLE_ECC_CIPHERSUITE,
  • NX_SECURE_TLS_TLS_1_3_ENABLED,
  • NX_SECURE_TLS_ENABLE_TLS_1_3.

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!

View solution in original post

2 REPLIES 2
Sander_UP
Associate III

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.h

 From 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?

Sander_UP
Associate III

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:

  • NX_SECURE_ENABLE_ECC_CIPHERSUITE,
  • NX_SECURE_TLS_TLS_1_3_ENABLED,
  • NX_SECURE_TLS_ENABLE_TLS_1_3.

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!