nvs_flash: Added helper component `nvs_sec_provider`

- For processing NVS encryption-related security configuration
pull/11500/head^2^2
Laukik Hase 2023-04-05 18:04:18 +05:30
rodzic c1bed366ba
commit 8efe2f86e9
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 11C571361F51A199
7 zmienionych plików z 478 dodań i 3 usunięć

Wyświetl plik

@ -125,6 +125,7 @@
/components/mqtt/ @esp-idf-codeowners/network
/components/newlib/ @esp-idf-codeowners/system @esp-idf-codeowners/tools
/components/nvs_flash/ @esp-idf-codeowners/storage
/components/nvs_sec_provider/ @esp-idf-codeowners/storage @esp-idf-codeowners/security
/components/openthread/ @esp-idf-codeowners/ieee802154
/components/partition_table/ @esp-idf-codeowners/system
/components/perfmon/ @esp-idf-codeowners/tools

Wyświetl plik

@ -72,6 +72,9 @@
#if __has_include("nvs.h")
#include "nvs.h"
#endif
#if __has_include("nvs_sec_provider.h")
#include "nvs_sec_provider.h"
#endif
#if __has_include("spi_flash_mmap.h")
#include "spi_flash_mmap.h"
#endif
@ -829,6 +832,25 @@ static const esp_err_msg_t esp_err_msg_table[] = {
# endif
# ifdef ESP_ERR_TCP_TRANSPORT_NO_MEM
ERR_TBL_IT(ESP_ERR_TCP_TRANSPORT_NO_MEM), /* 57348 0xe004 Memory allocation failed */
# endif
// components/nvs_sec_provider/include/nvs_sec_provider.h
# ifdef ESP_ERR_NVS_SEC_BASE
ERR_TBL_IT(ESP_ERR_NVS_SEC_BASE), /* 61440 0xf000 Starting number of error codes */
# endif
# ifdef ESP_ERR_NVS_SEC_HMAC_KEY_NOT_FOUND
ERR_TBL_IT(ESP_ERR_NVS_SEC_HMAC_KEY_NOT_FOUND), /* 61441 0xf001 HMAC Key required to generate the NVS
encryption keys not found */
# endif
# ifdef ESP_ERR_NVS_SEC_HMAC_KEY_BLK_ALREADY_USED
ERR_TBL_IT(ESP_ERR_NVS_SEC_HMAC_KEY_BLK_ALREADY_USED), /* 61442 0xf002 Provided eFuse block for HMAC key
generation is already in use */
# endif
# ifdef ESP_ERR_NVS_SEC_HMAC_KEY_GENERATION_FAILED
ERR_TBL_IT(ESP_ERR_NVS_SEC_HMAC_KEY_GENERATION_FAILED), /* 61443 0xf003 Failed to generate/write the HMAC key to eFuse */
# endif
# ifdef ESP_ERR_NVS_SEC_HMAC_XTS_KEYS_DERIV_FAILED
ERR_TBL_IT(ESP_ERR_NVS_SEC_HMAC_XTS_KEYS_DERIV_FAILED), /* 61444 0xf004 Failed to derive the NVS encryption keys
based on the HMAC-based scheme */
# endif
};
#endif //CONFIG_ESP_ERR_TO_NAME_LOOKUP

Wyświetl plik

@ -0,0 +1,12 @@
idf_component_register(SRCS "nvs_sec_provider.c"
INCLUDE_DIRS include
PRIV_REQUIRES bootloader_support efuse esp_partition nvs_flash)
# NOTE: In a case where only the default NVS partition is to be encrypted
# and no custom NVS partitions exist, `nvs_flash_init` is the only API that
# needs to be called. No API from the `nvs_sec_provider` component is called
# as neither the `nvs_flash` component nor the user app depends on it.
# Thus, the symbols from this component are not placed in the .map file and
# hence the constructor, which initialises the encryption scheme for the default
# NVS partition, never executes. The following is a workaround for the same.
target_link_libraries(${COMPONENT_LIB} PRIVATE "-u nvs_sec_provider_include_impl")

Wyświetl plik

@ -0,0 +1,46 @@
menu "NVS Security Provider"
visible if NVS_ENCRYPTION
choice NVS_SEC_KEY_PROTECTION_SCHEME
prompt "NVS Encryption: Key Protection Scheme"
depends on NVS_ENCRYPTION
default NVS_SEC_KEY_PROTECT_USING_FLASH_ENC
help
This choice defines the default NVS encryption keys protection scheme;
which will be used for the default NVS partition.
Users can use the corresponding scheme registration APIs to register other
schemes for the default as well as other NVS partitions.
config NVS_SEC_KEY_PROTECT_USING_FLASH_ENC
bool "Using Flash Encryption"
depends on SECURE_FLASH_ENC_ENABLED
help
Protect the NVS Encryption Keys using Flash Encryption
Requires a separate 'nvs_keys' partition (which will be encrypted by flash encryption)
for storing the NVS encryption keys
config NVS_SEC_KEY_PROTECT_USING_HMAC
bool "Using HMAC peripheral"
depends on SOC_HMAC_SUPPORTED
help
Derive and protect the NVS Encryption Keys using the HMAC peripheral
Requires the specified eFuse block (NVS_SEC_HMAC_EFUSE_KEY_ID or the v2 API argument)
to be empty or pre-written with a key with the purpose ESP_EFUSE_KEY_PURPOSE_HMAC_UP
endchoice
config NVS_SEC_HMAC_EFUSE_KEY_ID
int "eFuse key ID storing the HMAC key"
depends on NVS_SEC_KEY_PROTECT_USING_HMAC
range 0 6
default 6
help
eFuse block key ID storing the HMAC key for deriving the NVS encryption keys
Note: The eFuse block key ID required by the HMAC scheme
(CONFIG_NVS_SEC_KEY_PROTECT_USING_HMAC) is set using this config when the default
NVS partition is initialized with nvs_flash_init(). The eFuse block key ID can
also be set at runtime by passing the appropriate value to the NVS security scheme
registration APIs.
endmenu

Wyświetl plik

@ -0,0 +1,114 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include "esp_err.h"
#include "soc/soc_caps.h"
#include "nvs_flash.h"
#include "esp_partition.h"
#if SOC_HMAC_SUPPORTED
#include "esp_hmac.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define ESP_ERR_NVS_SEC_BASE 0xF000 /*!< Starting number of error codes */
#define ESP_ERR_NVS_SEC_HMAC_KEY_NOT_FOUND (ESP_ERR_NVS_SEC_BASE + 0x01) /*!< HMAC Key required to generate the NVS encryption keys not found */
#define ESP_ERR_NVS_SEC_HMAC_KEY_BLK_ALREADY_USED (ESP_ERR_NVS_SEC_BASE + 0x02) /*!< Provided eFuse block for HMAC key generation is already in use */
#define ESP_ERR_NVS_SEC_HMAC_KEY_GENERATION_FAILED (ESP_ERR_NVS_SEC_BASE + 0x03) /*!< Failed to generate/write the HMAC key to eFuse */
#define ESP_ERR_NVS_SEC_HMAC_XTS_KEYS_DERIV_FAILED (ESP_ERR_NVS_SEC_BASE + 0x04) /*!< Failed to derive the NVS encryption keys based on the HMAC-based scheme */
/**
* @brief NVS Encryption Keys Protection Scheme
*/
typedef enum {
NVS_SEC_SCHEME_FLASH_ENC = 0, /*!< Protect NVS encryption keys using Flash Encryption */
NVS_SEC_SCHEME_HMAC, /*!< Protect NVS encryption keys using HMAC peripheral */
NVS_SEC_SCHEME_MAX
} nvs_sec_scheme_id_t;
/**
* @brief Flash encryption-based scheme specific configuration data
*/
typedef struct {
const esp_partition_t *nvs_keys_part; /*!< Partition of subtype `nvs_keys` holding the NVS encryption keys */
} nvs_sec_config_flash_enc_t;
/**
* @brief Helper for populating the Flash encryption-based scheme specific configuration data
*/
#define NVS_SEC_PROVIDER_CFG_FLASH_ENC_DEFAULT() { \
.nvs_keys_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, \
ESP_PARTITION_SUBTYPE_DATA_NVS_KEYS, \
NULL), \
}
#if SOC_HMAC_SUPPORTED
/**
* @brief HMAC-based scheme specific configuration data
*/
typedef struct {
hmac_key_id_t hmac_key_id; /*!< HMAC Key ID used for generating the NVS encryption keys */
} nvs_sec_config_hmac_t;
/**
* @brief Helper for populating the HMAC-based scheme specific configuration data
*/
#define NVS_SEC_PROVIDER_CFG_HMAC_DEFAULT() { \
.hmac_key_id = (hmac_key_id_t)(CONFIG_NVS_SEC_HMAC_EFUSE_KEY_ID), \
}
#endif /* SOC_HMAC_SUPPORTED */
/**
* @brief Register the Flash-Encryption based scheme for NVS Encryption
*
* @param[in] sec_scheme_cfg Security scheme specific configuration data
* @param[out] sec_scheme_handle_out Security scheme specific configuration handle
*
* @return
* - ESP_OK, if `sec_scheme_handle_out` was populated successfully with the scheme configuration;
* - ESP_ERR_INVALID_ARG, if `scheme_cfg_hmac` is NULL;
* - ESP_ERR_NO_MEM, No memory for the scheme-specific handle `sec_scheme_handle_out`
* - ESP_ERR_NOT_FOUND, if no `nvs_keys` partition is found
*/
esp_err_t nvs_sec_provider_register_flash_enc(const nvs_sec_config_flash_enc_t *sec_scheme_cfg, nvs_sec_scheme_t **sec_scheme_handle_out);
#if SOC_HMAC_SUPPORTED
/**
* @brief Register the HMAC-based scheme for NVS Encryption
*
* @param[in] sec_scheme_cfg Security scheme specific configuration data
* @param[out] sec_scheme_handle_out Security scheme specific configuration handle
*
* @return
* - ESP_OK, if `sec_scheme_handle_out` was populated successfully with the scheme configuration;
* - ESP_ERR_INVALID_ARG, if `scheme_cfg_hmac` is NULL;
* - ESP_ERR_NO_MEM, No memory for the scheme-specific handle `sec_scheme_handle_out`
*/
esp_err_t nvs_sec_provider_register_hmac(const nvs_sec_config_hmac_t *sec_scheme_cfg, nvs_sec_scheme_t **sec_scheme_handle_out);
#endif /* SOC_HMAC_SUPPORTED */
/**
* @brief Deregister the NVS encryption scheme registered with the given handle
*
* @param[in] sec_scheme_handle Security scheme specific configuration handle
* @return
* - ESP_OK, if the scheme registered with `sec_scheme_handle` was deregistered successfully
* - ESP_ERR_INVALID_ARG, if `sec_scheme_handle` is NULL;
*/
esp_err_t nvs_sec_provider_deregister(nvs_sec_scheme_t *sec_scheme_handle);
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -0,0 +1,279 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "esp_err.h"
#include "esp_log.h"
#include "esp_fault.h"
#include "soc/soc_caps.h"
#include "sdkconfig.h"
#include "nvs_flash.h"
#include "nvs_sec_provider.h"
#if SOC_HMAC_SUPPORTED
#include "bootloader_random.h"
#include "esp_random.h"
#include "esp_efuse.h"
#include "esp_efuse_chip.h"
#endif // SOC_HMAC_SUPPORTED
static __attribute__((unused)) const char *TAG = "nvs_sec_provider";
#if CONFIG_NVS_SEC_KEY_PROTECT_USING_FLASH_ENC
static esp_err_t generate_keys_flash_enc(const void* sec_scheme_cfg, nvs_sec_cfg_t* cfg)
{
if (sec_scheme_cfg == NULL || cfg == NULL) {
return ESP_ERR_INVALID_ARG;
}
nvs_sec_config_flash_enc_t *scheme_cfg_flash_enc = (nvs_sec_config_flash_enc_t *)sec_scheme_cfg;
return nvs_flash_generate_keys(scheme_cfg_flash_enc->nvs_keys_part, cfg);
}
static esp_err_t read_security_cfg_flash_enc(const void* sec_scheme_cfg, nvs_sec_cfg_t* cfg)
{
if (sec_scheme_cfg == NULL || cfg == NULL) {
return ESP_ERR_INVALID_ARG;
}
nvs_sec_config_flash_enc_t *scheme_cfg_flash_enc = (nvs_sec_config_flash_enc_t *)sec_scheme_cfg;
return nvs_flash_read_security_cfg(scheme_cfg_flash_enc->nvs_keys_part, cfg);
}
esp_err_t nvs_sec_provider_register_flash_enc(const nvs_sec_config_flash_enc_t *sec_scheme_cfg, nvs_sec_scheme_t **sec_scheme_handle_out)
{
if (sec_scheme_cfg == NULL || sec_scheme_handle_out == NULL) {
return ESP_ERR_INVALID_ARG;
}
nvs_sec_scheme_t *sec_scheme = calloc(1, sizeof(nvs_sec_scheme_t));
if (sec_scheme == NULL) {
return ESP_ERR_NO_MEM;
}
sec_scheme->scheme_id = NVS_SEC_SCHEME_FLASH_ENC;
sec_scheme->nvs_flash_key_gen = &generate_keys_flash_enc;
sec_scheme->nvs_flash_read_cfg = &read_security_cfg_flash_enc;
sec_scheme->scheme_data = calloc(1, sizeof(nvs_sec_config_flash_enc_t));
if (sec_scheme->scheme_data == NULL) {
return ESP_ERR_NO_MEM;
}
memcpy(sec_scheme->scheme_data, (void *)sec_scheme_cfg, sizeof(nvs_sec_config_flash_enc_t));
esp_err_t err = nvs_flash_register_security_scheme(sec_scheme);
if (err != ESP_OK) {
return err;
}
*sec_scheme_handle_out = sec_scheme;
return ESP_OK;
}
static void __attribute__((constructor)) nvs_sec_provider_register_flash_enc_ctr(void)
{
ESP_EARLY_LOGI(TAG, "NVS Encryption - Registering Flash encryption-based scheme...");
nvs_sec_config_flash_enc_t sec_scheme_cfg = NVS_SEC_PROVIDER_CFG_FLASH_ENC_DEFAULT();
nvs_sec_scheme_t *sec_scheme_handle_out = NULL;
nvs_sec_provider_register_flash_enc(&sec_scheme_cfg, &sec_scheme_handle_out);
}
#endif
#if SOC_HMAC_SUPPORTED
#if CONFIG_NVS_SEC_HMAC_EFUSE_KEY_ID > 5
#error "NVS Encryption (HMAC): Configured eFuse block (CONFIG_NVS_SEC_HMAC_EFUSE_KEY_ID) out of range!"
#endif
static esp_err_t compute_nvs_keys_with_hmac(hmac_key_id_t hmac_key_id, nvs_sec_cfg_t* cfg)
{
uint32_t ekey_seed[8] = {[0 ... 7] = 0xAEBE5A5A};
uint32_t tkey_seed[8] = {[0 ... 7] = 0xCEDEA5A5};
esp_err_t err = esp_hmac_calculate(hmac_key_id, ekey_seed, sizeof(ekey_seed), (uint8_t *)cfg->eky);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to calculate seed HMAC: [0x%02X] (%s)", err, esp_err_to_name(err));
return err;
}
ESP_FAULT_ASSERT(err == ESP_OK);
err = esp_hmac_calculate(hmac_key_id, tkey_seed, sizeof(tkey_seed), (uint8_t *)cfg->tky);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to calculate seed HMAC: [0x%02X] (%s)", err, esp_err_to_name(err));
return err;
}
ESP_FAULT_ASSERT(err == ESP_OK);
/* NOTE: If the XTS E-key and T-key are the same, we have a hash collision */
ESP_FAULT_ASSERT(memcmp(cfg->eky, cfg->tky, NVS_KEY_SIZE) != 0);
return ESP_OK;
}
static esp_efuse_block_t convert_key_type(hmac_key_id_t key_id) {
return (esp_efuse_block_t)(EFUSE_BLK_KEY0 + (esp_efuse_block_t) key_id);
}
static bool is_hmac_key_burnt_in_efuse(hmac_key_id_t hmac_key_id)
{
bool ret = false;
esp_efuse_block_t hmac_key_blk = convert_key_type(hmac_key_id);
esp_efuse_purpose_t hmac_efuse_blk_purpose = esp_efuse_get_key_purpose(hmac_key_blk);
if (hmac_efuse_blk_purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_UP) {
ret = true;
}
return ret;
}
static esp_err_t generate_keys_hmac(const void* scheme_cfg, nvs_sec_cfg_t* cfg)
{
if (cfg == NULL) {
return ESP_ERR_INVALID_ARG;
}
nvs_sec_config_hmac_t *scheme_cfg_hmac = (nvs_sec_config_hmac_t *)scheme_cfg;
hmac_key_id_t hmac_key = scheme_cfg_hmac->hmac_key_id;
if (hmac_key >= HMAC_KEY_MAX) {
ESP_LOGE(TAG, "Invalid HMAC key ID received!");
return ESP_ERR_INVALID_ARG;
}
esp_err_t err = ESP_FAIL;
if (!is_hmac_key_burnt_in_efuse(hmac_key)) {
uint8_t hmac_key_buf[32] = {0};
bootloader_random_enable();
esp_fill_random(hmac_key_buf, sizeof(hmac_key_buf));
bootloader_random_disable();
esp_efuse_block_t hmac_key_blk = convert_key_type(hmac_key);
err = esp_efuse_write_key(hmac_key_blk, ESP_EFUSE_KEY_PURPOSE_HMAC_UP, hmac_key_buf, sizeof(hmac_key_buf));
if (err != ESP_OK) {
if (err == ESP_ERR_EFUSE_REPEATED_PROG) {
ESP_LOGE(TAG, "Configured eFuse block for HMAC key already-in-use!");
return ESP_ERR_NVS_SEC_HMAC_KEY_BLK_ALREADY_USED;
}
ESP_LOGE(TAG, "Failed to write the HMAC key to eFuse: [0x%02X] (%s)", err, esp_err_to_name(err));
return ESP_ERR_NVS_SEC_HMAC_KEY_GENERATION_FAILED;
}
memset(hmac_key_buf, 0x00, sizeof(hmac_key_buf));
} else {
ESP_LOGW(TAG, "HMAC Key already present in configured eFuse block, using the same for NVS encryption!");
}
err = compute_nvs_keys_with_hmac(hmac_key, cfg);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to derive the encryption keys using HMAC!");
return ESP_ERR_NVS_SEC_HMAC_XTS_KEYS_DERIV_FAILED;
}
return ESP_OK;
}
static esp_err_t read_security_cfg_hmac(const void* scheme_cfg, nvs_sec_cfg_t* cfg)
{
if (cfg == NULL) {
return ESP_ERR_INVALID_ARG;
}
nvs_sec_config_hmac_t *scheme_cfg_hmac = (nvs_sec_config_hmac_t *)scheme_cfg;
hmac_key_id_t hmac_key = scheme_cfg_hmac->hmac_key_id;
if (hmac_key >= HMAC_KEY_MAX) {
ESP_LOGE(TAG, "Invalid HMAC key ID received!");
return ESP_ERR_INVALID_ARG;
}
if (!is_hmac_key_burnt_in_efuse(hmac_key)) {
ESP_LOGE(TAG, "Could not find HMAC key in configured eFuse block!");
return ESP_ERR_NVS_SEC_HMAC_KEY_NOT_FOUND;
}
esp_err_t err = compute_nvs_keys_with_hmac(hmac_key, cfg);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to derive the encryption keys using HMAC!");
return ESP_ERR_NVS_SEC_HMAC_XTS_KEYS_DERIV_FAILED;
}
return ESP_OK;
}
esp_err_t nvs_sec_provider_register_hmac(const nvs_sec_config_hmac_t *sec_scheme_cfg, nvs_sec_scheme_t **sec_scheme_handle_out)
{
if (sec_scheme_cfg == NULL || sec_scheme_handle_out == NULL) {
return ESP_ERR_INVALID_ARG;
}
nvs_sec_scheme_t *sec_scheme = calloc(1, sizeof(nvs_sec_scheme_t));
if (sec_scheme == NULL) {
return ESP_ERR_NO_MEM;
}
sec_scheme->scheme_id = NVS_SEC_SCHEME_HMAC;
sec_scheme->nvs_flash_key_gen = &generate_keys_hmac;
sec_scheme->nvs_flash_read_cfg = &read_security_cfg_hmac;
sec_scheme->scheme_data = calloc(1, sizeof(nvs_sec_config_hmac_t));
if (sec_scheme->scheme_data == NULL) {
return ESP_ERR_NO_MEM;
}
memcpy(sec_scheme->scheme_data, (void *)sec_scheme_cfg, sizeof(nvs_sec_config_hmac_t));
esp_err_t err = nvs_flash_register_security_scheme(sec_scheme);
if (err != ESP_OK) {
return err;
}
*sec_scheme_handle_out = sec_scheme;
return ESP_OK;
}
#if CONFIG_NVS_SEC_KEY_PROTECT_USING_HMAC
static void __attribute__((constructor)) nvs_sec_provider_register_hmac_ctr(void)
{
ESP_EARLY_LOGI(TAG, "NVS Encryption - Registering HMAC-based scheme...");
nvs_sec_config_hmac_t sec_scheme_cfg = NVS_SEC_PROVIDER_CFG_HMAC_DEFAULT();
nvs_sec_scheme_t *sec_scheme_handle_out = NULL;
nvs_sec_provider_register_hmac(&sec_scheme_cfg, &sec_scheme_handle_out);
}
#endif // CONFIG_NVS_SEC_KEY_PROTECT_USING_HMAC
#endif // SOC_HMAC_SUPPORTED
esp_err_t nvs_sec_provider_deregister(nvs_sec_scheme_t *sec_scheme_handle)
{
if (sec_scheme_handle == NULL) {
return ESP_ERR_INVALID_ARG;
}
if (sec_scheme_handle->scheme_data != NULL) {
free(sec_scheme_handle->scheme_data);
}
free(sec_scheme_handle);
return ESP_OK;
}
void nvs_sec_provider_include_impl(void)
{
// Linker hook, exists for no other purpose
}

Wyświetl plik

@ -54,7 +54,8 @@ menu "Partition Table"
for more information.
config PARTITION_TABLE_SINGLE_APP_ENCRYPTED_NVS
bool "Single factory app, no OTA, encrypted NVS"
depends on !ESP32_COREDUMP_ENABLE_TO_FLASH && NVS_ENCRYPTION
depends on !ESP32_COREDUMP_ENABLE_TO_FLASH && NVS_SEC_KEY_PROTECT_USING_FLASH_ENC
help
This is a variation of the default "Single factory app, no OTA" partition table
that supports encrypted NVS when using flash encryption. See the Flash Encryption section
@ -64,7 +65,7 @@ menu "Partition Table"
components/partition_table/partitions_singleapp_encr_nvs.csv
config PARTITION_TABLE_SINGLE_APP_LARGE_ENC_NVS
bool "Single factory app (large), no OTA, encrypted NVS"
depends on !ESP32_COREDUMP_ENABLE_TO_FLASH && NVS_ENCRYPTION
depends on !ESP32_COREDUMP_ENABLE_TO_FLASH && NVS_SEC_KEY_PROTECT_USING_FLASH_ENC
help
This is a variation of the "Single factory app (large), no OTA" partition table
that supports encrypted NVS when using flash encryption. See the Flash Encryption section
@ -74,7 +75,7 @@ menu "Partition Table"
components/partition_table/partitions_singleapp_large_encr_nvs.csv
config PARTITION_TABLE_TWO_OTA_ENCRYPTED_NVS
bool "Factory app, two OTA definitions, encrypted NVS"
depends on !ESP_COREDUMP_ENABLE_TO_FLASH && NVS_ENCRYPTION
depends on !ESP_COREDUMP_ENABLE_TO_FLASH && NVS_SEC_KEY_PROTECT_USING_FLASH_ENC
help
This is a variation of the "Factory app, two OTA definitions" partition table
that supports encrypted NVS when using flash encryption. See the Flash Encryption section