Introduction to NVS Encryption

The flash encryption scheme does not directly protect the data stored in the NVS partition. To protect the confidentiality of the data stored in NVS partition, NVS encryption scheme should be used. NVS encryption can be enabled through menuconfig → Component config → NVS → Enable NVS encryption or by calling nvs_flash_secure_init().

The basic principle of the NVS encryption scheme is to define a partition in the partition table with a size of no less than 4 KB and the subtype of nvs_key. After enabling the NVS encryption scheme, the NVS partition will be encrypted using the key in the nvs_key partition. A typical partition table that supports NVS encryption is shown below:

# Name,     Type,   SubType,    Offset, Size,   Flags
nvs,        data,   nvs,        ,       0x6000,
phy_init,   data,   phy,        ,       0x1000,
factory,    app,    factory,    ,       1M,
nvs_key,    data,   nvs_keys,   ,       0x1000, encrypted,

NVS encryption scheme is similar to the flash encryption scheme in many ways, such as:

  • The encryption algorithm used by the NVS encryption scheme is the symmetric encryption algorithm AES-XTS. As mentioned earlier, symmetric encryption algorithm requires its key to be kept secret to ensure that the encrypted data cannot be analysed and cracked. The key of the NVS encryption scheme cannot be plaintext, so this scheme is often used together with the flash encryption scheme, where flash encryption is responsible for protecting the confidentiality of the nvs_key, while NVS encryption uses nvs_key to protect the confidentiality of the NVS partition.

  • There are two methods for storing the NVS encryption key: one is the manual method, that is, manually generate a key and write the key to the designated partition; the other is the automatic method, that is, when the NVS encryption scheme is first enabled and the nvs_key partition is empty, the device automatically calls the nvs_flash_generate_keys() function to generate the key, and then writes the key to the nvs_key partition, and subsequently uses the key to complete NVS encryption/decryption.

    The steps to manually store the NVS encryption key are as follows:

    First, generate a file containing the key by running the following command:

    $ espsecure.py generate_flash_encryption_key my_nvs_encryption_key.bin

    Then, compile and burn the partition table with the following command:

    $ idf.py -p (PORT) partition_table-flash

    Finally, burn the key to the specified partition with the following command:

    $ parttool.py -p (PORT) --partition-table-offset "nvs_key partition offset" write_partition --partition-name="name of
    nvs_key partition" --input "nvs_key partition"
  • After enabling NVS encryption, APIs starting with nvs_get or nvs_set automatically perform data encryption/decryption when reading/writing data in the NVS partition.

Please note that when flash encryption is enabled, it is highly recommended to also enable NVS encryption (which is enabled by default). This is important because the Wi-Fi driver stores sensitive data, such as SSID and password, in the default NVS partition. The NVS encryption scheme allows for the use of different keys (nvs_key) in different NVS partitions. When initialising a specific NVS partition, you only need to specify the corresponding nvs_key.

📌 Tip

Visit https://bookc3.espressif.com/nvs for further information about NVS encryption.