nvs_encrypted_partition.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. // Copyright 2019 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. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <cstring>
  15. #include "nvs_encrypted_partition.hpp"
  16. #include "nvs_types.hpp"
  17. namespace nvs {
  18. NVSEncryptedPartition::NVSEncryptedPartition(const esp_partition_t *partition)
  19. : NVSPartition(partition) { }
  20. esp_err_t NVSEncryptedPartition::init(nvs_sec_cfg_t* cfg)
  21. {
  22. uint8_t* eky = reinterpret_cast<uint8_t*>(cfg);
  23. mbedtls_aes_xts_init(&mEctxt);
  24. mbedtls_aes_xts_init(&mDctxt);
  25. if (mbedtls_aes_xts_setkey_enc(&mEctxt, eky, 2 * NVS_KEY_SIZE * 8) != 0) {
  26. return ESP_ERR_NVS_XTS_CFG_FAILED;
  27. }
  28. if (mbedtls_aes_xts_setkey_dec(&mDctxt, eky, 2 * NVS_KEY_SIZE * 8) != 0) {
  29. return ESP_ERR_NVS_XTS_CFG_FAILED;
  30. }
  31. return ESP_OK;
  32. }
  33. esp_err_t NVSEncryptedPartition::read(size_t src_offset, void* dst, size_t size)
  34. {
  35. /** Currently upper layer of NVS reads entries one by one even for variable size
  36. * multi-entry data types. So length should always be equal to size of an entry.*/
  37. if (size != sizeof(Item)) return ESP_ERR_INVALID_SIZE;
  38. // read data
  39. esp_err_t read_result = esp_partition_read(mESPPartition, src_offset, dst, size);
  40. if (read_result != ESP_OK) {
  41. return read_result;
  42. }
  43. // decrypt data
  44. //sector num required as an arr by mbedtls. Should have been just uint64/32.
  45. uint8_t data_unit[16];
  46. uint32_t relAddr = src_offset;
  47. memset(data_unit, 0, sizeof(data_unit));
  48. memcpy(data_unit, &relAddr, sizeof(relAddr));
  49. uint8_t *destination = reinterpret_cast<uint8_t*>(dst);
  50. if (mbedtls_aes_crypt_xts(&mDctxt, MBEDTLS_AES_DECRYPT, size, data_unit, destination, destination) != 0) {
  51. return ESP_ERR_NVS_XTS_DECR_FAILED;
  52. }
  53. return ESP_OK;
  54. }
  55. esp_err_t NVSEncryptedPartition::write(size_t addr, const void* src, size_t size)
  56. {
  57. if (size % ESP_ENCRYPT_BLOCK_SIZE != 0) return ESP_ERR_INVALID_SIZE;
  58. // copy data to buffer for encryption
  59. uint8_t* buf = new (std::nothrow) uint8_t [size];
  60. if (!buf) return ESP_ERR_NO_MEM;
  61. memcpy(buf, src, size);
  62. // encrypt data
  63. uint8_t entrySize = sizeof(Item);
  64. //sector num required as an arr by mbedtls. Should have been just uint64/32.
  65. uint8_t data_unit[16];
  66. /* Use relative address instead of absolute address (relocatable), so that host-generated
  67. * encrypted nvs images can be used*/
  68. uint32_t relAddr = addr;
  69. memset(data_unit, 0, sizeof(data_unit));
  70. for(uint8_t entry = 0; entry < (size/entrySize); entry++)
  71. {
  72. uint32_t offset = entry * entrySize;
  73. uint32_t *addr_loc = (uint32_t*) &data_unit[0];
  74. *addr_loc = relAddr + offset;
  75. if (mbedtls_aes_crypt_xts(&mEctxt,
  76. MBEDTLS_AES_ENCRYPT,
  77. entrySize,
  78. data_unit,
  79. buf + offset,
  80. buf + offset) != 0) {
  81. delete buf;
  82. return ESP_ERR_NVS_XTS_ENCR_FAILED;
  83. }
  84. }
  85. // write data
  86. esp_err_t result = esp_partition_write(mESPPartition, addr, buf, size);
  87. delete buf;
  88. return result;
  89. }
  90. } // nvs