nvs_api.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  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 nvs::Storage((const char *)partName);
  91. storage = new_storage;
  92. }
  93. esp_err_t err = storage->init(baseSector, sectorCount);
  94. if (new_storage != NULL) {
  95. if (err == ESP_OK) {
  96. s_nvs_storage_list.push_back(new_storage);
  97. } else {
  98. delete new_storage;
  99. }
  100. }
  101. return err;
  102. }
  103. #ifdef CONFIG_NVS_ENCRYPTION
  104. extern "C" esp_err_t nvs_flash_secure_init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount, nvs_sec_cfg_t* cfg)
  105. {
  106. ESP_LOGD(TAG, "nvs_flash_secure_init_custom partition=%s start=%d count=%d", partName, baseSector, sectorCount);
  107. if(cfg) {
  108. auto encrMgr = EncrMgr::getInstance();
  109. auto err = encrMgr->setSecurityContext(baseSector, sectorCount, cfg);
  110. if(err != ESP_OK) {
  111. return err;
  112. }
  113. }
  114. return nvs_flash_init_custom(partName, baseSector, sectorCount);
  115. }
  116. #endif
  117. #ifdef ESP_PLATFORM
  118. extern "C" esp_err_t nvs_flash_init_partition(const char *part_name)
  119. {
  120. Lock::init();
  121. Lock lock;
  122. nvs::Storage* mStorage;
  123. mStorage = lookup_storage_from_name(part_name);
  124. if (mStorage) {
  125. return ESP_OK;
  126. }
  127. const esp_partition_t* partition = esp_partition_find_first(
  128. ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, part_name);
  129. if (partition == NULL) {
  130. return ESP_ERR_NOT_FOUND;
  131. }
  132. return nvs_flash_init_custom(part_name, partition->address / SPI_FLASH_SEC_SIZE,
  133. partition->size / SPI_FLASH_SEC_SIZE);
  134. }
  135. extern "C" esp_err_t nvs_flash_init(void)
  136. {
  137. return nvs_flash_init_partition(NVS_DEFAULT_PART_NAME);
  138. }
  139. #ifdef CONFIG_NVS_ENCRYPTION
  140. extern "C" esp_err_t nvs_flash_secure_init_partition(const char *part_name, nvs_sec_cfg_t* cfg)
  141. {
  142. Lock::init();
  143. Lock lock;
  144. nvs::Storage* mStorage;
  145. mStorage = lookup_storage_from_name(part_name);
  146. if (mStorage) {
  147. return ESP_OK;
  148. }
  149. const esp_partition_t* partition = esp_partition_find_first(
  150. ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, part_name);
  151. if (partition == NULL) {
  152. return ESP_ERR_NOT_FOUND;
  153. }
  154. return nvs_flash_secure_init_custom(part_name, partition->address / SPI_FLASH_SEC_SIZE,
  155. partition->size / SPI_FLASH_SEC_SIZE, cfg);
  156. }
  157. extern "C" esp_err_t nvs_flash_secure_init(nvs_sec_cfg_t* cfg)
  158. {
  159. return nvs_flash_secure_init_partition(NVS_DEFAULT_PART_NAME, cfg);
  160. }
  161. #endif
  162. extern "C" esp_err_t nvs_flash_erase_partition(const char *part_name)
  163. {
  164. const esp_partition_t* partition = esp_partition_find_first(
  165. ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, part_name);
  166. if (partition == NULL) {
  167. return ESP_ERR_NOT_FOUND;
  168. }
  169. return esp_partition_erase_range(partition, 0, partition->size);
  170. }
  171. extern "C" esp_err_t nvs_flash_erase()
  172. {
  173. return nvs_flash_erase_partition(NVS_DEFAULT_PART_NAME);
  174. }
  175. #endif // ESP_PLATFORM
  176. extern "C" esp_err_t nvs_flash_deinit_partition(const char* partition_name)
  177. {
  178. Lock::init();
  179. Lock lock;
  180. nvs::Storage* storage = lookup_storage_from_name(partition_name);
  181. if (!storage) {
  182. return ESP_ERR_NVS_NOT_INITIALIZED;
  183. }
  184. #ifdef CONFIG_NVS_ENCRYPTION
  185. if(EncrMgr::isEncrActive()) {
  186. auto encrMgr = EncrMgr::getInstance();
  187. encrMgr->removeSecurityContext(storage->getBaseSector());
  188. }
  189. #endif
  190. /* Clean up handles related to the storage being deinitialized */
  191. auto it = s_nvs_handles.begin();
  192. auto next = it;
  193. while(it != s_nvs_handles.end()) {
  194. next++;
  195. if (it->mStoragePtr == storage) {
  196. ESP_LOGD(TAG, "Deleting handle %d (ns=%d) related to partition \"%s\" (missing call to nvs_close?)",
  197. it->mHandle, it->mNsIndex, partition_name);
  198. s_nvs_handles.erase(it);
  199. delete static_cast<HandleEntry*>(it);
  200. }
  201. it = next;
  202. }
  203. /* Finally delete the storage itself */
  204. s_nvs_storage_list.erase(storage);
  205. delete storage;
  206. return ESP_OK;
  207. }
  208. extern "C" esp_err_t nvs_flash_deinit(void)
  209. {
  210. return nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME);
  211. }
  212. static esp_err_t nvs_find_ns_handle(nvs_handle handle, HandleEntry& entry)
  213. {
  214. auto it = find_if(begin(s_nvs_handles), end(s_nvs_handles), [=](HandleEntry& e) -> bool {
  215. return e.mHandle == handle;
  216. });
  217. if (it == end(s_nvs_handles)) {
  218. return ESP_ERR_NVS_INVALID_HANDLE;
  219. }
  220. entry = *it;
  221. return ESP_OK;
  222. }
  223. 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)
  224. {
  225. Lock lock;
  226. ESP_LOGD(TAG, "%s %s %d", __func__, name, open_mode);
  227. uint8_t nsIndex;
  228. nvs::Storage* sHandle;
  229. sHandle = lookup_storage_from_name(part_name);
  230. if (sHandle == NULL) {
  231. return ESP_ERR_NVS_PART_NOT_FOUND;
  232. }
  233. esp_err_t err = sHandle->createOrOpenNamespace(name, open_mode == NVS_READWRITE, nsIndex);
  234. if (err != ESP_OK) {
  235. return err;
  236. }
  237. HandleEntry *handle_entry = new HandleEntry(open_mode==NVS_READONLY, nsIndex, sHandle);
  238. s_nvs_handles.push_back(handle_entry);
  239. *out_handle = handle_entry->mHandle;
  240. return ESP_OK;
  241. }
  242. extern "C" esp_err_t nvs_open(const char* name, nvs_open_mode open_mode, nvs_handle *out_handle)
  243. {
  244. if (s_nvs_storage_list.size() == 0) {
  245. return ESP_ERR_NVS_NOT_INITIALIZED;
  246. }
  247. return nvs_open_from_partition(NVS_DEFAULT_PART_NAME, name, open_mode, out_handle);
  248. }
  249. extern "C" void nvs_close(nvs_handle handle)
  250. {
  251. Lock lock;
  252. ESP_LOGD(TAG, "%s %d", __func__, handle);
  253. auto it = find_if(begin(s_nvs_handles), end(s_nvs_handles), [=](HandleEntry& e) -> bool {
  254. return e.mHandle == handle;
  255. });
  256. if (it == end(s_nvs_handles)) {
  257. return;
  258. }
  259. s_nvs_handles.erase(it);
  260. delete static_cast<HandleEntry*>(it);
  261. }
  262. extern "C" esp_err_t nvs_erase_key(nvs_handle handle, const char* key)
  263. {
  264. Lock lock;
  265. ESP_LOGD(TAG, "%s %s\r\n", __func__, key);
  266. HandleEntry entry;
  267. auto err = nvs_find_ns_handle(handle, entry);
  268. if (err != ESP_OK) {
  269. return err;
  270. }
  271. if (entry.mReadOnly) {
  272. return ESP_ERR_NVS_READ_ONLY;
  273. }
  274. return entry.mStoragePtr->eraseItem(entry.mNsIndex, key);
  275. }
  276. extern "C" esp_err_t nvs_erase_all(nvs_handle handle)
  277. {
  278. Lock lock;
  279. ESP_LOGD(TAG, "%s\r\n", __func__);
  280. HandleEntry entry;
  281. auto err = nvs_find_ns_handle(handle, entry);
  282. if (err != ESP_OK) {
  283. return err;
  284. }
  285. if (entry.mReadOnly) {
  286. return ESP_ERR_NVS_READ_ONLY;
  287. }
  288. return entry.mStoragePtr->eraseNamespace(entry.mNsIndex);
  289. }
  290. template<typename T>
  291. static esp_err_t nvs_set(nvs_handle handle, const char* key, T value)
  292. {
  293. Lock lock;
  294. ESP_LOGD(TAG, "%s %s %d %d", __func__, key, sizeof(T), (uint32_t) value);
  295. HandleEntry entry;
  296. auto err = nvs_find_ns_handle(handle, entry);
  297. if (err != ESP_OK) {
  298. return err;
  299. }
  300. if (entry.mReadOnly) {
  301. return ESP_ERR_NVS_READ_ONLY;
  302. }
  303. return entry.mStoragePtr->writeItem(entry.mNsIndex, key, value);
  304. }
  305. extern "C" esp_err_t nvs_set_i8 (nvs_handle handle, const char* key, int8_t value)
  306. {
  307. return nvs_set(handle, key, value);
  308. }
  309. extern "C" esp_err_t nvs_set_u8 (nvs_handle handle, const char* key, uint8_t value)
  310. {
  311. return nvs_set(handle, key, value);
  312. }
  313. extern "C" esp_err_t nvs_set_i16 (nvs_handle handle, const char* key, int16_t value)
  314. {
  315. return nvs_set(handle, key, value);
  316. }
  317. extern "C" esp_err_t nvs_set_u16 (nvs_handle handle, const char* key, uint16_t value)
  318. {
  319. return nvs_set(handle, key, value);
  320. }
  321. extern "C" esp_err_t nvs_set_i32 (nvs_handle handle, const char* key, int32_t value)
  322. {
  323. return nvs_set(handle, key, value);
  324. }
  325. extern "C" esp_err_t nvs_set_u32 (nvs_handle handle, const char* key, uint32_t value)
  326. {
  327. return nvs_set(handle, key, value);
  328. }
  329. extern "C" esp_err_t nvs_set_i64 (nvs_handle handle, const char* key, int64_t value)
  330. {
  331. return nvs_set(handle, key, value);
  332. }
  333. extern "C" esp_err_t nvs_set_u64 (nvs_handle handle, const char* key, uint64_t value)
  334. {
  335. return nvs_set(handle, key, value);
  336. }
  337. extern "C" esp_err_t nvs_commit(nvs_handle handle)
  338. {
  339. Lock lock;
  340. // no-op for now, to be used when intermediate cache is added
  341. HandleEntry entry;
  342. return nvs_find_ns_handle(handle, entry);
  343. }
  344. extern "C" esp_err_t nvs_set_str(nvs_handle handle, const char* key, const char* value)
  345. {
  346. Lock lock;
  347. ESP_LOGD(TAG, "%s %s %s", __func__, key, value);
  348. HandleEntry entry;
  349. auto err = nvs_find_ns_handle(handle, entry);
  350. if (err != ESP_OK) {
  351. return err;
  352. }
  353. return entry.mStoragePtr->writeItem(entry.mNsIndex, nvs::ItemType::SZ, key, value, strlen(value) + 1);
  354. }
  355. extern "C" esp_err_t nvs_set_blob(nvs_handle handle, const char* key, const void* value, size_t length)
  356. {
  357. Lock lock;
  358. ESP_LOGD(TAG, "%s %s %d", __func__, key, length);
  359. HandleEntry entry;
  360. auto err = nvs_find_ns_handle(handle, entry);
  361. if (err != ESP_OK) {
  362. return err;
  363. }
  364. return entry.mStoragePtr->writeItem(entry.mNsIndex, nvs::ItemType::BLOB, key, value, length);
  365. }
  366. template<typename T>
  367. static esp_err_t nvs_get(nvs_handle handle, const char* key, T* out_value)
  368. {
  369. Lock lock;
  370. ESP_LOGD(TAG, "%s %s %d", __func__, key, sizeof(T));
  371. HandleEntry entry;
  372. auto err = nvs_find_ns_handle(handle, entry);
  373. if (err != ESP_OK) {
  374. return err;
  375. }
  376. return entry.mStoragePtr->readItem(entry.mNsIndex, key, *out_value);
  377. }
  378. extern "C" esp_err_t nvs_get_i8 (nvs_handle handle, const char* key, int8_t* out_value)
  379. {
  380. return nvs_get(handle, key, out_value);
  381. }
  382. extern "C" esp_err_t nvs_get_u8 (nvs_handle handle, const char* key, uint8_t* out_value)
  383. {
  384. return nvs_get(handle, key, out_value);
  385. }
  386. extern "C" esp_err_t nvs_get_i16 (nvs_handle handle, const char* key, int16_t* out_value)
  387. {
  388. return nvs_get(handle, key, out_value);
  389. }
  390. extern "C" esp_err_t nvs_get_u16 (nvs_handle handle, const char* key, uint16_t* out_value)
  391. {
  392. return nvs_get(handle, key, out_value);
  393. }
  394. extern "C" esp_err_t nvs_get_i32 (nvs_handle handle, const char* key, int32_t* out_value)
  395. {
  396. return nvs_get(handle, key, out_value);
  397. }
  398. extern "C" esp_err_t nvs_get_u32 (nvs_handle handle, const char* key, uint32_t* out_value)
  399. {
  400. return nvs_get(handle, key, out_value);
  401. }
  402. extern "C" esp_err_t nvs_get_i64 (nvs_handle handle, const char* key, int64_t* out_value)
  403. {
  404. return nvs_get(handle, key, out_value);
  405. }
  406. extern "C" esp_err_t nvs_get_u64 (nvs_handle handle, const char* key, uint64_t* out_value)
  407. {
  408. return nvs_get(handle, key, out_value);
  409. }
  410. static esp_err_t nvs_get_str_or_blob(nvs_handle handle, nvs::ItemType type, const char* key, void* out_value, size_t* length)
  411. {
  412. Lock lock;
  413. ESP_LOGD(TAG, "%s %s", __func__, key);
  414. HandleEntry entry;
  415. auto err = nvs_find_ns_handle(handle, entry);
  416. if (err != ESP_OK) {
  417. return err;
  418. }
  419. size_t dataSize;
  420. err = entry.mStoragePtr->getItemDataSize(entry.mNsIndex, type, key, dataSize);
  421. if (err != ESP_OK) {
  422. return err;
  423. }
  424. if (length == nullptr) {
  425. return ESP_ERR_NVS_INVALID_LENGTH;
  426. } else if (out_value == nullptr) {
  427. *length = dataSize;
  428. return ESP_OK;
  429. } else if (*length < dataSize) {
  430. *length = dataSize;
  431. return ESP_ERR_NVS_INVALID_LENGTH;
  432. }
  433. *length = dataSize;
  434. return entry.mStoragePtr->readItem(entry.mNsIndex, type, key, out_value, dataSize);
  435. }
  436. extern "C" esp_err_t nvs_get_str(nvs_handle handle, const char* key, char* out_value, size_t* length)
  437. {
  438. return nvs_get_str_or_blob(handle, nvs::ItemType::SZ, key, out_value, length);
  439. }
  440. extern "C" esp_err_t nvs_get_blob(nvs_handle handle, const char* key, void* out_value, size_t* length)
  441. {
  442. return nvs_get_str_or_blob(handle, nvs::ItemType::BLOB, key, out_value, length);
  443. }
  444. extern "C" esp_err_t nvs_get_stats(const char* part_name, nvs_stats_t* nvs_stats)
  445. {
  446. Lock lock;
  447. nvs::Storage* pStorage;
  448. if (nvs_stats == NULL) {
  449. return ESP_ERR_INVALID_ARG;
  450. }
  451. nvs_stats->used_entries = 0;
  452. nvs_stats->free_entries = 0;
  453. nvs_stats->total_entries = 0;
  454. nvs_stats->namespace_count = 0;
  455. pStorage = lookup_storage_from_name((part_name == NULL) ? NVS_DEFAULT_PART_NAME : part_name);
  456. if (pStorage == NULL) {
  457. return ESP_ERR_NVS_NOT_INITIALIZED;
  458. }
  459. if(!pStorage->isValid()){
  460. return ESP_ERR_NVS_INVALID_STATE;
  461. }
  462. return pStorage->fillStats(*nvs_stats);
  463. }
  464. extern "C" esp_err_t nvs_get_used_entry_count(nvs_handle handle, size_t* used_entries)
  465. {
  466. Lock lock;
  467. if(used_entries == NULL){
  468. return ESP_ERR_INVALID_ARG;
  469. }
  470. *used_entries = 0;
  471. HandleEntry entry;
  472. auto err = nvs_find_ns_handle(handle, entry);
  473. if (err != ESP_OK) {
  474. return err;
  475. }
  476. size_t used_entry_count;
  477. err = entry.mStoragePtr->calcEntriesInNamespace(entry.mNsIndex, used_entry_count);
  478. if(err == ESP_OK){
  479. *used_entries = used_entry_count;
  480. }
  481. return err;
  482. }
  483. #if (defined CONFIG_NVS_ENCRYPTION) && (defined ESP_PLATFORM)
  484. extern "C" esp_err_t nvs_flash_generate_keys(const esp_partition_t* partition, nvs_sec_cfg_t* cfg)
  485. {
  486. auto err = esp_partition_erase_range(partition, 0, partition->size);
  487. if(err != ESP_OK) {
  488. return err;
  489. }
  490. for(uint8_t cnt = 0; cnt < NVS_KEY_SIZE; cnt++) {
  491. cfg->eky[cnt] = 0xff;
  492. cfg->tky[cnt] = 0xee;
  493. }
  494. err = spi_flash_write(partition->address, cfg->eky, NVS_KEY_SIZE);
  495. if(err != ESP_OK) {
  496. return err;
  497. }
  498. err = spi_flash_write(partition->address + NVS_KEY_SIZE, cfg->tky, NVS_KEY_SIZE);
  499. if(err != ESP_OK) {
  500. return err;
  501. }
  502. err = esp_partition_read(partition, 0, cfg->eky, NVS_KEY_SIZE);
  503. if(err != ESP_OK) {
  504. return err;
  505. }
  506. err = esp_partition_read(partition, NVS_KEY_SIZE, cfg->tky, NVS_KEY_SIZE);
  507. if(err != ESP_OK) {
  508. return err;
  509. }
  510. uint32_t crc_calc = crc32_le(0xffffffff, cfg->eky, NVS_KEY_SIZE);
  511. crc_calc = crc32_le(crc_calc, cfg->tky, NVS_KEY_SIZE);
  512. uint8_t crc_wr[16];
  513. memset(crc_wr, 0xff, sizeof(crc_wr));
  514. memcpy(crc_wr, &crc_calc, 4);
  515. err = esp_partition_write(partition, 2 * NVS_KEY_SIZE, crc_wr, sizeof(crc_wr));
  516. if(err != ESP_OK) {
  517. return err;
  518. }
  519. return ESP_OK;
  520. }
  521. extern "C" esp_err_t nvs_flash_read_security_cfg(const esp_partition_t* partition, nvs_sec_cfg_t* cfg)
  522. {
  523. uint8_t eky_raw[NVS_KEY_SIZE], tky_raw[NVS_KEY_SIZE];
  524. uint32_t crc_raw, crc_read, crc_calc;
  525. auto err = spi_flash_read(partition->address, eky_raw, NVS_KEY_SIZE);
  526. if(err != ESP_OK) {
  527. return err;
  528. }
  529. err = spi_flash_read(partition->address + NVS_KEY_SIZE, tky_raw, NVS_KEY_SIZE);
  530. if(err != ESP_OK) {
  531. return err;
  532. }
  533. err = spi_flash_read(partition->address + 2 * NVS_KEY_SIZE, &crc_raw, 4);
  534. if(err != ESP_OK) {
  535. return err;
  536. }
  537. uint8_t cnt = 0;
  538. while(cnt < NVS_KEY_SIZE && eky_raw[cnt] == 0xff && tky_raw[cnt] == 0xff) cnt++;
  539. if(cnt == NVS_KEY_SIZE && crc_raw == 0xffffffff) {
  540. /* This is an uninitialized key partition*/
  541. return ESP_ERR_NVS_KEYS_NOT_INITIALIZED;
  542. }
  543. err = esp_partition_read(partition, 0, cfg->eky, NVS_KEY_SIZE);
  544. if(err != ESP_OK) {
  545. return err;
  546. }
  547. err = esp_partition_read(partition, NVS_KEY_SIZE, cfg->tky, NVS_KEY_SIZE);
  548. if(err != ESP_OK) {
  549. return err;
  550. }
  551. err = esp_partition_read(partition, 2 * NVS_KEY_SIZE, &crc_read, 4);
  552. if(err != ESP_OK) {
  553. return err;
  554. }
  555. crc_calc = crc32_le(0xffffffff, cfg->eky, NVS_KEY_SIZE);
  556. crc_calc = crc32_le(crc_calc, cfg->tky, NVS_KEY_SIZE);
  557. if(crc_calc != crc_read) {
  558. return ESP_ERR_NVS_CORRUPT_KEY_PART;
  559. }
  560. return ESP_OK;
  561. }
  562. #endif