mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
esp_flash: add support for encrypted read and write
Using legacy implementation.
This commit is contained in:
parent
5e0cc123ee
commit
b9a2639ab4
@ -569,28 +569,27 @@ esp_err_t IRAM_ATTR esp_flash_write(esp_flash_t *chip, const void *buffer, uint3
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//currently the legacy implementation is used, from flash_ops.c
|
||||||
|
esp_err_t spi_flash_write_encrypted(size_t dest_addr, const void *src, size_t size);
|
||||||
|
|
||||||
esp_err_t IRAM_ATTR esp_flash_write_encrypted(esp_flash_t *chip, uint32_t address, const void *buffer, uint32_t length)
|
esp_err_t IRAM_ATTR esp_flash_write_encrypted(esp_flash_t *chip, uint32_t address, const void *buffer, uint32_t length)
|
||||||
{
|
{
|
||||||
VERIFY_OP(write_encrypted);
|
/*
|
||||||
if (((memspi_host_data_t*)chip->host->driver_data)->spi != 0) {
|
* Since currently this feature is supported only by the hardware, there
|
||||||
// Encrypted operations have to use SPI0
|
* is no way to support non-standard chips. We use the legacy
|
||||||
return ESP_ERR_FLASH_UNSUPPORTED_HOST;
|
* implementation and skip the chip and driver layers.
|
||||||
|
*/
|
||||||
|
if (chip == NULL) {
|
||||||
|
chip = esp_flash_default_chip;
|
||||||
|
} else if (chip != esp_flash_default_chip) {
|
||||||
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
if (buffer == NULL || address > chip->size || address+length > chip->size) {
|
if (buffer == NULL || address > chip->size || address+length > chip->size) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
return spi_flash_write_encrypted(address, buffer, length);
|
||||||
esp_err_t err = spiflash_start(chip);
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = chip->chip_drv->write_encrypted(chip, buffer, address, length);
|
|
||||||
|
|
||||||
return spiflash_end(chip, err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline static IRAM_ATTR bool regions_overlap(uint32_t a_start, uint32_t a_len,uint32_t b_start, uint32_t b_len)
|
inline static IRAM_ATTR bool regions_overlap(uint32_t a_start, uint32_t a_len,uint32_t b_start, uint32_t b_len)
|
||||||
{
|
{
|
||||||
uint32_t a_end = a_start + a_len;
|
uint32_t a_end = a_start + a_len;
|
||||||
@ -598,6 +597,23 @@ inline static IRAM_ATTR bool regions_overlap(uint32_t a_start, uint32_t a_len,ui
|
|||||||
return (a_end > b_start && b_end > a_start);
|
return (a_end > b_start && b_end > a_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//currently the legacy implementation is used, from flash_ops.c
|
||||||
|
esp_err_t spi_flash_read_encrypted(size_t src, void *dstv, size_t size);
|
||||||
|
|
||||||
|
esp_err_t IRAM_ATTR esp_flash_read_encrypted(esp_flash_t *chip, uint32_t address, void *out_buffer, uint32_t length)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Since currently this feature is supported only by the hardware, there
|
||||||
|
* is no way to support non-standard chips. We use the legacy
|
||||||
|
* implementation and skip the chip and driver layers.
|
||||||
|
*/
|
||||||
|
if (chip == NULL) {
|
||||||
|
chip = esp_flash_default_chip;
|
||||||
|
} else if (chip != esp_flash_default_chip) {
|
||||||
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
return spi_flash_read_encrypted(address, out_buffer, length);
|
||||||
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
Adapter layer to original api before IDF v4.0
|
Adapter layer to original api before IDF v4.0
|
||||||
|
@ -247,17 +247,34 @@ esp_err_t esp_flash_write(esp_flash_t *chip, const void *buffer, uint32_t addres
|
|||||||
|
|
||||||
/** @brief Encrypted and write data to the SPI flash chip using on-chip hardware flash encryption
|
/** @brief Encrypted and write data to the SPI flash chip using on-chip hardware flash encryption
|
||||||
*
|
*
|
||||||
* @param chip Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()
|
* @param chip Pointer to identify flash chip. Must be NULL (the main flash chip). For other chips, encrypted write is not supported.
|
||||||
* @param address Address on flash to write to. 16 byte aligned. Must be previously erased (SPI NOR flash can only write bits 1->0).
|
* @param address Address on flash to write to. 16 byte aligned. Must be previously erased (SPI NOR flash can only write bits 1->0).
|
||||||
* @param buffer Pointer to a buffer with the data to write.
|
* @param buffer Pointer to a buffer with the data to write.
|
||||||
* @param length Length (in bytes) of data to write. 16 byte aligned.
|
* @param length Length (in bytes) of data to write. 16 byte aligned.
|
||||||
*
|
*
|
||||||
* @note Both address & length must be 16 byte aligned, as this is the encryption block size
|
* @note Both address & length must be 16 byte aligned, as this is the encryption block size
|
||||||
*
|
*
|
||||||
* @return ESP_OK on success, or a flash error code if operation failed.
|
* @return
|
||||||
|
* - ESP_OK: on success
|
||||||
|
* - ESP_ERR_NOT_SUPPORTED: encrypted write not supported for this chip.
|
||||||
|
* - ESP_ERR_INVALID_ARG: Either the address, buffer or length is invalid.
|
||||||
|
* - or other flash error code from spi_flash_write_encrypted().
|
||||||
*/
|
*/
|
||||||
esp_err_t esp_flash_write_encrypted(esp_flash_t *chip, uint32_t address, const void *buffer, uint32_t length);
|
esp_err_t esp_flash_write_encrypted(esp_flash_t *chip, uint32_t address, const void *buffer, uint32_t length);
|
||||||
|
|
||||||
|
/** @brief Read and decrypt data from the SPI flash chip using on-chip hardware flash encryption
|
||||||
|
*
|
||||||
|
* @param chip Pointer to identify flash chip. Must be NULL (the main flash chip). For other chips, encrypted read is not supported.
|
||||||
|
* @param address Address on flash to read from.
|
||||||
|
* @param out_buffer Pointer to a buffer for the data to read to.
|
||||||
|
* @param length Length (in bytes) of data to read.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: on success
|
||||||
|
* - ESP_ERR_NOT_SUPPORTED: encrypted read not supported for this chip.
|
||||||
|
* - or other flash error code from spi_flash_read_encrypted().
|
||||||
|
*/
|
||||||
|
esp_err_t esp_flash_read_encrypted(esp_flash_t *chip, uint32_t address, void *out_buffer, uint32_t length);
|
||||||
|
|
||||||
/** @brief Pointer to the "default" SPI flash chip, ie the main chip attached to the MCU.
|
/** @brief Pointer to the "default" SPI flash chip, ie the main chip attached to the MCU.
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
|
#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
|
||||||
|
|
||||||
static void test_encrypted_write(size_t offset, const uint8_t *data, size_t length);
|
static void test_encrypted_write(size_t offset, const uint8_t *data, size_t length);
|
||||||
|
static void test_encrypted_write_new_impl(size_t offset, const uint8_t *data, size_t length);
|
||||||
static void verify_erased_flash(size_t offset, size_t length);
|
static void verify_erased_flash(size_t offset, size_t length);
|
||||||
|
|
||||||
static size_t start;
|
static size_t start;
|
||||||
@ -86,6 +87,67 @@ static void test_encrypted_write(size_t offset, const uint8_t *data, size_t leng
|
|||||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(data, readback, length);
|
TEST_ASSERT_EQUAL_HEX8_ARRAY(data, readback, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("test 16 byte encrypted writes (esp_flash)", "[flash_encryption][esp_flash_enc][test_env=UT_T1_FlashEncryption]")
|
||||||
|
{
|
||||||
|
setup_tests();
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_HEX(ESP_OK,
|
||||||
|
spi_flash_erase_sector(start / SPI_FLASH_SEC_SIZE));
|
||||||
|
|
||||||
|
uint8_t fortyeight_bytes[0x30]; // 0, 1, 2, 3, 4... 47
|
||||||
|
for(int i = 0; i < sizeof(fortyeight_bytes); i++) {
|
||||||
|
fortyeight_bytes[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify unaligned start or length fails */
|
||||||
|
TEST_ASSERT_EQUAL_HEX(ESP_ERR_INVALID_ARG,
|
||||||
|
esp_flash_write_encrypted(NULL, start+1, fortyeight_bytes, 32));
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_HEX(ESP_ERR_INVALID_SIZE,
|
||||||
|
esp_flash_write_encrypted(NULL, start, fortyeight_bytes, 15));
|
||||||
|
|
||||||
|
/* ensure nothing happened to the flash yet */
|
||||||
|
verify_erased_flash(start, 0x20);
|
||||||
|
|
||||||
|
/* Write 32 byte block, this is the "normal" encrypted write */
|
||||||
|
test_encrypted_write_new_impl(start, fortyeight_bytes, 0x20);
|
||||||
|
verify_erased_flash(start + 0x20, 0x20);
|
||||||
|
|
||||||
|
/* Slip in an unaligned esp_flash_read_encrypted() test */
|
||||||
|
uint8_t buf[0x10];
|
||||||
|
esp_flash_read_encrypted(NULL, start+0x10, buf, 0x10);
|
||||||
|
TEST_ASSERT_EQUAL_HEX8_ARRAY(fortyeight_bytes+0x10, buf, 16);
|
||||||
|
|
||||||
|
/* Write 16 bytes unaligned */
|
||||||
|
test_encrypted_write_new_impl(start + 0x30, fortyeight_bytes, 0x10);
|
||||||
|
/* the 16 byte regions before and after the 16 bytes we just wrote should still be 0xFF */
|
||||||
|
verify_erased_flash(start + 0x20, 0x10);
|
||||||
|
verify_erased_flash(start + 0x40, 0x10);
|
||||||
|
|
||||||
|
/* Write 48 bytes starting at a 32-byte aligned offset */
|
||||||
|
test_encrypted_write_new_impl(start + 0x40, fortyeight_bytes, 0x30);
|
||||||
|
/* 16 bytes after this write should still be 0xFF -unencrypted- */
|
||||||
|
verify_erased_flash(start + 0x70, 0x10);
|
||||||
|
|
||||||
|
/* Write 48 bytes starting at a 16-byte aligned offset */
|
||||||
|
test_encrypted_write_new_impl(start + 0x90, fortyeight_bytes, 0x30);
|
||||||
|
/* 16 bytes after this write should still be 0xFF -unencrypted- */
|
||||||
|
verify_erased_flash(start + 0x120, 0x10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_encrypted_write_new_impl(size_t offset, const uint8_t *data, size_t length)
|
||||||
|
{
|
||||||
|
uint8_t readback[length];
|
||||||
|
printf("encrypt %d bytes at 0x%x\n", length, offset);
|
||||||
|
TEST_ASSERT_EQUAL_HEX(ESP_OK,
|
||||||
|
esp_flash_write_encrypted(NULL, offset, data, length));
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_HEX(ESP_OK,
|
||||||
|
esp_flash_read_encrypted(NULL, offset, readback, length));
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_HEX8_ARRAY(data, readback, length);
|
||||||
|
}
|
||||||
|
|
||||||
static void verify_erased_flash(size_t offset, size_t length)
|
static void verify_erased_flash(size_t offset, size_t length)
|
||||||
{
|
{
|
||||||
uint8_t readback[length];
|
uint8_t readback[length];
|
||||||
|
Loading…
Reference in New Issue
Block a user