Raspberry Pi + ATECC608: Part 3 – Using PKCS#11 Token For MQTT Pub-Sub with AWS IoT Core

TLDR: In their run-time engine code, Amazon provides the ability to use PKCS#11 tokens to perform mutual TLS authentication with the cloud. Here, we use Microchip ATECC608 as a PKCS#11 token. By using Microchip’s ATECC608, the act of generating and storing keys and certificates is rendered unnecessary and the device-to-cloud on-boarding is a breeze!

Welcome to part 3 of this series on using Microchip’s ATECC608 with the world’s favourite computer – the Raspberry Pi! In case this is your first time here, do check out Part 1 and Part 2 at the links below.

In this part, we get down and dirty with AWS IoT Device SDK for Python and successfully do a PKCS#11 token-based MQTT Connect and subsequently Pub-Sub with AWS IoT Core.

But first – a recap of Parts 1 and 2!

Quick Recap of Parts 1 and 2

In part 1, we talked about the different variants of Microchip ATECC608 that are available in the market. The variants Trust&GO and TrustFLEX are truly amazing offerings that make the act of mass-producing secure IoT end nodes much simpler and hassle-free. Towards the end of part 1, we learnt about building and installing the cryptoauthlib software as well as libp11 in order to use them both successfully on our Raspberry Pi for talking to the ATECC608-TNGTLS (Trust&GO chip).

In part 2, we underwent a crash-course in PKCS#11 – basically talking about the why, how and what of this standard. We also saw how anyone can go about implementing their own PKCS#11 implementation using the Cryptoki API. You can always use my dummy PKCS#11 Cryptoki implementation as a base and build on it! Towards the end, we saw a common real-world use-case of PKCS#11 tokens – performing mutual authentication with a server. This was done by using Microchip ATECC608-TNGTLS as a PKCS#11 token.

About AWS IoT Core

If you already know about AWS IoT Core, you can safely skip this section! Not skipping? Alright, read on!

AWS IoT Core is a fully-managed IoT service from Amazon that can be tightly integrated with other AWS services. Essentially, it allows you to perform secure, bi-directional communication for your internet-connected devices (such as sensors, actuators, embedded devices, wireless devices, and smart appliances) to connect to the AWS Cloud over MQTT, HTTPS, and LoRaWAN.

Can you design your own IoT service? Yes, absolutely you can!

Why should you use a managed IoT service rather than build your own? Because while designing your own IoT service is possible, it can prove to be resource-intensive, time-taking and maybe even a wasteful exercise if doing cloud software is not your primary competency.

What makes AWS IoT Core a good choice? Amazon has done a decent job of simplifying the act of on-boarding, white-listing, black-listing and removing devices from operation. These are often the most important events in an IoT device’s lifecycle. What are we missing? Communications! AWS IoT Core allows only secure bi-directional communication with IoT devices over MQTT or HTTPS.

What are some alternatives to AWS IoT Core? Microsoft Azure IoT Hub and Device Provisioning Service is a powerful alternative to AWS IoT Core. In fact, the overall penetration of Microsoft into the corporate landscape often gives it the edge. Another alternative is Google Cloud IoT Core. Like everything else from Google, the IoT Core service is pretty simple to use and you are assured similar features as others.

About AWS IoT SDKs

In order to simplify and standardise the process of developing code for your IoT device which will connect to the AWS IoT Core, Amazon offers several SDKs (Software Development Kit). For IoT devices, Amazon offers device SDKs. Similarly, Amazon also offers mobile SDKs that contain software that helps you write applications on various mobile operating systems to connect to the AWS IoT Core. Finally, there is a something called an AWS IoT Device Client that can run on PCs and high-end processor-based devices to enable communication and management operations.

What device SDKs are available? For devices running a high-level OS like a linux distribution, Amazon offers the device SDK in 4 flavours – C++, Java, Python and Javascript. There is also a flavour for constrained devices like microcontrollers that run a real-time operating system or RTOS called Amazon FreeRTOS. This is based on the immensely popular RTOS called FreeRTOS which Amazon purchased a few years back.

What device SDK will we use in this post? We will be using the AWS IoT Device SDK for Python v2 running on a Raspberry Pi in this post. This SDK is located here.

Setting Up Raspberry Pi + ATECC608 as an AWS IoT Thing

An IoT device for us is a thing for AWS IoT Core.

Let us now learn how to set up our Raspberry Pi + ATECC608 hardware as a thing for AWS IoT Core.

  • Log into your AWS account and select the AWS IoT Core service
  • Click on Manage and then Things
  • Click on Create Things button
  • Select Create Single Thing and click Next
  • Enter Thing name as my_rpi_test_thing. We don’t need to configure any other optional feature as of now. Click Next.
  • Click on Upload CSR. We will now generate a CSR or Certificate Signing Request using our ATECC608-TNGTLS.
  • Connect the ATECC608-TNGTLS to the Raspberry Pi and execute the below command to generate the CSR. The below command will generate a CSR named my_rpi_test_thing_csr.csr in the /home/pi folder.
$ openssl req -engine pkcs11 -key "pkcs11:token=00ABC;object=device;type=private" -keyform engine -new -out ~/my_rpi_test_thing.csr -subj "/CN=MY RPI TEST THING"
  • Go back to the AWS IoT Core portal and click on Choose File and select the newly created my_rpi_test_thing_csr.csr file.
  • Select an existing policy if you have that allows an IoT Device to connect to your AWS IoT Core account. If you don’t have one, create one now using this documentation. Once done, click Create Thing.

Once the thing is created, you can select it, navigate to the Certificates tab and download the certificate associated with your thing and rename it to my_rpi_test_thing_crt.crt. We shall use this certificate in the coming steps.

NOTE: For R&D, we set up the device using the dashboard and by generating the CSR individually. For a larger number, it is a good idea to use Microchip’s manifest to securely on-board all devices in one go!

Setting Up AWS IoT Device SDK For Python For Usage

We will set up the SDK in two steps.

Getting the AWS IoT Device SDK for Python

Navigate into any preferred path on your system and clone the AWS IoT Python SDK.

$ git clone https://github.com/aws/aws-iot-device-sdk-python-v2.git

Installing the AWS IoT Device SDK for Python

  • It is recommended to use a virtual environment for your development unless you are confident that installing new packages in not going to break any existing feature.
  • Using Python3 is preferred. This procedure has been tested with Python3 only.

To set up and activate a virtual environment, navigate to the directory where you want the virtual environment to reside and execute the below.

$ python3 -m venv vpython3
$ . vpython3/bin/activate
(vpython3) $

You should now see your bash prompt preceded by the name of your virtual environment surrounded by parentheses (...).

To install the AWS IoT Python SDK, execute the below command.

(vpython3) $ python3 -m pip install path/to/the/aws-iot-device-sdk-python-v2/repo

To check that the installation was successful, run a pip freeze to see what modules the python environment has.

(vpython3) $ pip freeze

Testing PKCS#11 Connect using AWS IoT Device SDK For Python

We are now ready to try out the sample application provided in the SDK. This application simply tries to connect to your AWS endpoint using the private key from the ATECC608-TNGTLS and the certificate provided to the application as an argument. The device certificate is the rpi_test_thing_crt.crt file we downloaded previously.

Navigate into the samples directory of the AWS IoT Python SDK and execute the below command. Remember to do this in an activated virtual environment if the SDK is installed in a virtual environment previously.

(vpython3) $ python3 pkcs11_connect.py --endpoint a************-ats.iot.us-west-2.amazonaws.com --cert ~/my_rpi_test_thing_crt.crt --pkcs11_lib /usr/lib/libcryptoauth.so --token_label 00ABC --key_label device --pin 1234 --client_id my_rpi_test_thing --port 8883 --ca_file ~/AmazonRootCA1.pem --verbosity NoLogs

In the above command

  • Provide your own AWS endpoint – this can be obtained from the thing details on the AWS IoT Core dashboard
  • Provide a CA file in case you get a connection error. The AmazonRootCA1.pem can be obtained from here.

If all goes well, you should see a log as below.

Loading PKCS#11 library '/usr/lib/libcryptoauth.so' ...
Connecting to a************-ats.iot.us-west-2.amazonaws.com with client ID 'my_rpi_test_thing'...

PRO-TIP: You can verify that the connection was done successfully by going back to your AWS IoT Core dashboard and then going to the Monitor page. Refresh the page after a couple of minutes, and you should see that a successful connection was done recently.

Give yourself a pat on the back – you have successfully performed your first successful mutual TLS authentication to AWS IoT Core using ATECC608-TNGTLS!

Using A Custom Application For Doing Pub-Sub After PKCS#11 Connect

Follow the below steps after cloning the below repository.

  • Copy the pkcs11_pubsub.py from this repository into the samples folder of the aws-iot-device-sdk-python-v2 repository
  • In the AWS IoT Core dashboard, open an MQTT client by clicking on Test and then MQTT test client
  • Assuming that the Raspberry Pi will publish to a topic called $aws/things/my_rpi_test_thing/shadow/rpi_publish and will subscribe to a topic called $aws/things/my_rpi_test_thing/shadow/rpi_subscribe, we will subscribe and publish to these topics respectively from the MQTT test client
  • Navigate to the samples directory and execute the below command – ensure that the virtual environment we created before is activated beforehand.
(vpython3) $ python3 pkcs11_pubsub.py --endpoint a************-ats.iot.us-west-2.amazonaws.com --cert ~/my_rpi_test_thing_crt.crt --pkcs11_lib /usr/lib/libcryptoauth.so --token_label 00ABC --key_label device --pin 1234 --client_id my_rpi_test_thing --port 8883 --client_id my_rpi_test_thing --ca_file ~/AmazonRootCA1.pem --verbosity NoLogs --pub_topic rpi_publish --payload "My Message" --num_pub 5 --sub_topic rpi_subscribe --delay_secs 1

If all goes well, you should see logs similar to the below.

Loading PKCS#11 library '/usr/lib/libcryptoauth.so' ...
Connecting to a************-ats.iot.us-west-2.amazonaws.com with client ID 'my_rpi_test_thing'...
Subscribing to topic '$aws/things/my_rpi_test_thing/shadow/rpi_subscribe'...
Subscribed with QoS.AT_LEAST_ONCE
Publishing to topic $aws/things/my_rpi_test_thing/shadow/rpi_publish...
Publishing to topic $aws/things/my_rpi_test_thing/shadow/rpi_publish...
Publishing to topic $aws/things/my_rpi_test_thing/shadow/rpi_publish...
Publishing to topic $aws/things/my_rpi_test_thing/shadow/rpi_publish...
Publishing to topic $aws/things/my_rpi_test_thing/shadow/rpi_publish...
  • Next time you run this application, you can try to publish from the MQTT test client to the topic $aws/things/my_rpi_test_thing/shadow/rpi_subscribe and observe the console prints showing the messages you published.


In this post:

  • We learnt about AWS IoT Core and AWS IoT SDKs.
  • We move on to create an AWS IoT thing whose device private key is within the ATECC608-TNGTLS device. This is done by uploading a CSR (Certificate Signing Request) to AWS IoT Core.
  • We see how to install the the AWS IoT Device SDK for Python on our Raspberry Pi
  • Finally, this Raspberry Pi + ATECC608-TNGTLS setup is used to do a successful MQTT connect and then do pub-sub with the AWS IoT Core service. The TLS handshake for this communication is done by using the ATECC608-TNGTLS as a PKCS#11 token. This is achieved by providing the cryptoauthlib to the AWS IoT Device SDK for Python as a PKCS#11 library.

Leave a Reply