Quality RTOS & Embedded Software

  Real time embedded FreeRTOS RSS feed  
NOTE: The MQTT library and documentation are in the FreeRTOS Labs.  The libraries in the FreeRTOS Labs download directory are fully functional, but undergoing optimizations or refactoring to improve memory usage, modularity, documentation, demo usability, or test coverage.  They are available as part of the main download.

MQTT Demo (with TLS – Mutual Authentication)

Note: We recommend that you always use strong mutual authentication in any Internet of Things (IoT) application. The first project is only provided to validate that MQTT communication can be established prior to introducing encryption and authentication, and to allow the MQTT packets to be observed using a network packet sniffer such as Wireshark, for those who wish to do so. This example uses the recommended mutual authentication and is suitable for production IoT, while the first two projects are not suitable for production use.

Introduction

The MQTT demo project shows you hows you how to establish a connection to an MQTT broker using TLS with mutual authentication between the client and the server.  As most public brokers do not authenticate the client, this demo will showcase a connection to AWS (Amazon Web Services) IoT.  Except for the addition of client authentication by the server, this demo has the same functionality as the basic TLS MQTT demo.  

The 3 MQTT projects documented on these pages introduce the concepts described in the TLS Introduction section one at a time. The first example demonstrates unencrypted MQTT communication, the second example builds on the first to introduce weak server authentication, and the third example (this page) builds on the second to introduce strong mutual authentication.

The MQTT demo project uses the FreeRTOS Windows port, so it can be built and evaluated with the free Community version of Visual Studio on Windows without the need for any particular MCU hardware. 

Source Code Organization

The source code is organized in the same way as the basic MQTT demo (without TLS).

Configure the Demo Project

The demo project is configured in the same manner as the basic MQTT demo (without TLS).

Configure the AWS IoT Demo Profile

The Mutual Authentication MQTT demo requires client authentication in addition to the server authentication required in the MQTT with TLS (Server Auth) demo.  As most public brokers do not authenticate the client, this demo will showcase a connection to AWS (Amazon Web Services) IoT.  Additional steps are required to acquire and set up credentials using existing tools provided by AWS. After you complete the setup steps below, the configuration can be reused with other AWS IoT related demos (coming in a future release) such as the Mutual Authentication HTTPS, AWS Shadow, or AWS Jobs demos. For enhanced security, AWS IoT does not support plaintext and server side only authentication. See Security in AWS.

Follow the steps below for configuring your connection to AWS.  

  1. Set up an Amazon Web Services (AWS) account:
  2. Accounts and permissions are set using AWS Identity and Access Management (IAM). IAM allows you to manage the permissions for each user. By default, no users have permissions until granted by the root owner.
    • To add an IAM user to your AWS account, see the IAM User Guide
    • Set permissions for your AWS account to access AWS FreeRTOS and AWS IoT by adding the policies below: 
        • AmazonFreeRTOSFullAccess
        • AWSIoTFullAccess
    • To attach the AmazonFreeRTOSFullAccess policy to your IAM user:

      1. Browse to the IAM console, and from the navigation pane, choose Users.
      2. Enter your user name in the search text box, and then choose it from the list.
      3. Choose Add permissions.
      4. Choose Attach existing policies directly.
      5. In the search box, enter AmazonFreeRTOSFullAccess, choose it from the list, and then choose Next: Review.
      6. Choose Add permissions.

      To attach the AWSIoTFullAccess policy to your IAM user:

      1. Browse to the IAM console and, from the navigation pane, choose Users.
      2. Enter your user name in the search text box, and then choose it from the list.
      3. Choose Add permissions.
      4. Choose Attach existing policies directly.
      5. In the search box, enter AWSIoTFullAccess, choose it from the list, and then choose Next: Review.
      6. Choose Add permissions.

  1. Register a device as an AWS IoT thing with the AWS Command Line Interface (CLI) or AWS IoT Console.  AWS CLI allows you to perform configurations through the command line instead of through the AWS IoT Console interface.  For more information on setting up CLI, please view additional documentation here.  The AWS IoT console provides a user interface for you to setup a device manually.  

    • Option 1 (recommended): Set up through the AWS Command-Line Interface (CLI):

      1. Download and Install the AWS CLI on your computer.
      2. Install boto3 with pip: pip install boto3
      3. Continue with the steps in Quickly Configuring the AWS CLI to set it up with your AWS account information
      4. Register a device with the provided python script.  The script sets up the MQTT broker (using the “thing” name you entered), downloads the private key, and writes the credentials to FreeRTOS-Plus\Demo\FreeRTOS_IoT_Libraries\include\aws_iot_demo_profile.h

        1. In the file tools\aws_config_quick_start\configure.json change the "$thing_name" to your MQTT client ID. The thing name you enter should be enclosed within double quotes (""), and contain a combination of letters, numbers, semicolons (:), underscores (_), and hyphens (-) only.
        2. To finish setup, open a terminal, navigate to the tools\aws_config_quick_start directory and run: python SetupAWS.py setup

        3. If you used python3 for AWS CLI installation, run: python3 SetupAWS.py setup

    • Option 2: Manually setup a thing through the AWS IoT Console:

      1. Add a device to AWS IoT Console
        1. Follow the steps in creating an IoT thing, private key, and certificate for your device to register an AWS IoT.  Take note of your thing name and AWS IoT endpoint, and download the certificate and key associated with your thing.   

          To find your AWS IoT endpoint:

          1. Browse to the AWS IoT console.
          2. In the navigation pane, choose Settings.

          Your AWS IoT endpoint is displayed as the Endpoint. It should look like <account-number>-ats.iot.<us-east-1>.amazonaws.com.

      2. Once you have completed the setup on the service side, you need to configure credentials for AWS IoT credentials on the client side. The file aws_iot_demo_profile.h holds the information you need to connect your FreeRTOS project to AWS IoT, including endpoints, credentials, and keys set to the appropriate values.  Setup the credentials through the Certificate Configurator by following the steps below:

        1. In a browser window, open tools/aws_config_offline/CertificateConfigurator.html.
        2. Under Thing Name, enter the Thing name you registered on AWS IoT.
        3. Under AWS IoT Thing Endpoint, enter your AWS IoT endpoint.
        4. Under Certificate PEM file, choose the <ID>-certificate.pem.crt that you downloaded from the AWS IoT console.
        5. Under Private Key PEM file, choose the <ID>-private.pem.key that you downloaded from the AWS IoT console.
        6. Choose Generate and save aws_iot_demo_profile.h, and then save the file in FreeRTOS-Plus\Demo\FreeRTOS_IoT_Libraries\include. This overwrites the existing file in the directory.

Build the Demo Project

You build this demo project in the same way as the basic MQTT demo (without TLS).

  • Open the FreeRTOS-Plus\Demo\FreeRTOS_IoT_Libraries\mqtt\mqtt_tls_mutual_auth\mqtt_tls_mutual_auth_demo.sln Visual Studio solution file from within the Visual Studio IDE

Functionality

The demo provides the same functionality as the basic MQTT demo with the addition of secure connection to your AWS IoT.  For details on the additional functionality, please view the basic MQTT demo (without TLS).

Connect to the MQTT Broker (with mutual authentication)

The function prvMQTTConnect() demonstrates how to establish a TLS connection to an MQTT broker with a clean session. It uses the FreeRTOS+TCP network interface which is implemented in the file FreeRTOS-Plus\Source\FreeRTOS-IoT-Libraries\abstractions\platform\freertos\iot_network_freertos.c.

The definition of prvMQTTConnect() is shown below:

static void prvMQTTConnect( void )
{
IotMqttError_t xResult;

  /* Set the context to pass into the disconnect callback function. */
  xNetworkInfo.disconnectCallback.pCallbackContext = ( void * ) xTaskGetCurrentTaskHandle();

  /* Establish the connection to the MQTT broker - It is a blocking call and
   * will return only when connection is complete or a timeout occurs.  The
   * network and connection structures are declared and initialised at the top
   * of this file. */
  xResult = IotMqtt_Connect( &( xNetworkInfo ),
                             &( xConnectInfo ),
                             mqttexampleMQTT_TIMEOUT_MS,
                             &( xMQTTConnection ) );
  configASSERT( xResult == IOT_MQTT_SUCCESS );
}

Where xMQTTBrokerInfo, xNetworkInfo, and xConnectInfo is defined as: 

static const struct IotNetworkServerInfo xMQTTBrokerInfo =
{
  .pHostName = mqttexampleBROKER_ENDPOINT,
  .port = mqttexampleBROKER_PORT
};

static IotMqttNetworkInfo_t xNetworkInfo =
{
  /* No connection to the MQTT broker has been established yet and we want to
   * establish a new connection. */
  .createNetworkConnection = true,
  .u.setup.pNetworkServerInfo = &( xMQTTBrokerInfo ),

  /* Set the TLS credentials for the new MQTT connection. This member is NULL
   * for the plain text MQTT demo. */
  .u.setup.pNetworkCredentialInfo = &xNetworkSecurityCredentials,

  /* Use FreeRTOS+TCP network interface. */
  .pNetworkInterface = IOT_NETWORK_INTERFACE_FREERTOS,

  /* Setup the callback which is called when the MQTT connection is
   * disconnected. The task handle is passed as the callback context which
   * is used by the callback to send a task notification to this task.*/
  .disconnectCallback.function = prvExample_OnDisconnect
};

static const IotMqttConnectInfo_t xConnectInfo =
{
  /* Set this flag to true if connecting to the AWS IoT MQTT broker. */
  .awsIotMqttMode = true,

  /* Start with a clean session i.e. direct the MQTT broker to discard any
   * previous session data. Also, establishing a connection with clean session
   * will ensure that the broker does not store any data when this client
   * gets disconnected. */
  .cleanSession = true,

  /* Since we are starting with a clean session, there are no previous
   * subscriptions to be restored. */
  .pPreviousSubscriptions = NULL,
  .previousSubscriptionCount = 0,

  /* We do not want to publish Last Will and Testament (LWT) message if the
   * client gets disconnected. */
  .pWillInfo = NULL,

  /* Send an MQTT PING request every minute to keep the connection open if
   * there is no other MQTT traffic. */
  .keepAliveSeconds = mqttexampleKEEP_ALIVE_SECONDS,

  /* The client identifier is used to uniquely identify this MQTT client to
   * the MQTT broker.  In a production device the identifier can be something
   * unique, such as a device serial number. */
  .pClientIdentifier = mqttexampleCLIENT_IDENTIFIER,
  .clientIdentifierLength = ( uint16_t ) sizeof( mqttexampleCLIENT_IDENTIFIER ) - 1,

  /* This example does not authenticate the client and therefore username and
   * password fields are not used. */
  .pUserName = NULL,
  .userNameLength = 0,
  .pPassword = NULL,
  .passwordLength = 0
};

The xNetworkSecurityCredentials for adding broker credential is defined as:

static struct IotNetworkCredentials xNetworkSecurityCredentials =
{
  /* Optional TLS extensions. For this demo, they are disabled. */
  .pAlpnProtos = NULL,
  .maxFragmentLength = 0,

  /* SNI is enabled by default. */
  .disableSni = false,

  /* Provide the certificate for validating the server. Only required for
   * demos using TLS. */
  .pRootCa = mqttexampleBROKER_CERTIFICATE_PEM,
  .rootCaSize = sizeof( mqttexampleBROKER_CERTIFICATE_PEM ),

  /* Strong mutual authentication to authenticate both the broker and
   * the client. */
  .pClientCert = mqttexampleCLIENT_CERTIFICATE_PEM,
  .clientCertSize = sizeof( mqttexampleCLIENT_CERTIFICATE_PEM ),
  .pPrivateKey = mqttexampleCLIENT_PRIVATE_KEY_PEM,
  .privateKeySize = sizeof( mqttexampleCLIENT_PRIVATE_KEY_PEM )
};
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.