nvs_encr.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // Copyright 2015-2018 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_encr.hpp"
  14. #include "nvs_types.hpp"
  15. #include <string.h>
  16. namespace nvs
  17. {
  18. bool EncrMgr::isActive = false;
  19. EncrMgr* EncrMgr::instance = nullptr;
  20. EncrMgr* EncrMgr::getInstance()
  21. {
  22. if(!isActive)
  23. {
  24. instance = new (std::nothrow) EncrMgr();
  25. if (instance) {
  26. isActive = true;
  27. }
  28. }
  29. return instance;
  30. }
  31. void EncrMgr::resetInstance()
  32. {
  33. if(isActive) {
  34. delete instance;
  35. instance = nullptr;
  36. isActive = false;
  37. }
  38. }
  39. bool EncrMgr::isEncrActive() {
  40. return isActive;
  41. }
  42. XtsCtxt* EncrMgr::findXtsCtxtFromAddr(uint32_t addr) {
  43. auto it = find_if(std::begin(xtsCtxtList), std::end(xtsCtxtList), [=](XtsCtxt& ctx) -> bool
  44. { return (ctx.baseSector * SPI_FLASH_SEC_SIZE <= addr)
  45. && (addr < (ctx.baseSector + ctx.sectorCount) * SPI_FLASH_SEC_SIZE); });
  46. if (it == std::end(xtsCtxtList)) {
  47. return nullptr;
  48. }
  49. return it;
  50. }
  51. esp_err_t EncrMgr::setSecurityContext(uint32_t baseSector, uint32_t sectorCount, nvs_sec_cfg_t* cfg) {
  52. uint8_t* eky = reinterpret_cast<uint8_t*>(cfg);
  53. auto ctxt = new (std::nothrow) XtsCtxt();
  54. if (!ctxt) return ESP_ERR_NO_MEM;
  55. ctxt->baseSector = baseSector;
  56. ctxt->sectorCount = sectorCount;
  57. mbedtls_aes_xts_init(ctxt->ectxt);
  58. mbedtls_aes_xts_init(ctxt->dctxt);
  59. if(mbedtls_aes_xts_setkey_enc(ctxt->ectxt, eky, 2 * NVS_KEY_SIZE * 8)) {
  60. return ESP_ERR_NVS_XTS_CFG_FAILED;
  61. }
  62. if(mbedtls_aes_xts_setkey_dec(ctxt->dctxt, eky, 2 * NVS_KEY_SIZE * 8)) {
  63. return ESP_ERR_NVS_XTS_CFG_FAILED;
  64. }
  65. xtsCtxtList.push_back(ctxt);
  66. return ESP_OK;
  67. }
  68. esp_err_t EncrMgr::removeSecurityContext(uint32_t baseSector) {
  69. auto xtsCtxt = findXtsCtxtFromAddr(baseSector * SPI_FLASH_SEC_SIZE);
  70. if(!xtsCtxt) {
  71. return ESP_ERR_NVS_XTS_CFG_NOT_FOUND;
  72. }
  73. xtsCtxtList.erase(xtsCtxt);
  74. delete xtsCtxt;
  75. if(!xtsCtxtList.size()) {
  76. resetInstance();
  77. }
  78. return ESP_OK;
  79. }
  80. esp_err_t EncrMgr::encryptNvsData(uint8_t* ptxt, uint32_t addr, uint32_t ptxtLen, XtsCtxt* xtsCtxt) {
  81. uint8_t entrySize = sizeof(Item);
  82. //sector num required as an arr by mbedtls. Should have been just uint64/32.
  83. uint8_t data_unit[16];
  84. assert(ptxtLen % entrySize == 0);
  85. /* Use relative address instead of absolute address (relocatable), so that host-generated
  86. * encrypted nvs images can be used*/
  87. uint32_t relAddr = addr - (xtsCtxt->baseSector * SPI_FLASH_SEC_SIZE);
  88. memset(data_unit, 0, sizeof(data_unit));
  89. for(uint8_t entry = 0; entry < (ptxtLen/entrySize); entry++)
  90. {
  91. uint32_t offset = entry * entrySize;
  92. uint32_t *addr_loc = (uint32_t*) &data_unit[0];
  93. *addr_loc = relAddr + offset;
  94. if(mbedtls_aes_crypt_xts(xtsCtxt->ectxt, MBEDTLS_AES_ENCRYPT, entrySize, data_unit, ptxt + offset, ptxt + offset)) {
  95. return ESP_ERR_NVS_XTS_ENCR_FAILED;
  96. }
  97. }
  98. return ESP_OK;
  99. }
  100. esp_err_t EncrMgr::decryptNvsData(uint8_t* ctxt, uint32_t addr, uint32_t ctxtLen, XtsCtxt* xtsCtxt) {
  101. //sector num required as an arr by mbedtls. Should have been just uint64/32.
  102. uint8_t data_unit[16];
  103. /** Currently upper layer of NVS reads entries one by one even for variable size
  104. * multi-entry data types. So length should always be equal to size of an entry.*/
  105. assert(ctxtLen == sizeof(Item));
  106. uint32_t relAddr = addr - (xtsCtxt->baseSector * SPI_FLASH_SEC_SIZE);
  107. memset(data_unit, 0, sizeof(data_unit));
  108. memcpy(data_unit, &relAddr, sizeof(relAddr));
  109. if(mbedtls_aes_crypt_xts(xtsCtxt->dctxt, MBEDTLS_AES_DECRYPT, ctxtLen, data_unit, ctxt, ctxt)) {
  110. return ESP_ERR_NVS_XTS_DECR_FAILED;
  111. }
  112. return ESP_OK;
  113. }
  114. } // namespace nvs