From 5641123a97cf6be89226a0489a97fec061553b6d Mon Sep 17 00:00:00 2001 From: Suren Gabrielyan Date: Fri, 12 Apr 2024 12:07:36 +0400 Subject: [PATCH] feat(websocket): Enhance websocket example to test ds-peripherial --- .../examples/target/CMakeLists.txt | 7 ++ .../examples/target/README.md | 36 ++++++++ .../examples/target/main/idf_component.yml | 1 + .../examples/target/main/websocket_example.c | 83 +++++++++++++++++++ .../target/sdkconfig.ci.ds_peripheral | 7 ++ 5 files changed, 134 insertions(+) create mode 100644 components/esp_websocket_client/examples/target/sdkconfig.ci.ds_peripheral diff --git a/components/esp_websocket_client/examples/target/CMakeLists.txt b/components/esp_websocket_client/examples/target/CMakeLists.txt index 6858816b3e..6c10caee75 100644 --- a/components/esp_websocket_client/examples/target/CMakeLists.txt +++ b/components/esp_websocket_client/examples/target/CMakeLists.txt @@ -4,3 +4,10 @@ cmake_minimum_required(VERSION 3.5) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(websocket_example) + +# Flash the custom partition named `esp_secure_cert`. +set(partition esp_secure_cert) +idf_build_get_property(project_dir PROJECT_DIR) +set(image_file ${project_dir}/esp_secure_cert_data/${partition}.bin) +partition_table_get_partition_info(offset "--partition-name ${partition}" "offset") +esptool_py_flash_target_image(flash "${partition}" "${offset}" "${image_file}") diff --git a/components/esp_websocket_client/examples/target/README.md b/components/esp_websocket_client/examples/target/README.md index fd47add624..ae5c495885 100644 --- a/components/esp_websocket_client/examples/target/README.md +++ b/components/esp_websocket_client/examples/target/README.md @@ -63,6 +63,42 @@ Please see the openssl man pages (man openssl) for more details. It is **strongly recommended** to not reuse the example certificate in your application; it is included only for demonstration. +#### 3) Configure the DS peripheral + +* i) Install the [esp_secure_cert configuration utility](https://github.com/espressif/esp_secure_cert_mgr/tree/main/tools#esp_secure_cert-configuration-tool) with following comma nd: +``` +pip install esp-secure-cert-tool +``` +* ii) The DS peripheral can be configured by executing the following command: + +``` +configure_esp_secure_cert.py -p /* Serial port */ --device-cert /* Device cert */ --private-key /* RSA priv key */ --target_chip /* target chip */ --configure_ds --skip_flash +``` +This command shall generate a partition named `esp_secure_cert.bin` in the `esp_secure_cert_data` directory. This partition would be aumatically detected by the build system and flashed at appropriate offset when `idf.py flash` command is used. For this process, the command must be executed in the current folder only. + +In the command USB COM port is nothing but the serial port to which the ESP chip is connected. see +[check serial port](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/establish-serial-connection.html#check-port-on-windows) for more details. +RSA private key is nothing but the client private key ( RSA ) generated in Step 2. + +> Note: More details about the `esp-secure-cert-tool` utility can be found [here](https://github.com/espressif/esp_secure_cert_mgr/tree/main/tools). + +#### 4) Connection cofiguration +* Open the project configuration menu (`idf.py menuconfig`) +* Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../READM E.md) for more details. + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +idf.py -p PORT flash monitor +``` + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + + ### Build and Flash Build the project and flash it to the board, then run monitor tool to view serial output: diff --git a/components/esp_websocket_client/examples/target/main/idf_component.yml b/components/esp_websocket_client/examples/target/main/idf_component.yml index 0cc1eea4d0..dc7fb22435 100644 --- a/components/esp_websocket_client/examples/target/main/idf_component.yml +++ b/components/esp_websocket_client/examples/target/main/idf_component.yml @@ -1,4 +1,5 @@ dependencies: + espressif/esp_secure_cert_mgr: "^2.4.1" ## Required IDF version idf: ">=5.0" espressif/esp_websocket_client: diff --git a/components/esp_websocket_client/examples/target/main/websocket_example.c b/components/esp_websocket_client/examples/target/main/websocket_example.c index 112e9285c1..8beb317232 100644 --- a/components/esp_websocket_client/examples/target/main/websocket_example.c +++ b/components/esp_websocket_client/examples/target/main/websocket_example.c @@ -30,6 +30,18 @@ #include "esp_event.h" #include +#ifdef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL +#include "mbedtls/ssl.h" +#include "mbedtls/pk.h" +#include "mbedtls/x509.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" +#include "esp_idf_version.h" +#include "esp_secure_cert_read.h" +#include "esp_crt_bundle.h" +#endif + #define NO_DATA_TIMEOUT_SEC 5 static const char *TAG = "websocket"; @@ -69,6 +81,34 @@ static void get_string(char *line, size_t size) #endif /* CONFIG_WEBSOCKET_URI_FROM_STDIN */ +#ifdef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL +static esp_err_t test_ciphertext_validity(esp_ds_data_ctx_t *ds_data, unsigned char *dev_cert, size_t dev_cert_len) +{ + mbedtls_x509_crt crt; + mbedtls_x509_crt_init(&crt); + unsigned char *sig = NULL; + + if (ds_data == NULL || dev_cert == NULL) { + return ESP_ERR_INVALID_ARG; + } + + int ret = mbedtls_x509_crt_parse(&crt, dev_cert, dev_cert_len); + if (ret < 0) { + ESP_LOGE(TAG, "Parsing of device certificate failed, returned %02X", ret); + } + + esp_err_t esp_ret = esp_ds_init_data_ctx(ds_data); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialze the DS context"); + return esp_ret; + } + + const size_t sig_len = 256; + uint32_t hash[8] = {[0 ... 7] = 0xAABBCCDD}; + return esp_ret; +} +#endif + static void websocket_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) { esp_websocket_event_data_t *data = (esp_websocket_event_data_t *)event_data; @@ -163,6 +203,49 @@ static void websocket_app_start(void) websocket_cfg.cert_pem = cacert_start; #endif +#ifdef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL + uint32_t len = 0; + char *addr = NULL; + esp_err_t esp_ret = ESP_FAIL; + + esp_ds_data_ctx_t *ds_data = NULL; + ESP_LOGI(TAG, "Successfully obtained the ds context before"); + ds_data = esp_secure_cert_get_ds_ctx(); + ESP_LOGI(TAG, "Successfully obtained the ds context after"); + if (ds_data != NULL) { + ESP_LOGI(TAG, "Successfully obtained the ds context"); + ESP_LOG_BUFFER_HEX_LEVEL(TAG, ds_data->esp_ds_data->c, ESP_DS_C_LEN, ESP_LOG_DEBUG); + ESP_LOG_BUFFER_HEX_LEVEL(TAG, ds_data->esp_ds_data->iv, ESP_DS_IV_LEN, ESP_LOG_DEBUG); + ESP_LOGI(TAG, "The value of rsa length is %d", ds_data->rsa_length_bits); + ESP_LOGI(TAG, "The value of efuse key id is %d", ds_data->efuse_key_id); + } else { + ESP_LOGE(TAG, "Failed to obtain the ds context"); + } + + /* Read the dev_cert addr again */ + esp_ret = esp_secure_cert_get_device_cert(&addr, &len); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to obtain the dev cert flash address"); + } + + esp_ret = test_ciphertext_validity(ds_data, (unsigned char *)addr, len); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to validate ciphertext"); + } else { + ESP_LOGI(TAG, "Ciphertext validated succcessfully"); + } + websocket_cfg.client_cert = addr; + websocket_cfg.client_ds_data = ds_data; + // websocket_cfg.crt_bundle_attach = esp_crt_bundle_attach; + websocket_cfg.cert_pem = addr; + // extern const char cacert_start[] asm("_binary_ca_cert_pem_start"); // CA certificate + // websocket_cfg.cert_pem = cacert_start; + // websocket_cfg.client_key = NULL; + +// extern const char cacert_start[] asm("_binary_ca_certificate_public_domain_pem_start"); // CA cert of wss://echo.websocket.event, modify it if using another server +// websocket_cfg.cert_pem = cacert_start; +#endif + #if CONFIG_WS_OVER_TLS_SKIP_COMMON_NAME_CHECK websocket_cfg.skip_cert_common_name_check = true; #endif diff --git a/components/esp_websocket_client/examples/target/sdkconfig.ci.ds_peripheral b/components/esp_websocket_client/examples/target/sdkconfig.ci.ds_peripheral new file mode 100644 index 0000000000..e2c7de1982 --- /dev/null +++ b/components/esp_websocket_client/examples/target/sdkconfig.ci.ds_peripheral @@ -0,0 +1,7 @@ +CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL=y +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_OFFSET=0xC000 +CONFIG_IDF_TARGET="esp32s2" +CONFIG_WEBSOCKET_URI_FROM_STRING=y +CONFIG_WEBSOCKET_URI="wss://echo.websocket.events" +CONFIG_IDF_TARGET="esp32s2"