nrf5340 qspi has encountered question

Hi All.

Now I use soc:nrf5340, and ncs v2.9.0

I use QSPI to encrypt my external flash memory.
Adding some print functions in xxx_encrypt can ensure that it is encrypted only once and there are no changes in between

#ifdef CONFIG_MCUBOOT_ENC_EXT_FLASH
#define NONCE_CTX "test_string"
#include <hw_unique_key.h>
#include <nrfx_qspi.h>

static bool encrypt_completed = false;
int encrypt_external_flash(void)
{
    nrf_qspi_encryption_t encrypt_param = {0};
    uint8_t label[3] = {0}; // Label used for both key and nonce
    int ret = 0;

    if (encrypt_completed) {
        printk("External flash encryption already done.\n");
        return NRFX_SUCCESS;
    }

    if (!hw_unique_key_are_any_written())
        hw_unique_key_write_random();

    // Derive the key
    uint8_t key_context[16] = {0};
    memcpy(key_context, CONFIG_BOARD, strlen(CONFIG_BOARD));
    ret = hw_unique_key_derive_key(HUK_KEYSLOT_MEXT,
                                    key_context, sizeof(key_context),
                                    label, sizeof(label),
                                    (uint8_t *)encrypt_param.key, sizeof(encrypt_param.key));
    if (ret)
    {
        printk("derive board key error: %d\n", ret);
        return ret;
    }

    // Derive the nonce
    uint8_t nonce_context[32] = {0};
    memcpy(nonce_context, NONCE_CTX, strlen(NONCE_CTX));
    ret = hw_unique_key_derive_key(HUK_KEYSLOT_MEXT,
                                    nonce_context, sizeof(nonce_context),
                                    label, sizeof(label),
                                    (uint8_t *)encrypt_param.nonce, sizeof(encrypt_param.nonce));
    if (ret)
    {
        printk("derive nonce ctx key error: %d\n", ret);
        return ret;
    }

    // Perform encryption with DMA
    ret = nrfx_qspi_dma_encrypt(&encrypt_param);
    if (ret != NRFX_SUCCESS)
    {
        printk("nrfx_qspi_dma_encrypt error: %d\n", ret);
        return ret;
    }

    // Perform encryption with XIP
    ret = nrfx_qspi_xip_encrypt(&encrypt_param);
    if (ret != NRFX_SUCCESS)
    {
        printk("nrfx_qspi_xip_encrypt error: %d\n", ret);
        return ret;
    }

    MCUBOOT_WATCHDOG_FEED();

    encrypt_completed = true;
    printk("External flash encryption completed successfully.\n");
    return NRFX_SUCCESS;
}

SYS_INIT(encrypt_external_flash, POST_KERNEL, 42);
#endif /*CONFIG_MCUBOOT_ENC_EXT_FLASH*/

I found that during the Bluetooth upgrade process, the values written by the "boot_write_magic" function and the values read back were not consistent.

This is using flash_area_write and flash_area_read. This function seems to be using the encryption engine of the underlying QSPI, right?

When I tried to write the hexadecimal numbers from 0x1 to 0x10, the values read out were also inconsistent.

Of course, disabling QSPI encryption will definitely not cause any problems.

However, according to my understanding, the erasure process does not utilize the QSPI encryption engine, as it involves physical-level erasure rather than data stream processing.
This ordinary read/write operation should automatically invoke the encryption and decryption functions of QSPI, right?

Looking forward to reply. Thanks

Parents
  • In the img_mgmt_erase_image_data function located in zephyr\subsys\mgmt\mcumgr\grp\img_mgmt\src\zephyr_img_mgmt.c, the flash_area_write/read operations are normal and the data is consistent.

    but in the boot_write_magic function located in bootloader\mcuboot\boot\bootutil\src\bootutil_public.c, it was not work.the flash_area_write/read operations are normal and the data is inconsistent.

    bootloader\mcuboot\boot\zephyr\main.c, Is everything work normal here?

    SYS_INIT(encrypt_external_flash, POST_KERNEL, 42);

     

  • Hello,

    Since this is currently not supported in the driver I'm not sure how this HW feature is supposed to be used, but it seems to me that the issue is that the wrong nounce is used when encrypting and decrypting the image trailer data. 

    Could it be an option to disable the stream cipher when reading or writing image trailer data?

    Best regards,

    Vidar

  • Yes, you can write to a location that is all 0xFFs. However, if your application first writes 0xFFs, the actual flash content will not remain 0xFFs because the data is passed through the stream cipher before it's written.

  • Yes, you can write to a location that is all 0xFFs. However, if your application first writes 0xFFs, the actual flash content will not remain 0xFFs because the data is passed through the stream cipher before it's written.

    I mean is that I enabled QSPI encryption and wrote 0xFF. Therefore, the actual content stored in the memory is also 0xFF.

    At this point, if I write in other data such as magic val, the value read out will be different from the one I have written.

    read operation:
    read magc : 0xFF, 0xFF ... , 0xFF
    
    write operatoin:
    writing magic; fa_id=23 off=0xe1ff0 (0x2e1ff0)
    0x77 0xc2 0x95 0xf3 0x60 0xd2 0xef 0x7f 0x35 0x52 0x50 0x0f 0x2c 0xb6 0x79 0x80 
    
    read operation:
    read magic; fa_id=23 off=0xe1ff0 (0x2e1ff0)
    0x77 0xc3 0xb5 0xf3 0xfa 0xf2 0xef 0x7f 0xf5 0xf6 0xf9 0x8f 0x3c 0xfe 0xff 0xc0 

    What's going on here?

  • I mean is that I enabled QSPI encryption and wrote 0xFF. Therefore, the actual content stored in the memory is also 0xFF.

    No, the 0xFF plaintext will be encrypted, and the ciphertext will be stored in flash. 

    At this point, if I write in other data such as magic val, the value read out will be different from the one I have written.

    This will happen if you write to a non-erased location.

  • Ok I got it.  If QSPI encryption is enabled, the data written will be the encrypted value(ciphertext) rather than the plaintext(0xFF).

    At this point, if I write in other data such as magic val, the value read out will be different from the one I have written.

    So maybe the stored value has 0's  that it can't flip and then I got the wrong value.

    So currently, when performing flash operations during the Bluetooth DFU process (such as checking if the flash has been erased and writing new values), do I need to manually erase that partition again and again?

  • The problem is the bootutil functions expect the flash to read 0xFFs if the area is erased. A possible solution is to modify the bootutil_public.c source to run the bootutil_buffer_is_erased() check both with and without the QSPI encryption enabled. 

Reply Children
No Data
Related