The coreMQTT mutual authentication demo project shows you how to establish a connection to an MQTT broker using TLS with mutual authentication between the client and the server. This demo uses an mbedTLS-based transport interface implementation to establish a server and client-authenticated TLS connection, and demonstrates the subscribe-publish workflow of MQTT at QoS 1 level. It subscribes to a topic filter, then publishes to topics that match the filter and waits for receipt of those messages back from the server at QoS 1 level. This cycle of publishing to the broker and receiving the same message back from the broker is repeated indefinitely. Messages in this demo are sent at QoS 1, which guarantees at least one delivery according to the MQTT spec.
Note
To set up and run the FreeRTOS demos, follow the steps in Getting Started with FreeRTOS.
The demo source file is named mqtt_demo_mutual_auth.c
and can be found in the freertos/demos/coreMQTT/
directory and the GitHub website.
The demo creates a single application task that loops through a set of examples that demonstrate how to connect to the broker, subscribe to a topic on the broker, publish to a topic on the broker, then finally, disconnect from the broker. The demo application both subscribes to and publishes to the same topic. Each time the demo publishes a message to the MQTT broker, the broker sends the same message back to the demo application.
A successful completion of the demo will generate an output similar to the following image.
The AWS IoT console will generate an output similar to the following image.
The prvBackoffForRetry function shows how failed network operations with the server, for example, TLS connections or MQTT subscribe requests, can be retried with exponential backoff and jitter. The function calculates the backoff period for the next retry attempt, and performs the backoff delay if the retry attempts haven't been exhausted. Because the calculation of the backoff period requires the generation of a random number, the function uses the PKCS11 module to generate the random number. Use of the PKCS11 module allows access to a True Random Number Generator (TRNG) if the vendor platform supports it. We recommended that you seed the random number generator with a device-specific entropy source so that the probability of collisions from devices during connection retries is mitigated.
The prvConnectToServerWithBackoffRetries function attempts to make a mutually authenticated TLS connection to the MQTT broker. If the connection fails, it retries after a backoff period. The backoff period will exponentially increase until the maximum number of attempts is reached or the maximum backoff period is reached. The BackoffAlgorithm_GetNextBackoff
function provides an exponentially increasing backoff value and returns RetryUtilsRetriesExhausted
when the maximum number of attempts has been reached. The prvConnectToServerWithBackoffRetries
function returns a failure status if the TLS connection to the broker can't be established after the configured number of attempts.
The prvCreateMQTTConnectionWithBroker function demonstrates how to establish an MQTT connection to an MQTT broker with a clean session. It uses the TLS transport interface, which is implemented in the FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/src/tls_freertos.c
file. Keep in mind that we're setting the keep-alive seconds for the broker in xConnectInfo
.
The next function shows how the TLS transport interface and time function are set in an MQTT context using the MQTT_Init
function. It also shows how an event callback function pointer (prvEventCallback
) is set. This callback is used for reporting incoming messages.
The prvMQTTSubscribeWithBackoffRetries function demonstrates how to subscribe to a topic filter on the MQTT broker. The example demonstrates how to subscribe to one topic filter, but it's possible to pass a list of topic filters in the same subscribe API call to subscribe to more than one topic filter. Also, in case the MQTT broker rejects the subscription request, the subscription will retry, with exponential backoff, for RETRY_MAX_ATTEMPTS
.
The prvMQTTPublishToTopic function demonstrates how to publish to a topic on the MQTT broker.
The application registers an event callback function before it connects to the broker, as described earlier. The prvMQTTDemoTask
function calls the MQTT_ProcessLoop
function to receive incoming messages. When an incoming MQTT message is received, it calls the event callback function registered by the application. The prvEventCallback function is an example of such an event callback function. prvEventCallback
examines the incoming packet type and calls the appropriate handler. In the example below, the function either calls prvMQTTProcessIncomingPublish()
for handling incoming publish messages or prvMQTTProcessResponse()
to handle acknowledgements (ACK).
The prvMQTTProcessIncomingPublish function demonstrates how to process a publish packet from the MQTT broker.
The last step in the workflow is to unsubscribe from the topic so that the broker won't send any published messages from mqttexampleTOPIC
. Here is the definition of the function prvMQTTUnsubscribeFromTopic.
By default, the FreeRTOS demos use the Amazon Root CA 1 certificate (RSA 2048 bit key) to authenticate with the AWS IoT Core server. It is possible to use other CA certificates for server authentication, including the Amazon Root CA 3 certificate (ECC 256 bit key). To change the root CA for the coreMQTT mutual authentication demo:
-
In a text editor, open the
freertos/vendors/vendor/boards/board/aws_demos/config_files/mqtt_demo_mutual_auth_config.h
file. -
In the file, locate the following line.
* #define democonfigROOT_CA_PEM "...insert here..."
Uncomment this line and, if necessary, move it past the comment block end
*/
. -
Copy the CA certificate that you want to use and then paste it in the
"...insert here..."
text. The result should look like the following example.#define democonfigROOT_CA_PEM "-----BEGIN CERTIFICATE-----\n"\ "MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5\n"\ "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g\n"\ "Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG\n"\ "A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg\n"\ "Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl\n"\ "ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j\n"\ "QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr\n"\ "ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr\n"\ "BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM\n"\ "YyRIHN8wfdVoOw==\n"\ "-----END CERTIFICATE-----\n"
-
(Optional) You can change the root CA for other demos. Repeat steps 1 through 3 for each
freertos/vendors/vendor/boards/board/aws_demos/config_files/demo-name_config.h
file.