From 071dc73954b5e88b8ea56d1a9738e325e3d8163a Mon Sep 17 00:00:00 2001 From: Jakob Hasse Date: Wed, 27 May 2020 15:07:39 +0800 Subject: [PATCH] NVS: ensuring default partition * Also added encryption keys to CMakeLists.txt Closes https://github.com/espressif/esp-idf/issues/5347 Closes IDFGH-3372 --- components/nvs_flash/include/nvs_flash.h | 26 ++++++++++++------- components/nvs_flash/src/nvs_api.cpp | 24 +++++++++++++++++ .../nvs_flash/src/nvs_partition_manager.cpp | 8 ++++++ components/nvs_flash/test/CMakeLists.txt | 3 ++- components/nvs_flash/test/test_nvs.c | 18 +++++++++++++ .../test_nvs_host/spi_flash_emulation.cpp | 6 ++++- .../test_nvs_host/test_nvs_initialization.cpp | 16 ++++++++++++ 7 files changed, 89 insertions(+), 12 deletions(-) diff --git a/components/nvs_flash/include/nvs_flash.h b/components/nvs_flash/include/nvs_flash.h index eb5f2f9656..59d04e2d1b 100644 --- a/components/nvs_flash/include/nvs_flash.h +++ b/components/nvs_flash/include/nvs_flash.h @@ -14,13 +14,12 @@ #ifndef nvs_flash_h #define nvs_flash_h -#ifdef __cplusplus -extern "C" { -#endif - #include "nvs.h" #include "esp_partition.h" +#ifdef __cplusplus +extern "C" { +#endif #define NVS_KEY_SIZE 32 // AES-256 @@ -57,6 +56,7 @@ esp_err_t nvs_flash_init(void); * - ESP_ERR_NVS_NO_FREE_PAGES if the NVS storage contains no empty pages * (which may happen if NVS partition was truncated) * - ESP_ERR_NOT_FOUND if specified partition is not found in the partition table + * - ESP_ERR_NOT_SUPPORTED if the partition with name partition_label is not in internal flash * - one of the error codes from the underlying flash storage driver */ esp_err_t nvs_flash_init_partition(const char *partition_label); @@ -71,6 +71,7 @@ esp_err_t nvs_flash_init_partition(const char *partition_label); * - ESP_ERR_NVS_NO_FREE_PAGES if the NVS storage contains no empty pages * (which may happen if NVS partition was truncated) * - ESP_ERR_INVALID_ARG in case partition is NULL + * - ESP_ERR_NOT_SUPPORTED if the partition is not in internal flash * - one of the error codes from the underlying flash storage driver */ esp_err_t nvs_flash_init_partition_ptr(const esp_partition_t *partition); @@ -128,6 +129,7 @@ esp_err_t nvs_flash_erase(void); * - ESP_OK on success * - ESP_ERR_NOT_FOUND if there is no NVS partition with the specified name * in the partition table + * - ESP_ERR_NOT_SUPPORTED if the partition with part_name is not in internal flash * - different error in case de-initialization fails (shouldn't happen) */ esp_err_t nvs_flash_erase_partition(const char *part_name); @@ -148,6 +150,7 @@ esp_err_t nvs_flash_erase_partition(const char *part_name); * - ESP_ERR_NOT_FOUND if there is no partition with the specified * parameters in the partition table * - ESP_ERR_INVALID_ARG in case partition is NULL + * - ESP_ERR_NOT_SUPPORTED if the partition is not in internal flash * - one of the error codes from the underlying flash storage driver */ esp_err_t nvs_flash_erase_partition_ptr(const esp_partition_t *partition); @@ -183,6 +186,7 @@ esp_err_t nvs_flash_secure_init(nvs_sec_cfg_t* cfg); * - ESP_ERR_NVS_NO_FREE_PAGES if the NVS storage contains no empty pages * (which may happen if NVS partition was truncated) * - ESP_ERR_NOT_FOUND if specified partition is not found in the partition table + * - ESP_ERR_NOT_SUPPORTED if the partition is not in internal flash * - one of the error codes from the underlying flash storage driver */ esp_err_t nvs_flash_secure_init_partition(const char *partition_label, nvs_sec_cfg_t* cfg); @@ -199,8 +203,9 @@ esp_err_t nvs_flash_secure_init_partition(const char *partition_label, nvs_sec_c * * * @return - * -ESP_OK, if cfg was read successfully; - * -or error codes from esp_partition_write/erase APIs. + * - ESP_OK, if cfg was read successfully; + * - ESP_ERR_NOT_SUPPORTED if the partition is not in internal flash + * - or error codes from esp_partition_write/erase APIs. */ esp_err_t nvs_flash_generate_keys(const esp_partition_t* partition, nvs_sec_cfg_t* cfg); @@ -218,10 +223,11 @@ esp_err_t nvs_flash_generate_keys(const esp_partition_t* partition, nvs_sec_cfg_ * @note Provided parition is assumed to be marked 'encrypted'. * * @return - * -ESP_OK, if cfg was read successfully; - * -ESP_ERR_NVS_KEYS_NOT_INITIALIZED, if the partition is not yet written with keys. - * -ESP_ERR_NVS_CORRUPT_KEY_PART, if the partition containing keys is found to be corrupt - * -or error codes from esp_partition_read API. + * - ESP_OK, if cfg was read successfully; + * - ESP_ERR_NVS_KEYS_NOT_INITIALIZED, if the partition is not yet written with keys. + * - ESP_ERR_NVS_CORRUPT_KEY_PART, if the partition containing keys is found to be corrupt + * - ESP_ERR_NOT_SUPPORTED if the partition is not in internal flash + * - or error codes from esp_partition_read API. */ esp_err_t nvs_flash_read_security_cfg(const esp_partition_t* partition, nvs_sec_cfg_t* cfg); diff --git a/components/nvs_flash/src/nvs_api.cpp b/components/nvs_flash/src/nvs_api.cpp index 06d638f4c5..ee95cc2510 100644 --- a/components/nvs_flash/src/nvs_api.cpp +++ b/components/nvs_flash/src/nvs_api.cpp @@ -136,6 +136,10 @@ extern "C" esp_err_t nvs_flash_init_partition_ptr(const esp_partition_t *partiti return ESP_ERR_INVALID_ARG; } + if (partition->flash_chip != esp_flash_default_chip) { + return ESP_ERR_NOT_SUPPORTED; + } + return nvs_flash_init_custom(partition->label, partition->address / SPI_FLASH_SEC_SIZE, partition->size / SPI_FLASH_SEC_SIZE); @@ -173,6 +177,10 @@ extern "C" esp_err_t nvs_flash_secure_init_partition(const char *part_name, nvs_ return ESP_ERR_NOT_FOUND; } + if (partition->flash_chip != esp_flash_default_chip) { + return ESP_ERR_NOT_SUPPORTED; + } + return nvs_flash_secure_init_custom(part_name, partition->address / SPI_FLASH_SEC_SIZE, partition->size / SPI_FLASH_SEC_SIZE, cfg); } @@ -204,6 +212,10 @@ extern "C" esp_err_t nvs_flash_erase_partition(const char *part_name) return ESP_ERR_NOT_FOUND; } + if (partition->flash_chip != esp_flash_default_chip) { + return ESP_ERR_NOT_SUPPORTED; + } + return esp_partition_erase_range(partition, 0, partition->size); } @@ -216,6 +228,10 @@ extern "C" esp_err_t nvs_flash_erase_partition_ptr(const esp_partition_t *partit return ESP_ERR_INVALID_ARG; } + if (partition->flash_chip != esp_flash_default_chip) { + return ESP_ERR_NOT_SUPPORTED; + } + // if the partition is initialized, uninitialize it first if (NVSPartitionManager::get_instance()->lookup_storage_from_name(partition->label)) { const esp_err_t err = close_handles_and_deinit(partition->label); @@ -561,6 +577,10 @@ extern "C" esp_err_t nvs_get_used_entry_count(nvs_handle_t c_handle, size_t* use extern "C" esp_err_t nvs_flash_generate_keys(const esp_partition_t* partition, nvs_sec_cfg_t* cfg) { + if (partition->flash_chip != esp_flash_default_chip) { + return ESP_ERR_NOT_SUPPORTED; + } + auto err = esp_partition_erase_range(partition, 0, partition->size); if(err != ESP_OK) { return err; @@ -609,6 +629,10 @@ extern "C" esp_err_t nvs_flash_generate_keys(const esp_partition_t* partition, n extern "C" esp_err_t nvs_flash_read_security_cfg(const esp_partition_t* partition, nvs_sec_cfg_t* cfg) { + if (partition->flash_chip != esp_flash_default_chip) { + return ESP_ERR_NOT_SUPPORTED; + } + uint8_t eky_raw[NVS_KEY_SIZE], tky_raw[NVS_KEY_SIZE]; uint32_t crc_raw, crc_read, crc_calc; diff --git a/components/nvs_flash/src/nvs_partition_manager.cpp b/components/nvs_flash/src/nvs_partition_manager.cpp index 31108b486e..6ca672057d 100644 --- a/components/nvs_flash/src/nvs_partition_manager.cpp +++ b/components/nvs_flash/src/nvs_partition_manager.cpp @@ -45,6 +45,10 @@ esp_err_t NVSPartitionManager::init_partition(const char *partition_label) return ESP_ERR_NOT_FOUND; } + if (partition->flash_chip != esp_flash_default_chip) { + return ESP_ERR_NOT_SUPPORTED; + } + return init_custom(partition_label, partition->address / SPI_FLASH_SEC_SIZE, partition->size / SPI_FLASH_SEC_SIZE); } @@ -92,6 +96,10 @@ esp_err_t NVSPartitionManager::secure_init_partition(const char *part_name, nvs_ return ESP_ERR_NOT_FOUND; } + if (partition->flash_chip != esp_flash_default_chip) { + return ESP_ERR_NOT_SUPPORTED; + } + return secure_init_custom(part_name, partition->address / SPI_FLASH_SEC_SIZE, partition->size / SPI_FLASH_SEC_SIZE, cfg); } diff --git a/components/nvs_flash/test/CMakeLists.txt b/components/nvs_flash/test/CMakeLists.txt index 3c35870c69..71d39fe2c7 100644 --- a/components/nvs_flash/test/CMakeLists.txt +++ b/components/nvs_flash/test/CMakeLists.txt @@ -1,3 +1,4 @@ idf_component_register(SRC_DIRS "." PRIV_INCLUDE_DIRS "." - PRIV_REQUIRES unity test_utils nvs_flash bootloader_support) + PRIV_REQUIRES unity test_utils nvs_flash bootloader_support + EMBED_TXTFILES encryption_keys.bin partition_encrypted.bin sample.bin) diff --git a/components/nvs_flash/test/test_nvs.c b/components/nvs_flash/test/test_nvs.c index 529147e497..b66ffa5e75 100644 --- a/components/nvs_flash/test/test_nvs.c +++ b/components/nvs_flash/test/test_nvs.c @@ -321,6 +321,24 @@ TEST_CASE("check underlying xts code for 32-byte size sector encryption", "[nvs] TEST_ASSERT_TRUE(!memcmp(ptxt_hex, ctxt_hex, 32)); } +TEST_CASE("nvs_flash_generate_keys fails due to external partition", "[nvs_custom_part]") +{ + nvs_sec_cfg_t keys; + struct esp_flash_t spi_flash = {}; + esp_partition_t partition = {}; + partition.flash_chip = &spi_flash; + TEST_ESP_ERR(nvs_flash_generate_keys(&partition, &keys), ESP_ERR_NOT_SUPPORTED); +} + +TEST_CASE("nvs_flash_read_security_cfg fails due to external partition", "[nvs_custom_part]") +{ + nvs_sec_cfg_t keys; + struct esp_flash_t spi_flash = {}; + esp_partition_t partition = {}; + partition.flash_chip = &spi_flash; + TEST_ESP_ERR(nvs_flash_read_security_cfg(&partition, &keys), ESP_ERR_NOT_SUPPORTED); +} + TEST_CASE("Check nvs key partition APIs (read and generate keys)", "[nvs]") { nvs_sec_cfg_t cfg, cfg2; diff --git a/components/nvs_flash/test_nvs_host/spi_flash_emulation.cpp b/components/nvs_flash/test_nvs_host/spi_flash_emulation.cpp index 9881203083..10dd584d2d 100644 --- a/components/nvs_flash/test_nvs_host/spi_flash_emulation.cpp +++ b/components/nvs_flash/test_nvs_host/spi_flash_emulation.cpp @@ -12,11 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. #include "esp_spi_flash.h" +#include "esp_flash.h" #include "spi_flash_emulation.h" - static SpiFlashEmulator* s_emulator = nullptr; +static esp_flash_t esp_flash_default_chip_instance; + +esp_flash_t *esp_flash_default_chip = &esp_flash_default_chip_instance; + void spi_flash_emulator_set(SpiFlashEmulator* e) { s_emulator = e; diff --git a/components/nvs_flash/test_nvs_host/test_nvs_initialization.cpp b/components/nvs_flash/test_nvs_host/test_nvs_initialization.cpp index c709922e6f..15324d687b 100644 --- a/components/nvs_flash/test_nvs_host/test_nvs_initialization.cpp +++ b/components/nvs_flash/test_nvs_host/test_nvs_initialization.cpp @@ -29,6 +29,21 @@ TEST_CASE("nvs_flash_init_partition_ptr fails due to nullptr arg", "[nvs_custom_ CHECK(nvs_flash_init_partition_ptr(nullptr) == ESP_ERR_INVALID_ARG); } +TEST_CASE("nvs_flash_init_partition_ptr fails due to external partition", "[nvs_custom_part]") +{ + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + SpiFlashEmulator emu(10); + + struct esp_flash_t spi_flash = {}; + esp_partition_t partition = {}; + strcpy(partition.label, "test"); + partition.address = NVS_FLASH_SECTOR * SPI_FLASH_SEC_SIZE; + partition.size = NVS_FLASH_SECTOR_COUNT_MIN * SPI_FLASH_SEC_SIZE; + partition.flash_chip = &spi_flash; + CHECK(nvs_flash_init_partition_ptr(&partition) == ESP_ERR_NOT_SUPPORTED); +} + TEST_CASE("nvs_flash_init_partition_ptr inits one partition", "[nvs_custom_part]") { const uint32_t NVS_FLASH_SECTOR = 6; @@ -39,6 +54,7 @@ TEST_CASE("nvs_flash_init_partition_ptr inits one partition", "[nvs_custom_part] strcpy(partition.label, "test"); partition.address = NVS_FLASH_SECTOR * SPI_FLASH_SEC_SIZE; partition.size = NVS_FLASH_SECTOR_COUNT_MIN * SPI_FLASH_SEC_SIZE; + partition.flash_chip = esp_flash_default_chip; CHECK(nvs_flash_init_partition_ptr(&partition) == ESP_OK); CHECK(NVSPartitionManager::get_instance()->lookup_storage_from_name("test") != nullptr);