Using legacy implementation.
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)
{
- VERIFY_OP(write_encrypted);
- if (((memspi_host_data_t*)chip->host->driver_data)->spi != 0) {
- // Encrypted operations have to use SPI0
- return ESP_ERR_FLASH_UNSUPPORTED_HOST;
+ /*
+ * 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;
}
if (buffer == NULL || address > chip->size || address+length > chip->size) {
return ESP_ERR_INVALID_ARG;
}
-
- 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);
+ return spi_flash_write_encrypted(address, buffer, length);
}
-
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;
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
/** @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 buffer Pointer to a buffer with the data to write.
* @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
*
- * @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);
+/** @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.
#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_new_impl(size_t offset, const uint8_t *data, size_t length);
static void verify_erased_flash(size_t offset, size_t length);
static size_t start;
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)
{
uint8_t readback[length];