@@ -90,7 +90,7 @@ size_t spi_flash_get_chip_size()
9090 return g_rom_flashchip .chip_size ;
9191}
9292
93- SpiFlashOpResult IRAM_ATTR spi_flash_unlock ()
93+ static SpiFlashOpResult IRAM_ATTR spi_flash_unlock ()
9494{
9595 static bool unlocked = false;
9696 if (!unlocked ) {
@@ -250,42 +250,80 @@ esp_err_t IRAM_ATTR spi_flash_write(size_t dst, const void *srcv, size_t size)
250250 }
251251out :
252252 COUNTER_STOP (write );
253+
254+ spi_flash_op_lock ();
255+ spi_flash_mark_modified_region (dst , size );
256+ spi_flash_op_unlock ();
257+
253258 return spi_flash_translate_rc (rc );
254259}
255260
256261esp_err_t IRAM_ATTR spi_flash_write_encrypted (size_t dest_addr , const void * src , size_t size )
257262{
258- if ((dest_addr % 32 ) != 0 ) {
263+ const uint8_t * ssrc = (const uint8_t * )src ;
264+ if ((dest_addr % 16 ) != 0 ) {
259265 return ESP_ERR_INVALID_ARG ;
260266 }
261- if ((size % 32 ) != 0 ) {
267+ if ((size % 16 ) != 0 ) {
262268 return ESP_ERR_INVALID_SIZE ;
263269 }
264- if ((uint32_t ) src < 0x3ff00000 ) {
265- // if source address is in DROM, we won't be able to read it
266- // from within SPIWrite
267- // TODO: consider buffering source data using heap and writing it anyway?
268- return ESP_ERR_INVALID_ARG ;
269- }
270+
270271 COUNTER_START ();
271272 spi_flash_disable_interrupts_caches_and_other_cpu ();
272273 SpiFlashOpResult rc ;
273274 rc = spi_flash_unlock ();
275+ spi_flash_enable_interrupts_caches_and_other_cpu ();
276+
274277 if (rc == SPI_FLASH_RESULT_OK ) {
275278 /* SPI_Encrypt_Write encrypts data in RAM as it writes,
276279 so copy to a temporary buffer - 32 bytes at a time.
280+
281+ Each call to SPI_Encrypt_Write takes a 32 byte "row" of
282+ data to encrypt, and each row is two 16 byte AES blocks
283+ that share a key (as derived from flash address).
277284 */
278- uint32_t encrypt_buf [32 /sizeof (uint32_t )];
279- for (size_t i = 0 ; i < size ; i += 32 ) {
280- memcpy (encrypt_buf , ((const uint8_t * )src ) + i , 32 );
281- rc = SPI_Encrypt_Write ((uint32_t ) dest_addr + i , encrypt_buf , 32 );
285+ uint8_t encrypt_buf [32 ] __attribute__((aligned (4 )));
286+ uint32_t row_size ;
287+ for (size_t i = 0 ; i < size ; i += row_size ) {
288+ uint32_t row_addr = dest_addr + i ;
289+ if (i == 0 && (row_addr % 32 ) != 0 ) {
290+ /* writing to second block of a 32 byte row */
291+ row_size = 16 ;
292+ row_addr -= 16 ;
293+ /* copy to second block in buffer */
294+ memcpy (encrypt_buf + 16 , ssrc + i , 16 );
295+ /* decrypt the first block from flash, will reencrypt to same bytes */
296+ spi_flash_read_encrypted (row_addr , encrypt_buf , 16 );
297+ }
298+ else if (size - i == 16 ) {
299+ /* 16 bytes left, is first block of a 32 byte row */
300+ row_size = 16 ;
301+ /* copy to first block in buffer */
302+ memcpy (encrypt_buf , ssrc + i , 16 );
303+ /* decrypt the second block from flash, will reencrypt to same bytes */
304+ spi_flash_read_encrypted (row_addr + 16 , encrypt_buf + 16 , 16 );
305+ }
306+ else {
307+ /* Writing a full 32 byte row (2 blocks) */
308+ row_size = 32 ;
309+ memcpy (encrypt_buf , ssrc + i , 32 );
310+ }
311+
312+ spi_flash_disable_interrupts_caches_and_other_cpu ();
313+ rc = SPI_Encrypt_Write (row_addr , (uint32_t * )encrypt_buf , 32 );
314+ spi_flash_enable_interrupts_caches_and_other_cpu ();
282315 if (rc != SPI_FLASH_RESULT_OK ) {
283316 break ;
284317 }
285318 }
286319 bzero (encrypt_buf , sizeof (encrypt_buf ));
287320 }
288321 COUNTER_ADD_BYTES (write , size );
322+
323+ spi_flash_op_lock ();
324+ spi_flash_mark_modified_region (dest_addr , size );
325+ spi_flash_op_unlock ();
326+
289327 return spi_flash_translate_rc (rc );
290328}
291329
@@ -381,6 +419,31 @@ esp_err_t IRAM_ATTR spi_flash_read(size_t src, void *dstv, size_t size)
381419 return spi_flash_translate_rc (rc );
382420}
383421
422+ esp_err_t IRAM_ATTR spi_flash_read_encrypted (size_t src , void * dstv , size_t size )
423+ {
424+ if (src + size > g_rom_flashchip .chip_size ) {
425+ return ESP_ERR_INVALID_SIZE ;
426+ }
427+ if (size == 0 ) {
428+ return ESP_OK ;
429+ }
430+
431+ esp_err_t err ;
432+ const uint8_t * map ;
433+ spi_flash_mmap_handle_t map_handle ;
434+ size_t map_src = src & ~(SPI_FLASH_MMU_PAGE_SIZE - 1 );
435+ size_t map_size = size + (src - map_src );
436+
437+ err = spi_flash_mmap (map_src , map_size , SPI_FLASH_MMAP_DATA , (const void * * )& map , & map_handle );
438+ if (err != ESP_OK ) {
439+ return err ;
440+ }
441+ memcpy (dstv , map + (src - map_src ), size );
442+ spi_flash_munmap (map_handle );
443+ return err ;
444+ }
445+
446+
384447static esp_err_t spi_flash_translate_rc (SpiFlashOpResult rc )
385448{
386449 switch (rc ) {
0 commit comments