This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

The function modem_key_mgmt_cmp() fails to identify valid certificate

Hi,

I'm running of the fw-nrfconnect-nrf master branch (commit: 96e75dba598320c2707dede3ffef44bf326a89e3) because there are some improvements since the release of SDK v1.2.0 that are of use to me. I'm testing the http_application_update sample in the nrf9160-dk v0.9.0 and modem firmware v1.2.0.

Recently, I have been trying to make use of one of the latest additions: the function modem_key_mgmt_cmp() in the Modem Key Management library. However, on my tests this function is failing to identify valid certificates already commissioned to the modem and always returns 1 (meaning that there is a mismatch between the length of the certificates read from the modem and the ones my app is trying to compare). In fact, this function seems to fail at:

/* Compare the size first, it's cheap */
at_params_size_get(&cmng, AT_CMNG_CONTENT_INDEX, &size);
if (size != len) {
	LOG_DBG("Credential length %d bytes (expected %d)", size, len);
	at_params_list_free(&cmng);
	return 1;
}

This is what I get on the debug console:

D: Credential length 0 bytes (expected 2171)

As the returned length of the certificates in the modem is always 0, I suspect that at_params_size_get() is not returning the correct length for some reason, even though I've checked that the certificates are present in the modem.

The following code snippet can be used to reproduce this behavior:

int cert_provision(const char* cert, const u32_t cert_len, enum modem_key_mgnt_cred_type cred_type)
{
	int err;
	bool exists;
	u8_t unused;

        /* Check if the certificate/key already exists in the modem */
	err = modem_key_mgmt_exists(TLS_SEC_TAG, cred_type, &exists, &unused);
	if (err) {
		printk("Failed to check for certificates err %d\n", err);
		return err;
	}

	if (exists) {         
          /* Check if the certificate/key under the same tag matches the certificate to be provisioned */
          err = modem_key_mgmt_cmp(TLS_SEC_TAG, cred_type, cert, cert_len); 
          if (err) {
            printk("Certificate/key mismatch. Deleting existing certificate/key..., err %d\n", err);
            
            /* Delete the existing certificate/key in case of mismatch */
            err = modem_key_mgmt_delete(TLS_SEC_TAG, cred_type);
            if (err) {
                  printk("Failed to delete existing certificate/key, err %d\n", err);
            }
          } else {
            
            /* The certificate/key already exists in the modem and matches the certificate to be provisioned */
            printk("Valid Certificate/key found.\n");
            return 0;        
          }      
	}     
             
        /* Provision certificate/key to modem */
        printk("Provisioning certificate...\n");

        /*  Provision certificate to the modem */
        err = modem_key_mgmt_write(TLS_SEC_TAG, cred_type, cert, cert_len);
        if (err) {
                printk("Failed to provision certificate/key, err %d\n", err);
                return err;
        }

	return 0;
}

To use the snippet, call:

static const char CA_CERT[] = {
#include "../cert/ca.crt"
}; 
BUILD_ASSERT_MSG(sizeof(CA_CERT) < KB(4), "CA Certificate too large");
static const u32_t CA_CERT_LEN = sizeof(CA_CERT) - 1;

cert_provision(CA_CERT, CA_CERT_LEN, MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN);

Thanks,

Best Regards,

TC

Parents
  • Hi,

    I think I've managed to identify the problem, although I don't have a solution for it yet. 

    After further looking into the Modem Key Management library, I've noticed that the following function call under lib/at_cmd/at_cmd.c is returning a wrong payload length (of 626, significantly less than the certificate's size), which in turn causes the certificates' size comparison to fail:

     

    payload_len = get_return_code(item->data, &ret);

    The function seems to return when it finds the string "OK" in the certificate's content being read from the modem. At a first glance, it seems this function might not be escaping AT command return codes correctly in the certificate's payload string, and gets tricked into returning a wrong length because of that. 

    I believe a modem firmware fix might be necessary before this can be handled, either to do byte stuffing when reading certificates' strings from the modem, or simply by providing the certificate's length in advance and having the function parse a known length.

Reply
  • Hi,

    I think I've managed to identify the problem, although I don't have a solution for it yet. 

    After further looking into the Modem Key Management library, I've noticed that the following function call under lib/at_cmd/at_cmd.c is returning a wrong payload length (of 626, significantly less than the certificate's size), which in turn causes the certificates' size comparison to fail:

     

    payload_len = get_return_code(item->data, &ret);

    The function seems to return when it finds the string "OK" in the certificate's content being read from the modem. At a first glance, it seems this function might not be escaping AT command return codes correctly in the certificate's payload string, and gets tricked into returning a wrong length because of that. 

    I believe a modem firmware fix might be necessary before this can be handled, either to do byte stuffing when reading certificates' strings from the modem, or simply by providing the certificate's length in advance and having the function parse a known length.

Children
No Data
Related