/ components / bootloader_support / src / flash_encrypt.c
flash_encrypt.c
  1  // Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
  2  //
  3  // Licensed under the Apache License, Version 2.0 (the "License");
  4  // you may not use this file except in compliance with the License.
  5  // You may obtain a copy of the License at
  6  
  7  //     http://www.apache.org/licenses/LICENSE-2.0
  8  //
  9  // Unless required by applicable law or agreed to in writing, software
 10  // distributed under the License is distributed on an "AS IS" BASIS,
 11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12  // See the License for the specific language governing permissions and
 13  // limitations under the License.
 14  
 15  #include <strings.h>
 16  #include "sdkconfig.h"
 17  #include "esp_log.h"
 18  #include "esp_efuse.h"
 19  #include "esp_efuse_table.h"
 20  #include "esp_flash_encrypt.h"
 21  #include "esp_secure_boot.h"
 22  
 23  #if CONFIG_IDF_TARGET_ESP32
 24  #define CRYPT_CNT ESP_EFUSE_FLASH_CRYPT_CNT
 25  #define WR_DIS_CRYPT_CNT ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT
 26  #elif CONFIG_IDF_TARGET_ESP32S2
 27  #define CRYPT_CNT ESP_EFUSE_SPI_BOOT_CRYPT_CNT
 28  #define WR_DIS_CRYPT_CNT ESP_EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT
 29  #elif CONFIG_IDF_TARGET_ESP32S3
 30  #define CRYPT_CNT ESP_EFUSE_SPI_BOOT_CRYPT_CNT
 31  #define WR_DIS_CRYPT_CNT ESP_EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT
 32  #endif
 33  
 34  #ifndef BOOTLOADER_BUILD
 35  static const char *TAG = "flash_encrypt";
 36  
 37  void esp_flash_encryption_init_checks()
 38  {
 39      esp_flash_enc_mode_t mode;
 40  
 41      // First check is: if Release mode flash encryption & secure boot are enabled then
 42      // FLASH_CRYPT_CNT *must* be write protected. This will have happened automatically
 43      // if bootloader is IDF V4.0 or newer but may not have happened for previous ESP-IDF bootloaders.
 44  #ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
 45  #ifdef CONFIG_SECURE_BOOT
 46      if (esp_secure_boot_enabled() && esp_flash_encryption_enabled()) {
 47          bool flash_crypt_cnt_wr_dis = esp_efuse_read_field_bit(WR_DIS_CRYPT_CNT);
 48          if (!flash_crypt_cnt_wr_dis) {
 49              uint8_t flash_crypt_cnt = 0;
 50              esp_efuse_read_field_blob(CRYPT_CNT, &flash_crypt_cnt,  CRYPT_CNT[0]->bit_count);
 51              if (flash_crypt_cnt == (1<<(CRYPT_CNT[0]->bit_count))-1) {
 52                  // If encryption counter is already max, no need to write protect it
 53                  // (this distinction is important on ESP32 ECO3 where write-procted FLASH_CRYPT_CNT also write-protects UART_DL_DIS)
 54                  return;
 55              }
 56              ESP_LOGE(TAG, "Flash encryption & Secure Boot together requires FLASH_CRYPT_CNT efuse to be write protected. Fixing now...");
 57              esp_flash_write_protect_crypt_cnt();
 58          }
 59      }
 60  #endif // CONFIG_SECURE_BOOT
 61  #endif // CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
 62  
 63      // Second check is to print a warning or error if the current running flash encryption mode
 64      // doesn't match the expectation from project config (due to mismatched bootloader and app, probably)
 65      mode = esp_get_flash_encryption_mode();
 66      if (mode == ESP_FLASH_ENC_MODE_DEVELOPMENT) {
 67  #ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
 68          ESP_LOGE(TAG, "Flash encryption settings error: app is configured for RELEASE but efuses are set for DEVELOPMENT");
 69          ESP_LOGE(TAG, "Mismatch found in security options in bootloader menuconfig and efuse settings. Device is not secure.");
 70  #else
 71          ESP_LOGW(TAG, "Flash encryption mode is DEVELOPMENT (not secure)");
 72  #endif
 73      } else if (mode == ESP_FLASH_ENC_MODE_RELEASE) {
 74          ESP_LOGI(TAG, "Flash encryption mode is RELEASE");
 75      }
 76  }
 77  #endif
 78  
 79  void esp_flash_write_protect_crypt_cnt(void)
 80  {
 81      esp_efuse_write_field_bit(WR_DIS_CRYPT_CNT);
 82  }
 83  
 84  esp_flash_enc_mode_t esp_get_flash_encryption_mode(void)
 85  {
 86      bool flash_crypt_cnt_wr_dis = false;
 87  #if CONFIG_IDF_TARGET_ESP32   
 88      uint8_t dis_dl_enc = 0, dis_dl_dec = 0, dis_dl_cache = 0;
 89  #elif CONFIG_IDF_TARGET_ESP32S2
 90      uint8_t  dis_dl_enc = 0; 
 91      uint8_t dis_dl_icache = 0; 
 92      uint8_t dis_dl_dcache = 0; 
 93  
 94  #endif
 95  
 96      esp_flash_enc_mode_t mode = ESP_FLASH_ENC_MODE_DEVELOPMENT;
 97  
 98      if (esp_flash_encryption_enabled()) {
 99          /* Check if FLASH CRYPT CNT is write protected */
100  
101          flash_crypt_cnt_wr_dis = esp_efuse_read_field_bit(WR_DIS_CRYPT_CNT);
102          if (!flash_crypt_cnt_wr_dis) {
103              uint8_t flash_crypt_cnt = 0;
104              esp_efuse_read_field_blob(CRYPT_CNT, &flash_crypt_cnt, CRYPT_CNT[0]->bit_count);
105              if (flash_crypt_cnt == (1 << (CRYPT_CNT[0]->bit_count)) - 1) {
106                  flash_crypt_cnt_wr_dis = true;
107              }
108          }
109  
110          if (flash_crypt_cnt_wr_dis) {
111  
112  #if CONFIG_IDF_TARGET_ESP32
113              dis_dl_cache = esp_efuse_read_field_bit(ESP_EFUSE_DISABLE_DL_CACHE);
114              dis_dl_enc = esp_efuse_read_field_bit(ESP_EFUSE_DISABLE_DL_ENCRYPT);
115              dis_dl_dec = esp_efuse_read_field_bit(ESP_EFUSE_DISABLE_DL_DECRYPT);
116              /* Check if DISABLE_DL_DECRYPT, DISABLE_DL_ENCRYPT & DISABLE_DL_CACHE are set */
117              if ( dis_dl_cache && dis_dl_enc && dis_dl_dec ) {
118                  mode = ESP_FLASH_ENC_MODE_RELEASE;
119              }
120  #elif CONFIG_IDF_TARGET_ESP32S2
121              dis_dl_enc = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT);
122              dis_dl_icache = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_ICACHE);
123              dis_dl_dcache = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_DCACHE);
124  
125              if (dis_dl_enc && dis_dl_icache && dis_dl_dcache) {
126                  mode = ESP_FLASH_ENC_MODE_RELEASE;
127              }
128  #endif
129          }
130      } else {
131          mode = ESP_FLASH_ENC_MODE_DISABLED;
132      }
133  
134      return mode;
135  }