freeRTOS OTA Code Signing Certificate Got Expired

We are using self-signed certificates for code signing our OTA devices. This certificate has expired and we want to update all our devices with the new certificates.

This certificate is hardcoded in the OTA devices which is not allowing us to update it in any other way.
Your help in this matter will be highly appreciated.

Hello Aditi,

Welcome to the FreeRTOS community.

I do not think that the device will allow you to use an expired certificate to update itself. The libraries are designed as such keeping security in mind. I think you might need to update it manually. That being said, I am talking to experts in our team and will get back to you with a definitive answer.

I understand that this may not be very useful to you in your current situation but might help you out in the future - this page outlines how is the device supposed to updated its certificate before it expires: How to manage IoT device certificate rotation using AWS IoT | The Internet of Things on AWS – Official Blog.

Thanks,
Aniruddha

Hello again,

We would like to see the OTA PAL implementation that you are using. That is because most PALs ignore the certificate part and only verify the public key contained in the cert.
If that is the case, then probably you can use the same key to generate a new cert which would work.

Let us know if that helps or you need any more clarification.

Thanks,
Aniruddha

1 Like

Thank you so much, Aniruddha, for the quick response.

Below is the implemented code.

/* Verify the signature of the specified file. */
OtaPalStatus_t otaPal_CheckFileSignature(OtaFileContext_t *const pFileContext)
{
    OtaPalStatus_t result;
    uint32_t ulSignerCertSize;
    void *pvSigVerifyContext;
    uint8_t *pucSignerCert = 0;
    static spi_flash_mmap_handle_t ota_data_map;
    uint32_t mmu_free_pages_count, len, flash_offset = 0;
 
    /* Verify an ECDSA-SHA256 signature. */
    if (CRYPTO_SignatureVerificationStart(&pvSigVerifyContext, cryptoASYMMETRIC_ALGORITHM_ECDSA,
                                          cryptoHASH_ALGORITHM_SHA256) == pdFALSE)
    {
        LogError(("Signature verification start failed"));
        return OTA_PAL_COMBINE_ERR(OtaPalSignatureCheckFailed, 0);
    }
 
    pucSignerCert = (uint8_t *)codeSigningCertificatePEM;
 
    if (pucSignerCert == NULL)
    {
        LogError(("Cert read failed"));
        return OTA_PAL_COMBINE_ERR(OtaPalBadSignerCert, 0);
    }
    else
    {
        ulSignerCertSize = strlen(codeSigningCertificatePEM) + 1;
    }
 
    mmu_free_pages_count = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA);
    len = ota_ctx.data_write_len;
 
    while (len > 0)
    {
        /* Data we could map in case we are not aligned to PAGE boundary is one page size lesser.
         * 0x0000FFFF is mmap aligned mask for 64K boundary */
        uint32_t mmu_page_offset = ((flash_offset & 0x0000FFFF) != 0) ? 1 : 0;
        /* Read the image that fits in the free MMU pages */
        uint32_t partial_image_len = MIN(len, ((mmu_free_pages_count - mmu_page_offset) * SPI_FLASH_MMU_PAGE_SIZE));
        const void *buf = NULL;
 
        esp_err_t ret = esp_partition_mmap(ota_ctx.update_partition, flash_offset, partial_image_len,
                                           SPI_FLASH_MMAP_DATA, &buf, &ota_data_map);
 
        if (ret != ESP_OK)
        {
            LogError(("Partition mmap failed %d", ret));
            result = OTA_PAL_COMBINE_ERR(OtaPalSignatureCheckFailed, 0);
            goto end;
        }
 
        CRYPTO_SignatureVerificationUpdate(pvSigVerifyContext, buf, partial_image_len);
        spi_flash_munmap(ota_data_map);
        flash_offset += partial_image_len;
        len -= partial_image_len;
    }
 
    if (CRYPTO_SignatureVerificationFinal(pvSigVerifyContext, (char *)pucSignerCert, ulSignerCertSize,
                                          pFileContext->pSignature->data, pFileContext->pSignature->size) == pdFALSE)
    {
        LogError(("Signature verification failed."));
        result = OTA_PAL_COMBINE_ERR(OtaPalSignatureCheckFailed, 0);
    }
    else
    {
        LogInfo(("Signature verification succeeded."));
        result = OTA_PAL_COMBINE_ERR(OtaPalSuccess, 0);
    }
 
end:
 
    return result;
}

Thanks, Aniruddha, for your excellent suggestion. We’ve generated a new certificate using the existing key and successfully imported it into AWS ACM. Following the build creation with this certificate, everything appears to be functioning smoothly.

Appreciate your help.