Is there a way to programmatically set the 'security tag' that the MQTT HELPER library uses? If not, could you provide support for our proposed device provisioning process?

Hello Nordic team. Please let me know if you can provide assistance or advice on this issue. Any help is much appreciated. 

Our issue: 

Myself and my team are wondering if there is any way to programmatically set the security tag that the MQTT HELPER library uses, to determine which TLS credentials are used by the AWS IoT library for communication with AWS IoT core.

To summarize, our current approach to provisioning requires the device to use a set of 'factory flashed' TLS credentials for provisioning itself with the server, and then must use a different set of 'operational' TLS credentials, received from the server through the provisioning request, for nominal operation thereon. The problem is that it seems the AWS IoT core lib has the MQTT Helper lib baked into it, and the MQTT Helper lib appears to only be able to use the security tag defined in the Kconfig symbol 'CONFIG_MQTT_HELPER_SEC_TAG'. After looking over the code, I cannot see any way to set a different security tag for use by the MQTT Helper lib, thus limiting its use to only the security tag value that was assigned at build time (and thus cannot be changed to allows the AWS IoT lib to use any other set of TLS credentials). 

For context, our devices are intented to be installed in remote areas and must be robust, and handle provsioning themselves upon their first boot up and network connection in the field. 

If you have a simpler or perhaps more idiomatic suggestion to handling device provisioning, please let me know, as it seems this has become more complex than I had originally anticipated. 

Overview of our approach to provisioning our devices: 

- All of our devices are pre-flashed (along with the initial firmware image) with a specifc set of TLS credentials, called provisioning credentials which ONLY allow the device to subscribe to a  '/provisioning' MQTT topic, and then publish a '/provision_request' message. The provisioning credentials associated policy has extremely limited permission. 

- Upon first time startup in the field after being installed, the device will connect to a network using the cellular modem, and then connect to our AWS IoT server using the provisioning credentials. The device will then subcribe to the /provisioning topic, and publish a message to the '/provision_request' topic. The message published to the '/provision request' topic, has a payload which contains the device ID (unique for every device). Then the AWS IoT MQTT broker relays the message to an AWS Lambda function, which handles setting up associated tables and configuring a database for that device to send data to, associated with its device ID. 

- The AWS IoT server responds by publishing a message to the 'provisioning' topic associated with that device id, containing a payload with various information, and a new set of operational credentials

- Assuming provisioning was successful, the device should now continue to communicate with the AWS IoT server using these operational credentials. 

BOTH sets of credentials should be stored securely in non volatile memory on the device, so that in the event of power loss, the device does not have to go through the process of provisioning again. Should the device need to perform provisioning again, it will rely on the originally factory flashed provisioning credentials (thus I do not want to overwrite the provisioning credentials).

Because the MQTT Helper does not seem to be able to take a security tag as an argument, and the MQTT Helper must use the security tag defined by Kconfig symbol at build time, I am forced to make inconvenient (hacky?) workarounds, unless there is something I am not aware of or am missing. 

My only options, as far as I can tell: 

1. Setup the firmware, AWS IoT server, and associated Lambda functions so that every time a device connects using the provisioning credentials, the server replies with the devices operational credentials

2. Store both sets of credentials on the device using NVS (or equivalent) lib, with our own managed encryption - to avoid storing keys in plain text on flash 

3. (Really not desirable) Overwrite the provisioning credentials with the newly received operational credentials, to the same security tag id. 

3. (Pretty much not an option for us) Use two seperate firmware builds, one with a Kconfig CONFIG_MQTT_HELPER_SEC_TAG value set to the security tag which holds the provisioning credentials, and a different one which is later flashed after provisioning that uses a Kconfig symbol set to the security tag associated with the operational credentials. 

4. (Again, pretty much not an option given time and resource contstraints) We modify the MQTT Helper lib (and in effect, the AWS IoT lib), and maintain a fork OR we re-write a nearly identical lib entirely for in house use. 

What I've tried / explored so far: 

- I have looked into the Zephyr TLS credential manager lib, but as far as I can tell, it only uses keys stored in RAM, which leaves it relatively useless in our case given we want the values to stay in persistent storage. 

- I have looked into the nrf 'modem key manger' lib, and notices it provides a convenient API (rather than having to use the AT commands myself) to interact with the modem flash (which appears to be where the TLS credentials are stored and indexed via security tag). Unfortunately for our case, certain types of credentials cannot be 'read' back (which makes sense from a security perspective). This means that although I can write the newly received operational credentials to the modem flash with their own different security tag, I cannot read the values back to copy them to a different security tag - thus I am not able to just use the same hardcoded CONFIG_MQTT_HELPER_SEC_TAG security tag as a placeholder for whichever set of credentials I currently want to use. 

- I am acquainted with the settings API and persistent storage libs, so I should not need any help or support with setting up these things. 

My dev setup: 

nRF9151DK , HW: v0.9

nRF Connect SDK  v2.9.1 

Thank you for your support! 

Related