nvs_api.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. // Copyright 2015-2016 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. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. #include "nvs.hpp"
  14. #include "nvs_flash.h"
  15. #include "nvs_storage.hpp"
  16. #include "intrusive_list.h"
  17. #include "nvs_platform.hpp"
  18. #include "esp_partition.h"
  19. #include "sdkconfig.h"
  20. #ifdef CONFIG_NVS_ENCRYPTION
  21. #include "nvs_encr.hpp"
  22. #endif
  23. #ifdef ESP_PLATFORM
  24. #include <rom/crc.h>
  25. // Uncomment this line to force output from this module
  26. // #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
  27. #include "esp_log.h"
  28. static const char* TAG = "nvs";
  29. #else
  30. #include "crc.h"
  31. #define ESP_LOGD(...)
  32. #endif
  33. extern "C" void nvs_dump(const char *partName);
  34. extern "C" esp_err_t nvs_flash_init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount);
  35. #ifdef CONFIG_NVS_ENCRYPTION
  36. extern "C" esp_err_t nvs_flash_secure_init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount, nvs_sec_cfg_t* cfg);
  37. #endif
  38. class HandleEntry : public intrusive_list_node<HandleEntry>
  39. {
  40. static uint32_t s_nvs_next_handle;
  41. public:
  42. HandleEntry() {}
  43. HandleEntry(bool readOnly, uint8_t nsIndex, nvs::Storage* StoragePtr) :
  44. mHandle(++s_nvs_next_handle), // Begin the handle value with 1
  45. mReadOnly(readOnly),
  46. mNsIndex(nsIndex),
  47. mStoragePtr(StoragePtr)
  48. {
  49. }
  50. nvs_handle mHandle;
  51. uint8_t mReadOnly;
  52. uint8_t mNsIndex;
  53. nvs::Storage* mStoragePtr;
  54. };
  55. #ifdef ESP_PLATFORM
  56. SemaphoreHandle_t nvs::Lock::mSemaphore = NULL;
  57. #endif
  58. using namespace std;
  59. using namespace nvs;
  60. static intrusive_list<HandleEntry> s_nvs_handles;
  61. uint32_t HandleEntry::s_nvs_next_handle;
  62. static intrusive_list<nvs::Storage> s_nvs_storage_list;
  63. static nvs::Storage* lookup_storage_from_name(const char *name)
  64. {
  65. auto it = find_if(begin(s_nvs_storage_list), end(s_nvs_storage_list), [=](Storage& e) -> bool {
  66. return (strcmp(e.getPartName(), name) == 0);
  67. });
  68. if (it == end(s_nvs_storage_list)) {
  69. return NULL;
  70. }
  71. return it;
  72. }
  73. extern "C" void nvs_dump(const char *partName)
  74. {
  75. Lock lock;
  76. nvs::Storage* pStorage;
  77. pStorage = lookup_storage_from_name(partName);
  78. if (pStorage == NULL) {
  79. return;
  80. }
  81. pStorage->debugDump();
  82. return;
  83. }
  84. extern "C" esp_err_t nvs_flash_init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount)
  85. {
  86. ESP_LOGD(TAG, "nvs_flash_init_custom partition=%s start=%d count=%d", partName, baseSector, sectorCount);
  87. nvs::Storage* new_storage = NULL;
  88. nvs::Storage* storage = lookup_storage_from_name(partName);
  89. if (storage == NULL) {
  90. new_storage = new (std::nothrow) nvs::Storage((const char *)partName);
  91. if (!new_storage) return ESP_ERR_NO_MEM;
  92. storage = new_storage;
  93. }
  94. esp_err_t err = storage->init(baseSector, sectorCount);
  95. if (new_storage != NULL) {
  96. if (err == ESP_OK) {
  97. s_nvs_storage_list.push_back(new_storage);
  98. } else {
  99. delete new_storage;
  100. }
  101. }
  102. return err;
  103. }
  104. #ifdef CONFIG_NVS_ENCRYPTION
  105. extern "C" esp_err_t nvs_flash_secure_init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount, nvs_sec_cfg_t* cfg)
  106. {
  107. ESP_LOGD(TAG, "nvs_flash_secure_init_custom partition=%s start=%d count=%d", partName, baseSector, sectorCount);
  108. if(cfg) {
  109. auto encrMgr = EncrMgr::getInstance();
  110. if (!encrMgr) return ESP_ERR_NO_MEM;
  111. auto err = encrMgr->setSecurityContext(baseSector, sectorCount, cfg);
  112. if(err != ESP_OK) {
  113. return err;
  114. }
  115. }
  116. return nvs_flash_init_custom(partName, baseSector, sectorCount);
  117. }
  118. #endif
  119. static esp_err_t close_handles_and_deinit(const char* part_name)
  120. {
  121. nvs::Storage* storage = lookup_storage_from_name(part_name);
  122. if (!storage) {
  123. return ESP_ERR_NVS_NOT_INITIALIZED;
  124. }
  125. #ifdef CONFIG_NVS_ENCRYPTION
  126. if(EncrMgr::isEncrActive()) {
  127. auto encrMgr = EncrMgr::getInstance();
  128. encrMgr->removeSecurityContext(storage->getBaseSector());
  129. }
  130. #endif
  131. /* Clean up handles related to the storage being deinitialized */
  132. auto it = s_nvs_handles.begin();
  133. auto next = it;
  134. while(it != s_nvs_handles.end()) {
  135. next++;
  136. if (it->mStoragePtr == storage) {
  137. ESP_LOGD(TAG, "Deleting handle %d (ns=%d) related to partition \"%s\" (missing call to nvs_close?)",
  138. it->mHandle, it->mNsIndex, part_name);
  139. s_nvs_handles.erase(it);
  140. delete static_cast<HandleEntry*>(it);
  141. }
  142. it = next;
  143. }
  144. /* Finally delete the storage itself */
  145. s_nvs_storage_list.erase(storage);
  146. delete storage;
  147. return ESP_OK;
  148. }
  149. #ifdef ESP_PLATFORM
  150. extern "C" esp_err_t nvs_flash_init_partition(const char *part_name)
  151. {
  152. Lock::init();
  153. Lock lock;
  154. nvs::Storage* mStorage;
  155. mStorage = lookup_storage_from_name(part_name);
  156. if (mStorage) {
  157. return ESP_OK;
  158. }
  159. const esp_partition_t* partition = esp_partition_find_first(
  160. ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, part_name);
  161. if (partition == NULL) {
  162. return ESP_ERR_NOT_FOUND;
  163. }
  164. return nvs_flash_init_custom(part_name, partition->address / SPI_FLASH_SEC_SIZE,
  165. partition->size / SPI_FLASH_SEC_SIZE);
  166. }
  167. extern "C" esp_err_t nvs_flash_init(void)
  168. {
  169. return nvs_flash_init_partition(NVS_DEFAULT_PART_NAME);
  170. }
  171. #ifdef CONFIG_NVS_ENCRYPTION
  172. extern "C" esp_err_t nvs_flash_secure_init_partition(const char *part_name, nvs_sec_cfg_t* cfg)
  173. {
  174. Lock::init();
  175. Lock lock;
  176. nvs::Storage* mStorage;
  177. mStorage = lookup_storage_from_name(part_name);
  178. if (mStorage) {
  179. return ESP_OK;
  180. }
  181. const esp_partition_t* partition = esp_partition_find_first(
  182. ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, part_name);
  183. if (partition == NULL) {
  184. return ESP_ERR_NOT_FOUND;
  185. }
  186. return nvs_flash_secure_init_custom(part_name, partition->address / SPI_FLASH_SEC_SIZE,
  187. partition->size / SPI_FLASH_SEC_SIZE, cfg);
  188. }
  189. extern "C" esp_err_t nvs_flash_secure_init(nvs_sec_cfg_t* cfg)
  190. {
  191. return nvs_flash_secure_init_partition(NVS_DEFAULT_PART_NAME, cfg);
  192. }
  193. #endif
  194. extern "C" esp_err_t nvs_flash_erase_partition(const char *part_name)
  195. {
  196. Lock::init();
  197. Lock lock;
  198. // if the partition is initialized, uninitialize it first
  199. if (lookup_storage_from_name(part_name)) {
  200. esp_err_t err = close_handles_and_deinit(part_name);
  201. // only hypothetical/future case, deinit_partition() only fails if partition is uninitialized
  202. if (err != ESP_OK) {
  203. return err;
  204. }
  205. }
  206. const esp_partition_t* partition = esp_partition_find_first(
  207. ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, part_name);
  208. if (partition == NULL) {
  209. return ESP_ERR_NOT_FOUND;
  210. }
  211. return esp_partition_erase_range(partition, 0, partition->size);
  212. }
  213. extern "C" esp_err_t nvs_flash_erase()
  214. {
  215. return nvs_flash_erase_partition(NVS_DEFAULT_PART_NAME);
  216. }
  217. #endif // ESP_PLATFORM
  218. extern "C" esp_err_t nvs_flash_deinit_partition(const char* partition_name)
  219. {
  220. Lock::init();
  221. Lock lock;
  222. return close_handles_and_deinit(partition_name);
  223. }
  224. extern "C" esp_err_t nvs_flash_deinit(void)
  225. {
  226. return nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME);
  227. }
  228. static esp_err_t nvs_find_ns_handle(nvs_handle handle, HandleEntry& entry)
  229. {
  230. auto it = find_if(begin(s_nvs_handles), end(s_nvs_handles), [=](HandleEntry& e) -> bool {
  231. return e.mHandle == handle;
  232. });
  233. if (it == end(s_nvs_handles)) {
  234. return ESP_ERR_NVS_INVALID_HANDLE;
  235. }
  236. entry = *it;
  237. return ESP_OK;
  238. }
  239. extern "C" esp_err_t nvs_open_from_partition(const char *part_name, const char* name, nvs_open_mode open_mode, nvs_handle *out_handle)
  240. {
  241. Lock lock;
  242. ESP_LOGD(TAG, "%s %s %d", __func__, name, open_mode);
  243. uint8_t nsIndex;
  244. nvs::Storage* sHandle;
  245. sHandle = lookup_storage_from_name(part_name);
  246. if (sHandle == NULL) {
  247. return ESP_ERR_NVS_PART_NOT_FOUND;
  248. }
  249. esp_err_t err = sHandle->createOrOpenNamespace(name, open_mode == NVS_READWRITE, nsIndex);
  250. if (err != ESP_OK) {
  251. return err;
  252. }
  253. HandleEntry *handle_entry = new (std::nothrow) HandleEntry(open_mode==NVS_READONLY, nsIndex, sHandle);
  254. if (!handle_entry) return ESP_ERR_NO_MEM;
  255. s_nvs_handles.push_back(handle_entry);
  256. *out_handle = handle_entry->mHandle;
  257. return ESP_OK;
  258. }
  259. extern "C" esp_err_t nvs_open(const char* name, nvs_open_mode open_mode, nvs_handle *out_handle)
  260. {
  261. if (s_nvs_storage_list.size() == 0) {
  262. return ESP_ERR_NVS_NOT_INITIALIZED;
  263. }
  264. return nvs_open_from_partition(NVS_DEFAULT_PART_NAME, name, open_mode, out_handle);
  265. }
  266. extern "C" void nvs_close(nvs_handle handle)
  267. {
  268. Lock lock;
  269. ESP_LOGD(TAG, "%s %d", __func__, handle);
  270. auto it = find_if(begin(s_nvs_handles), end(s_nvs_handles), [=](HandleEntry& e) -> bool {
  271. return e.mHandle == handle;
  272. });
  273. if (it == end(s_nvs_handles)) {
  274. return;
  275. }
  276. s_nvs_handles.erase(it);
  277. delete static_cast<HandleEntry*>(it);
  278. }
  279. extern "C" esp_err_t nvs_erase_key(nvs_handle handle, const char* key)
  280. {
  281. Lock lock;
  282. ESP_LOGD(TAG, "%s %s\r\n", __func__, key);
  283. HandleEntry entry;
  284. auto err = nvs_find_ns_handle(handle, entry);
  285. if (err != ESP_OK) {
  286. return err;
  287. }
  288. if (entry.mReadOnly) {
  289. return ESP_ERR_NVS_READ_ONLY;
  290. }
  291. return entry.mStoragePtr->eraseItem(entry.mNsIndex, key);
  292. }
  293. extern "C" esp_err_t nvs_erase_all(nvs_handle handle)
  294. {
  295. Lock lock;
  296. ESP_LOGD(TAG, "%s\r\n", __func__);
  297. HandleEntry entry;
  298. auto err = nvs_find_ns_handle(handle, entry);
  299. if (err != ESP_OK) {
  300. return err;
  301. }
  302. if (entry.mReadOnly) {
  303. return ESP_ERR_NVS_READ_ONLY;
  304. }
  305. return entry.mStoragePtr->eraseNamespace(entry.mNsIndex);
  306. }
  307. template<typename T>
  308. static esp_err_t nvs_set(nvs_handle handle, const char* key, T value)
  309. {
  310. Lock lock;
  311. ESP_LOGD(TAG, "%s %s %d %d", __func__, key, sizeof(T), (uint32_t) value);
  312. HandleEntry entry;
  313. auto err = nvs_find_ns_handle(handle, entry);
  314. if (err != ESP_OK) {
  315. return err;
  316. }
  317. if (entry.mReadOnly) {
  318. return ESP_ERR_NVS_READ_ONLY;
  319. }
  320. return entry.mStoragePtr->writeItem(entry.mNsIndex, key, value);
  321. }
  322. extern "C" esp_err_t nvs_set_i8 (nvs_handle handle, const char* key, int8_t value)
  323. {
  324. return nvs_set(handle, key, value);
  325. }
  326. extern "C" esp_err_t nvs_set_u8 (nvs_handle handle, const char* key, uint8_t value)
  327. {
  328. return nvs_set(handle, key, value);
  329. }
  330. extern "C" esp_err_t nvs_set_i16 (nvs_handle handle, const char* key, int16_t value)
  331. {
  332. return nvs_set(handle, key, value);
  333. }
  334. extern "C" esp_err_t nvs_set_u16 (nvs_handle handle, const char* key, uint16_t value)
  335. {
  336. return nvs_set(handle, key, value);
  337. }
  338. extern "C" esp_err_t nvs_set_i32 (nvs_handle handle, const char* key, int32_t value)
  339. {
  340. return nvs_set(handle, key, value);
  341. }
  342. extern "C" esp_err_t nvs_set_u32 (nvs_handle handle, const char* key, uint32_t value)
  343. {
  344. return nvs_set(handle, key, value);
  345. }
  346. extern "C" esp_err_t nvs_set_i64 (nvs_handle handle, const char* key, int64_t value)
  347. {
  348. return nvs_set(handle, key, value);
  349. }
  350. extern "C" esp_err_t nvs_set_u64 (nvs_handle handle, const char* key, uint64_t value)
  351. {
  352. return nvs_set(handle, key, value);
  353. }
  354. extern "C" esp_err_t nvs_commit(nvs_handle handle)
  355. {
  356. Lock lock;
  357. // no-op for now, to be used when intermediate cache is added
  358. HandleEntry entry;
  359. return nvs_find_ns_handle(handle, entry);
  360. }
  361. extern "C" esp_err_t nvs_set_str(nvs_handle handle, const char* key, const char* value)
  362. {
  363. Lock lock;
  364. ESP_LOGD(TAG, "%s %s %s", __func__, key, value);
  365. HandleEntry entry;
  366. auto err = nvs_find_ns_handle(handle, entry);
  367. if (err != ESP_OK) {
  368. return err;
  369. }
  370. return entry.mStoragePtr->writeItem(entry.mNsIndex, nvs::ItemType::SZ, key, value, strlen(value) + 1);
  371. }
  372. extern "C" esp_err_t nvs_set_blob(nvs_handle handle, const char* key, const void* value, size_t length)
  373. {
  374. Lock lock;
  375. ESP_LOGD(TAG, "%s %s %d", __func__, key, length);
  376. HandleEntry entry;
  377. auto err = nvs_find_ns_handle(handle, entry);
  378. if (err != ESP_OK) {
  379. return err;
  380. }
  381. return entry.mStoragePtr->writeItem(entry.mNsIndex, nvs::ItemType::BLOB, key, value, length);
  382. }
  383. template<typename T>
  384. static esp_err_t nvs_get(nvs_handle handle, const char* key, T* out_value)
  385. {
  386. Lock lock;
  387. ESP_LOGD(TAG, "%s %s %d", __func__, key, sizeof(T));
  388. HandleEntry entry;
  389. auto err = nvs_find_ns_handle(handle, entry);
  390. if (err != ESP_OK) {
  391. return err;
  392. }
  393. return entry.mStoragePtr->readItem(entry.mNsIndex, key, *out_value);
  394. }
  395. extern "C" esp_err_t nvs_get_i8 (nvs_handle handle, const char* key, int8_t* out_value)
  396. {
  397. return nvs_get(handle, key, out_value);
  398. }
  399. extern "C" esp_err_t nvs_get_u8 (nvs_handle handle, const char* key, uint8_t* out_value)
  400. {
  401. return nvs_get(handle, key, out_value);
  402. }
  403. extern "C" esp_err_t nvs_get_i16 (nvs_handle handle, const char* key, int16_t* out_value)
  404. {
  405. return nvs_get(handle, key, out_value);
  406. }
  407. extern "C" esp_err_t nvs_get_u16 (nvs_handle handle, const char* key, uint16_t* out_value)
  408. {
  409. return nvs_get(handle, key, out_value);
  410. }
  411. extern "C" esp_err_t nvs_get_i32 (nvs_handle handle, const char* key, int32_t* out_value)
  412. {
  413. return nvs_get(handle, key, out_value);
  414. }
  415. extern "C" esp_err_t nvs_get_u32 (nvs_handle handle, const char* key, uint32_t* out_value)
  416. {
  417. return nvs_get(handle, key, out_value);
  418. }
  419. extern "C" esp_err_t nvs_get_i64 (nvs_handle handle, const char* key, int64_t* out_value)
  420. {
  421. return nvs_get(handle, key, out_value);
  422. }
  423. extern "C" esp_err_t nvs_get_u64 (nvs_handle handle, const char* key, uint64_t* out_value)
  424. {
  425. return nvs_get(handle, key, out_value);
  426. }
  427. static esp_err_t nvs_get_str_or_blob(nvs_handle handle, nvs::ItemType type, const char* key, void* out_value, size_t* length)
  428. {
  429. Lock lock;
  430. ESP_LOGD(TAG, "%s %s", __func__, key);
  431. HandleEntry entry;
  432. auto err = nvs_find_ns_handle(handle, entry);
  433. if (err != ESP_OK) {
  434. return err;
  435. }
  436. size_t dataSize;
  437. err = entry.mStoragePtr->getItemDataSize(entry.mNsIndex, type, key, dataSize);
  438. if (err != ESP_OK) {
  439. return err;
  440. }
  441. if (length == nullptr) {
  442. return ESP_ERR_NVS_INVALID_LENGTH;
  443. } else if (out_value == nullptr) {
  444. *length = dataSize;
  445. return ESP_OK;
  446. } else if (*length < dataSize) {
  447. *length = dataSize;
  448. return ESP_ERR_NVS_INVALID_LENGTH;
  449. }
  450. *length = dataSize;
  451. return entry.mStoragePtr->readItem(entry.mNsIndex, type, key, out_value, dataSize);
  452. }
  453. extern "C" esp_err_t nvs_get_str(nvs_handle handle, const char* key, char* out_value, size_t* length)
  454. {
  455. return nvs_get_str_or_blob(handle, nvs::ItemType::SZ, key, out_value, length);
  456. }
  457. extern "C" esp_err_t nvs_get_blob(nvs_handle handle, const char* key, void* out_value, size_t* length)
  458. {
  459. return nvs_get_str_or_blob(handle, nvs::ItemType::BLOB, key, out_value, length);
  460. }
  461. extern "C" esp_err_t nvs_get_stats(const char* part_name, nvs_stats_t* nvs_stats)
  462. {
  463. Lock lock;
  464. nvs::Storage* pStorage;
  465. if (nvs_stats == NULL) {
  466. return ESP_ERR_INVALID_ARG;
  467. }
  468. nvs_stats->used_entries = 0;
  469. nvs_stats->free_entries = 0;
  470. nvs_stats->total_entries = 0;
  471. nvs_stats->namespace_count = 0;
  472. pStorage = lookup_storage_from_name((part_name == NULL) ? NVS_DEFAULT_PART_NAME : part_name);
  473. if (pStorage == NULL) {
  474. return ESP_ERR_NVS_NOT_INITIALIZED;
  475. }
  476. if(!pStorage->isValid()){
  477. return ESP_ERR_NVS_INVALID_STATE;
  478. }
  479. return pStorage->fillStats(*nvs_stats);
  480. }
  481. extern "C" esp_err_t nvs_get_used_entry_count(nvs_handle handle, size_t* used_entries)
  482. {
  483. Lock lock;
  484. if(used_entries == NULL){
  485. return ESP_ERR_INVALID_ARG;
  486. }
  487. *used_entries = 0;
  488. HandleEntry entry;
  489. auto err = nvs_find_ns_handle(handle, entry);
  490. if (err != ESP_OK) {
  491. return err;
  492. }
  493. size_t used_entry_count;
  494. err = entry.mStoragePtr->calcEntriesInNamespace(entry.mNsIndex, used_entry_count);
  495. if(err == ESP_OK){
  496. *used_entries = used_entry_count;
  497. }
  498. return err;
  499. }
  500. #if (defined CONFIG_NVS_ENCRYPTION) && (defined ESP_PLATFORM)
  501. extern "C" esp_err_t nvs_flash_generate_keys(const esp_partition_t* partition, nvs_sec_cfg_t* cfg)
  502. {
  503. auto err = esp_partition_erase_range(partition, 0, partition->size);
  504. if(err != ESP_OK) {
  505. return err;
  506. }
  507. for(uint8_t cnt = 0; cnt < NVS_KEY_SIZE; cnt++) {
  508. cfg->eky[cnt] = 0xff;
  509. cfg->tky[cnt] = 0xee;
  510. }
  511. err = spi_flash_write(partition->address, cfg->eky, NVS_KEY_SIZE);
  512. if(err != ESP_OK) {
  513. return err;
  514. }
  515. err = spi_flash_write(partition->address + NVS_KEY_SIZE, cfg->tky, NVS_KEY_SIZE);
  516. if(err != ESP_OK) {
  517. return err;
  518. }
  519. err = esp_partition_read(partition, 0, cfg->eky, NVS_KEY_SIZE);
  520. if(err != ESP_OK) {
  521. return err;
  522. }
  523. err = esp_partition_read(partition, NVS_KEY_SIZE, cfg->tky, NVS_KEY_SIZE);
  524. if(err != ESP_OK) {
  525. return err;
  526. }
  527. uint32_t crc_calc = crc32_le(0xffffffff, cfg->eky, NVS_KEY_SIZE);
  528. crc_calc = crc32_le(crc_calc, cfg->tky, NVS_KEY_SIZE);
  529. uint8_t crc_wr[16];
  530. memset(crc_wr, 0xff, sizeof(crc_wr));
  531. memcpy(crc_wr, &crc_calc, 4);
  532. err = esp_partition_write(partition, 2 * NVS_KEY_SIZE, crc_wr, sizeof(crc_wr));
  533. if(err != ESP_OK) {
  534. return err;
  535. }
  536. return ESP_OK;
  537. }
  538. extern "C" esp_err_t nvs_flash_read_security_cfg(const esp_partition_t* partition, nvs_sec_cfg_t* cfg)
  539. {
  540. uint8_t eky_raw[NVS_KEY_SIZE], tky_raw[NVS_KEY_SIZE];
  541. uint32_t crc_raw, crc_read, crc_calc;
  542. auto check_if_initialized = [](uint8_t* eky, uint8_t* tky, uint32_t crc) {
  543. uint8_t cnt = 0;
  544. while(cnt < NVS_KEY_SIZE && eky[cnt] == 0xff && tky[cnt] == 0xff) cnt++;
  545. if(cnt == NVS_KEY_SIZE && crc == 0xffffffff) {
  546. return false;
  547. }
  548. return true;
  549. };
  550. auto err = spi_flash_read(partition->address, eky_raw, NVS_KEY_SIZE);
  551. if(err != ESP_OK) {
  552. return err;
  553. }
  554. err = spi_flash_read(partition->address + NVS_KEY_SIZE, tky_raw, NVS_KEY_SIZE);
  555. if(err != ESP_OK) {
  556. return err;
  557. }
  558. err = spi_flash_read(partition->address + 2 * NVS_KEY_SIZE, &crc_raw, 4);
  559. if(err != ESP_OK) {
  560. return err;
  561. }
  562. if(!check_if_initialized(eky_raw, tky_raw, crc_raw)) {
  563. /* This is an uninitialized key partition*/
  564. return ESP_ERR_NVS_KEYS_NOT_INITIALIZED;
  565. }
  566. err = esp_partition_read(partition, 0, cfg->eky, NVS_KEY_SIZE);
  567. if(err != ESP_OK) {
  568. return err;
  569. }
  570. err = esp_partition_read(partition, NVS_KEY_SIZE, cfg->tky, NVS_KEY_SIZE);
  571. if(err != ESP_OK) {
  572. return err;
  573. }
  574. err = esp_partition_read(partition, 2 * NVS_KEY_SIZE, &crc_read, 4);
  575. if(err != ESP_OK) {
  576. return err;
  577. }
  578. crc_calc = crc32_le(0xffffffff, cfg->eky, NVS_KEY_SIZE);
  579. crc_calc = crc32_le(crc_calc, cfg->tky, NVS_KEY_SIZE);
  580. if(crc_calc != crc_read) {
  581. if(!check_if_initialized(cfg->eky, cfg->tky, crc_read)) {
  582. /* This is an uninitialized key partition*/
  583. return ESP_ERR_NVS_KEYS_NOT_INITIALIZED;
  584. }
  585. return ESP_ERR_NVS_CORRUPT_KEY_PART;
  586. }
  587. return ESP_OK;
  588. }
  589. #endif