Files
espressif--esp-idf/examples/security/psa_its_custom_backend/main/app_main.c
T
2026-07-13 13:04:25 +08:00

166 lines
5.4 KiB
C

/*
* PSA ITS custom storage backend example
*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*
* Demonstrates the PSA ITS custom storage backend feature:
*
* Key IDs 0x00000001 .. 0x2FFFFFFF → default NVS backend (framework)
* Key IDs 0x30000000 .. 0x3FFFFFFF → user-registered custom backend
* (this example: a separate NVS
* namespace "psa_its_ext")
*
* The custom UID range is configured via Kconfig
* (CONFIG_MBEDTLS_PSA_ITS_CUSTOM_BACKEND_UID_{MIN,MAX}).
*/
#include <stdio.h>
#include <string.h>
#include "esp_err.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "psa/crypto.h"
#include "esp_psa_its.h"
#include "custom_nvs_its_backend.h"
static const char *TAG = "example";
/* ---- Key IDs ---- */
/* Default NVS range (handled by the framework) */
#define NVS_KEY_ID ((psa_key_id_t) 0x00000001)
/* Custom range routed to the registered backend */
#define CUSTOM_KEY_ID ((psa_key_id_t) 0x30000001)
/* ---- Helpers ---- */
static psa_status_t provision_aes_key(psa_key_id_t key_id, const char *label)
{
psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t handle;
psa_status_t status;
status = psa_get_key_attributes(key_id, &attr);
if (status == PSA_SUCCESS) {
ESP_LOGI(TAG, "[%s] Key 0x%lx already exists", label, (unsigned long)key_id);
psa_reset_key_attributes(&attr);
return PSA_SUCCESS;
}
psa_reset_key_attributes(&attr);
psa_set_key_id(&attr, key_id);
psa_set_key_lifetime(&attr, PSA_KEY_LIFETIME_PERSISTENT);
psa_set_key_type(&attr, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attr, 256);
psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attr, PSA_ALG_CBC_NO_PADDING);
status = psa_generate_key(&attr, &handle);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "[%s] Failed to generate key 0x%lx: %d",
label, (unsigned long)key_id, (int)status);
} else {
ESP_LOGI(TAG, "[%s] Generated persistent key 0x%lx",
label, (unsigned long)key_id);
}
psa_reset_key_attributes(&attr);
return status;
}
static psa_status_t test_encrypt_decrypt(psa_key_id_t key_id, const char *label)
{
const uint8_t plaintext[32] = "Hello PSA ITS custom backend!!";
uint8_t ciphertext[16 + sizeof(plaintext)];
uint8_t decrypted[sizeof(plaintext)];
size_t ciphertext_len = 0;
size_t decrypted_len = 0;
psa_status_t status = psa_cipher_encrypt(key_id, PSA_ALG_CBC_NO_PADDING,
plaintext, sizeof(plaintext),
ciphertext, sizeof(ciphertext),
&ciphertext_len);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "[%s] Encrypt failed: %d", label, (int)status);
return status;
}
status = psa_cipher_decrypt(key_id, PSA_ALG_CBC_NO_PADDING,
ciphertext, ciphertext_len,
decrypted, sizeof(decrypted),
&decrypted_len);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "[%s] Decrypt failed: %d", label, (int)status);
return status;
}
if (decrypted_len != sizeof(plaintext) ||
memcmp(decrypted, plaintext, sizeof(plaintext)) != 0) {
ESP_LOGE(TAG, "[%s] Decrypted data mismatch!", label);
return PSA_ERROR_CORRUPTION_DETECTED;
}
ESP_LOGI(TAG, "[%s] Encrypt/decrypt OK with key 0x%lx",
label, (unsigned long)key_id);
return PSA_SUCCESS;
}
/* ---- Application entry ---- */
void app_main(void)
{
psa_status_t status;
ESP_LOGI(TAG, "=== PSA ITS Custom Storage Backend ===");
/* Initialize NVS (used by both the default backend and our custom backend,
* which keep their entries in distinct namespaces). */
esp_err_t err = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
err = nvs_flash_init();
}
ESP_ERROR_CHECK(err);
/* Register the custom backend. The signatures of custom_nvs_its_*
* match esp_psa_its_custom_ops_t exactly, so they can be bound directly. */
static const esp_psa_its_custom_ops_t custom_ops = {
.set = custom_nvs_its_set,
.get = custom_nvs_its_get,
.get_info = custom_nvs_its_get_info,
.remove = custom_nvs_its_remove,
.ctx = NULL,
};
status = esp_psa_its_register_custom_backend(&custom_ops);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Failed to register custom backend: %d", (int)status);
return;
}
ESP_LOGI(TAG, "Custom ITS backend registered");
/* Provision and exercise one key per storage path. */
ESP_LOGI(TAG, "--- Provisioning keys ---");
if (provision_aes_key(NVS_KEY_ID, "NVS") != PSA_SUCCESS) {
return;
}
if (provision_aes_key(CUSTOM_KEY_ID, "CUSTOM") != PSA_SUCCESS) {
return;
}
ESP_LOGI(TAG, "--- Testing encryption/decryption ---");
if (test_encrypt_decrypt(NVS_KEY_ID, "NVS") != PSA_SUCCESS) {
return;
}
if (test_encrypt_decrypt(CUSTOM_KEY_ID, "CUSTOM") != PSA_SUCCESS) {
return;
}
ESP_LOGI(TAG, "=== All tests passed ===");
}