From 3b7e2f9a0c1288b4d3c3e0147f5a57b5504e3107 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Fri, 23 Aug 2024 21:00:18 +0200 Subject: [PATCH] WIP enroll device --- esp32_device/.vscode/settings.json | 14 +++++++- esp32_device/main/CMakeLists.txt | 2 ++ esp32_device/main/constants.h | 15 ++++++++ esp32_device/main/http_client.h | 2 +- esp32_device/main/main.c | 46 ++++++++++++++++++++++--- esp32_device/main/secure_api.c | 55 ++++++++++++++++++++++++++++-- esp32_device/main/secure_api.h | 5 +++ python_device/src/main.py | 2 +- 8 files changed, 132 insertions(+), 9 deletions(-) diff --git a/esp32_device/.vscode/settings.json b/esp32_device/.vscode/settings.json index d08f6b8..7b9add5 100644 --- a/esp32_device/.vscode/settings.json +++ b/esp32_device/.vscode/settings.json @@ -34,6 +34,18 @@ "http_client.h": "c", "string.h": "c", "cjson.h": "c", - "stddef.h": "c" + "stddef.h": "c", + "array": "c", + "chrono": "c", + "deque": "c", + "list": "c", + "string": "c", + "unordered_map": "c", + "vector": "c", + "iterator": "c", + "string_view": "c", + "format": "c", + "span": "c", + "regex": "c" } } diff --git a/esp32_device/main/CMakeLists.txt b/esp32_device/main/CMakeLists.txt index e64f73e..82ce304 100755 --- a/esp32_device/main/CMakeLists.txt +++ b/esp32_device/main/CMakeLists.txt @@ -1,3 +1,5 @@ idf_component_register(SRCS "secure_api.c" "http_client.c" "ethernet.c" "unsecure_api.c" "system.c" "crypto.c" "random.c" "storage.c" "main.c" "dev_name.c" INCLUDE_DIRS ".") + +target_compile_options(${COMPONENT_LIB} PRIVATE -Werror) \ No newline at end of file diff --git a/esp32_device/main/constants.h b/esp32_device/main/constants.h index 1056a7d..cfe45a7 100644 --- a/esp32_device/main/constants.h +++ b/esp32_device/main/constants.h @@ -1,5 +1,20 @@ #pragma once +/** + * Device reference + */ +#define DEV_REFERENCE "Wt32-Eth01" + +/** + * Device version + */ +#define DEV_VERSION "0.0.1" + +/** + * Device max number of relays + */ +#define DEV_MAX_RELAYS 1 + /** * Backend unsecure API URL */ diff --git a/esp32_device/main/http_client.h b/esp32_device/main/http_client.h index c730da5..ff4eeaf 100644 --- a/esp32_device/main/http_client.h +++ b/esp32_device/main/http_client.h @@ -13,7 +13,7 @@ extern "C" typedef struct { - char *url; + const char *url; char *root_ca; } http_request_opts; diff --git a/esp32_device/main/main.c b/esp32_device/main/main.c index 8ed99da..752db95 100755 --- a/esp32_device/main/main.c +++ b/esp32_device/main/main.c @@ -98,11 +98,49 @@ void app_main(void) ESP_LOGI(TAG, "Current root CA:\n%s", root_ca); free(root_ca); - // Check current device enrollment status - ESP_LOGI(TAG, "Check enrollment status"); - int status = secure_api_get_device_enrollment_status(); - ESP_LOGI(TAG, "Current enrollment status: %d\n", status); + bool validated = false; + while (!validated) + { + // Check current device enrollment status + ESP_LOGI(TAG, "Check enrollment status"); + enum DevEnrollmentStatus status = secure_api_get_device_enrollment_status(); + ESP_LOGI(TAG, "Current enrollment status: %d\n", status); + switch (status) + { + case DevEnrollError: + ESP_LOGE(TAG, "Failed to retrieve device enrollment status!"); + break; + + case DevEnrollPending: + ESP_LOGI(TAG, "Device enrolled, but not validated yet. Please accept device on central system web UI"); + break; + + case DevEnrollValidated: + ESP_LOGI(TAG, "Device enrolled and validated. Ready to operate!"); + validated = true; + break; + + case DevEnrollUnknown: + ESP_LOGI(TAG, "Device unknown, need to enroll!"); + + // TODO : remove certificate if present + + if (secure_api_enroll_device() != 0) + { + ESP_LOGE(TAG, "Failed to enroll device!"); + reboot(); + } + break; + } + + // Wait before next try + system_sleep(60); + }; + + // TODO : retrieve certificate if missing + + ESP_LOGI(TAG, "Starting main loop"); system_sleep(120); reboot(); diff --git a/esp32_device/main/secure_api.c b/esp32_device/main/secure_api.c index 3fb8367..600b915 100644 --- a/esp32_device/main/secure_api.c +++ b/esp32_device/main/secure_api.c @@ -6,13 +6,14 @@ #include "storage.h" #include "http_client.h" #include "constants.h" +#include "crypto.h" #include "cJSON.h" #include "esp_log.h" static const char *TAG = "secure_api"; -static char *process_secure_request(const char *uri) +static char *process_secure_request(const char *uri, const char *body) { char *url = calloc(1, 255); assert(url); @@ -46,7 +47,7 @@ enum DevEnrollmentStatus secure_api_get_device_enrollment_status() sprintf(uri, "/devices_api/mgmt/enrollment_status?id="); assert(storage_get_dev_name(uri + strlen(uri)) > 0); - char *res = process_secure_request(uri); + char *res = process_secure_request(uri, NULL); free(uri); @@ -89,4 +90,54 @@ fail: free(res); return s; +} + +/** + * Generate device information. Pointer to be released by caller + */ +static cJSON *genDevInfo() +{ + cJSON *json = cJSON_CreateObject(); + if (!json) + return NULL; + cJSON_AddStringToObject(json, "reference", DEV_REFERENCE); + cJSON_AddStringToObject(json, "version", DEV_VERSION); + cJSON_AddNumberToObject(json, "max_relays", DEV_MAX_RELAYS); + return json; +} + +int secure_api_enroll_device() +{ + char *csr = crypto_get_csr(); + if (!csr) + { + ESP_LOGE(TAG, "Failed to get CSR!"); + return 1; + } + + cJSON *obj = cJSON_CreateObject(); + if (!obj) + { + ESP_LOGE(TAG, "Failed allocate memory to store JSON object!"); + return 1; + } + + cJSON_AddItemToObject(obj, "info", genDevInfo()); + cJSON_AddStringToObject(obj, "csr", csr); + + char *body = cJSON_PrintUnformatted(obj); + if (!body) + { + ESP_LOGE(TAG, "Failed to generate JSON body!"); + return 1; + } + + // TODO : perform request + printf("res = %s\n", body); + + cJSON_Delete(obj); + free(body); + free(csr); + + return 0; } \ No newline at end of file diff --git a/esp32_device/main/secure_api.h b/esp32_device/main/secure_api.h index fe8fe45..849328d 100644 --- a/esp32_device/main/secure_api.h +++ b/esp32_device/main/secure_api.h @@ -30,6 +30,11 @@ extern "C" enum DevEnrollmentStatus secure_api_get_device_enrollment_status(); + /** + * Enroll device + */ + int secure_api_enroll_device(); + #ifdef __cplusplus } #endif diff --git a/python_device/src/main.py b/python_device/src/main.py index dde6e7b..c066e7b 100644 --- a/python_device/src/main.py +++ b/python_device/src/main.py @@ -66,7 +66,7 @@ if status == "Unknown": csr = "".join(f.read()) print("Enrolling device...") - crt = api.enroll_device(csr) + api.enroll_device(csr) print("Done. Please accept the device on central system web UI") exit(0)