From f74b116a92efc25990d72b643cf1234972d8d267 Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Thu, 11 Jan 2024 09:18:31 +0100 Subject: [PATCH] ESP32: software update using hawkbit over HTTPS --- .github/workflows/build.yml | 9 +- port/esp32/README.md | 1 + port/esp32/adapter/include/debug_print.h | 24 +-- port/esp32/adapter/src/debug_print.c | 80 +++------ port/esp32/adapter/src/ipadapter.c | 7 +- port/esp32/adapter/src/tcpadapter.c | 2 + port/esp32/hawkbit/hawkbit.c | 219 ++++++++++++++++------- port/esp32/hawkbit/hawkbit_action.c | 13 +- port/esp32/hawkbit/hawkbit_action.h | 7 +- port/esp32/hawkbit/hawkbit_buffer.c | 62 +++++++ port/esp32/hawkbit/hawkbit_buffer.h | 57 ++++++ port/esp32/hawkbit/hawkbit_certificate.c | 84 +++++++++ port/esp32/hawkbit/hawkbit_certificate.h | 51 ++++++ port/esp32/hawkbit/hawkbit_context.c | 44 ++--- port/esp32/hawkbit/hawkbit_context.h | 50 +++--- port/esp32/hawkbit/hawkbit_deployment.c | 3 + port/esp32/hawkbit/hawkbit_download.c | 25 ++- port/esp32/hawkbit/hawkbit_download.h | 26 ++- port/esp32/hawkbit/hawkbit_feedback.c | 58 ++++-- port/esp32/hawkbit/hawkbit_feedback.h | 11 +- port/esp32/hawkbit/hawkbit_http.c | 43 +++-- port/esp32/hawkbit/hawkbit_http.h | 41 +++-- port/esp32/hawkbit/hawkbit_internal.h | 29 +-- port/esp32/hawkbit/hawkbit_resource.c | 2 + port/esp32/hawkbit/hawkbit_update.c | 19 +- port/esp32/hawkbit/hawkbit_update.h | 14 +- port/esp32/hawkbit/hawkbit_util.c | 3 - port/esp32/hawkbit/hawkbit_util.h | 26 +-- port/esp32/main/CMakeLists.txt | 45 +++-- port/esp32/main/Kconfig.projbuild | 23 ++- port/esp32/main/main.c | 158 ++++------------ port/esp32/sdkconfig.defaults | 10 +- 32 files changed, 769 insertions(+), 477 deletions(-) create mode 100644 port/esp32/hawkbit/hawkbit_buffer.c create mode 100644 port/esp32/hawkbit/hawkbit_buffer.h create mode 100644 port/esp32/hawkbit/hawkbit_certificate.c create mode 100644 port/esp32/hawkbit/hawkbit_certificate.h diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 559fd7d3f3..d480a70d1c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -99,14 +99,11 @@ jobs: run: | sudo apt install -y git wget flex bison gperf python3 python3-pip python3-setuptools python3-serial python3-click python3-cryptography python3-future python3-pyparsing python3-pyelftools cmake ninja-build ccache libffi-dev libssl-dev libusb-1.0-0 cd ./port/esp32 - # git clone --recursive -b release/v5.0 https://github.com/espressif/esp-idf.git - git clone -b release/v5.0 https://github.com/espressif/esp-idf.git - ( cd esp-idf && git checkout 335ca8a687d4f507b8ffe8a4ec3132ba4a4a4be3 ) - ( cd esp-idf && git submodule update --init --recursive ) + git clone --recursive -b release/v5.1 https://github.com/espressif/esp-idf.git ./esp-idf/install.sh . ./esp-idf/export.sh idf.py ${{ matrix.args }} set-target esp32 - ( cd esp-idf/components/mbedtls/mbedtls && patch -p1 < ../../../../../../patches/mbedtls/3.1/01-ocf-x509san-anon-psk.patch) - ( cd esp-idf/components/mbedtls/mbedtls && patch -p1 < ../../../../patches/mbedtls/3.1/02-ocf-mbedtls-config.patch) + ( cd esp-idf/components/mbedtls/mbedtls && patch -p1 < ../../../../../../patches/mbedtls/3.5/01-ocf-anon-psk.patch ) + ( cd esp-idf/components/mbedtls/mbedtls && patch -p1 < ../../../../patches/mbedtls/3.5/02-ocf-mbedtls-config.patch ) ( cd esp-idf/components/lwip/lwip && find ../../../../patches/lwip/ -type f -name '*.patch' -exec patch -p1 -i {} \; ) idf.py build diff --git a/port/esp32/README.md b/port/esp32/README.md index edce90ae97..fc68326ba8 100644 --- a/port/esp32/README.md +++ b/port/esp32/README.md @@ -70,6 +70,7 @@ for mbedTLS v3.1.0: # apply iotivity-lite patches for mbedTLS v3.1.0 ( cd esp-idf/components/mbedtls/mbedtls && patch -p1 < ../../../../../../patches/mbedtls/3.1/01-ocf-x509san-anon-psk.patch ) ( cd esp-idf/components/mbedtls/mbedtls && patch -p1 < ../../../../patches/mbedtls/3.1/02-ocf-mbedtls-config.patch ) + ( cd esp-idf/components/lwip/lwip && find ../../../../patches/lwip/ -type f -name '*.patch' -exec patch -p1 -i {} \; ) --> ```bash diff --git a/port/esp32/adapter/include/debug_print.h b/port/esp32/adapter/include/debug_print.h index c875a7e6c5..54ff881be3 100644 --- a/port/esp32/adapter/include/debug_print.h +++ b/port/esp32/adapter/include/debug_print.h @@ -18,8 +18,6 @@ extern "C" { #endif -#define APP_PRINT(...) printf(__VA_ARGS__) - /** * @brief print current all macro information * @@ -38,23 +36,7 @@ void print_macro_info(); * @param[in] message: the struct oc_message_t to print * */ -void print_message_info(oc_message_t *message); - -/** - * @brief print the data detail information - * - * print input data, print from data[0] to data[len-1], addtionally add notes - * string - * - * @param[in] data: input data pointer to print - * @param[in] len: data length - * @param[in] note: notes for read easily - * @param[in] mode: 0x00, 0x01, 0x10, 0x11 to decide the BINARY_SHOW && - * BYTES_SHOW - * - */ -void print_debug(const char *data, const unsigned int len, const char *note, - int mode); +void print_message_info(const oc_message_t *message); /** * @brief print the fatal error information and cycle it @@ -73,8 +55,8 @@ void print_debug(const char *data, const unsigned int len, const char *note, #define APP_LOG(level, ...) \ do { \ - APP_PRINT("%s: %s <%s:%d>: ", level, __FILE__, __FUNCTION__, __LINE__); \ - APP_PRINT(__VA_ARGS__); \ + printf("%s: %s <%s:%d>: ", level, __FILE__, __FUNCTION__, __LINE__); \ + printf(__VA_ARGS__); \ printf("\n"); \ } while (0) #define APP_DBG(...) APP_LOG("DEBUG", __VA_ARGS__) diff --git a/port/esp32/adapter/src/debug_print.c b/port/esp32/adapter/src/debug_print.c index c0a658e805..1dc7fd4132 100644 --- a/port/esp32/adapter/src/debug_print.c +++ b/port/esp32/adapter/src/debug_print.c @@ -7,6 +7,7 @@ */ #include "debug_print.h" #include "port/oc_connectivity.h" +#include "port/oc_log_internal.h" #include #include @@ -15,11 +16,7 @@ print_macro_info() { printf("\n****************************************\n"); -#ifdef OC_DEBUG - printf("OC_DEBUG defined!\n"); -#else - printf("OC_DEBUG not defined!\n"); -#endif + printf("OC_LOG_MAXIMUM_LEVEL=%d\n", OC_LOG_MAXIMUM_LEVEL); #ifdef APP_DEBUG printf("APP_DEBUG defined!\n"); @@ -45,6 +42,12 @@ print_macro_info() printf("OC_IPV4 not defined!\n"); #endif +#ifdef OC_CLOUD + printf("OC_CLOUD defined!\n"); +#else + printf("OC_CLOUD not defined!\n"); +#endif + #ifdef ENABLE_LIGHT printf("ENABLE_LIGHT defined!\n"); #else @@ -57,6 +60,12 @@ print_macro_info() printf("OC_SECURITY not defined!\n"); #endif +#ifdef OC_PKI + printf("OC_PKI defined!\n"); +#else + printf("OC_PKI not defined!\n"); +#endif + #ifdef OC_DYNAMIC_ALLOCATION printf("OC_DYNAMIC_ALLOCATION defined!\n"); #else @@ -69,13 +78,25 @@ print_macro_info() printf("OC_BLOCK_WISE not defined!\n"); #endif +#ifdef OC_SOFTWARE_UPDATE + printf("OC_SOFTWARE_UPDATE defined!\n"); +#else + printf("OC_SOFTWARE_UPDATE not defined!\n"); +#endif + +#ifdef PLGD_DEV_HAWKBIT + printf("PLGD_DEV_HAWKBIT defined!\n"); +#else + printf("PLGD_DEV_HAWKBIT not defined!\n"); +#endif + printf("\n****************************************\n"); } void -print_message_info(oc_message_t *message) +print_message_info(const oc_message_t *message) { -#ifdef OC_DEBUG +#ifdef APP_DEBUG printf("\n****************************************\n"); #ifdef OC_IPV4 @@ -106,48 +127,3 @@ print_message_info(oc_message_t *message) printf("\n****************************************\n"); #endif } - -/** - * @brief print the data detail information - * - * print input data, print from data[0] to data[len-1], addtionally add notes - * string - * - * @param[in] data: input data pointer to print - * @param[in] len: data length - * @param[in] note: notes for read easily - * @param[in] mode: 0x00, 0x01, 0x10, 0x11 to decide the BINARY_SHOW && - * BYTES_SHOW - * - * @return noreturn - * - */ -void -print_debug(const char *data, const unsigned int len, const char *note, - int mode) -{ -#define BINARY_SHOW 0x10 -#define BYTES_SHOW 0x01 - printf("\n********** %s [len:%u] start addr:%p **********\n", note, len, - data); - int i = 0; - for (i = 0; i < len; ++i) { - if (BINARY_SHOW & mode) { - printf("%02x ", data[i]); - } else { - if (data[i] < 32 || data[i] > 126) { // control || invisible charset - if (i > 0 && (data[i - 1] >= 33 && data[i - 1] <= 126)) - printf(" "); - printf("%02x ", data[i]); - } else { - printf("%c", data[i]); - } - } - - if ((BYTES_SHOW & mode) && ((i + 1) % 32 == 0)) { - printf(" | %d Bytes\n", i + 1); - } - } // end for - - printf("\n---------- %s End ----------\n", note); -} diff --git a/port/esp32/adapter/src/ipadapter.c b/port/esp32/adapter/src/ipadapter.c index ae0bd6b027..09730dc824 100644 --- a/port/esp32/adapter/src/ipadapter.c +++ b/port/esp32/adapter/src/ipadapter.c @@ -1722,12 +1722,7 @@ oc_dns_lookup(const char *domain, oc_string_t *addr, transport_flags flags) #endif /* OC_DNS_CACHE */ freeaddrinfo(result); } else { -#ifdef OC_DEBUG - OC_ERR("failed to resolve address(%s) with error(%d): %s", domain, ret, - gai_strerror(ret)); -#else /* OC_DEBUG */ - OC_ERR("failed to resolve address(%s) with error(%d)", domain, ret); -#endif /* !OC_DEBUG */ + OC_ERR("failed to resolve address(%s) with error(%d)", domain, ret); } #ifdef OC_DNS_CACHE } else { diff --git a/port/esp32/adapter/src/tcpadapter.c b/port/esp32/adapter/src/tcpadapter.c index b1738baf28..45acfc8a67 100644 --- a/port/esp32/adapter/src/tcpadapter.c +++ b/port/esp32/adapter/src/tcpadapter.c @@ -16,7 +16,9 @@ * ****************************************************************************/ +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif #include "api/oc_message_internal.h" #include "api/oc_session_events_internal.h" diff --git a/port/esp32/hawkbit/hawkbit.c b/port/esp32/hawkbit/hawkbit.c index d3ed014e98..3fbc80fed4 100644 --- a/port/esp32/hawkbit/hawkbit.c +++ b/port/esp32/hawkbit/hawkbit.c @@ -20,6 +20,8 @@ #include "debug_print.h" #include "oc_esp.h" #include "hawkbit_action.h" +#include "hawkbit_buffer.h" +#include "hawkbit_certificate.h" #include "hawkbit_context.h" #include "hawkbit_deployment.h" #include "hawkbit_feedback.h" @@ -28,6 +30,7 @@ #include "hawkbit_json.h" #include "hawkbit_util.h" +#include "api/oc_helpers_internal.h" #include "api/oc_swupdate_internal.h" #include "oc_api.h" #include "oc_core_res.h" @@ -35,6 +38,7 @@ #ifdef OC_SECURITY #include "oc_store.h" #include "security/oc_doxm_internal.h" +#include "security/oc_cred_util_internal.h" #endif /* OC_SECURITY */ #include @@ -46,6 +50,7 @@ #include #include +#include #include #include #include @@ -53,17 +58,43 @@ #include static cJSON * -hawkbit_fetch_by_http_get(const char *url) +hawkbit_fetch_by_http_get(const hawkbit_context_t *ctx, oc_string_view_t url) { - char buffer[HAWKBIT_HTTP_MAX_OUTPUT_BUFFER] = { 0 }; - int code = hawkbit_http_perform_get(url, buffer, sizeof(buffer)); +#if defined(OC_SECURITY) && defined(OC_PKI) + hawkbit_buffer_t hb; + long pem_len = hawkbit_certificate_get_CA(hawkbit_get_device(ctx), &hb); + if (pem_len < 0) { + APP_ERR("cannot obtain certificate"); + return false; + } + oc_string_view_t pem = oc_string_view(hb.buffer, (size_t)pem_len); +#else /* !OC_SECURITY || !OC_PKI */ + (void)ctx; + oc_string_view_t pem = OC_STRING_VIEW_NULL; +#endif /* OC_SECURITY && OC_PKI */ + + hawkbit_buffer_t output; + if (!hawkbit_buffer_init(&output, HAWKBIT_HTTP_MAX_OUTPUT_BUFFER)) { + APP_ERR("fetch by HTTP GET: failed to allocate output buffer"); +#if defined(OC_SECURITY) && defined(OC_PKI) + hawkbit_buffer_free(&hb); +#endif /* OC_SECURITY && OC_PKI */ + return false; + } + int code = hawkbit_http_perform_get(url, pem, output.buffer, + hawkbit_buffer_size(&output)); +#if defined(OC_SECURITY) && defined(OC_PKI) + hawkbit_buffer_free(&hb); +#endif /* OC_SECURITY && OC_PKI */ if (code < 0 || code != HAWKBIT_HTTP_CODE_OK) { APP_ERR("fetch by HTTP GET: unexpected HTTP code(%d)", code); + hawkbit_buffer_free(&output); return NULL; } - APP_DBG("Fetch by HTTP GET payload: %s", buffer); - cJSON *root = cJSON_Parse(buffer); + APP_DBG("Fetch by HTTP GET payload: %s", output.buffer); + cJSON *root = cJSON_Parse(output.buffer); + hawkbit_buffer_free(&output); if (root == NULL) { #ifdef APP_DEBUG const char *json_error = cJSON_GetErrorPtr(); @@ -105,15 +136,18 @@ hawkbit_get_url_tenant(size_t device, hawkbit_url_t hurl, char *tenant, tenant[hurl.tenant_length] = '\0'; return true; } + (void)device; +#if 0 #ifdef OC_SECURITY + // TODO: devowneruuid doesn't seem to work for hawkbit, check if the tenant_id + // must have some format const oc_sec_doxm_t *doxm = oc_sec_get_doxm(device); if (doxm->owned && tenant_size >= OC_UUID_LEN) { oc_uuid_to_str(&doxm->devowneruuid, tenant, tenant_size); return true; } -#else /* !OC_SECURITY */ - (void)device; #endif /* OC_SECURITY */ +#endif return false; } @@ -143,10 +177,6 @@ hawkbit_get_url(const hawkbit_context_t *ctx, char *server_url, size_t server_url_size, char *tenant, size_t tenant_size, char *controller_id, size_t controller_id_size) { - assert(server_url != NULL); - assert(tenant != NULL); - assert(controller_id != NULL); - const char *purl = hawkbit_get_package_url(ctx); if (purl == NULL) { return HAWKBIT_ERROR_PACKAGE_URL_NOT_SET; @@ -162,8 +192,6 @@ hawkbit_get_url(const hawkbit_context_t *ctx, char *server_url, return HAWKBIT_ERROR_GENERAL; } - // TODO: devowneruuid doesn't seem to work for hawkbit, check if the tenant_id - // must have some format if (!hawkbit_get_url_tenant(hawkbit_get_device(ctx), hurl, tenant, tenant_size)) { APP_ERR("get URL failed: cannot get tenant"); @@ -181,7 +209,7 @@ hawkbit_get_url(const hawkbit_context_t *ctx, char *server_url, return HAWKBIT_OK; } -static hawkbit_error_t +static int hawkbit_base_resource_url(const hawkbit_context_t *ctx, char *buffer, size_t buffer_size) { @@ -201,15 +229,16 @@ hawkbit_base_resource_url(const hawkbit_context_t *ctx, char *buffer, APP_ERR("get resource URL failed: %s", "cannot get url"); return HAWKBIT_ERROR_GENERAL; } - return HAWKBIT_OK; + return len; } static bool -hawkbit_fetch_deployment(const char *url, hawkbit_deployment_t *deployment) +hawkbit_fetch_deployment(const hawkbit_context_t *ctx, oc_string_view_t url, + hawkbit_deployment_t *deployment) { - assert(url != NULL); + assert(url.data != NULL); assert(deployment != NULL); - cJSON *root = hawkbit_fetch_by_http_get(url); + cJSON *root = hawkbit_fetch_by_http_get(ctx, url); if (root == NULL) { return false; } @@ -220,11 +249,12 @@ hawkbit_fetch_deployment(const char *url, hawkbit_deployment_t *deployment) } static bool -hawkbit_fetch_cancel(const char *url, hawkbit_action_t *action) +hawkbit_fetch_cancel(const hawkbit_context_t *ctx, oc_string_view_t url, + hawkbit_action_t *action) { - assert(url != NULL); + assert(url.data != NULL); assert(action != NULL); - cJSON *root = hawkbit_fetch_by_http_get(url); + cJSON *root = hawkbit_fetch_by_http_get(ctx, url); if (root == NULL) { return false; } @@ -296,16 +326,14 @@ hawkbit_error_t hawkbit_poll_base_resource(hawkbit_context_t *ctx, hawkbit_action_t *action, hawkbit_configuration_t *cfg) { - assert(ctx != NULL); - assert(action != NULL); - char url[256]; - hawkbit_error_t err = hawkbit_base_resource_url(ctx, url, sizeof(url)); - if (err != HAWKBIT_OK) { - return err; + int ret = hawkbit_base_resource_url(ctx, url, sizeof(url)); + if (ret < 0) { + return (hawkbit_error_t)ret; } APP_DBG("Base resource URL: %s", url); - cJSON *root = hawkbit_fetch_by_http_get(url); + oc_string_view_t urlv = oc_string_view(url, (size_t)ret); + cJSON *root = hawkbit_fetch_by_http_get(ctx, urlv); if (root == NULL) { return HAWKBIT_ERROR_GENERAL; } @@ -328,8 +356,9 @@ hawkbit_poll_base_resource(hawkbit_context_t *ctx, hawkbit_action_t *action, hawkbit_json_get_string(root, "_links.deploymentBase.href"); if (href != NULL) { APP_DBG("Deployment URL: %s", href); + oc_string_view_t hrefv = oc_string_view(href, strlen(href)); hawkbit_deployment_t deployment; - if (!hawkbit_fetch_deployment(href, &deployment)) { + if (!hawkbit_fetch_deployment(ctx, hrefv, &deployment)) { cJSON_Delete(root); return HAWKBIT_ERROR_GENERAL; } @@ -350,7 +379,8 @@ hawkbit_poll_base_resource(hawkbit_context_t *ctx, hawkbit_action_t *action, href = hawkbit_json_get_string(root, "_links.cancelAction.href"); if (href != NULL) { APP_DBG("Cancel URL: %s", href); - bool result = hawkbit_fetch_cancel(href, action); + oc_string_view_t hrefv = oc_string_view(href, strlen(href)); + bool result = hawkbit_fetch_cancel(ctx, hrefv, action); cJSON_Delete(root); return result ? HAWKBIT_OK : HAWKBIT_ERROR_GENERAL; } @@ -367,7 +397,7 @@ typedef struct } hawkbit_data_item_t; static bool -hawkbit_configure(const hawkbit_context_t *ctx, const char *url) +hawkbit_configure(const hawkbit_context_t *ctx, oc_string_view_t url) { oc_esp_mac_address_t mac; if (!oc_esp_get_mac_address(&mac)) { @@ -408,12 +438,12 @@ hawkbit_configure(const hawkbit_context_t *ctx, const char *url) }; const size_t data_size = sizeof(data) / sizeof(data[0]); - if (url == NULL || url[0] == '\0') { + if (url.data == NULL || url.data[0] == '\0') { APP_ERR("hawkbit configure error: invalid configuration URL"); return -1; } - APP_DBG("hawkbit configure at href(%s)", url); + APP_DBG("hawkbit configure at href(%s)", url.data); cJSON *root = cJSON_CreateObject(); // mode @@ -445,9 +475,36 @@ hawkbit_configure(const hawkbit_context_t *ctx, const char *url) return false; } - char output[HAWKBIT_HTTP_MAX_OUTPUT_BUFFER] = { 0 }; - int code = hawkbit_http_perform_put(url, body, output, sizeof(output)); +#if defined(OC_SECURITY) && defined(OC_PKI) + hawkbit_buffer_t hb; + long pem_len = hawkbit_certificate_get_CA(hawkbit_get_device(ctx), &hb); + if (pem_len < 0) { + APP_ERR("cannot obtain certificate"); + free(body); + return false; + } + oc_string_view_t pem = oc_string_view(hb.buffer, (size_t)pem_len); +#else /* !OC_SECURITY || !OC_PKI */ + oc_string_view_t pem = OC_STRING_VIEW_NULL; +#endif /* OC_SECURITY && OC_PKI */ + + hawkbit_buffer_t output; + if (!hawkbit_buffer_init(&output, HAWKBIT_HTTP_MAX_OUTPUT_BUFFER)) { + APP_ERR("hawkbit configure error: failed to allocate output buffer"); +#if defined(OC_SECURITY) && defined(OC_PKI) + hawkbit_buffer_free(&hb); +#endif /* OC_SECURITY && OC_PKI */ + free(body); + return false; + } + int code = hawkbit_http_perform_put(url, body, pem, output.buffer, + hawkbit_buffer_size(&output)); + hawkbit_buffer_free(&output); +#if defined(OC_SECURITY) && defined(OC_PKI) + hawkbit_buffer_free(&hb); +#endif /* OC_SECURITY && OC_PKI */ free(body); + if (code < 0 || code != HAWKBIT_HTTP_CODE_OK) { APP_ERR("hawkbit configure error: unexpected HTTP code(%d)", code); return false; @@ -456,39 +513,55 @@ hawkbit_configure(const hawkbit_context_t *ctx, const char *url) } static esp_http_client_config_t -hawkbit_download_get_client_config(hawkbit_download_links_t links) +hawkbit_download_get_client_config(hawkbit_download_links_t links, + oc_string_view_t pem) { - if (oc_string(links.download) != NULL) { - // TODO - } - if (oc_string(links.downloadHttp) != NULL) { - esp_http_client_config_t config = {}; - config.url = oc_string(links.downloadHttp); - config.cert_pem = (char *)""; - config.skip_cert_common_name_check = true; - return config; - } + assert(oc_string(links.downloadHttp) != NULL); + esp_http_client_config_t config = {}; + config.url = oc_string(links.downloadHttp); + config.cert_pem = pem.data; + config.cert_len = + pem.length + 1; // must include the nul-terminator for mbedTLS + config.keep_alive_enable = true; + config.timeout_ms = 5000; return config; } bool -hawkbit_download_from_links(hawkbit_download_links_t links) +hawkbit_download_from_links(const hawkbit_context_t *ctx, + hawkbit_download_links_t links) { if (oc_string(links.download) == NULL && oc_string(links.downloadHttp) == NULL) { return false; } - esp_http_client_config_t config = hawkbit_download_get_client_config(links); + +#if defined(OC_SECURITY) && defined(OC_PKI) + hawkbit_buffer_t hb; + long pem_len = hawkbit_certificate_get_CA(hawkbit_get_device(ctx), &hb); + if (pem_len < 0) { + APP_ERR("cannot obtain certificate"); + return false; + } + oc_string_view_t pem = oc_string_view(hb.buffer, (size_t)pem_len); +#else /* !OC_SECURITY || !OC_PKI */ + (void)ctx; + oc_string_view_t pem = OC_STRING_VIEW_NULL; +#endif /* OC_SECURITY && OC_PKI */ + + esp_http_client_config_t config = + hawkbit_download_get_client_config(links, pem); esp_https_ota_config_t ota_config = { .http_config = &config, - .partial_http_download = false, + .partial_http_download = true, + .max_http_request_size = CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN, }; esp_https_ota_handle_t https_ota_handle = NULL; esp_err_t err = esp_https_ota_begin(&ota_config, &https_ota_handle); if (err != ESP_OK) { APP_ERR("OTA update begin failed: %s", esp_err_to_name(err)); - return false; + goto error; } while (true) { @@ -496,28 +569,43 @@ hawkbit_download_from_links(hawkbit_download_links_t links) if (err != ESP_ERR_HTTPS_OTA_IN_PROGRESS) { break; } + APP_DBG("Image bytes read: %d", + esp_https_ota_get_image_len_read(https_ota_handle)); } if (err != ESP_OK) { APP_ERR("OTA update perform failed: %s", esp_err_to_name(err)); - err = esp_https_ota_abort(https_ota_handle); - if (err != ESP_OK) { - APP_ERR("OTA abort failed: %s", esp_err_to_name(err)); - } - return false; + esp_https_ota_abort(https_ota_handle); + goto error; + } + + if (!esp_https_ota_is_complete_data_received(https_ota_handle)) { + APP_ERR("Complete data was not received."); + esp_https_ota_abort(https_ota_handle); + goto error; } err = esp_https_ota_finish(https_ota_handle); if (err != ESP_OK) { APP_ERR("OTA update finish failed: %s", esp_err_to_name(err)); - return false; + goto error; } + +#if defined(OC_SECURITY) && defined(OC_PKI) + hawkbit_buffer_free(&hb); +#endif /* OC_SECURITY && OC_PKI */ return true; + +error: +#if defined(OC_SECURITY) && defined(OC_PKI) + hawkbit_buffer_free(&hb); +#endif /* OC_SECURITY && OC_PKI */ + return false; } static void hawkbit_send_deploy_feedback_and_log_error( - const hawkbit_context_t *ctx, const char *id, + const hawkbit_context_t *ctx, oc_string_view_t id, hawkbit_feedback_execution_t execution, hawkbit_feedback_result_t result) { if (!hawkbit_send_deploy_feedback(ctx, id, execution, result)) { @@ -526,8 +614,9 @@ hawkbit_send_deploy_feedback_and_log_error( } static bool -hawkbit_prepare_async_update(hawkbit_context_t *ctx, const char *deployment_id, - const char *version, +hawkbit_prepare_async_update(hawkbit_context_t *ctx, + oc_string_view_t deployment_id, + oc_string_view_t version, hawkbit_sha256_digest_t digest) { const esp_partition_t *update = esp_ota_get_boot_partition(); @@ -578,7 +667,7 @@ hawkbit_download_execute(hawkbit_context_t *ctx) ctx, hawkbit_download_get_deployment_id(download), HAWKBIT_FEEDBACK_EXECUTION_PROCEEDING, HAWKBIT_FEEDBACK_RESULT_NONE); - if (!hawkbit_download_from_links(hawkbit_download_get_links(download))) { + if (!hawkbit_download_from_links(ctx, hawkbit_download_get_links(download))) { APP_ERR("hawkbit download error: failed to download the update"); hawkbit_send_deploy_feedback_and_log_error( ctx, hawkbit_download_get_deployment_id(download), @@ -668,8 +757,8 @@ hawkbit_update(hawkbit_context_t *ctx) if (update_partition == NULL) { APP_ERR("partition with stored update not found"); hawkbit_send_deploy_feedback_and_log_error( - ctx, oc_string(update->deployment_id), HAWKBIT_FEEDBACK_EXECUTION_CLOSED, - HAWKBIT_FEEDBACK_RESULT_FAILURE); + ctx, oc_string_view2(&update->deployment_id), + HAWKBIT_FEEDBACK_EXECUTION_CLOSED, HAWKBIT_FEEDBACK_RESULT_FAILURE); hawkbit_clear_update(ctx); return false; } @@ -678,8 +767,8 @@ hawkbit_update(hawkbit_context_t *ctx) return false; } hawkbit_send_deploy_feedback_and_log_error( - ctx, oc_string(update->deployment_id), HAWKBIT_FEEDBACK_EXECUTION_CLOSED, - HAWKBIT_FEEDBACK_RESULT_SUCCESS); + ctx, oc_string_view2(&update->deployment_id), + HAWKBIT_FEEDBACK_EXECUTION_CLOSED, HAWKBIT_FEEDBACK_RESULT_SUCCESS); return true; } @@ -805,7 +894,7 @@ hawkbit_poll(hawkbit_context_t *ctx, hawkbit_configuration_t *cfg) APP_DBG("hawkbit action: %s(%d)", hawkbit_action_type_to_string(action.type), action.type); if (action.type == HAWKBIT_ACTION_CONFIGURE) { - if (!hawkbit_configure(ctx, oc_string(action.data.configure.url))) { + if (!hawkbit_configure(ctx, oc_string_view2(&action.data.configure.url))) { APP_ERR("cannot configure device in hawkbit server"); hawkbit_action_free(&action); return HAWKBIT_ERROR_GENERAL; diff --git a/port/esp32/hawkbit/hawkbit_action.c b/port/esp32/hawkbit/hawkbit_action.c index 91c243d22d..dd8d22b9fe 100644 --- a/port/esp32/hawkbit/hawkbit_action.c +++ b/port/esp32/hawkbit/hawkbit_action.c @@ -19,8 +19,6 @@ #include "hawkbit_action.h" -#include - #define HAWKBIT_ACTION_NONE_STR "no action" #define HAWKBIT_ACTION_CONFIGURE_STR "configure" #define HAWKBIT_ACTION_DEPLOY_STR "deploy" @@ -56,7 +54,6 @@ hawkbit_action_none() hawkbit_action_t hawkbit_action_cancel(const char *id) { - assert(id != NULL); hawkbit_action_t action = { .type = HAWKBIT_ACTION_CANCEL, }; @@ -67,7 +64,6 @@ hawkbit_action_cancel(const char *id) hawkbit_action_t hawkbit_action_configure(const char *url) { - assert(url != NULL); hawkbit_action_t action = { .type = HAWKBIT_ACTION_CONFIGURE, }; @@ -85,14 +81,13 @@ hawkbit_action_deploy(hawkbit_deployment_t deployment) return action; } -/** - * @brief Deallocate data for given action type - * - * @param action action to clear (cannot be NULL) - */ void hawkbit_action_free(hawkbit_action_t *action) { + if (action == NULL) { + return; + } + if (action->type == HAWKBIT_ACTION_CANCEL) { oc_free_string(&action->data.cancel.id); return; diff --git a/port/esp32/hawkbit/hawkbit_action.h b/port/esp32/hawkbit/hawkbit_action.h index 2fec5d8d96..f00629f832 100644 --- a/port/esp32/hawkbit/hawkbit_action.h +++ b/port/esp32/hawkbit/hawkbit_action.h @@ -22,6 +22,7 @@ #include "hawkbit_deployment.h" #include "oc_helpers.h" +#include "util/oc_compiler.h" #ifdef __cplusplus extern "C" { @@ -68,10 +69,10 @@ const char *hawkbit_action_type_to_string(hawkbit_action_type_t action); hawkbit_action_t hawkbit_action_none(); /** Create cancel action */ -hawkbit_action_t hawkbit_action_cancel(const char *id); +hawkbit_action_t hawkbit_action_cancel(const char *id) OC_NONNULL(); /** Create configure action */ -hawkbit_action_t hawkbit_action_configure(const char *url); +hawkbit_action_t hawkbit_action_configure(const char *url) OC_NONNULL(); /** Create deploy action */ hawkbit_action_t hawkbit_action_deploy(hawkbit_deployment_t deployment); @@ -79,7 +80,7 @@ hawkbit_action_t hawkbit_action_deploy(hawkbit_deployment_t deployment); /** * @brief Deallocate data for given action type * - * @param action action to free (cannot be NULL) + * @param action action to free */ void hawkbit_action_free(hawkbit_action_t *action); diff --git a/port/esp32/hawkbit/hawkbit_buffer.c b/port/esp32/hawkbit/hawkbit_buffer.c new file mode 100644 index 0000000000..f1d242888a --- /dev/null +++ b/port/esp32/hawkbit/hawkbit_buffer.c @@ -0,0 +1,62 @@ +/**************************************************************************** + * + * Copyright (c) 2024 plgd.dev s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ + +#include "hawkbit_buffer.h" + +#ifdef OC_DYNAMIC_ALLOCATION +#include +#endif /* OC_DYNAMIC_ALLOCATION */ +#include + +bool +hawkbit_buffer_init(hawkbit_buffer_t *hb, size_t size) +{ +#ifdef OC_DYNAMIC_ALLOCATION + hb->buffer = (char *)calloc(1, size); + if (hb->buffer == NULL) { + return false; + } + hb->buffer_size = size; + return true; +#else /* !OC_DYNAMIC_ALLOCATION */ + (void)size; + memset(hb, 0, sizeof(*hb)); + return true; +#endif /* OC_DYNAMIC_ALLOCATION */ +} + +void +hawkbit_buffer_free(hawkbit_buffer_t *hb) +{ + if (hb == NULL) { + return; + } +#ifdef OC_DYNAMIC_ALLOCATION + free(hb->buffer); +#endif /* OC_DYNAMIC_ALLOCATION */ +} + +size_t +hawkbit_buffer_size(const hawkbit_buffer_t *hb) +{ +#ifdef OC_DYNAMIC_ALLOCATION + return hb->buffer_size; +#else /* !OC_DYNAMIC_ALLOCATION */ + return HAWKBIT_BUFFER_SIZE; +#endif /* OC_DYNAMIC_ALLOCATION */ +} diff --git a/port/esp32/hawkbit/hawkbit_buffer.h b/port/esp32/hawkbit/hawkbit_buffer.h new file mode 100644 index 0000000000..22421b9e2d --- /dev/null +++ b/port/esp32/hawkbit/hawkbit_buffer.h @@ -0,0 +1,57 @@ +/**************************************************************************** + * + * Copyright (c) 2024 plgd.dev s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ + +#ifndef HAWKBIT_BUFFER_H +#define HAWKBIT_BUFFER_H + +#include "util/oc_compiler.h" + +#include +#include + +#ifndef OC_DYNAMIC_ALLOCATION +#define HAWKBIT_BUFFER_SIZE (2048) +#endif /* OC_DYNAMIC_ALLOCATION */ + +typedef struct +{ +#ifdef OC_DYNAMIC_ALLOCATION + char *buffer; + size_t buffer_size; +#else /* !OC_DYNAMIC_ALLOCATION */ + char buffer[HAWKBIT_BUFFER_SIZE]; +#endif /* OC_DYNAMIC_ALLOCATION */ +} hawkbit_buffer_t; + +/** + * @brief Initialize buffer + * + * @param hb buffer to initialize (cannot be NULL) + * @param size size of the allocated buffer (only relevant if dynamic allocation + * is enabled, otherwise the buffer is static with size HAWKBIT_BUFFER_SIZE) + * @return hawkbit_buffer_t + */ +bool hawkbit_buffer_init(hawkbit_buffer_t *hb, size_t size) OC_NONNULL(); + +/** Deallocate buffer */ +void hawkbit_buffer_free(hawkbit_buffer_t *hb); + +/** Get size of the buffer */ +size_t hawkbit_buffer_size(const hawkbit_buffer_t *hb) OC_NONNULL(); + +#endif /* HAWKBIT_BUFFER_H */ diff --git a/port/esp32/hawkbit/hawkbit_certificate.c b/port/esp32/hawkbit/hawkbit_certificate.c new file mode 100644 index 0000000000..2275b3d258 --- /dev/null +++ b/port/esp32/hawkbit/hawkbit_certificate.c @@ -0,0 +1,84 @@ +/**************************************************************************** + * + * Copyright (c) 2023 plgd.dev s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ + +#include "util/oc_features.h" + +#if defined(OC_SECURITY) || defined(OC_PKI) + +#include "hawkbit_certificate.h" +#include "oc_cred.h" +#include "security/oc_cred_util_internal.h" + +#ifdef OC_DYNAMIC_ALLOCATION +#include +#endif /* OC_DYNAMIC_ALLOCATION */ + +#define HAWKBIT_PEM_BUFFER_SIZE (2048) + +static bool +certificate_is_CA(const oc_sec_cred_t *cred, void *user_data) +{ + (void)user_data; + return cred->credusage == OC_CREDUSAGE_TRUSTCA || + cred->credusage == OC_CREDUSAGE_MFG_TRUSTCA; +} + +static long +hawkbit_certificate_get_CA_pem(size_t device, char *buffer, size_t buffer_size) +{ + oc_sec_creds_t *creds = oc_sec_get_creds(device); + if (creds == NULL) { + return -1; + } + long pem_size = oc_cred_serialize(creds->creds, certificate_is_CA, NULL, + buffer, buffer_size); + + if (pem_size < 0 || buffer == NULL) { + return pem_size; + } + if ((size_t)pem_size == buffer_size) { + return -1; + } + buffer[(size_t)pem_size] = '\0'; + return pem_size; +} + +long +hawkbit_certificate_get_CA(size_t device, hawkbit_buffer_t *hb) +{ +#ifdef OC_DYNAMIC_ALLOCATION + long pem_size = hawkbit_certificate_get_CA_pem(device, NULL, 0); + if (pem_size < 0) { + return -1; + } + if (!hawkbit_buffer_init(hb, pem_size + 1)) { // +1 for nul-terminator + return -1; + } +#else /* !OC_DYNAMIC_ALLOCATION */ + hawkbit_buffer_init(hb, HAWKBIT_PEM_BUFFER_SIZE); +#endif /* OC_DYNAMIC_ALLOCATION */ + long ret = + hawkbit_certificate_get_CA_pem(device, hb->buffer, hawkbit_buffer_size(hb)); + if (ret < 0) { + hawkbit_buffer_free(hb); + return -1; + } + return ret; +} + +#endif /* OC_SECURITY || OC_PKI */ diff --git a/port/esp32/hawkbit/hawkbit_certificate.h b/port/esp32/hawkbit/hawkbit_certificate.h new file mode 100644 index 0000000000..9598122d64 --- /dev/null +++ b/port/esp32/hawkbit/hawkbit_certificate.h @@ -0,0 +1,51 @@ +/**************************************************************************** + * + * Copyright (c) 2023 plgd.dev s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ + +#ifndef HAWKBIT_CERTIFICATE_H +#define HAWKBIT_CERTIFICATE_H + +#if defined(OC_SECURITY) || defined(OC_PKI) + +#include "hawkbit_buffer.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Get concatenated PEM strings of all CA certificates on given device + * + * @param device device index + * @param[out] hb output buffer (cannot be NULL, the buffer must have enough + * space to write the certificates and the nul-terminator at the end) + * + * @return -1 on failure + * @return >=0 length of the written data (not including the nul-terminator) + */ +long hawkbit_certificate_get_CA(size_t device, hawkbit_buffer_t *hb) + OC_NONNULL(); + +#ifdef __cplusplus +} +#endif + +#endif /* OC_SECURITY || OC_PKI */ + +#endif /* HAWKBIT_CERTIFICATE_H */ diff --git a/port/esp32/hawkbit/hawkbit_context.c b/port/esp32/hawkbit/hawkbit_context.c index 0b5a82cd23..2e60807537 100644 --- a/port/esp32/hawkbit/hawkbit_context.c +++ b/port/esp32/hawkbit/hawkbit_context.c @@ -24,6 +24,7 @@ #include "hawkbit_internal.h" #include "hawkbit_update.h" +#include "api/oc_helpers_internal.h" #include "api/oc_rep_internal.h" #include "api/oc_swupdate_internal.h" #include "oc_api.h" @@ -39,7 +40,7 @@ #include #ifndef OC_SOFTWARE_UPDATE -#error Preprocessor macro PLGD_HAWKBIT is defined but OC_SOFTWARE_UPDATE is not defined. +#error Preprocessor macro OC_SOFTWARE_UPDATE is not defined. #endif typedef struct @@ -153,13 +154,15 @@ static void hawkbit_encode_download(const hawkbit_download_t *download) { oc_rep_open_object(root, download); - oc_rep_set_text_string(download, deployment_id, - hawkbit_download_get_deployment_id(download)); - oc_rep_set_text_string(download, version, - hawkbit_download_get_version(download)); - oc_rep_set_text_string(download, name, hawkbit_download_get_name(download)); - oc_rep_set_text_string(download, filename, - hawkbit_download_get_filename(download)); + oc_string_view_t deployment_id = hawkbit_download_get_deployment_id(download); + oc_rep_set_text_string_v1(download, deployment_id, deployment_id.data, + deployment_id.length); + oc_string_view_t version = hawkbit_download_get_version(download); + oc_rep_set_text_string_v1(download, version, version.data, version.length); + oc_string_view_t name = hawkbit_download_get_name(download); + oc_rep_set_text_string_v1(download, name, name.data, name.length); + oc_string_view_t filename = hawkbit_download_get_filename(download); + oc_rep_set_text_string_v1(download, filename, filename.data, filename.length); oc_rep_set_int(download, size, (int64_t)hawkbit_download_get_size(download)); hawkbit_sha256_hash_t sha256 = hawkbit_sha256_digest_to_hash(hawkbit_download_get_hash(download)); @@ -262,7 +265,8 @@ hawkbit_decode(hawkbit_context_t *ctx, const oc_rep_t *rep, bool from_storage) if (deployment_id != NULL && newVersion != NULL && newVersionPartitionSha256 != NULL && newVersionSha256 != NULL) { - hawkbit_set_update(ctx, oc_string(*deployment_id), oc_string(*newVersion), + hawkbit_set_update(ctx, oc_string_view2(deployment_id), + oc_string_view2(newVersion), oc_cast(*newVersionSha256, const uint8_t), oc_string_len(*newVersionSha256), oc_cast(*newVersionPartitionSha256, const uint8_t), @@ -340,7 +344,7 @@ hawkbit_store_save(const hawkbit_context_t *ctx) if (buf == NULL) { return -1; } - oc_rep_new_realloc(&buf, OC_MIN_APP_DATA_SIZE, OC_MAX_APP_DATA_SIZE); + oc_rep_new_realloc_v1(&buf, OC_MIN_APP_DATA_SIZE, OC_MAX_APP_DATA_SIZE); #else /* OC_DYNAMIC_ALLOCATION */ uint8_t buf[OC_MIN_APP_DATA_SIZE]; oc_rep_new(buf, OC_MIN_APP_DATA_SIZE); @@ -453,35 +457,30 @@ hawkbit_get_context(size_t device) size_t hawkbit_get_device(const hawkbit_context_t *ctx) { - assert(ctx != NULL); return ctx->device; } const char * hawkbit_get_package_url(const hawkbit_context_t *ctx) { - assert(ctx != NULL); return oc_string(oc_swupdate_get(ctx->device)->purl); } void hawkbit_set_version(hawkbit_context_t *ctx, const char *version, size_t length) { - assert(ctx != NULL); oc_set_string(&ctx->version, version, length); } const char * hawkbit_get_version(const hawkbit_context_t *ctx) { - assert(ctx != NULL); return oc_string(ctx->version); } void hawkbit_set_polling_interval(hawkbit_context_t *ctx, uint64_t pollingInterval) { - assert(ctx != NULL); assert(pollingInterval > 0); ctx->polling.interval = pollingInterval; }; @@ -489,14 +488,12 @@ hawkbit_set_polling_interval(hawkbit_context_t *ctx, uint64_t pollingInterval) hawkbit_on_polling_action_cb_t hawkbit_get_polling_action_cb(const hawkbit_context_t *ctx) { - assert(ctx != NULL); return ctx->polling.action; } void hawkbit_set_download(hawkbit_context_t *ctx, hawkbit_deployment_t deployment) { - assert(ctx != NULL); if (ctx->download == NULL) { ctx->download = hawkbit_download_alloc(); } @@ -506,14 +503,12 @@ hawkbit_set_download(hawkbit_context_t *ctx, hawkbit_deployment_t deployment) const hawkbit_download_t * hawkbit_get_download(const hawkbit_context_t *ctx) { - assert(ctx != NULL); return ctx->download; } void hawkbit_clear_download(hawkbit_context_t *ctx) { - assert(ctx != NULL); hawkbit_download_free(ctx->download); ctx->download = NULL; } @@ -522,24 +517,21 @@ void hawkbit_set_on_download_done_cb( hawkbit_context_t *ctx, hawkbit_on_download_done_cb_t on_download_done_cb) { - assert(ctx != NULL); ctx->downloadDoneAction = on_download_done_cb; } hawkbit_on_download_done_cb_t hawkbit_get_on_download_done_cb(const hawkbit_context_t *ctx) { - assert(ctx != NULL); return ctx->downloadDoneAction; } void -hawkbit_set_update(hawkbit_context_t *ctx, const char *deployment_id, - const char *version, const uint8_t *sha256, +hawkbit_set_update(hawkbit_context_t *ctx, oc_string_view_t deployment_id, + oc_string_view_t version, const uint8_t *sha256, size_t sha256_size, const uint8_t *partition_sha256, size_t partition_sha256_size) { - assert(ctx != NULL); hawkbit_update_free(&ctx->store.update); ctx->store.update = hawkbit_update_create(deployment_id, version, sha256, sha256_size, @@ -549,7 +541,6 @@ hawkbit_set_update(hawkbit_context_t *ctx, const char *deployment_id, const hawkbit_async_update_t * hawkbit_get_update(const hawkbit_context_t *ctx) { - assert(ctx != NULL); if (oc_string(ctx->store.update.version) == NULL) { return NULL; } @@ -559,20 +550,17 @@ hawkbit_get_update(const hawkbit_context_t *ctx) void hawkbit_clear_update(hawkbit_context_t *ctx) { - assert(ctx != NULL); hawkbit_update_free(&ctx->store.update); } void hawkbit_set_execute_all_steps(hawkbit_context_t *ctx, bool execute_all_steps) { - assert(ctx != NULL); ctx->execute_all_steps = execute_all_steps; } bool hawkbit_execute_all_steps(const hawkbit_context_t *ctx) { - assert(ctx != NULL); return ctx->execute_all_steps; } diff --git a/port/esp32/hawkbit/hawkbit_context.h b/port/esp32/hawkbit/hawkbit_context.h index 6814617ead..01bfbea7b0 100644 --- a/port/esp32/hawkbit/hawkbit_context.h +++ b/port/esp32/hawkbit/hawkbit_context.h @@ -23,8 +23,11 @@ #include "hawkbit_action.h" #include "hawkbit_download.h" #include "hawkbit_update.h" + +#include "api/oc_helpers_internal.h" #include "oc_rep.h" #include "oc_ri.h" +#include "util/oc_compiler.h" #include #include @@ -47,7 +50,7 @@ hawkbit_context_t *hawkbit_get_context(size_t device); * @param to_storage encoding to storage */ void hawkbit_encode(const hawkbit_context_t *ctx, oc_resource_t *resource, - oc_interface_mask_t iface, bool to_storage); + oc_interface_mask_t iface, bool to_storage) OC_NONNULL(1); /** * @brief Decode representation into the hawkbit structure @@ -60,7 +63,7 @@ void hawkbit_encode(const hawkbit_context_t *ctx, oc_resource_t *resource, * @return false on failure */ bool hawkbit_decode(hawkbit_context_t *ctx, const oc_rep_t *rep, - bool from_storage); + bool from_storage) OC_NONNULL(1); /** * @brief Load hawkbit data from storage @@ -70,7 +73,7 @@ bool hawkbit_decode(hawkbit_context_t *ctx, const oc_rep_t *rep, * @return -1 on error * @return >=0 on success, number of bytes loaded from storage */ -long hawkbit_store_load(hawkbit_context_t *ctx); +long hawkbit_store_load(hawkbit_context_t *ctx) OC_NONNULL(); /** * @brief Save hawkbit data to storage @@ -80,71 +83,74 @@ long hawkbit_store_load(hawkbit_context_t *ctx); * @return <0 on error * @return >=0 on success, number of bytes written to storage */ -long hawkbit_store_save(const hawkbit_context_t *ctx); +long hawkbit_store_save(const hawkbit_context_t *ctx) OC_NONNULL(); /** Set device version */ void hawkbit_set_version(hawkbit_context_t *ctx, const char *version, - size_t length); + size_t length) OC_NONNULL(1); /** Get device index */ -size_t hawkbit_get_device(const hawkbit_context_t *ctx); +size_t hawkbit_get_device(const hawkbit_context_t *ctx) OC_NONNULL(); /** Get device version */ -const char *hawkbit_get_version(const hawkbit_context_t *ctx); +const char *hawkbit_get_version(const hawkbit_context_t *ctx) OC_NONNULL(); /** Get package url from /oc/swu resource */ -const char *hawkbit_get_package_url(const hawkbit_context_t *ctx); +const char *hawkbit_get_package_url(const hawkbit_context_t *ctx) OC_NONNULL(); /** Set polling interval */ void hawkbit_set_polling_interval(hawkbit_context_t *ctx, - uint64_t pollingInterval); + uint64_t pollingInterval) OC_NONNULL(); typedef void (*hawkbit_on_polling_action_cb_t)(hawkbit_context_t *ctx, const hawkbit_action_t *action); /** Get callback to be called when a new command is received by polling */ hawkbit_on_polling_action_cb_t hawkbit_get_polling_action_cb( - const hawkbit_context_t *ctx); + const hawkbit_context_t *ctx) OC_NONNULL(); /** Set download from parsed deployment */ void hawkbit_set_download(hawkbit_context_t *ctx, - hawkbit_deployment_t deployment); + hawkbit_deployment_t deployment) OC_NONNULL(); /** Get download */ -const hawkbit_download_t *hawkbit_get_download(const hawkbit_context_t *ctx); +const hawkbit_download_t *hawkbit_get_download(const hawkbit_context_t *ctx) + OC_NONNULL(); /** Clear stored download */ -void hawkbit_clear_download(hawkbit_context_t *ctx); +void hawkbit_clear_download(hawkbit_context_t *ctx) OC_NONNULL(); typedef void (*hawkbit_on_download_done_cb_t)(hawkbit_context_t *ctx, bool success); /** Set callback to be called when donwload succeeds or fails with some error */ void hawkbit_set_on_download_done_cb( - hawkbit_context_t *ctx, hawkbit_on_download_done_cb_t on_download_done_cb); + hawkbit_context_t *ctx, hawkbit_on_download_done_cb_t on_download_done_cb) + OC_NONNULL(); /** Get callback to be called when donwload succeeds or fails with some error */ hawkbit_on_download_done_cb_t hawkbit_get_on_download_done_cb( - const hawkbit_context_t *ctx); + const hawkbit_context_t *ctx) OC_NONNULL(); /** Set update */ -void hawkbit_set_update(hawkbit_context_t *ctx, const char *deployment_id, - const char *version, const uint8_t *sha256, +void hawkbit_set_update(hawkbit_context_t *ctx, oc_string_view_t deployment_id, + oc_string_view_t version, const uint8_t *sha256, size_t sha256_size, const uint8_t *partition_sha256, - size_t partition_sha256_size); + size_t partition_sha256_size) OC_NONNULL(1); /** Get update */ -const hawkbit_async_update_t *hawkbit_get_update(const hawkbit_context_t *ctx); +const hawkbit_async_update_t *hawkbit_get_update(const hawkbit_context_t *ctx) + OC_NONNULL(); /** Clear stored update */ -void hawkbit_clear_update(hawkbit_context_t *ctx); +void hawkbit_clear_update(hawkbit_context_t *ctx) OC_NONNULL(); /** All update steps should executed automatically without manually trigger */ void hawkbit_set_execute_all_steps(hawkbit_context_t *ctx, - bool execute_all_steps); + bool execute_all_steps) OC_NONNULL(); /** Check if all update steps should executed automatically */ -bool hawkbit_execute_all_steps(const hawkbit_context_t *ctx); +bool hawkbit_execute_all_steps(const hawkbit_context_t *ctx) OC_NONNULL(); #ifdef __cplusplus } diff --git a/port/esp32/hawkbit/hawkbit_deployment.c b/port/esp32/hawkbit/hawkbit_deployment.c index 119d244c95..f89df04f84 100644 --- a/port/esp32/hawkbit/hawkbit_deployment.c +++ b/port/esp32/hawkbit/hawkbit_deployment.c @@ -243,6 +243,9 @@ hawkbit_deployment_get_chunk(const cJSON *json, void hawkbit_deployment_free(hawkbit_deployment_t *deployment) { + if (deployment == NULL) { + return; + } hawkbit_deployment_chunk_free(&deployment->chunk); oc_free_string(&deployment->id); } diff --git a/port/esp32/hawkbit/hawkbit_download.c b/port/esp32/hawkbit/hawkbit_download.c index be0208ac56..636452d024 100644 --- a/port/esp32/hawkbit/hawkbit_download.c +++ b/port/esp32/hawkbit/hawkbit_download.c @@ -23,6 +23,8 @@ #include "oc_helpers.h" #include "port/oc_assert.h" #include "util/oc_memb.h" + +#include #include typedef struct hawkbit_download_t @@ -91,51 +93,44 @@ hawkbit_download_free(hawkbit_download_t *download) oc_memb_free(&g_hawkbit_download_s, download); } -const char * +oc_string_view_t hawkbit_download_get_deployment_id(const hawkbit_download_t *download) { - assert(download != NULL); - return oc_string(download->deployment_id); + return oc_string_view2(&download->deployment_id); } -const char * +oc_string_view_t hawkbit_download_get_version(const hawkbit_download_t *download) { - assert(download != NULL); - return oc_string(download->version); + return oc_string_view2(&download->version); } -const char * +oc_string_view_t hawkbit_download_get_name(const hawkbit_download_t *download) { - assert(download != NULL); - return oc_string(download->name); + return oc_string_view2(&download->name); } -const char * +oc_string_view_t hawkbit_download_get_filename(const hawkbit_download_t *download) { - assert(download != NULL); - return oc_string(download->filename); + return oc_string_view2(&download->filename); } size_t hawkbit_download_get_size(const hawkbit_download_t *download) { - assert(download != NULL); return download->size; } hawkbit_sha256_digest_t hawkbit_download_get_hash(const hawkbit_download_t *download) { - assert(download != NULL); return download->hash; } hawkbit_download_links_t hawkbit_download_get_links(const hawkbit_download_t *download) { - assert(download != NULL); return download->links; } diff --git a/port/esp32/hawkbit/hawkbit_download.h b/port/esp32/hawkbit/hawkbit_download.h index bd36b2a493..75e4afd4d0 100644 --- a/port/esp32/hawkbit/hawkbit_download.h +++ b/port/esp32/hawkbit/hawkbit_download.h @@ -21,7 +21,10 @@ #define HAWKBIT_DOWNLOAD_H #include "hawkbit_util.h" + +#include "api/oc_helpers_internal.h" #include "oc_helpers.h" +#include "util/oc_compiler.h" #ifdef __cplusplus extern "C" { @@ -45,31 +48,36 @@ typedef struct hawkbit_deployment_t hawkbit_deployment_t; /** Copy data to download from deployment */ void hawkbit_download_set_from_deployment( - hawkbit_download_t *download, const hawkbit_deployment_t *deployment); + hawkbit_download_t *download, const hawkbit_deployment_t *deployment) + OC_NONNULL(); /** Get deployment id */ -const char *hawkbit_download_get_deployment_id( - const hawkbit_download_t *download); +oc_string_view_t hawkbit_download_get_deployment_id( + const hawkbit_download_t *download) OC_NONNULL(); /** Get version */ -const char *hawkbit_download_get_version(const hawkbit_download_t *download); +oc_string_view_t hawkbit_download_get_version( + const hawkbit_download_t *download) OC_NONNULL(); /** Get deployment name */ -const char *hawkbit_download_get_name(const hawkbit_download_t *download); +oc_string_view_t hawkbit_download_get_name(const hawkbit_download_t *download) + OC_NONNULL(); /** Get filename */ -const char *hawkbit_download_get_filename(const hawkbit_download_t *download); +oc_string_view_t hawkbit_download_get_filename( + const hawkbit_download_t *download) OC_NONNULL(); /** Get download size */ -size_t hawkbit_download_get_size(const hawkbit_download_t *download); +size_t hawkbit_download_get_size(const hawkbit_download_t *download) + OC_NONNULL(); /** Get sha256 */ hawkbit_sha256_digest_t hawkbit_download_get_hash( - const hawkbit_download_t *download); + const hawkbit_download_t *download) OC_NONNULL(); /** Get download links */ hawkbit_download_links_t hawkbit_download_get_links( - const hawkbit_download_t *download); + const hawkbit_download_t *download) OC_NONNULL(); #ifdef __cplusplus } diff --git a/port/esp32/hawkbit/hawkbit_feedback.c b/port/esp32/hawkbit/hawkbit_feedback.c index e9f2c20e16..059769a265 100644 --- a/port/esp32/hawkbit/hawkbit_feedback.c +++ b/port/esp32/hawkbit/hawkbit_feedback.c @@ -18,10 +18,14 @@ ****************************************************************************/ #include "debug_print.h" +#include "hawkbit_buffer.h" +#include "hawkbit_certificate.h" #include "hawkbit_feedback.h" #include "hawkbit_http.h" #include "hawkbit_internal.h" +#include "api/oc_helpers_internal.h" + #include #include @@ -73,7 +77,8 @@ hawkbit_feedback_result_to_string(hawkbit_feedback_result_t result) } static bool -hawkbit_send_feedback(const char *url, const char *id, +hawkbit_send_feedback(const hawkbit_context_t *ctx, oc_string_view_t url, + oc_string_view_t id, hawkbit_feedback_execution_t execution, hawkbit_feedback_result_t result) { @@ -82,7 +87,7 @@ hawkbit_send_feedback(const char *url, const char *id, APP_ERR("send feedback error: cannot create root JSON object"); return false; } - if (!cJSON_AddItemToObject(root, "id", cJSON_CreateString(id))) { + if (!cJSON_AddItemToObject(root, "id", cJSON_CreateString(id.data))) { APP_ERR("send feedback error: cannot set 'id' property object"); return false; } @@ -131,11 +136,39 @@ hawkbit_send_feedback(const char *url, const char *id, APP_ERR("send feedback error: cannot render JSON object"); return false; } + +#if defined(OC_SECURITY) && defined(OC_PKI) + hawkbit_buffer_t hb; + long pem_len = hawkbit_certificate_get_CA(hawkbit_get_device(ctx), &hb); + if (pem_len < 0) { + APP_ERR("cannot obtain certificate"); + free(body); + return false; + } + oc_string_view_t pem = oc_string_view(hb.buffer, (size_t)pem_len); +#else /* !OC_SECURITY || !OC_PKI */ + (void)ctx; + oc_string_view_t pem = OC_STRING_VIEW_NULL; +#endif /* OC_SECURITY && OC_PKI */ + APP_DBG("send feedback payload: %s", body); - char output[HAWKBIT_HTTP_MAX_OUTPUT_BUFFER] = { 0 }; - int code = hawkbit_http_perform_post(url, body, output, sizeof(output)); + hawkbit_buffer_t output; + if (!hawkbit_buffer_init(&output, HAWKBIT_HTTP_MAX_OUTPUT_BUFFER)) { + APP_ERR("send feedback error: failed to allocate output buffer"); +#if defined(OC_SECURITY) && defined(OC_PKI) + hawkbit_buffer_free(&hb); +#endif /* OC_SECURITY && OC_PKI */ + free(body); + return false; + } + int code = hawkbit_http_perform_post(url, body, pem, output.buffer, + hawkbit_buffer_size(&output)); + hawkbit_buffer_free(&output); free(body); +#if defined(OC_SECURITY) && defined(OC_PKI) + hawkbit_buffer_free(&hb); +#endif /* OC_SECURITY && OC_PKI */ if (code != HAWKBIT_HTTP_CODE_OK) { APP_ERR("send feedback error: unexpected HTTP code(%d)", code); return false; @@ -143,7 +176,7 @@ hawkbit_send_feedback(const char *url, const char *id, return true; } -static bool +static int hawkbit_feedback_get_url(const hawkbit_context_t *ctx, const char *action, const char *actionId, char *buffer, size_t buffer_size) { @@ -157,7 +190,7 @@ hawkbit_feedback_get_url(const hawkbit_context_t *ctx, const char *action, if (hawkbit_get_url(ctx, server_url, sizeof(server_url), tenant, sizeof(tenant), controller_id, sizeof(controller_id)) != HAWKBIT_OK) { - return false; + return -1; } int len = snprintf(buffer, buffer_size, "%s/%s/controller/v1/%s/%s/%s/feedback", @@ -165,19 +198,22 @@ hawkbit_feedback_get_url(const hawkbit_context_t *ctx, const char *action, if (len < 0 || (size_t)len >= buffer_size) { APP_ERR("get feedback URL failed: %s", "cannot get URL"); - return false; + return -1; } - return true; + return len; } bool -hawkbit_send_deploy_feedback(const hawkbit_context_t *ctx, const char *id, +hawkbit_send_deploy_feedback(const hawkbit_context_t *ctx, oc_string_view_t id, hawkbit_feedback_execution_t execution, hawkbit_feedback_result_t result) { char url[512]; - if (!hawkbit_feedback_get_url(ctx, "deploymentBase", id, url, sizeof(url))) { + int url_len = + hawkbit_feedback_get_url(ctx, "deploymentBase", id.data, url, sizeof(url)); + if (url_len < 0) { return false; } - return hawkbit_send_feedback(url, id, execution, result); + oc_string_view_t urlview = oc_string_view(url, url_len); + return hawkbit_send_feedback(ctx, urlview, id, execution, result); } diff --git a/port/esp32/hawkbit/hawkbit_feedback.h b/port/esp32/hawkbit/hawkbit_feedback.h index de53a3288b..4ac5bbe126 100644 --- a/port/esp32/hawkbit/hawkbit_feedback.h +++ b/port/esp32/hawkbit/hawkbit_feedback.h @@ -20,7 +20,10 @@ #ifndef HAWKBIT_FEEDBACK_H #define HAWKBIT_FEEDBACK_H +#include "api/oc_helpers_internal.h" #include "hawkbit_context.h" +#include "util/oc_compiler.h" + #include #ifdef __cplusplus @@ -50,14 +53,16 @@ typedef enum { * @brief Send deployment feedback to Hawkbit server * * @param ctx hawkbit context (cannot be NULL) - * @param id deployment id (cannot be NULL) + * @param id deployment id * @param execution feedback execution * @param result feedback result * @return true on success * @return false on failure */ -bool hawkbit_send_deploy_feedback(const hawkbit_context_t *ctx, const char *id, +bool hawkbit_send_deploy_feedback(const hawkbit_context_t *ctx, + oc_string_view_t id, hawkbit_feedback_execution_t execution, - hawkbit_feedback_result_t result); + hawkbit_feedback_result_t result) + OC_NONNULL(); #endif /* HAWKBIT_FEEDBACK_H */ diff --git a/port/esp32/hawkbit/hawkbit_http.c b/port/esp32/hawkbit/hawkbit_http.c index 6ca3880e4d..642f04c1e1 100644 --- a/port/esp32/hawkbit/hawkbit_http.c +++ b/port/esp32/hawkbit/hawkbit_http.c @@ -17,6 +17,7 @@ * ****************************************************************************/ +#include "hawkbit_certificate.h" #include "hawkbit_context.h" #include "hawkbit_http.h" #include "debug_print.h" @@ -97,12 +98,18 @@ http_event_handler(esp_http_client_event_t *evt) } static esp_http_client_config_t -hawkbit_get_client_config(const char *url, hawkbit_http_buffer_t *buffer) +hawkbit_get_client_config(const char *url, oc_string_view_t cert, + hawkbit_http_buffer_t *buffer) { esp_http_client_config_t config = {}; config.url = url; config.user_data = buffer; config.event_handler = http_event_handler; + config.cert_pem = cert.data; + config.cert_len = + cert.length + 1; // must include the nul-terminator for mbedTLS + config.keep_alive_enable = true; + config.timeout_ms = 5000; return config; } @@ -143,14 +150,16 @@ hawkbit_prepare_client(esp_http_client_config_t config, } int -hawkbit_http_perform_get(const char *url, char *buffer, size_t buffer_size) +hawkbit_http_perform_get(oc_string_view_t url, oc_string_view_t cert, + char *buffer, size_t buffer_size) { + assert(url.data != NULL); hawkbit_http_buffer_t data = { .data = buffer, .size = buffer_size, }; esp_http_client_handle_t client = - hawkbit_prepare_client(hawkbit_get_client_config(url, &data), + hawkbit_prepare_client(hawkbit_get_client_config(url.data, cert, &data), HTTP_METHOD_GET, "application/hal+json", NULL); if (client == NULL) { APP_ERR("perform HTTP GET failed: %s", "failed to get http client"); @@ -169,21 +178,21 @@ hawkbit_http_perform_get(const char *url, char *buffer, size_t buffer_size) } static int -hawkbit_http_perform_update(esp_http_client_method_t method, const char *url, - const char *body, char *buffer, size_t buffer_size) +hawkbit_http_perform_update(esp_http_client_method_t method, + oc_string_view_t url, const char *body, + oc_string_view_t cert, char *buffer, + size_t buffer_size) { - assert(url != NULL); - if (method != HTTP_METHOD_POST && method != HTTP_METHOD_PUT) { - APP_ERR("invalid method(%d)", (int)method); - return -1; - } + assert(url.data != NULL); + assert(method == HTTP_METHOD_POST || method == HTTP_METHOD_PUT); + hawkbit_http_buffer_t data = { .data = buffer, .size = buffer_size, }; esp_http_client_handle_t client = - hawkbit_prepare_client(hawkbit_get_client_config(url, &data), method, - "application/hal+json", "application/json"); + hawkbit_prepare_client(hawkbit_get_client_config(url.data, cert, &data), + method, "application/hal+json", "application/json"); if (client == NULL) { APP_ERR("perform HTTP %s failed: failed to get http client", method == HTTP_METHOD_POST ? "POST" : "GET"); @@ -214,17 +223,19 @@ hawkbit_http_perform_update(esp_http_client_method_t method, const char *url, } int -hawkbit_http_perform_post(const char *url, const char *body, char *buffer, +hawkbit_http_perform_post(oc_string_view_t url, const char *body, + oc_string_view_t cert, char *buffer, size_t buffer_size) { - return hawkbit_http_perform_update(HTTP_METHOD_POST, url, body, buffer, + return hawkbit_http_perform_update(HTTP_METHOD_POST, url, body, cert, buffer, buffer_size); } int -hawkbit_http_perform_put(const char *url, const char *body, char *buffer, +hawkbit_http_perform_put(oc_string_view_t url, const char *body, + oc_string_view_t cert, char *buffer, size_t buffer_size) { - return hawkbit_http_perform_update(HTTP_METHOD_PUT, url, body, buffer, + return hawkbit_http_perform_update(HTTP_METHOD_PUT, url, body, cert, buffer, buffer_size); } diff --git a/port/esp32/hawkbit/hawkbit_http.h b/port/esp32/hawkbit/hawkbit_http.h index eac25922b3..8b4f646ee6 100644 --- a/port/esp32/hawkbit/hawkbit_http.h +++ b/port/esp32/hawkbit/hawkbit_http.h @@ -20,7 +20,10 @@ #ifndef HAWKBIT_HTTP_H #define HAWKBIT_HTTP_H -#include "esp_http_client.h" +#include "api/oc_helpers_internal.h" +#include "util/oc_compiler.h" + +#include #include @@ -28,45 +31,51 @@ extern "C" { #endif -#define HAWKBIT_HTTP_CODE_OK 200 -#define HAWKBIT_HTTP_MAX_OUTPUT_BUFFER 2048 +#define HAWKBIT_HTTP_CODE_OK (200) +#define HAWKBIT_HTTP_MAX_OUTPUT_BUFFER (2048) /** * @brief Perform GET request and store response to buffer. * - * @param[in] url request url + * @param url request url (cannot be empty) + * @param cert certificate in PEM format (for HTTPS) * @param[out] buffer output buffer (cannot be NULL) - * @param[in] buffer_size size of the output buffer + * @param buffer_size size of the output buffer * @return -1 on error * @return >=0 on success, status code */ -int hawkbit_http_perform_get(const char *url, char *buffer, size_t buffer_size); +int hawkbit_http_perform_get(oc_string_view_t url, oc_string_view_t cert, + char *buffer, size_t buffer_size) OC_NONNULL(3); /** * @brief Perform POST request and store response to buffer. * - * @param[in] url request url - * @param[in] body request body + * @param url request url (cannot be empty) + * @param body request body + * @param cert certificate in PEM format (for HTTPS) * @param[out] buffer output buffer (cannot be NULL) - * @param[in] buffer_size size of the output buffer + * @param buffer_size size of the output buffer * @return -1 on error * @return >=0 on success, status code */ -int hawkbit_http_perform_post(const char *url, const char *body, char *buffer, - size_t buffer_size); +int hawkbit_http_perform_post(oc_string_view_t url, const char *body, + oc_string_view_t cert, char *buffer, + size_t buffer_size) OC_NONNULL(4); /** * @brief Perform PUT request and store response to buffer. * - * @param[in] url request url - * @param[in] body request body + * @param url request url (cannot be empty) + * @param body request body + * @param cert certificate in PEM format (for HTTPS) * @param[out] buffer output buffer (cannot be NULL) - * @param[in] buffer_size size of the output buffer + * @param buffer_size size of the output buffer * @return -1 on error * @return >=0 on success, status code */ -int hawkbit_http_perform_put(const char *url, const char *body, char *buffer, - size_t buffer_size); +int hawkbit_http_perform_put(oc_string_view_t url, const char *body, + oc_string_view_t cert, char *buffer, + size_t buffer_size) OC_NONNULL(4); #ifdef __cplusplus } diff --git a/port/esp32/hawkbit/hawkbit_internal.h b/port/esp32/hawkbit/hawkbit_internal.h index cec0788814..eb02afd363 100644 --- a/port/esp32/hawkbit/hawkbit_internal.h +++ b/port/esp32/hawkbit/hawkbit_internal.h @@ -23,6 +23,9 @@ #include "hawkbit_action.h" #include "hawkbit_context.h" #include "hawkbit_deployment.h" + +#include "util/oc_compiler.h" + #include #include @@ -59,7 +62,7 @@ typedef enum { * @see hawkbit_stop_polling */ hawkbit_error_t hawkbit_poll(hawkbit_context_t *ctx, - hawkbit_configuration_t *cfg); + hawkbit_configuration_t *cfg) OC_NONNULL(1); /** * @brief Invoke hawkbit_poll function and reschedule polling interval if @@ -70,14 +73,15 @@ hawkbit_error_t hawkbit_poll(hawkbit_context_t *ctx, * @return true polling was rescheduled * @return false polling was not rescheduled */ -bool hawkbit_poll_and_reschedule(hawkbit_context_t *ctx, bool forceReschedule); +bool hawkbit_poll_and_reschedule(hawkbit_context_t *ctx, bool forceReschedule) + OC_NONNULL(); /** * @brief Start device with Hawkbit. * * @param ctx hawkbit context (cannot be NULL) */ -void hawkbit_start(hawkbit_context_t *ctx); +void hawkbit_start(hawkbit_context_t *ctx) OC_NONNULL(); /** * @brief Start polling Hawkbit base resource @@ -90,16 +94,15 @@ void hawkbit_start(hawkbit_context_t *ctx); * polled */ void hawkbit_start_polling(hawkbit_context_t *ctx, - hawkbit_on_polling_action_cb_t on_action); + hawkbit_on_polling_action_cb_t on_action) + OC_NONNULL(1); /** * @brief Stop polling Hawkbit base resource * * @param ctx hawkbit context (cannot be NULL) */ -void hawkbit_stop_polling(hawkbit_context_t *ctx); - -void hawkbit_reschedule_polling(hawkbit_context_t *ctx); +void hawkbit_stop_polling(hawkbit_context_t *ctx) OC_NONNULL(); /** * @brief Poll the base resource to obtain the current actions for the device. @@ -114,7 +117,8 @@ void hawkbit_reschedule_polling(hawkbit_context_t *ctx); */ hawkbit_error_t hawkbit_poll_base_resource(hawkbit_context_t *ctx, hawkbit_action_t *action, - hawkbit_configuration_t *cfg); + hawkbit_configuration_t *cfg) + OC_NONNULL(1, 2); /** * @brief Download upgrade from Hawkbit server and store it to currently unused @@ -128,7 +132,8 @@ hawkbit_error_t hawkbit_poll_base_resource(hawkbit_context_t *ctx, * @param download_action callback invoked after download finishes */ void hawkbit_download(hawkbit_context_t *ctx, - hawkbit_on_download_done_cb_t download_action); + hawkbit_on_download_done_cb_t download_action) + OC_NONNULL(1); /** * @brief Check whether on currently unused OTA partition contains a valid @@ -138,14 +143,14 @@ void hawkbit_download(hawkbit_context_t *ctx, * @return true on success * @return false on error */ -bool hawkbit_update(hawkbit_context_t *ctx); +bool hawkbit_update(hawkbit_context_t *ctx) OC_NONNULL(); /** * @brief Save resources to storage and restart ESP. * * @param ctx hawkbit context (cannot be NULL) */ -void hawkbit_restart_device(hawkbit_context_t *ctx); +void hawkbit_restart_device(hawkbit_context_t *ctx) OC_NONNULL(); /** * @brief Parse purl property of the /oc/swupdate resource to expected Hawkbit @@ -166,7 +171,7 @@ void hawkbit_restart_device(hawkbit_context_t *ctx); hawkbit_error_t hawkbit_get_url(const hawkbit_context_t *ctx, char *server_url, size_t server_url_size, char *tenant, size_t tenant_size, char *controller_id, - size_t controller_id_size); + size_t controller_id_size) OC_NONNULL(); #ifdef __cplusplus } diff --git a/port/esp32/hawkbit/hawkbit_resource.c b/port/esp32/hawkbit/hawkbit_resource.c index d6724e8c70..001f09dc42 100644 --- a/port/esp32/hawkbit/hawkbit_resource.c +++ b/port/esp32/hawkbit/hawkbit_resource.c @@ -21,7 +21,9 @@ #include "debug_print.h" #include "hawkbit_context.h" #include "hawkbit.h" + #include "oc_api.h" +#include "oc_cloud.h" #include "oc_ri.h" static void diff --git a/port/esp32/hawkbit/hawkbit_update.c b/port/esp32/hawkbit/hawkbit_update.c index c4884b2842..d49257c62e 100644 --- a/port/esp32/hawkbit/hawkbit_update.c +++ b/port/esp32/hawkbit/hawkbit_update.c @@ -19,19 +19,25 @@ #include "hawkbit_update.h" +#include "oc_helpers.h" + +#include +#include + hawkbit_async_update_t -hawkbit_update_create(const char *deployment_id, const char *version, +hawkbit_update_create(oc_string_view_t deployment_id, oc_string_view_t version, const uint8_t *sha256, size_t sha256_size, const uint8_t *partition_sha256, size_t partition_sha256_size) { - assert(deployment_id != NULL); - assert(version != NULL); + assert(deployment_id.data != NULL); + assert(version.data != NULL); hawkbit_async_update_t update; memset(&update, 0, sizeof(hawkbit_async_update_t)); - oc_new_string(&update.deployment_id, deployment_id, strlen(deployment_id)); - oc_new_string(&update.version, version, strlen(version)); + oc_new_string(&update.deployment_id, deployment_id.data, + deployment_id.length); + oc_new_string(&update.version, version.data, version.length); assert(sha256_size == sizeof(update.sha256)); memcpy(update.sha256, sha256, sha256_size); assert(partition_sha256_size == sizeof(update.partition_sha256)); @@ -42,6 +48,9 @@ hawkbit_update_create(const char *deployment_id, const char *version, void hawkbit_update_free(hawkbit_async_update_t *update) { + if (update == NULL) { + return; + } oc_free_string(&update->deployment_id); oc_free_string(&update->version); memset(update, 0, sizeof(hawkbit_async_update_t)); diff --git a/port/esp32/hawkbit/hawkbit_update.h b/port/esp32/hawkbit/hawkbit_update.h index cc7637860a..e2be6f80e3 100644 --- a/port/esp32/hawkbit/hawkbit_update.h +++ b/port/esp32/hawkbit/hawkbit_update.h @@ -20,8 +20,12 @@ #ifndef HAWKBIT_UPDATE_H #define HAWKBIT_UPDATE_H +#include "api/oc_helpers_internal.h" #include "oc_helpers.h" +#include "util/oc_compiler.h" + #include +#include #include #ifdef __cplusplus @@ -43,12 +47,10 @@ typedef struct } hawkbit_async_update_t; /** @brief Create instance with given data */ -hawkbit_async_update_t hawkbit_update_create(const char *deployment_id, - const char *version, - const uint8_t *sha256, - size_t sha256_size, - const uint8_t *partition_sha256, - size_t partition_sha256_size); +hawkbit_async_update_t hawkbit_update_create( + oc_string_view_t deployment_id, oc_string_view_t version, + const uint8_t *sha256, size_t sha256_size, const uint8_t *partition_sha256, + size_t partition_sha256_size) OC_NONNULL(); /** @brief Deallocate instance data */ void hawkbit_update_free(hawkbit_async_update_t *update); diff --git a/port/esp32/hawkbit/hawkbit_util.c b/port/esp32/hawkbit/hawkbit_util.c index 23f57aa33e..a1fbd4f5f5 100644 --- a/port/esp32/hawkbit/hawkbit_util.c +++ b/port/esp32/hawkbit/hawkbit_util.c @@ -20,7 +20,6 @@ #include "hawkbit_util.h" #include "debug_print.h" -#include #include #include #include @@ -91,8 +90,6 @@ hawkbit_sha256_digest_to_hash(hawkbit_sha256_digest_t digest) bool hawkbit_parse_package_url(const char *purl, hawkbit_url_t *url) { - assert(purl != NULL); - const char *pattern = "^https?://[^[:space:]/$.?#].[^[:space:]/]+(" "/([^[:space:]/]+)/controller/v1/([^[:space:]/]+)|" "/([^[:space:]/]+)|" diff --git a/port/esp32/hawkbit/hawkbit_util.h b/port/esp32/hawkbit/hawkbit_util.h index 9e72db6b0e..a8a711fe3b 100644 --- a/port/esp32/hawkbit/hawkbit_util.h +++ b/port/esp32/hawkbit/hawkbit_util.h @@ -20,6 +20,8 @@ #ifndef HAWKBIT_UTIL_H #define HAWKBIT_UTIL_H +#include "util/oc_compiler.h" + #include #include #include @@ -28,23 +30,6 @@ extern "C" { #endif -#define HAWKBIT_MAC_ADDRESS_SIZE 18 - -typedef struct -{ - char address[HAWKBIT_MAC_ADDRESS_SIZE]; -} hawkbit_mac_address_t; - -/** - * @brief Get MAC address of the device. - * - * @param[out] address output variable to store the obtained address (cannot be - * NULL) - * @return true on success - * @return false otherwise - */ -bool hawkbit_get_mac_address(hawkbit_mac_address_t *address); - #define HAWKBIT_SHA1_DIGEST_SIZE 20 #define HAWKBIT_SHA1_HASH_SIZE ((20 * 2) + 1) @@ -64,7 +49,7 @@ hawkbit_sha1_digest_t hawkbit_sha1_hash_to_digest(hawkbit_sha1_hash_t hash); /** Convert sha1 byte array to hex string */ hawkbit_sha1_hash_t hawkbit_sha1_digest_to_hash(hawkbit_sha1_digest_t digest); -#define HAWKBIT_SHA256_DIGEST_SIZE 32 +#define HAWKBIT_SHA256_DIGEST_SIZE (32) #define HAWKBIT_SHA256_HASH_SIZE ((32 * 2) + 1) typedef struct @@ -98,13 +83,14 @@ typedef struct /** * @brief Verify package url and parse it to Hawkbit url components. * - * @param[in] purl package url + * @param[in] purl package url (cannot be NULL) * @param[out] url offsets (from the input package url) and lengths of expected * Hawkbit url components * @return true on success * @return false on failure */ -bool hawkbit_parse_package_url(const char *purl, hawkbit_url_t *url); +bool hawkbit_parse_package_url(const char *purl, hawkbit_url_t *url) + OC_NONNULL(1); #ifdef __cplusplus } diff --git a/port/esp32/main/CMakeLists.txt b/port/esp32/main/CMakeLists.txt index 376647dc1d..4f8332e471 100644 --- a/port/esp32/main/CMakeLists.txt +++ b/port/esp32/main/CMakeLists.txt @@ -90,20 +90,33 @@ set(sources set(CMAKE_VERBOSE_MAKEFILE ON) +set(OC_DEFINITIONS -DOC_SERVER -DOC_CLIENT) if(CONFIG_APP_DEBUG) - add_definitions(-DAPP_DEBUG) + list(APPEND OC_DEFINITIONS -DAPP_DEBUG) endif() -if(CONFIG_OC_DEBUG) - add_definitions(-DOC_DEBUG -DOC_LOG_MAXIMUM_LEVEL=8) +if(CONFIG_OC_LOG_LEVEL_DISABLED) + list(APPEND OC_DEFINITIONS "-DOC_LOG_MAXIMUM_LEVEL=(-1)") +elseif(CONFIG_OC_LOG_LEVEL_ERROR) + list(APPEND OC_DEFINITIONS "-DOC_LOG_MAXIMUM_LEVEL=(3)") +elseif(CONFIG_OC_LOG_LEVEL_WARNING) + list(APPEND OC_DEFINITIONS "-DOC_LOG_MAXIMUM_LEVEL=(4)") +elseif(CONFIG_OC_LOG_LEVEL_NOTICE) + list(APPEND OC_DEFINITIONS "-DOC_LOG_MAXIMUM_LEVEL=(5)") +elseif(CONFIG_OC_LOG_LEVEL_INFO) + list(APPEND OC_DEFINITIONS "-DOC_LOG_MAXIMUM_LEVEL=(6)") +elseif(CONFIG_OC_LOG_LEVEL_DEBUG) + list(APPEND OC_DEFINITIONS "-DOC_LOG_MAXIMUM_LEVEL=(7)") +elseif(CONFIG_OC_LOG_LEVEL_TRACE) + list(APPEND OC_DEFINITIONS "-DOC_LOG_MAXIMUM_LEVEL=(8)") endif() if(CONFIG_IPV4) - add_definitions(-DOC_IPV4) + list(APPEND OC_DEFINITIONS -DOC_IPV4) endif() if (CONFIG_TCP) - add_definitions(-DOC_TCP) + list(APPEND OC_DEFINITIONS -DOC_TCP) list(APPEND sources ${CMAKE_CURRENT_SOURCE_DIR}/../adapter/src/tcpadapter.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../api/oc_tcp.c @@ -112,7 +125,7 @@ if (CONFIG_TCP) endif() if (CONFIG_CLOUD) - add_definitions(-DOC_CLOUD -DOC_DYNAMIC_ALLOCATION -DOC_IPV4) + list(APPEND OC_DEFINITIONS -DOC_CLOUD -DOC_DYNAMIC_ALLOCATION -DOC_IPV4) list(APPEND sources ${CMAKE_CURRENT_SOURCE_DIR}/../../../api/cloud/oc_cloud_access.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../api/cloud/oc_cloud_apis.c @@ -139,12 +152,14 @@ if(CONFIG_PLGD_DEV_HAWKBIT OR CONFIG_SECURE) endif() if(CONFIG_PLGD_DEV_HAWKBIT) - add_definitions(-DOC_SOFTWARE_UPDATE -DPLGD_DEV_HAWKBIT) + list(APPEND OC_DEFINITIONS -DOC_SOFTWARE_UPDATE -DPLGD_DEV_HAWKBIT) list(APPEND sources ${CMAKE_CURRENT_SOURCE_DIR}/../../../api/oc_swupdate.c ${CMAKE_CURRENT_SOURCE_DIR}/../hawkbit/hawkbit.c ${CMAKE_CURRENT_SOURCE_DIR}/../hawkbit/hawkbit_action.c + ${CMAKE_CURRENT_SOURCE_DIR}/../hawkbit/hawkbit_buffer.c + ${CMAKE_CURRENT_SOURCE_DIR}/../hawkbit/hawkbit_certificate.c ${CMAKE_CURRENT_SOURCE_DIR}/../hawkbit/hawkbit_context.c ${CMAKE_CURRENT_SOURCE_DIR}/../hawkbit/hawkbit_deployment.c ${CMAKE_CURRENT_SOURCE_DIR}/../hawkbit/hawkbit_download.c @@ -159,14 +174,14 @@ if(CONFIG_PLGD_DEV_HAWKBIT) endif() if(CONFIG_DYNAMIC) - add_definitions(-DOC_DYNAMIC_ALLOCATION) + list(APPEND OC_DEFINITIONS -DOC_DYNAMIC_ALLOCATION) list(APPEND sources ${CMAKE_CURRENT_SOURCE_DIR}/../../../api/oc_collection.c ) endif() if(CONFIG_SECURE) - add_definitions(-DOC_SECURITY -DOC_PKI) + list(APPEND OC_DEFINITIONS -DOC_SECURITY -DOC_PKI) list(APPEND sources ${CMAKE_CURRENT_SOURCE_DIR}/../../../security/oc_acl.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../security/oc_ael.c @@ -175,6 +190,7 @@ if(CONFIG_SECURE) ${CMAKE_CURRENT_SOURCE_DIR}/../../../security/oc_certs_generate.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../security/oc_certs_validate.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../security/oc_cred.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../security/oc_cred_util.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../security/oc_csr.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../security/oc_doxm.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../security/oc_entropy.c @@ -197,21 +213,19 @@ if(CONFIG_SECURE) endif() if (CONFIG_ETAG) - add_definitions(-DOC_ETAG) + list(APPEND OC_DEFINITIONS -DOC_ETAG) list(APPEND sources ${CMAKE_CURRENT_SOURCE_DIR}/../../../api/oc_etag.c ) endif() if (CONFIG_PLGD_DEV_TIME) - add_definitions(-DPLGD_DEV_TIME) + list(APPEND OC_DEFINITIONS -DPLGD_DEV_TIME) list(APPEND sources ${CMAKE_CURRENT_SOURCE_DIR}/../../../api/plgd/plgd_time.c ) endif() -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-format-truncation") - idf_component_register( SRCS ${sources} @@ -219,7 +233,4 @@ idf_component_register( ${includes} ) -set_source_files_properties(${sources} - PROPERTIES COMPILE_FLAGS - "-DOC_SERVER -DOC_CLIENT" -) +idf_build_set_property(COMPILE_OPTIONS "${OC_DEFINITIONS}" APPEND) diff --git a/port/esp32/main/Kconfig.projbuild b/port/esp32/main/Kconfig.projbuild index d50fd8ee18..80e3255124 100644 --- a/port/esp32/main/Kconfig.projbuild +++ b/port/esp32/main/Kconfig.projbuild @@ -19,10 +19,27 @@ config SNTP_TIME_SERVER help Hostname of the main SNTP server. -config OC_DEBUG - bool "OC_DEBUG" +choice OC_LOG_MAXIMUM_LEVEL + prompt "Maximal log level" + default OC_LOG_LEVEL_INFO help - enable or disable IoTivity-constrained debug + set compile-time IoTivity-constrained log level + + config OC_LOG_LEVEL_DISABLED + bool "Disabled" + config OC_LOG_LEVEL_ERROR + bool "Error" + config OC_LOG_LEVEL_WARNING + bool "Warning" + config OC_LOG_LEVEL_NOTICE + bool "Notice" + config OC_LOG_LEVEL_INFO + bool "Info" + config OC_LOG_LEVEL_DEBUG + bool "Debug" + config OC_LOG_LEVEL_TRACE + bool "Trace" +endchoice config APP_DEBUG bool "APP_DEBUG" diff --git a/port/esp32/main/main.c b/port/esp32/main/main.c index c2f02e7f0a..601154fc75 100644 --- a/port/esp32/main/main.c +++ b/port/esp32/main/main.c @@ -16,6 +16,7 @@ * ******************************************************************/ +#include "debug_print.h" #include "oc_api.h" #include "oc_clock_util.h" #include "oc_core_res.h" @@ -32,7 +33,6 @@ #include "hawkbit.h" #endif /* OC_HAS_FEATURE_PLGD_HAWKBIT */ -#include "debug_print.h" #include "driver/gpio.h" #include "esp_event.h" #include "esp_log.h" @@ -61,8 +61,6 @@ static const int IPV6_CONNECTED_BIT = BIT1; static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t g_cv = PTHREAD_COND_INITIALIZER; -static struct timespec ts; -static int quit = 0; static bool light_state = false; static const char *TAG = "iotivity server"; @@ -128,14 +126,10 @@ post_light(oc_request_t *request, oc_interface_mask_t interface, state = rep->value.boolean; OC_PRINTF("value: %d\n", state); gpio_set_level(BLINK_GPIO, state); - break; - - // case ... default: oc_send_response(request, OC_STATUS_BAD_REQUEST); return; - break; } rep = rep->next; } @@ -304,6 +298,8 @@ cloud_status_handler(oc_cloud_context_t *ctx, oc_cloud_status_t status, void factory_presets_cb_new(size_t device, void *data) { + OC_PRINTF("factory_presets_cb: %d\n", (int)device); + gpio_set_level(BLINK_GPIO, false); gpio_reset_pin(BLINK_GPIO); gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT); @@ -312,106 +308,10 @@ factory_presets_cb_new(size_t device, void *data) oc_free_string(&dev->name); oc_new_string(&dev->name, device_name, strlen(device_name)); (void)data; -#if defined(OC_SECURITY) && defined(OC_PKI) - OC_PRINTF("factory_presets_cb: %d\n", (int)device); - - const char *cert = - "-----BEGIN CERTIFICATE-----\n" - "MIIEFDCCA7qgAwIBAgIJAI0K+3tTsk4eMAoGCCqGSM49BAMCMFsxDDAKBgNVBAoM\n" - "A09DRjEiMCAGA1UECwwZS3lyaW8gVGVzdCBJbmZyYXN0cnVjdHVyZTEnMCUGA1UE\n" - "AwweS3lyaW8gVEVTVCBJbnRlcm1lZGlhdGUgQ0EwMDAyMB4XDTIwMDQxNDE3MzMy\n" - "NloXDTIwMDUxNDE3MzMyNlowYTEMMAoGA1UECgwDT0NGMSIwIAYDVQQLDBlLeXJp\n" - "byBUZXN0IEluZnJhc3RydWN0dXJlMS0wKwYDVQQDDCQyYjI1ODQ4Mi04ZDZhLTQ5\n" - "OTEtOGQ2OS0zMTAxNDE5ODE2NDYwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARZ\n" - "H0LnMEg5BR41xctwQMPoNwa0ERVB1J9WWUvdrKq4GVkX/HwPUGvViISpmIS0GM8z\n" - "Ky2IjHm+rMrc4oSTfyX0o4ICXzCCAlswCQYDVR0TBAIwADAOBgNVHQ8BAf8EBAMC\n" - "A4gwKQYDVR0lBCIwIAYIKwYBBQUHAwIGCCsGAQUFBwMBBgorBgEEAYLefAEGMB0G\n" - "A1UdDgQWBBTS5/x0htLNUYt8JoL82HU2rkjuWDAfBgNVHSMEGDAWgBQZc2oEGgsH\n" - "cE9TeVM2h/wMunyuCzCBlgYIKwYBBQUHAQEEgYkwgYYwXQYIKwYBBQUHMAKGUWh0\n" - "dHA6Ly90ZXN0cGtpLmt5cmlvLmNvbS9vY2YvY2FjZXJ0cy9CQkU2NEY5QTdFRTM3\n" - "RDI5QTA1RTRCQjc3NTk1RjMwOEJFNDFFQjA3LmNydDAlBggrBgEFBQcwAYYZaHR0\n" - "cDovL3Rlc3RvY3NwLmt5cmlvLmNvbTBfBgNVHR8EWDBWMFSgUqBQhk5odHRwOi8v\n" - "dGVzdHBraS5reXJpby5jb20vb2NmL2NybHMvQkJFNjRGOUE3RUUzN0QyOUEwNUU0\n" - "QkI3NzU5NUYzMDhCRTQxRUIwNy5jcmwwGAYDVR0gBBEwDzANBgsrBgEEAYORVgAB\n" - "AjBhBgorBgEEAYORVgEABFMwUTAJAgECAgEAAgEAMDYMGTEuMy42LjEuNC4xLjUx\n" - "NDE0LjAuMC4xLjAMGTEuMy42LjEuNC4xLjUxNDE0LjAuMC4yLjAMBUxpdGUxDAVM\n" - "aXRlMTAqBgorBgEEAYORVgEBBBwwGgYLKwYBBAGDkVYBAQAGCysGAQQBg5FWAQEB\n" - "MDAGCisGAQQBg5FWAQIEIjAgDA4xLjMuNi4xLjQuMS43MQwJRGlzY292ZXJ5DAMx\n" - "LjAwCgYIKoZIzj0EAwIDSAAwRQIgedG7zHeLh9YzM0bU3DQBnKDRIFnJHiDayyuE\n" - "8pVfJOQCIQCo/llZOZD87IHzsyxEfXm/QhkTNA5WJOa7sjF2ngQ1/g==\n" - "-----END CERTIFICATE-----\n"; - - const char *key = - "-----BEGIN EC PARAMETERS-----\n" - "BggqhkjOPQMBBw==\n" - "-----END EC PARAMETERS-----\n" - "-----BEGIN EC PRIVATE KEY-----\n" - "MHcCAQEEIBF8S8rq+h8EnykDcCpAyvMam+u3D9i/5oYF5owt/+SnoAoGCCqGSM49\n" - "AwEHoUQDQgAEWR9C5zBIOQUeNcXLcEDD6DcGtBEVQdSfVllL3ayquBlZF/x8D1Br\n" - "1YiEqZiEtBjPMystiIx5vqzK3OKEk38l9A==\n" - "-----END EC PRIVATE KEY-----\n"; - const char *inter_ca = - "-----BEGIN CERTIFICATE-----\n" - "MIIC+jCCAqGgAwIBAgIJAPObjMBXKhG1MAoGCCqGSM49BAMCMFMxDDAKBgNVBAoM\n" - "A09DRjEiMCAGA1UECwwZS3lyaW8gVGVzdCBJbmZyYXN0cnVjdHVyZTEfMB0GA1UE\n" - "AwwWS3lyaW8gVEVTVCBST09UIENBMDAwMjAeFw0xODExMzAxODEyMTVaFw0yODEx\n" - "MjYxODEyMTVaMFsxDDAKBgNVBAoMA09DRjEiMCAGA1UECwwZS3lyaW8gVGVzdCBJ\n" - "bmZyYXN0cnVjdHVyZTEnMCUGA1UEAwweS3lyaW8gVEVTVCBJbnRlcm1lZGlhdGUg\n" - "Q0EwMDAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEvA+Gn3ofRpH40XuVppBR\n" - "f78mDtfclOkBd7/32yQcmK2LQ0wm/uyl2cyeABPuN6NFcR9+LYkXZ5P4Ovy9R43Q\n" - "vqOCAVQwggFQMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMB0G\n" - "A1UdDgQWBBQZc2oEGgsHcE9TeVM2h/wMunyuCzAfBgNVHSMEGDAWgBQoSOTlJ1jZ\n" - "CO4JNOSxuz1ZZh/I9TCBjQYIKwYBBQUHAQEEgYAwfjBVBggrBgEFBQcwAoZJaHR0\n" - "cDovL3Rlc3Rwa2kua3lyaW8uY29tL29jZi80RTY4RTNGQ0YwRjJFNEY4MEE4RDE0\n" - "MzhGNkExQkE1Njk1NzEzRDYzLmNydDAlBggrBgEFBQcwAYYZaHR0cDovL3Rlc3Rv\n" - "Y3NwLmt5cmlvLmNvbTBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vdGVzdHBraS5r\n" - "eXJpby5jb20vb2NmLzRFNjhFM0ZDRjBGMkU0RjgwQThEMTQzOEY2QTFCQTU2OTU3\n" - "MTNENjMuY3JsMAoGCCqGSM49BAMCA0cAMEQCHwXkRYd+u5pOPH544wBmBRJz/b0j\n" - "ppvUIHx8IUH0CioCIQDC8CnMVTOC5aIoo5Yg4k7BDDNxbRQoPujYes0OTVGgPA==\n" - "-----END CERTIFICATE-----\n"; - - const char *root_ca = - "-----BEGIN CERTIFICATE-----\n" - "MIIB3zCCAYWgAwIBAgIJAPObjMBXKhGyMAoGCCqGSM49BAMCMFMxDDAKBgNVBAoM\n" - "A09DRjEiMCAGA1UECwwZS3lyaW8gVGVzdCBJbmZyYXN0cnVjdHVyZTEfMB0GA1UE\n" - "AwwWS3lyaW8gVEVTVCBST09UIENBMDAwMjAeFw0xODExMzAxNzMxMDVaFw0yODEx\n" - "MjcxNzMxMDVaMFMxDDAKBgNVBAoMA09DRjEiMCAGA1UECwwZS3lyaW8gVGVzdCBJ\n" - "bmZyYXN0cnVjdHVyZTEfMB0GA1UEAwwWS3lyaW8gVEVTVCBST09UIENBMDAwMjBZ\n" - "MBMGByqGSM49AgEGCCqGSM49AwEHA0IABGt1sU2QhQcK/kflKSF9TCrvKaDckLWd\n" - "ZoyvP6z0OrqNdtBscZgVYsSHMQZ1R19wWxsflvNr8bMVW1K3HWMkpsijQjBAMA8G\n" - "A1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBQoSOTlJ1jZ\n" - "CO4JNOSxuz1ZZh/I9TAKBggqhkjOPQQDAgNIADBFAiAlMUwgVeL8d5W4jZdFJ5Zg\n" - "clk7XT66LNMfGkExSjU1ngIhANOvTmd32A0kEtIpHbiKA8+RFDCPJWjN4loxrBC7\n" - "v0JE\n" - "-----END CERTIFICATE-----\n"; - - int ee_credid = - oc_pki_add_mfg_cert(0, (const unsigned char *)cert, strlen(cert), - (const unsigned char *)key, strlen(key)); - if (ee_credid < 0) { - OC_PRINTF("ERROR installing manufacturer EE cert\n"); - return; - } - - int subca_credid = oc_pki_add_mfg_intermediate_cert( - 0, ee_credid, (const unsigned char *)inter_ca, strlen(inter_ca)); - - if (subca_credid < 0) { - OC_PRINTF("ERROR installing intermediate CA cert\n"); - return; - } - - int rootca_credid = oc_pki_add_mfg_trust_anchor( - 0, (const unsigned char *)root_ca, strlen(root_ca)); - if (rootca_credid < 0) { - OC_PRINTF("ERROR installing root cert\n"); - return; - } - - oc_pki_set_security_profile(0, OC_SP_BLACK, OC_SP_BLACK, ee_credid); -#endif /* OC_SECURITY && OC_PKI */ } +#ifdef APP_DEBUG + oc_event_callback_retval_t heap_dbg(void *v) { @@ -419,11 +319,13 @@ heap_dbg(void *v) return OC_EVENT_CONTINUE; } +#endif /* APP_DEBUG */ + static void initialize_sntp(void) { ESP_LOGI(TAG, "Initializing SNTP"); - sntp_setoperatingmode(SNTP_OPMODE_POLL); + esp_sntp_setoperatingmode(SNTP_OPMODE_POLL); /* * If 'NTP over DHCP' is enabled, we set dynamic pool address @@ -431,37 +333,38 @@ initialize_sntp(void) * address provided via NTP over DHCP is not accessible */ #if LWIP_DHCP_GET_NTP_SRV && SNTP_MAX_SERVERS > 1 - sntp_setservername(1, "pool.ntp.org"); + esp_sntp_setservername(1, "pool.ntp.org"); #if LWIP_IPV6 && \ SNTP_MAX_SERVERS > 2 // statically assigned IPv6 address is also possible ip_addr_t ip6; if (ipaddr_aton("2a01:3f7::1", &ip6)) { // ipv6 ntp source "ntp.netnod.se" - sntp_setserver(2, &ip6); + esp_sntp_setserver(2, &ip6); } #endif /* LWIP_IPV6 */ #else /* LWIP_DHCP_GET_NTP_SRV && (SNTP_MAX_SERVERS > 1) */ // otherwise, use DNS address from a pool - sntp_setservername(0, CONFIG_SNTP_TIME_SERVER); + esp_sntp_setservername(0, CONFIG_SNTP_TIME_SERVER); - sntp_setservername(1, - "pool.ntp.org"); // set the secondary NTP server (will be - // used only if SNTP_MAX_SERVERS > 1) + esp_sntp_setservername( + 1, + "pool.ntp.org"); // set the secondary NTP server (will be + // used only if SNTP_MAX_SERVERS > 1) #endif - sntp_set_sync_mode(SNTP_SYNC_MODE_SMOOTH); - sntp_init(); + esp_sntp_set_sync_mode(SNTP_SYNC_MODE_SMOOTH); + esp_sntp_init(); ESP_LOGI(TAG, "List of configured NTP servers:"); for (uint8_t i = 0; i < SNTP_MAX_SERVERS; ++i) { - if (sntp_getservername(i)) { - ESP_LOGI(TAG, "server %d: %s", i, sntp_getservername(i)); + if (esp_sntp_getservername(i)) { + ESP_LOGI(TAG, "server %d: %s", i, esp_sntp_getservername(i)); } else { // we have either IPv4 or IPv6 address, let's print it char buff[IPADDR_STRLEN_MAX]; - ip_addr_t const *ip = sntp_getserver(i); + ip_addr_t const *ip = esp_sntp_getserver(i); if (ipaddr_ntoa_r(ip, buff, IPADDR_STRLEN_MAX) != NULL) ESP_LOGI(TAG, "server %d: %s", i, buff); } @@ -471,14 +374,14 @@ initialize_sntp(void) static void obtain_time(void) { -#ifdef LWIP_DHCP_GET_NTP_SRV - sntp_servermode_dhcp(1); // accept NTP offers from DHCP server, if any +#if defined(LWIP_DHCP_GET_NTP_SRV) && LWIP_DHCP_GET_NTP_SRV + esp_sntp_servermode_dhcp(1); // accept NTP offers from DHCP server, if any #endif initialize_sntp(); // wait for time to be set int retry = 0; const int retry_count = 15; - while (sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET && + while (esp_sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET && ++retry < retry_count) { ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count); @@ -508,6 +411,7 @@ static oc_swupdate_cb_t hawkbit_swupdate_impl = { static void server_main(void *pvParameter) { + (void)pvParameter; ESP_LOGI(TAG, "iotivity server task started(version=%s)", oc_esp_get_application_version()); // wait to fetch IPv4 && ipv6 address @@ -524,7 +428,7 @@ server_main(void *pvParameter) print_error("get IPv4 address failed"); } else { char buf[32]; - ESP_LOGI(TAG, "got IPv4 addr:%s", + ESP_LOGI(TAG, "got IPv4 addr: %s", esp_ip4addr_ntoa(&(ip4_info.ip), buf, sizeof(buf))); } #endif /* OC_IPV4 */ @@ -544,13 +448,17 @@ server_main(void *pvParameter) register_resources }; #ifdef OC_SECURITY +#ifdef OC_STORAGE if (oc_storage_config("storage") != 0) { ESP_LOGE(TAG, "cannot create storage"); } +#endif /* OC_STORAGE */ oc_set_factory_presets_cb(factory_presets_cb_new, NULL); -#endif /* OC_SECURITY */ + oc_set_max_app_data_size(CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN); +#else /* !OC_SECURITY */ oc_set_max_app_data_size(10000); +#endif /* OC_SECURITY */ if (oc_main_init(&handler) < 0) { return; @@ -569,9 +477,11 @@ server_main(void *pvParameter) } #endif /* OC_HAS_FEATURE_PLGD_HAWKBIT */ +#ifdef APP_DEBUG oc_set_delayed_callback(NULL, heap_dbg, 1); +#endif /* APP_DEBUG */ - while (quit != 1) { + while (true) { oc_clock_time_t next_event = oc_main_poll(); pthread_mutex_lock(&g_mutex); if (oc_main_needs_poll()) { @@ -581,7 +491,7 @@ server_main(void *pvParameter) if (next_event == 0) { pthread_cond_wait(&g_cv, &g_mutex); } else { - ts = oc_clock_time_to_timespec(next_event); + struct timespec ts = oc_clock_time_to_timespec(next_event); pthread_cond_timedwait(&g_cv, &g_mutex, &ts); } pthread_mutex_unlock(&g_mutex); diff --git a/port/esp32/sdkconfig.defaults b/port/esp32/sdkconfig.defaults index 09b1c96139..72f16ca710 100644 --- a/port/esp32/sdkconfig.defaults +++ b/port/esp32/sdkconfig.defaults @@ -733,9 +733,9 @@ CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 CONFIG_MBEDTLS_DEBUG=y # CONFIG_MBEDTLS_DEBUG_LEVEL_WARN is not set # CONFIG_MBEDTLS_DEBUG_LEVEL_INFO is not set -# CONFIG_MBEDTLS_DEBUG_LEVEL_DEBUG is not set -CONFIG_MBEDTLS_DEBUG_LEVEL_VERBOSE=y -CONFIG_MBEDTLS_DEBUG_LEVEL=4 +CONFIG_MBEDTLS_DEBUG_LEVEL_DEBUG=y +# CONFIG_MBEDTLS_DEBUG_LEVEL_VERBOSE is not set +CONFIG_MBEDTLS_DEBUG_LEVEL=3 # # Certificate Bundle @@ -773,10 +773,10 @@ CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK=y # CONFIG_MBEDTLS_KEY_EXCHANGE_RSA is not set # CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA is not set CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y -# CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y -# CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y # end of TLS Key Exchange Methods CONFIG_MBEDTLS_SSL_RENEGOTIATION=y