how to handle expired SSL CA certificates in nrf9160

Dear Nordic,

The SSL certificate is hard-coded, it means that the certificate is stored in the source code folder and cannot be changed without a firmware update.
This can be problematic because SSL certificates typically have an expiration date, after which they are no longer valid.
If the certificate is expired, the device may not be able to establish a secure connection with the server, which can lead to security issues and service disruptions.

My environment

Device: nrf9160 customized one

SDK - ncs v1.9.1

I would like to know, is there any way to handle expired SSL CA certificate and update it programatically without upgrading the firmware? (FOTA).
Currently our SSL CA cerificate renewed every year.
I also know that, it is recommended to use SSL certificates with a sufficiently long validity period,
so that they do not expire frequently.

carrie_certs.c

#include <stdint.h>
#include <string.h>
#include <toolchain.h>
#include <sys/util.h>
#include <modem/modem_key_mgmt.h>
#include <logging/log.h>

#include "carrier_certs.h"
#include "ex_common.h"

#define TLS_MC_API_SEC_TAG	42
#if 0
#define TLS_FOTA_SEC_TAG	43
#endif //end if 0

#if 0
static int tags[] = { TLS_MC_API_SEC_TAG, TLS_FOTA_SEC_TAG };
#endif //end if 0

static const char ca42[] = {
	/* API certificate */
#if 0	
	#include "./certs/api.cer" 
#else
	#include "./certs/api_2023_12_24.cer"
#endif
};

#if 0
static const char ca43[] = {
	/* FOTA server certificate */
	#include "./certs/fota.cer"
};
#endif //end if 0

BUILD_ASSERT(sizeof(ca42) < KB(4), "Cert is too large");
#if 0
BUILD_ASSERT(sizeof(ca43) < KB(4), "Cert is too large");
#endif //end if 0

static const struct {
	uint16_t tag;
	const char *data;
} certs[] = {
	{
		.tag = TLS_MC_API_SEC_TAG,
		.data = ca42,
	},
	#if 0
	{
		.tag = TLS_FOTA_SEC_TAG,
		.data = ca43,
	}
	#endif //end if 0
};

int carrier_certs_provision()
{
	int err;
	bool mismatch = 0;
	bool provisioned;

	for (int i = 0; i < ARRAY_SIZE(certs); i++) {
		err = modem_key_mgmt_exists(
			certs[i].tag, MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN, &provisioned);
		if (err) {
			goto cert_exit_empty;
		}

		if (provisioned) {
			err = modem_key_mgmt_cmp(
				certs[i].tag, MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN,
				certs[i].data, strlen(certs[i].data));

			/* 0 on match, 1 otherwise; like memcmp() */
			mismatch = err;

			LOG_DBG("Certificate found, tag %d: %s", certs[i].tag,
				mismatch ? "mismatch" : "match");
		} else {
			LOG_DBG("Certificate tag %d not found", certs[i].tag);
		}

		if (mismatch || !provisioned) {
			/* overwrite the certificate */
			err = modem_key_mgmt_write(
				certs[i].tag, MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN,
				certs[i].data, strlen(certs[i].data));
			if (err) {
				MLOG_ERROR("Unable to provision certificate, error: %d", err);		
			}

			LOG_DBG("Certificate provisioned, tag %d", certs[i].tag);
		}
	}

	return 0;

cert_exit_empty:
	return -1;
	
}



Any help will be appreciated.

Best Regards

Praveen Deshmane

Parents Reply
  • Hi Praveen. 

    In order to implement some sort of method to update the certificates, you will need to implement this into you firmware. E.g. rotate SSL certificates using the Modem Key Manager.

    The main thing to consider when implementing this type of solution is the security aspect. You must ensure that you can download the certs in safe manner. For inspiration you can have a look at this commit, please see the README for more information. Here 

    new certificates from AWS are stored in the non secure partition and is not recommended for production.
    You could use MQTT and subscribe to e.g. <deviceID>/certs, where new certificates are pushed once time is closing in on an update/expired certs. Then the application can download and provision new certificates using the modem_key_manager library. 
    Kind regards,
    Øyvind
Children
Related