1
1
/*
2
- * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
2
+ * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
3
3
*
4
4
* SPDX-License-Identifier: Apache-2.0
5
5
*/
19
19
#include "bootloader_util.h"
20
20
#include "bootloader_common.h"
21
21
#include "esp_rom_sys.h"
22
+ #include "esp_efuse.h"
23
+ #include "esp_app_desc.h"
22
24
#include "bootloader_memory_utils.h"
23
25
#include "soc/soc_caps.h"
24
26
#include "hal/cache_ll.h"
@@ -89,10 +91,10 @@ static bool should_map(uint32_t load_addr);
89
91
90
92
static esp_err_t process_segments (esp_image_metadata_t * data , bool silent , bool do_load , bootloader_sha256_handle_t sha_handle , uint32_t * checksum );
91
93
/* Load or verify a segment */
92
- static esp_err_t process_segment (int index , uint32_t flash_addr , esp_image_segment_header_t * header , bool silent , bool do_load , bootloader_sha256_handle_t sha_handle , uint32_t * checksum );
94
+ static esp_err_t process_segment (int index , uint32_t flash_addr , esp_image_segment_header_t * header , bool silent , bool do_load , bootloader_sha256_handle_t sha_handle , uint32_t * checksum , esp_image_metadata_t * metadata );
93
95
94
96
/* split segment and verify if data_len is too long */
95
- static esp_err_t process_segment_data (intptr_t load_addr , uint32_t data_addr , uint32_t data_len , bool do_load , bootloader_sha256_handle_t sha_handle , uint32_t * checksum );
97
+ static esp_err_t process_segment_data (int segment , intptr_t load_addr , uint32_t data_addr , uint32_t data_len , bool do_load , bootloader_sha256_handle_t sha_handle , uint32_t * checksum , esp_image_metadata_t * metadata );
96
98
97
99
/* Verify the main image header */
98
100
static esp_err_t verify_image_header (uint32_t src_addr , const esp_image_header_t * image , bool silent );
@@ -240,6 +242,21 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
240
242
cache_ll_writeback_all (CACHE_LL_LEVEL_INT_MEM , CACHE_TYPE_DATA , CACHE_LL_ID_ALL );
241
243
#endif
242
244
}
245
+
246
+ #if CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
247
+ /* For anti-rollback case, reconfirm security version of the application to prevent FI attacks */
248
+ bool sec_ver = false;
249
+ if (do_load ) {
250
+ sec_ver = esp_efuse_check_secure_version (data -> secure_version );
251
+ if (!sec_ver ) {
252
+ err = ESP_FAIL ;
253
+ goto err ;
254
+ }
255
+ }
256
+ /* Ensure that the security version check passes for image loading scenario */
257
+ ESP_FAULT_ASSERT (!do_load || sec_ver == true);
258
+ #endif // CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
259
+
243
260
#endif // BOOTLOADER_BUILD
244
261
245
262
// Success!
@@ -522,7 +539,7 @@ static esp_err_t process_segments(esp_image_metadata_t *data, bool silent, bool
522
539
for (int i = 0 ; i < data -> image .segment_count ; i ++ ) {
523
540
esp_image_segment_header_t * header = & data -> segments [i ];
524
541
ESP_LOGV (TAG , "loading segment header %d at offset 0x%" PRIx32 , i , next_addr );
525
- CHECK_ERR (process_segment (i , next_addr , header , silent , do_load , sha_handle , checksum ));
542
+ CHECK_ERR (process_segment (i , next_addr , header , silent , do_load , sha_handle , checksum , data ));
526
543
next_addr += sizeof (esp_image_segment_header_t );
527
544
data -> segment_data [i ] = next_addr ;
528
545
next_addr += header -> data_len ;
@@ -543,7 +560,7 @@ static esp_err_t process_segments(esp_image_metadata_t *data, bool silent, bool
543
560
return err ;
544
561
}
545
562
546
- static esp_err_t process_segment (int index , uint32_t flash_addr , esp_image_segment_header_t * header , bool silent , bool do_load , bootloader_sha256_handle_t sha_handle , uint32_t * checksum )
563
+ static esp_err_t process_segment (int index , uint32_t flash_addr , esp_image_segment_header_t * header , bool silent , bool do_load , bootloader_sha256_handle_t sha_handle , uint32_t * checksum , esp_image_metadata_t * metadata )
547
564
{
548
565
esp_err_t err ;
549
566
@@ -601,7 +618,7 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
601
618
uint32_t offset_page = ((data_addr & MMAP_ALIGNED_MASK ) != 0 ) ? 1 : 0 ;
602
619
/* Data we could map in case we are not aligned to PAGE boundary is one page size lesser. */
603
620
data_len = MIN (data_len_remain , ((free_page_count - offset_page ) * SPI_FLASH_MMU_PAGE_SIZE ));
604
- CHECK_ERR (process_segment_data (load_addr , data_addr , data_len , do_load , sha_handle , checksum ));
621
+ CHECK_ERR (process_segment_data (index , load_addr , data_addr , data_len , do_load , sha_handle , checksum , metadata ));
605
622
data_addr += data_len ;
606
623
data_len_remain -= data_len ;
607
624
}
@@ -616,7 +633,42 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
616
633
return err ;
617
634
}
618
635
619
- static esp_err_t process_segment_data (intptr_t load_addr , uint32_t data_addr , uint32_t data_len , bool do_load , bootloader_sha256_handle_t sha_handle , uint32_t * checksum )
636
+ #if CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
637
+ /* The __attribute__((optimize("O0"))) is used to disable optimizations for this function,
638
+ * preventing the compiler from potentially optimizing data_buffer and reading data directly from src.
639
+ * This is crucial as we want to read from Flash only once, ensuring the integrity of the data.
640
+ */
641
+ __attribute__((optimize ("O0" )))
642
+ static size_t process_esp_app_desc_data (const uint32_t * src , bootloader_sha256_handle_t sha_handle , uint32_t * checksum , esp_image_metadata_t * metadata )
643
+ {
644
+ /* Using data_buffer here helps to securely read secure_version
645
+ * (for anti-rollback) from esp_app_desc_t, preventing FI attack.
646
+ * We read data from Flash into this buffer, which is covered by sha256.
647
+ * Therefore, if the flash is under attackers control and contents are modified
648
+ * the sha256 comparison will fail.
649
+ *
650
+ * The esp_app_desc_t structure is located in DROM and is always in segment #0.
651
+ *
652
+ * esp_app_desc_t is always at #0 segment (index==0).
653
+ * secure_version field of esp_app_desc_t is located at #2 word (w_i==1).
654
+ */
655
+ uint32_t data_buffer [2 ];
656
+ memcpy (data_buffer , src , sizeof (data_buffer ));
657
+ assert (data_buffer [0 ] == ESP_APP_DESC_MAGIC_WORD );
658
+ metadata -> secure_version = data_buffer [1 ];
659
+ if (checksum != NULL ) {
660
+ * checksum ^= data_buffer [0 ] ^ data_buffer [1 ];
661
+ }
662
+ if (sha_handle != NULL ) {
663
+ bootloader_sha256_data (sha_handle , data_buffer , sizeof (data_buffer ));
664
+ }
665
+ ESP_FAULT_ASSERT (memcmp (data_buffer , src , sizeof (data_buffer )) == 0 );
666
+ ESP_FAULT_ASSERT (memcmp (& metadata -> secure_version , & src [1 ], sizeof (uint32_t )) == 0 );
667
+ return sizeof (data_buffer );
668
+ }
669
+ #endif // CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
670
+
671
+ static esp_err_t process_segment_data (int segment , intptr_t load_addr , uint32_t data_addr , uint32_t data_len , bool do_load , bootloader_sha256_handle_t sha_handle , uint32_t * checksum , esp_image_metadata_t * metadata )
620
672
{
621
673
// If we are not loading, and the checksum is empty, skip processing this
622
674
// segment for data
@@ -653,6 +705,16 @@ static esp_err_t process_segment_data(intptr_t load_addr, uint32_t data_addr, ui
653
705
654
706
const uint32_t * src = data ;
655
707
708
+ #if CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
709
+ if (segment == 0 ) {
710
+ // The esp_app_desc_t structure is located in DROM and is always in segment #0.
711
+ size_t len = process_esp_app_desc_data (src , sha_handle , checksum , metadata );
712
+ data_len -= len ;
713
+ src += len / 4 ;
714
+ // In BOOTLOADER_BUILD, for DROM (segment #0) we do not load it into dest (only map it), do_load = false.
715
+ }
716
+ #endif // CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
717
+
656
718
for (size_t i = 0 ; i < data_len ; i += 4 ) {
657
719
int w_i = i / 4 ; // Word index
658
720
uint32_t w = src [w_i ];
0 commit comments