Cant make ESP32 NVS encryption work. What am I doing wrong?

tales_hein
Posts: 1
Joined: Wed Aug 14, 2024 6:42 pm

Cant make ESP32 NVS encryption work. What am I doing wrong?

Postby tales_hein » Tue Jan 21, 2025 12:48 pm

Hi people! I've been struggling to set up a workflow for flash encryption, NVS encryption and secure boot. I am using the ESP32C3 chip. But after adding NVS encryption i can't retrieve the data from NVS and dont know what I am doing wrong. Any insights?

Heres my current workflow:
  1. # 1. Create keys:
  2. espsecure.py generate_flash_encryption_key flash_encryption_key.bin
  3. nvs_partition_gen.py generate-key --key_protect_hmac --kp_hmac_keygen \
  4.  --kp_hmac_keyfile hmac_key.bin --keyfile nvs_encr_key.bin
  5.  
  6. # 2. Burn keys:
  7. espefuse.py -p /dev/ttyACM0 burn_key BLOCK_KEY2 flash_encryption_key.bin XTS_AES_128_KEY
  8. espefuse.py -p /dev/ttyACM0 burn_key BLOCK_KEY3 keys/hmac_key.bin HMAC_UP
  9.  
  10. # 3. Create nvs partition image:
  11. nvs_partition_gen.py encrypt certs/cert_data.csv nvs_encr_partition.bin 0x8000 --inputkey keys/nvs_encr_key.bin
  12.  
  13. # 4. Encrypt build:
  14. espsecure.py encrypt_flash_data --aes_xts --keyfile flash_encryption_key.bin \
  15.  --address 0x0 --output bootloader-enc.bin build/bootloader/bootloader.bin
  16. espsecure.py encrypt_flash_data --aes_xts --keyfile flash_encryption_key.bin \
  17.  --address 0x8000 --output partition-table-enc.bin build/partition_table/partition-table.bin
  18. espsecure.py encrypt_flash_data --aes_xts --keyfile flash_encryption_key.bin \
  19.  --address 0x19000 --output ota_data_initial-enc.bin build/ota_data_initial.bin
  20. espsecure.py encrypt_flash_data --aes_xts --keyfile flash_encryption_key.bin \
  21.  --address 0x20000 --output app-enc.bin build/app.bin
  22. espsecure.py encrypt_flash_data --aes_xts --keyfile flash_encryption_key.bin \
  23.  --address 0xf000 --output final_nvs_encr_partition.bin nvs_encr_partition.bin
  24.  
  25. # 5. Flash encrypted data:
  26. esptool.py --chip esp32c3 -p /dev/ttyACM0 -b 460800 --before=default_reset \
  27.  --after=no_reset --no-stub write_flash --flash_mode dio --flash_freq 80m --flash_size keep \
  28.  0x0 bootloader-enc.bin \
  29.  0xf000 final_nvs_encr_partition.bin \
  30.  0x8000 partition-table-enc.bin \
  31.  0x19000 ota_data_initial-enc.bin \
  32.  0x20000 app-enc.bin
But when I try to execute a reading of the NVS data i get the following:

  1. I (279) cpu_start: Unicore app
  2. I (287) cpu_start: Pro cpu start user code
  3. I (287) cpu_start: cpu freq: 160000000 Hz
  4. I (288) app_init: Application information:
  5. I (290) app_init: Project name:     icollector
  6. I (295) app_init: App version:      4c30755-dirty
  7. I (301) app_init: Compile time:     Jan 17 2025 16:33:19
  8. I (307) app_init: ELF file SHA256:  ec0e0f887...
  9. I (312) app_init: ESP-IDF:          v5.3.1
  10. I (317) efuse_init: Min chip rev:     v0.3
  11. I (322) efuse_init: Max chip rev:     v1.99
  12. I (327) efuse_init: Chip rev:         v0.4
  13. I (331) heap_init: Initializing. RAM available for dynamic allocation:
  14. I (339) heap_init: At 3FC9F0D0 len 00020F30 (131 KiB): RAM
  15. I (345) heap_init: At 3FCC0000 len 0001C710 (113 KiB): Retention RAM
  16. I (352) heap_init: At 3FCDC710 len 00002950 (10 KiB): Retention RAM
  17. I (359) heap_init: At 50000204 len 00001DE4 (7 KiB): RTCRAM
  18. I (366) spi_flash: detected chip: generic
  19. I (370) spi_flash: flash io: dio
  20. W (374) flash_encrypt: Flash encryption mode is DEVELOPMENT (not secure)
  21. I (382) nvs_sec_provider: NVS Encryption - Registering HMAC-based scheme...
  22. I (389) sleep: Configure to isolate all GPIO pins in sleep state
  23. I (395) sleep: Enable automatic switching of GPIO sleep configuration
  24. I (403) main_task: Started on CPU0
  25. I (403) main_task: Calling app_main()
  26. I (403) gpio: GPIO[0]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
  27. I (413) MAIN: Collector code: 0076A727843C
  28. I (423) CERT_MANAGER: NVS security cfg set up successfully.
  29. I (453) STORAGE: Partition size: total: 956561, used: 502
  30. I (453) gpio: GPIO[9]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:2
  31. I (463) WIFI STATION: Content retrieved from last successful connection. Using it...
  32. I (463) WIFI STATION: Trying to connect to wifi access point...
  33. I (513) nvs: NVS partition "nvs" is encrypted.
  34. I (513) pp: pp rom version: 9387209
  35. I (513) net80211: net80211 rom version: 9387209
  36. (... wifi related stuff)
  37. I (17353) CERT_MANAGER: NVS Partition labeled "nvs_storage" found.
  38. I (17353) CERT_MANAGER: Flash initialized successfully.
  39. I (17353) CERT_MANAGER: NVS handle opened successfully.
  40. E (17363) CERT_MANAGER: Failed to retrieve PEM: ESP_ERR_NVS_NOT_FOUND
  41. E (17363) MQTT: Could not retrieve certification data. Retrying...
  42. I (17373) CERT_MANAGER: NVS Partition labeled "nvs_storage" found.
  43. (.. loops)

Functions involved in the process:
Context: secure_nvs_cfg_init is called in the app_main on start up and retrieve_certification_data is called after wifi has been setup and I will use certificates to setup mqtt client.

  1. esp_err_t secure_nvs_cfg_init(void)
  2. {
  3.     esp_err_t err = ESP_FAIL;
  4.  
  5.     nvs_sec_scheme_t *sec_scheme_handle  = NULL;
  6.     nvs_sec_config_hmac_t sec_scheme_cfg = NVS_SEC_PROVIDER_CFG_HMAC_DEFAULT();
  7.  
  8.     err = nvs_sec_provider_register_hmac(&sec_scheme_cfg, &sec_scheme_handle);
  9.     if (err != ESP_OK) {
  10.         ESP_LOGE(TAG, "Failed to register HMAC scheme for NVS encription: [0x%02X] (%s)", err, esp_err_to_name(err));
  11.         return err;
  12.     }
  13.  
  14.     err = nvs_flash_read_security_cfg_v2(sec_scheme_handle, &nvs_sec_cfg);
  15.     if (err != ESP_OK)
  16.     {
  17.         ESP_LOGE(TAG, "Failed to read NVS security cfg: [0x%02X] (%s)", err, esp_err_to_name(err));
  18.     }
  19.     else
  20.     {
  21.         ESP_LOGI(TAG, "NVS security cfg set up successfully.");
  22.     }
  23.  
  24.     return err;
  25. }
Commented portions of the code where used to add some logging to try to understand whats happening. But both versions result in the same output.
  1. bool retrieve_certification_data(char* certificate_id, char* pem, char* private_key, char* ca_cert, char* type)
  2. {
  3.     nvs_handle_t nvs_handle;
  4.  
  5.     esp_err_t err = nvs_flash_secure_init_partition(NVS_CUSTOM_PARTITION_LABEL, &nvs_sec_cfg);
  6.     if (err != ESP_OK)
  7.     {
  8.         ESP_LOGE(TAG, "Error: %s", esp_err_to_name(err));
  9.         return false;
  10.     }
  11.  
  12.     // const esp_partition_t* nvs_storage_partition_pointer = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, NVS_CUSTOM_PARTITION_LABEL);
  13.  
  14.     // if (nvs_storage_partition_pointer == NULL)
  15.     // {
  16.     //     ESP_LOGI(TAG, "NVS Partition with name \"%s\" not found.", NVS_CUSTOM_PARTITION_LABEL);
  17.     //     nvs_flash_deinit_partition(NVS_CUSTOM_PARTITION_LABEL);
  18.     //     return false;
  19.     // }
  20.     // else
  21.     // {
  22.     //     ESP_LOGI(TAG, "NVS Partition labeled \"%s\" found.", nvs_storage_partition_pointer->label);
  23.     // }
  24.  
  25.     // err = nvs_flash_init_partition_ptr(nvs_storage_partition_pointer);
  26.     // if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND)
  27.     // {
  28.     //     ESP_LOGI(TAG, "Flash could not be initialized successfully. Error: %s", esp_err_to_name(err));
  29.     //     nvs_flash_deinit_partition(NVS_CUSTOM_PARTITION_LABEL);
  30.     //     return false;
  31.     // }
  32.     // if (err == ESP_OK)
  33.     // {
  34.     //     ESP_LOGI(TAG, "Flash initialized successfully.");
  35.     // }
  36.  
  37.     err = nvs_open_from_partition(
  38.         NVS_CUSTOM_PARTITION_LABEL, // nvs_storage_partition_pointer->label,
  39.         "cert_storage",
  40.         NVS_READWRITE,
  41.         &nvs_handle
  42.     );
  43.     if (err != ESP_OK)
  44.     {
  45.         ESP_LOGE(TAG, "Failed to open NVS handle: %s", esp_err_to_name(err));
  46.         nvs_flash_deinit_partition(NVS_CUSTOM_PARTITION_LABEL);
  47.         return false;
  48.     }
  49.     else
  50.     {
  51.         ESP_LOGI(TAG, "NVS handle opened successfully.");
  52.     }
  53.  
  54.     if (certificate_id != NULL)
  55.     {
  56.         size_t certificate_id_size = CERTIFICATE_ID_SIZE;
  57.         err = nvs_get_str(nvs_handle, "cert_id", certificate_id, &certificate_id_size);
  58.         if (err != ESP_OK)
  59.         {
  60.             ESP_LOGE(TAG, "Failed to retrieve certificate_id: %s", esp_err_to_name(err));
  61.             nvs_close(nvs_handle);
  62.             nvs_flash_deinit_partition(NVS_CUSTOM_PARTITION_LABEL);
  63.             return false;
  64.         }
  65.         certificate_id[certificate_id_size - 1] = '\0';
  66.     }
  67.  
  68.     size_t pem_size = CERTIFICATE_PAYLOAD_SIZE;
  69.     err = nvs_get_str(nvs_handle, "pem", pem, &pem_size);
  70.     if (err != ESP_OK)
  71.     {
  72.         ESP_LOGE(TAG, "Failed to retrieve PEM: %s", esp_err_to_name(err));
  73.         nvs_close(nvs_handle);
  74.         nvs_flash_deinit_partition(NVS_CUSTOM_PARTITION_LABEL);
  75.         return false;
  76.     }
  77.     pem[pem_size - 1] = '\0';
  78.  
  79.     size_t private_key_size = CERTIFICATE_PAYLOAD_SIZE;
  80.     err = nvs_get_str(nvs_handle, "private_key", private_key, &private_key_size);
  81.     if (err != ESP_OK)
  82.     {
  83.         ESP_LOGE(TAG, "Failed to retrieve private key: %s", esp_err_to_name(err));
  84.         nvs_close(nvs_handle);
  85.         nvs_flash_deinit_partition(NVS_CUSTOM_PARTITION_LABEL);
  86.         return false;
  87.     }
  88.     private_key[private_key_size - 1] = '\0';
  89.  
  90.     if (ca_cert != NULL)
  91.     {
  92.         size_t ca_cert_size = CERTIFICATE_PAYLOAD_SIZE;
  93.         err = nvs_get_str(nvs_handle, "ca_cert", ca_cert, &ca_cert_size);
  94.         if (err != ESP_OK)
  95.         {
  96.             ESP_LOGE(TAG, "Failed to retrieve ca cert: %s", esp_err_to_name(err));
  97.             nvs_close(nvs_handle);
  98.             nvs_flash_deinit_partition(NVS_CUSTOM_PARTITION_LABEL);
  99.             return false;
  100.         }
  101.         ca_cert[ca_cert_size - 1] = '\0';
  102.     }
  103.  
  104.     if (type != NULL)
  105.     {
  106.         size_t type_size = 10;
  107.         err = nvs_get_str(nvs_handle, "type", type, &type_size);
  108.         if (err != ESP_OK)
  109.         {
  110.             ESP_LOGE(TAG, "Failed to retrieve certification data type: %s", esp_err_to_name(err));
  111.             nvs_close(nvs_handle);
  112.             nvs_flash_deinit_partition(NVS_CUSTOM_PARTITION_LABEL);
  113.             return false;
  114.         }
  115.         type[type_size - 1] = '\0';
  116.     }
  117.  
  118.     nvs_close(nvs_handle);
  119.     nvs_flash_deinit_partition(NVS_CUSTOM_PARTITION_LABEL);
  120.  
  121.     ESP_LOGI(TAG, "Certificate data successfully retrieved.");
  122.  
  123.     return true;
  124. }

Who is online

Users browsing this forum: No registered users and 78 guests