Issue:
There seem to be plenty of ways to securely store TLS credentials (generated off the device), or any sort of string data, in persistent storage on an nRF91x device. I would like to know what the recommended and simplest approach is to do this for my application.
We are using an Ethernet network interface along with the nRF9151 internal LTE modem, to communicate with an AWS IoT MQTT broker. I have found out that credentials stored on the modem flash are NOT accessible to the application core, and trying to use AT commands to read these credentials does not work (which makes sense, that would be a big security vulnerability).
I would like to use the same credentials for both the Ethernet and LTE interfaces, and thus it appears I will have to store a copy of the credentials somewhere outside of the modem flash. Ideally I want to use the simplest and most NCS / Zephyr idomatic way to do this, while keeping code bloat from added libraries as small as possible.
What I've done:
I have tried to use the PSA Protected storage library, , following this sample code, but it seems like the keys are too large. The sample works fine on my nRF9151DK board out-of-the-box, but when I replace the test strings with my key, the program crashes only only console logs the boot header. The TF-M PSA Protected Storage README mentions that the PS_MAX_ASSET_SIZE value is how to set the size of a value in the PSA, but I have tried to use CONFIG_PSA_ASSET_SIZE=2048, and it appears this Kconfig symbol does not exist.
psa_protected_storage/prj.conf:10: warning: attempt to assign the value '2048' to the undefined symbol PS_MAX_ASSET_SIZE
I've also looked over the PSA_crypto sample, although that appears to be for handling cyptography and device cert signing, rather than just key-value persistent storage of private data.
I've also read the Key storage in the nRF Connect SDK docs, and they mendion using the PSA crypto API, but I am not sure this is what I am looking for, or if this is the best approach to accomplish this.
Given psa_import_key() fxn seems to import a key in binary format, I am not sure the *.pem type certs would work with this.
I was thinking I could potentially create a seperate 'credential flashing' application, which will run at the factory when device firmware is initally flashed and modem firmware is updated, and put the keys in a seperate directory and source file (like the zephyr aws iot mqtt sample seems to do), and then run the 'credential flashing' application to take those keys and write them to device persistent storage.
It seems like however I get the keys stored on the device securely, at the beginning of the devices life I can use the tls_credentials lib to pull the keys into RAM and assign a security tag to them, allowing me to configure the mqtt clients tls config struct accordingly. As a reference this is the fxn used in the zephyr aws iot mqtt sample:
static int setup_credentials(void)
{
int ret;
ret = tls_credential_add(TLS_TAG_DEVICE_CERTIFICATE, TLS_CREDENTIAL_SERVER_CERTIFICATE,
public_cert, public_cert_len);
if (ret < 0) {
LOG_ERR("Failed to add device certificate: %d", ret);
goto exit;
}
ret = tls_credential_add(TLS_TAG_DEVICE_PRIVATE_KEY, TLS_CREDENTIAL_PRIVATE_KEY,
private_key, private_key_len);
if (ret < 0) {
LOG_ERR("Failed to add device private key: %d", ret);
goto exit;
}
ret = tls_credential_add(TLS_TAG_AWS_CA_CERTIFICATE, TLS_CREDENTIAL_CA_CERTIFICATE, ca_cert,
ca_cert_len);
if (ret < 0) {
LOG_ERR("Failed to add device private key: %d", ret);
goto exit;
}
exit:
return ret;
}
It seems like its 'left to the reader' to figure out how to place the credentials in secure persistent memory / non volatile flash, but however its done, the above approach should allow me to use them with an mqtt client.
Also for reference, I have been following the nRF AWS IoT docs on credential generation (nRF91: Keys generated by AWS), and this has worked fine so far with LTE (because the credentials are then flashed to modem firmware using the nrfcredstore cli utility - but these are not accessible to the application core code).
Dev setup:
OS: Linux Ubuntu 24.04.1
Board: nrf9151DK HW v0.9.0 , AND our custom board built around the nRF9151 SiP
SDK: nRF Connect SDK V3.1.0
All advice, support, and feedback is greatly appreciated!
Thank you Devzone team :)