Enable NVS and flash encryption at rest (fw 0.8.3).
Add initEncryptedStorage, development-mode Kconfig defaults, production overlay, and security HIL docs; wire NetBootstrap through encrypted NVS bring-up. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -7,7 +7,7 @@ idf_component_register(
|
||||
"src/NetBootstrap.cpp"
|
||||
INCLUDE_DIRS "include"
|
||||
EMBED_FILES "www/index.html.gz"
|
||||
REQUIRES core esp_wifi esp_netif esp_event nvs_flash esp_http_server tuner audio bluetooth station integration bt1035
|
||||
REQUIRES core esp_wifi esp_netif esp_event nvs_flash esp_http_server secure_store tuner audio bluetooth station integration bt1035
|
||||
)
|
||||
|
||||
target_compile_features(${COMPONENT_LIB} PUBLIC cxx_std_23)
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
#include "esp_log.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "audio/AudioService.hpp"
|
||||
#include "bluetooth/BluetoothService.hpp"
|
||||
#include "secure_store/NvsPlatformInit.hpp"
|
||||
#include "station/StationService.hpp"
|
||||
#include "tuner/TunerService.hpp"
|
||||
|
||||
@@ -38,21 +38,16 @@ constexpr char kTag[] = "NetBootstrap";
|
||||
*
|
||||
* @dname initPlatform
|
||||
* @return Ok on success, or a NetError describing the failure.
|
||||
* @pubstate initialises NVS, esp_netif, and the default event loop.
|
||||
* @pubstate initialises encrypted NVS, esp_netif, and the default event loop.
|
||||
*
|
||||
* @author Michele Bigi
|
||||
* @date 2026-07-06
|
||||
*/
|
||||
[[nodiscard]] std::expected<void, NetError> initPlatform()
|
||||
{
|
||||
esp_err_t nvsErr = nvs_flash_init();
|
||||
if (nvsErr == ESP_ERR_NVS_NO_FREE_PAGES
|
||||
|| nvsErr == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
nvsErr = nvs_flash_init();
|
||||
}
|
||||
if (nvsErr != ESP_OK) {
|
||||
ESP_LOGE(kTag, "nvs_flash_init failed");
|
||||
const auto nvsResult = secure_store::initEncryptedStorage();
|
||||
if (!nvsResult) {
|
||||
ESP_LOGE(kTag, "encrypted NVS init failed");
|
||||
return std::unexpected(NetError::NvsInitFailed);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace net {
|
||||
|
||||
namespace {
|
||||
constexpr char kTag[] = "SetupWebServer";
|
||||
constexpr char kFirmwareVersion[] = "0.8.2";
|
||||
constexpr char kFirmwareVersion[] = "0.8.3";
|
||||
constexpr unsigned kRebootDelaySec = 3;
|
||||
|
||||
extern const uint8_t www_index_html_gz_start[] asm(
|
||||
|
||||
@@ -2,6 +2,7 @@ idf_component_register(
|
||||
SRCS
|
||||
"src/NvsSecureStore.cpp"
|
||||
"src/NvsAudioProfileStore.cpp"
|
||||
"src/NvsPlatformInit.cpp"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES core nvs_flash
|
||||
)
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @file NvsPlatformInit.hpp
|
||||
* @brief Encrypted NVS partition bring-up for ISecureStore backends.
|
||||
*
|
||||
* DigiRadio firmware — https://github.com/manvalan/DigiRadio
|
||||
*
|
||||
* Copyright 2026 Michele Bigi
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @author Michele Bigi
|
||||
* @date 2026-07-07
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <expected>
|
||||
|
||||
namespace secure_store {
|
||||
|
||||
/**
|
||||
* @brief NvsInitError — failure mode for encrypted NVS initialisation.
|
||||
*
|
||||
* @dname NvsInitError
|
||||
* @return n/a (type)
|
||||
* @pubstate none
|
||||
*
|
||||
* @author Michele Bigi
|
||||
* @date 2026-07-07
|
||||
*/
|
||||
enum class NvsInitError {
|
||||
EraseFailed, ///< nvs_flash_erase failed during recovery.
|
||||
InitFailed, ///< nvs_flash_init failed after recovery attempt.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief initEncryptedStorage — initialise default NVS (+ nvs_keys when enabled).
|
||||
*
|
||||
* @dname initEncryptedStorage
|
||||
* @return Ok on success, or NvsInitError describing the failure.
|
||||
* @pubstate When CONFIG_NVS_ENCRYPTION is set, nvs_flash_init() uses the
|
||||
* nvs_keys partition and flash-encryption key protection per
|
||||
* ESP-IDF v5.5 security docs. Erases and retries on layout mismatch.
|
||||
*
|
||||
* @author Michele Bigi
|
||||
* @date 2026-07-07
|
||||
*/
|
||||
[[nodiscard]] std::expected<void, NvsInitError> initEncryptedStorage() noexcept;
|
||||
|
||||
} // namespace secure_store
|
||||
@@ -12,9 +12,9 @@
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Production builds should enable NVS encryption (nvs_keys partition in
|
||||
* partitions.csv) per ESP-IDF security docs; this slice uses plain NVS
|
||||
* for development bring-up.
|
||||
* Production: NVS encryption + flash encryption enabled in sdkconfig.defaults
|
||||
* (fw 0.8.3+). Call secure_store::initEncryptedStorage() before first use;
|
||||
* see docs/security-flash-nvs.md.
|
||||
*
|
||||
* @author Michele Bigi
|
||||
* @date 2026-07-06
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* @file NvsPlatformInit.cpp
|
||||
* @brief Encrypted NVS partition bring-up implementation.
|
||||
*
|
||||
* DigiRadio firmware — https://github.com/manvalan/DigiRadio
|
||||
*
|
||||
* Copyright 2026 Michele Bigi
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @author Michele Bigi
|
||||
* @date 2026-07-07
|
||||
*/
|
||||
|
||||
#include "secure_store/NvsPlatformInit.hpp"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
namespace secure_store {
|
||||
|
||||
namespace {
|
||||
constexpr char kTag[] = "NvsPlatformInit";
|
||||
|
||||
/**
|
||||
* @brief logEncryptionMode — log active NVS security Kconfig (no secrets).
|
||||
*
|
||||
* @dname logEncryptionMode
|
||||
* @pubstate none; INFO log only.
|
||||
*
|
||||
* @author Michele Bigi
|
||||
* @date 2026-07-07
|
||||
*/
|
||||
void logEncryptionMode() noexcept
|
||||
{
|
||||
#if CONFIG_NVS_ENCRYPTION
|
||||
ESP_LOGI(kTag, "NVS encryption enabled");
|
||||
#if CONFIG_SECURE_FLASH_ENC_ENABLED
|
||||
ESP_LOGI(kTag, "Flash encryption enabled (development=%d)",
|
||||
static_cast<int>(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT));
|
||||
#else
|
||||
ESP_LOGW(kTag, "NVS encryption without flash encryption — check Kconfig");
|
||||
#endif
|
||||
#else
|
||||
ESP_LOGW(kTag, "NVS encryption disabled — not for production");
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::expected<void, NvsInitError> initEncryptedStorage() noexcept
|
||||
{
|
||||
logEncryptionMode();
|
||||
|
||||
esp_err_t err = nvs_flash_init();
|
||||
if (err == ESP_ERR_NVS_NO_FREE_PAGES
|
||||
|| err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_LOGW(kTag, "NVS partition needs erase (err=0x%x)", static_cast<unsigned>(err));
|
||||
err = nvs_flash_erase();
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(kTag, "nvs_flash_erase failed (0x%x)", static_cast<unsigned>(err));
|
||||
return std::unexpected(NvsInitError::EraseFailed);
|
||||
}
|
||||
err = nvs_flash_init();
|
||||
}
|
||||
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(kTag, "nvs_flash_init failed (0x%x)", static_cast<unsigned>(err));
|
||||
return std::unexpected(NvsInitError::InitFailed);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace secure_store
|
||||
Reference in New Issue
Block a user