Golioth has a Reference Design Template that is a great place to start your IoT firmware projects. Based on the nRF9160 Developer Kit, by default it uses Pre-Shared Key (PSK) authentication. But with an eye to production, you should be using Public Key Infrastructure (PKI) which is what I mean when I say “certificates”.
Today, we’ll walk through the process of converting the RD Template to use certificate authentication.
Overview
- Generate the certificate
- Securely store the certificate on the nRF9160
- Configure the application to use “socket offload” to utilize the certificate
1. Generate the certificate
The first step is to generate your certificates.
Today I’m using the scripts in the Golioth Firmware SDK to generate a self-signed root certificate and a device certificate.
Before running the device_certificate script, comment out the lines near the bottom that delete the .pem
files. We’ll need that format when using this approach.
cd modules/lib/golioth-firmware-sdk/scripts/certificates
./generate_root_certificate.sh
./generate_device_certificate.sh developer-training my-unique-device-name
- You only need to generate the self-signed CA certificate once, it may be used to generate as many device certificates as you like.
- IMPORTANT: Upload your self-signed certificate to the
Credentials
→Certificates
section of your Golioth project. (this file is called golioth.crt.pem in my example.)
- IMPORTANT: Upload your self-signed certificate to the
- For each device certificate:
- Supply the project ID that matches your project on Golioth. (developer-training in my example)
- Choose a unique device name, this will be used to identify the device the first time it authenticates with Golioth (my-unique-device-name in my example.)
Additional resources for this section
2. Securely store the certificate on the nRF9160
The nRF9160 has secure storage built right into the hardware that we can use for the PKI. We need to write three things to the device:
- CA Certificate (from Let’s Encrypt, download here): this was used to issue Golioth’s certificates
- Client Certificate: The <servername>-<devicename>.crt.pem file produced in section 1.
- Private Key The <servername>-<devicename>.key.pem file produced in section 1.
To write these values to the nRF9160:
- Build and install the
at_client
sample code from Nordic.- You can do so from the
deps/nrf/samples/cellular/at_client
folder in your RD Template installation, or directly from NCS.
- You can do so from the
- Install the nRF Connect for Desktop tools from Nordic
- Use the Cellular Monitor, clicking on the Certificate Manager tab
- Use the same Security Tag of your choosing while uploading each asset
- Upload each of the three assets one at a time, using the correct entry box for CA Certificate, Client Certificate:, and Private Key.
Additional resources for this section
3. Configure the application to use “socket offload” to utilize the certificate
The Golioth Firmware SDK has an example of how to do this using PSK authentication. We need to use the same approach but with certificate auth. Let’s edit the Reference Design Template accordingly:
-
Edit the prj.conf file
Add a symbol to select certificate auth, and remove symbols for runtime credentials.
# The rest of the runtime credentials config CONFIG_GOLIOTH_AUTH_METHOD_CERT=y #CONFIG_SETTINGS=y #CONFIG_SETTINGS_RUNTIME=y #CONFIG_GOLIOTH_SAMPLE_SETTINGS=y #CONFIG_GOLIOTH_SAMPLE_SETTINGS_AUTOLOAD=y #CONFIG_GOLIOTH_SAMPLE_SETTINGS_SHELL=y
-
Edit the nrf9160dk_nrf9160_ns.conf file
Remove the TLS socket priorities setting from the board file:
# Increase native TLS socket implementation, so that it is chosen instead of # offloaded nRF91 sockets #CONFIG_NET_SOCKETS_TLS_PRIORITY=35
-
Edit main.c to use certificate auth
Finally, we use certificate authentication with the same Security Tag number you chose when uploading assets to the nrf9160. Note that the configuration autoload has been commented out:
/* Get the client configuration from auto-loaded settings */ /*const struct golioth_client_config *client_config = golioth_sample_credentials_get();*/ const struct golioth_client_config client_config = { .credentials = { .auth_type = GOLIOTH_TLS_AUTH_TYPE_TAG, .tag = 1140, } }; /* Create and start a Golioth Client */ client = golioth_client_create(&client_config);
That’s eveything! Build and run your code and your device should be automatically provisioned onto Golioth when it first connects.
Troubleshooting
Here are some common things to check if you need to troubleshoot:
- Ensure your project ID on Golioth matches the one use when generating the device certificate
- Check that you uploaded the self-signed root certificate to your Golioth project
- Check that the Security Tag number you used when uploading to the device matches the one compiled into your code.