nvs_encr.cpp 4.5 KB

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