Files
keypitecc/main/provision_handlers.h
2026-02-27 22:17:33 +01:00

188 lines
6.3 KiB
C

#ifndef PROVISION_HANDLERS_H
#define PROVISION_HANDLERS_H
#include "provision.h"
#include "provision_web_page.h"
#include <cJSON.h>
#include <esp_http_server.h>
#include <esp_log.h>
static const char *TAG_PROVISION_HANDLERS = "provision_handlers";
// Forward declarations
extern httpd_handle_t server_http;
/**
* Serve the provisioning web page
*/
static esp_err_t handle_provision_page(httpd_req_t *req) {
httpd_resp_set_type(req, "text/html");
httpd_resp_sendstr(req, PROVISION_WEB_PAGE);
return ESP_OK;
}
/**
* API endpoint: Get provisioning status
*/
static esp_err_t handle_provision_status(httpd_req_t *req) {
cJSON *response = cJSON_CreateObject();
bool config_unlocked = !is_atecc608b_config_locked();
bool data_unlocked = !is_atecc608b_data_locked();
bool key5_unused = !is_efuse_key5_used();
bool needs_prov = needs_provisioning();
cJSON_AddBoolToObject(response, "needs_provisioning", needs_prov);
cJSON_AddBoolToObject(response, "config_unlocked", config_unlocked);
cJSON_AddBoolToObject(response, "data_unlocked", data_unlocked);
cJSON_AddBoolToObject(response, "key5_unused", key5_unused);
char *json_str = cJSON_PrintUnformatted(response);
cJSON_Delete(response);
httpd_resp_set_type(req, "application/json");
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
httpd_resp_sendstr(req, json_str);
free(json_str);
return ESP_OK;
}
/**
* API endpoint: Provision the device EFUSE
*/
static esp_err_t handle_provision_api(httpd_req_t *req) {
ESP_LOGI(TAG_PROVISION_HANDLERS, "Provisioning API called");
cJSON *response = cJSON_CreateObject();
bool success = false;
const char *message = "Unknown error";
// Check if provisioning is actually needed
if (!needs_provisioning()) {
message = "Device is already provisioned";
success = true;
ESP_LOGI(TAG_PROVISION_HANDLERS, "%s", message);
} else {
bool atecc_done = true;
bool efuse_done = true;
// Step 1: Provision ATECC608B config if needed
if (!is_atecc608b_config_locked()) {
ESP_LOGI(TAG_PROVISION_HANDLERS,
"Provisioning ATECC608B configuration...");
atecc_done = provision_atecc608b_config();
if (!atecc_done) {
message = "Failed to provision ATECC608B configuration";
success = false;
ESP_LOGE(TAG_PROVISION_HANDLERS, "%s", message);
}
}
// Step 2: Provision EFUSE KEY5 if needed and previous step succeeded
if (atecc_done && !is_efuse_key5_used()) {
ESP_LOGI(TAG_PROVISION_HANDLERS, "Provisioning EFUSE KEY5...");
efuse_done = provision_efuse_key5();
if (!efuse_done) {
message = "Failed to provision EFUSE KEY5";
success = false;
ESP_LOGE(TAG_PROVISION_HANDLERS, "%s", message);
}
}
if (!is_atecc608b_data_locked()) {
ESP_LOGI(TAG_PROVISION_HANDLERS, "Provisioning ATECC608B data zone...");
bool data_done = provision_atecc608b_data_zone();
if (!data_done) {
message = "Failed to provision ATECC608B data zone";
success = false;
ESP_LOGE(TAG_PROVISION_HANDLERS, "%s", message);
}
}
// Build success message
if (atecc_done && efuse_done) {
if (!is_atecc608b_config_locked() && !is_efuse_key5_used()) {
message =
"Provisioned ATECC608B configuration and EFUSE KEY5 successfully";
} else if (!is_atecc608b_config_locked()) {
message = "ATECC608B configuration provisioned and locked successfully";
} else {
message = "EFUSE KEY5 provisioned successfully with HMAC key";
}
success = true;
ESP_LOGI(TAG_PROVISION_HANDLERS, "%s", message);
}
}
// Build JSON response
cJSON_AddBoolToObject(response, "success", success);
cJSON_AddStringToObject(response, "message", message);
char *json_str = cJSON_PrintUnformatted(response);
cJSON_Delete(response);
// Send response
httpd_resp_set_type(req, "application/json");
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
httpd_resp_set_status(req, success ? "200 OK" : "500 Internal Server Error");
httpd_resp_sendstr(req, json_str);
free(json_str);
return ESP_OK;
}
/**
* Handle CORS preflight for provision API
*/
static esp_err_t handle_provision_options(httpd_req_t *req) {
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
httpd_resp_set_hdr(req, "Access-Control-Allow-Methods", "POST, GET, OPTIONS");
httpd_resp_set_hdr(req, "Access-Control-Allow-Headers", "Content-Type");
httpd_resp_set_status(req, "204 No Content");
httpd_resp_send(req, NULL, 0);
return ESP_OK;
}
/**
* Register provisioning handlers
*/
void register_provision_handlers(httpd_handle_t server) {
// Provision page
httpd_uri_t provision_page_uri = {.uri = "/provision",
.method = HTTP_GET,
.handler = handle_provision_page,
.user_ctx = NULL};
httpd_register_uri_handler(server, &provision_page_uri);
// API endpoint for getting status
httpd_uri_t provision_status_uri = {.uri = "/api/provision/status",
.method = HTTP_GET,
.handler = handle_provision_status,
.user_ctx = NULL};
httpd_register_uri_handler(server, &provision_status_uri);
// API endpoint for provisioning
httpd_uri_t provision_api_uri = {.uri = "/api/provision",
.method = HTTP_POST,
.handler = handle_provision_api,
.user_ctx = NULL};
httpd_register_uri_handler(server, &provision_api_uri);
// CORS preflight
httpd_uri_t provision_options_uri = {.uri = "/api/provision",
.method = HTTP_OPTIONS,
.handler = handle_provision_options,
.user_ctx = NULL};
httpd_register_uri_handler(server, &provision_options_uri);
ESP_LOGI(TAG_PROVISION_HANDLERS, "Provision routes registered:");
ESP_LOGI(TAG_PROVISION_HANDLERS,
" GET /provision - Provision page");
ESP_LOGI(TAG_PROVISION_HANDLERS,
" GET /api/provision/status - Provision status");
ESP_LOGI(TAG_PROVISION_HANDLERS, " POST /api/provision - Provision API");
}
#endif // PROVISION_HANDLERS_H