fix(spi_flash): Improve encryption write performance, Closes https://github.com/espressif/esp-idf/issues/12553

This commit is contained in:
Cao Sen Miao 2023-11-14 17:42:09 +08:00 committed by BOT
parent 2c289fed2f
commit ec28757007

View File

@ -1219,7 +1219,7 @@ esp_err_t IRAM_ATTR esp_flash_write_encrypted(esp_flash_t *chip, uint32_t addres
} }
if ((address % 16) != 0) { if ((address % 16) != 0) {
ESP_EARLY_LOGE(TAG, "flash encrypted write address must be 16 bytes aligned"); ESP_DRAM_LOGE(TAG, "flash encrypted write address must be 16 bytes aligned");
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
@ -1228,13 +1228,19 @@ esp_err_t IRAM_ATTR esp_flash_write_encrypted(esp_flash_t *chip, uint32_t addres
} }
if ((length % 16) != 0) { if ((length % 16) != 0) {
ESP_EARLY_LOGE(TAG, "flash encrypted write length must be multiple of 16"); ESP_DRAM_LOGE(TAG, "flash encrypted write length must be multiple of 16");
return ESP_ERR_INVALID_SIZE; return ESP_ERR_INVALID_SIZE;
} }
bool bus_acquired = false; bool bus_acquired = false;
const uint8_t *ssrc = (const uint8_t *)buffer; // Copy buffer to IRAM.
uint8_t *ssrc = (uint8_t*)heap_caps_calloc(1, length, MALLOC_CAP_INTERNAL);
if (ssrc == NULL) {
ESP_DRAM_LOGE(TAG, "No extra memory for encryption flash write");
return ESP_ERR_NO_MEM;
}
memcpy(ssrc, buffer, length);
COUNTER_START(); COUNTER_START();
@ -1253,6 +1259,27 @@ esp_err_t IRAM_ATTR esp_flash_write_encrypted(esp_flash_t *chip, uint32_t addres
*/ */
uint8_t encrypt_buf[64] __attribute__((aligned(4))); uint8_t encrypt_buf[64] __attribute__((aligned(4)));
uint32_t row_size_length; uint32_t row_size_length;
#if CONFIG_IDF_TARGET_ESP32
uint8_t pre_buf[16] = {0};
uint8_t post_buf[16] = {0};
if((address % 32) != 0) {
esp_flash_read_encrypted(chip, address - 16, pre_buf, 16);
}
if(((address + length) % 32) != 0) {
esp_flash_read_encrypted(chip, address + length, post_buf, 16);
}
#endif
#if CONFIG_IDF_TARGET_ESP32S2
esp_crypto_dma_lock_acquire();
#endif //CONFIG_IDF_TARGET_ESP32S2
err = rom_spiflash_api_funcs->start(chip);
if (err != ESP_OK) {
goto restore_cache;
}
bus_acquired = true;
for (size_t i = 0; i < length; i += row_size_length) { for (size_t i = 0; i < length; i += row_size_length) {
uint32_t row_addr = address + i; uint32_t row_addr = address + i;
uint8_t row_size; uint8_t row_size;
@ -1265,14 +1292,14 @@ esp_err_t IRAM_ATTR esp_flash_write_encrypted(esp_flash_t *chip, uint32_t addres
/* copy to second block in buffer */ /* copy to second block in buffer */
memcpy(encrypt_buf + 16, ssrc + i, row_size); memcpy(encrypt_buf + 16, ssrc + i, row_size);
/* decrypt the first block from flash, will reencrypt to same bytes */ /* decrypt the first block from flash, will reencrypt to same bytes */
esp_flash_read_encrypted(chip, row_addr, encrypt_buf, 16); memcpy(encrypt_buf, pre_buf, 16);
} else if (length - i == 16) { } else if (length - i == 16) {
/* 16 bytes left, is first block of a 32 byte row */ /* 16 bytes left, is first block of a 32 byte row */
row_size = 16; row_size = 16;
/* copy to first block in buffer */ /* copy to first block in buffer */
memcpy(encrypt_buf, ssrc + i, row_size); memcpy(encrypt_buf, ssrc + i, row_size);
/* decrypt the second block from flash, will reencrypt to same bytes */ /* decrypt the second block from flash, will reencrypt to same bytes */
esp_flash_read_encrypted(chip, row_addr + 16, encrypt_buf + 16, 16); memcpy(encrypt_buf + 16, post_buf, 16);
} else { } else {
/* Writing a full 32 byte row (2 blocks) */ /* Writing a full 32 byte row (2 blocks) */
row_size = 32; row_size = 32;
@ -1298,27 +1325,18 @@ esp_err_t IRAM_ATTR esp_flash_write_encrypted(esp_flash_t *chip, uint32_t addres
#if CONFIG_SPI_FLASH_WARN_SETTING_ZERO_TO_ONE #if CONFIG_SPI_FLASH_WARN_SETTING_ZERO_TO_ONE
err = s_check_setting_zero_to_one(chip, row_addr, encrypt_byte, NULL, is_encrypted); err = s_check_setting_zero_to_one(chip, row_addr, encrypt_byte, NULL, is_encrypted);
if (err != ESP_OK) { if (err != ESP_OK) {
//Error happens, we end flash operation. Re-enable cache and flush it rom_spiflash_api_funcs->end(chip, ESP_OK);
goto restore_cache;
}
#endif //#if CONFIG_SPI_FLASH_WARN_SETTING_ZERO_TO_ONE
#if CONFIG_IDF_TARGET_ESP32S2
esp_crypto_dma_lock_acquire();
#endif //CONFIG_IDF_TARGET_ESP32S2
err = rom_spiflash_api_funcs->start(chip);
if (err != ESP_OK) {
#if CONFIG_IDF_TARGET_ESP32S2 #if CONFIG_IDF_TARGET_ESP32S2
esp_crypto_dma_lock_release(); esp_crypto_dma_lock_release();
#endif //CONFIG_IDF_TARGET_ESP32S2 #endif //CONFIG_IDF_TARGET_ESP32S2
//Error happens, we end flash operation. Re-enable cache and flush it //Error happens, we end flash operation. Re-enable cache and flush it
goto restore_cache; goto restore_cache;
} }
bus_acquired = true; #endif //#if CONFIG_SPI_FLASH_WARN_SETTING_ZERO_TO_ONE
err = chip->chip_drv->write_encrypted(chip, (uint32_t *)encrypt_buf, row_addr, encrypt_byte); err = chip->chip_drv->write_encrypted(chip, (uint32_t *)encrypt_buf, row_addr, encrypt_byte);
if (err!= ESP_OK) { if (err!= ESP_OK) {
rom_spiflash_api_funcs->end(chip, ESP_OK);
#if CONFIG_IDF_TARGET_ESP32S2 #if CONFIG_IDF_TARGET_ESP32S2
esp_crypto_dma_lock_release(); esp_crypto_dma_lock_release();
#endif //CONFIG_IDF_TARGET_ESP32S2 #endif //CONFIG_IDF_TARGET_ESP32S2
@ -1327,33 +1345,46 @@ esp_err_t IRAM_ATTR esp_flash_write_encrypted(esp_flash_t *chip, uint32_t addres
//Error happens, we end flash operation. Re-enable cache and flush it //Error happens, we end flash operation. Re-enable cache and flush it
goto restore_cache; goto restore_cache;
} }
err = rom_spiflash_api_funcs->end(chip, ESP_OK);
COUNTER_ADD_BYTES(write, encrypt_byte); COUNTER_ADD_BYTES(write, encrypt_byte);
#if CONFIG_IDF_TARGET_ESP32S2
esp_crypto_dma_lock_release();
#endif //CONFIG_IDF_TARGET_ESP32S2
if (err != ESP_OK) {
bus_acquired = false;
//Error happens, we end flash operation. Re-enable cache and flush it
goto restore_cache;
}
bus_acquired = false;
#if CONFIG_SPI_FLASH_VERIFY_WRITE #if CONFIG_SPI_FLASH_VERIFY_WRITE
err = s_verify_write(chip, row_addr, encrypt_byte, (uint32_t *)encrypt_buf, is_encrypted); err = s_verify_write(chip, row_addr, encrypt_byte, (uint32_t *)encrypt_buf, is_encrypted);
if (err != ESP_OK) { if (err != ESP_OK) {
rom_spiflash_api_funcs->end(chip, ESP_OK);
#if CONFIG_IDF_TARGET_ESP32S2
esp_crypto_dma_lock_release();
#endif //CONFIG_IDF_TARGET_ESP32S2
//Error happens, we end flash operation. Re-enable cache and flush it //Error happens, we end flash operation. Re-enable cache and flush it
goto restore_cache; goto restore_cache;
} }
#endif //CONFIG_SPI_FLASH_VERIFY_WRITE #endif //CONFIG_SPI_FLASH_VERIFY_WRITE
} }
err = rom_spiflash_api_funcs->end(chip, ESP_OK);
#if CONFIG_IDF_TARGET_ESP32S2
esp_crypto_dma_lock_release();
#endif //CONFIG_IDF_TARGET_ESP32S2
if (err != ESP_OK) {
bus_acquired = false;
//Error happens, we end flash operation. Re-enable cache and flush it
goto restore_cache;
}
bus_acquired = false;
if(ssrc) {
free(ssrc);
}
COUNTER_STOP(write); COUNTER_STOP(write);
err = rom_spiflash_api_funcs->flash_end_flush_cache(chip, err, bus_acquired, address, length); err = rom_spiflash_api_funcs->flash_end_flush_cache(chip, err, bus_acquired, address, length);
return err; return err;
restore_cache: restore_cache:
if(ssrc) {
free(ssrc);
}
COUNTER_STOP(write); COUNTER_STOP(write);
ret = rom_spiflash_api_funcs->flash_end_flush_cache(chip, err, bus_acquired, address, length); ret = rom_spiflash_api_funcs->flash_end_flush_cache(chip, err, bus_acquired, address, length);
if (ret != ESP_OK) { if (ret != ESP_OK) {