Hello Community,
I’m facing an issue while trying to establish a secure MQTT connection to the AWS IoT Core MQTT broker using the Quectel BG95-M3 module. My setup involves the following:
Environment Details:
- Module: Quectel BG95-M3
- Protocol: MQTT over TLS (1.2)
- Broker: AWS IoT Core
- SDK: AWS IoT Device SDK for Embedded C
- TLS Library: mbedTLS (from the SDK)
Issue Description:
I am trying to connect to AWS IoT Core using the standard MQTT over TLS workflow:
- Establishing a TCP connection using the
AT+QIOPEN
command AT+QIOPEN=1,0,“TCP”,“–APN–”,8883,0,0. - Initiating the TLS handshake via mbedTLS.
However, the connection randomly fails during the TLS handshake process, and I receive a QICLOSE
from the module. This issue seems to occur intermittently after sending around 877 bytes during the handshake. The exact reason for the QICLOSE
event is unclear.
This is a sequence of handshaking
switch( ssl->state )
{
case MBEDTLS_SSL_HELLO_REQUEST:
ssl->state = MBEDTLS_SSL_CLIENT_HELLO;
break;
/*
* ==> ClientHello
*/
case MBEDTLS_SSL_CLIENT_HELLO:
ret = ssl_write_client_hello( ssl );
break;
/*
* <== ServerHello
* Certificate
* ( ServerKeyExchange )
* ( CertificateRequest )
* ServerHelloDone
*/
case MBEDTLS_SSL_SERVER_HELLO:
ret = ssl_parse_server_hello( ssl );
break;
case MBEDTLS_SSL_SERVER_CERTIFICATE:
ret = mbedtls_ssl_parse_certificate( ssl );
break;
case MBEDTLS_SSL_SERVER_KEY_EXCHANGE:
ret = ssl_parse_server_key_exchange( ssl );
break;
case MBEDTLS_SSL_CERTIFICATE_REQUEST:
ret = ssl_parse_certificate_request( ssl );
break;
case MBEDTLS_SSL_SERVER_HELLO_DONE:
ret = ssl_parse_server_hello_done( ssl );
break;
/*
* ==> ( Certificate/Alert )
* ClientKeyExchange
* ( CertificateVerify )
* ChangeCipherSpec
* Finished
*/
case MBEDTLS_SSL_CLIENT_CERTIFICATE:
ret = mbedtls_ssl_write_certificate( ssl );
break;
case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:
ret = ssl_write_client_key_exchange( ssl );
break;
case MBEDTLS_SSL_CERTIFICATE_VERIFY:
ret = ssl_write_certificate_verify( ssl );
break;
case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC:
ret = mbedtls_ssl_write_change_cipher_spec( ssl );
break;
case MBEDTLS_SSL_CLIENT_FINISHED:
ret = mbedtls_ssl_write_finished( ssl );
break;
/*
* <== ( NewSessionTicket )
* ChangeCipherSpec
* Finished
*/
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
case MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET:
ret = ssl_parse_new_session_ticket( ssl );
break;
#endif
case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC:
ret = mbedtls_ssl_parse_change_cipher_spec( ssl );
break;
case MBEDTLS_SSL_SERVER_FINISHED:
ret = mbedtls_ssl_parse_finished( ssl );
break;
case MBEDTLS_SSL_FLUSH_BUFFERS:
MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP;
break;
case MBEDTLS_SSL_HANDSHAKE_WRAPUP:
mbedtls_ssl_handshake_wrapup( ssl );
break;
default:
MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
Debugging Steps Taken So Far:
- Verified TLS Version:
I confirmed that TLS 1.2 is enabled and configured properly as required by AWS IoT Core.
- mbedTLS settings include proper cipher suites and key exchange algorithms (e.g.,
ECDHE_RSA
,ECDHE_ECDSA
).
- Certificate Verification:
- Using valid AWS IoT X.509 device certificates and Amazon Root CA1.
- Checked that the device certificate matches the Thing’s configuration on AWS IoT Core.
- Checked BG95 AT Logs:
The module logs showQICLOSE
right after sending/receiving approximately 877 bytes during the handshake. It seems like a timeout or resource constraint issue.
Questions to the Community:
- Has anyone experienced similar behavior with the BG95-M3 module, particularly random
QICLOSE
events during the TLS handshake? - Are there any known constraints on the BG95’s TLS buffer size or memory resources that could cause this issue?
- Would enabling TLS debug logs (from mbedTLS) or Quectel’s internal debug logs help pinpoint the root cause? If yes, how can I capture detailed logs?
- Is there a specific AT command sequence or configuration I should ensure for optimal TLS operation on the BG95-M3?
Additional Details:
Here’s a summary of the mbedTLS configuration I’m using:
/* Generate errors if deprecated functions are used. */
#define MBEDTLS_DEPRECATED_REMOVED
/* Place AES tables in ROM. */
#define MBEDTLS_AES_ROM_TABLES
/* Enable the following cipher modes. */
#define MBEDTLS_CIPHER_MODE_CBC
/* Cipher suite configuration. */
#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
#define MBEDTLS_ECP_NIST_OPTIM
#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
/* Enable the following SSL features. */
#define MBEDTLS_SSL_ENCRYPT_THEN_MAC
#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET
#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
#define MBEDTLS_SSL_PROTO_TLS1_2
#define MBEDTLS_SSL_ALPN
#define MBEDTLS_SSL_SERVER_NAME_INDICATION
/* Check certificate key usage. */
#define MBEDTLS_X509_CHECK_KEY_USAGE
#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
/* Disable platform entropy functions. */
#define MBEDTLS_NO_PLATFORM_ENTROPY
/* Enable the following mbed TLS features. */
#define MBEDTLS_AES_C
#define MBEDTLS_ASN1_PARSE_C
#define MBEDTLS_ASN1_WRITE_C
#define MBEDTLS_BASE64_C
#define MBEDTLS_BIGNUM_C
#define MBEDTLS_CIPHER_C
#define MBEDTLS_CTR_DRBG_C
#define MBEDTLS_ECDH_C
#define MBEDTLS_ECDSA_C
#define MBEDTLS_ECP_C
#define MBEDTLS_ENTROPY_C
#define MBEDTLS_GCM_C
#define MBEDTLS_MD_C
#define MBEDTLS_OID_C
#define MBEDTLS_PEM_PARSE_C
#define MBEDTLS_PK_C
#define MBEDTLS_PK_PARSE_C
#define MBEDTLS_PKCS1_V15
#define MBEDTLS_PLATFORM_C
#define MBEDTLS_RSA_C
#define MBEDTLS_SHA256_C
#define MBEDTLS_SSL_CLI_C
#define MBEDTLS_SHA512_C
#define MBEDTLS_SSL_TLS_C
#define MBEDTLS_THREADING_ALT
#define MBEDTLS_THREADING_C
#define MBEDTLS_X509_USE_C
#define MBEDTLS_X509_CRT_PARSE_C
#define MBEDTLS_CERTS_C
Any insights or suggestions would be greatly appreciated. Thank you in advance for your help!