From dec70a760120d3c6d1d63ac0257dce6a8561879c Mon Sep 17 00:00:00 2001 From: Riccardo Binetti Date: Fri, 28 Sep 2018 18:45:11 +0200 Subject: [PATCH 1/4] esp-tls: add support for mutual SSL authentication Signed-off-by: David Cermak --- components/esp-tls/esp_tls.c | 34 ++++++++++++++++++++++++++++++++-- components/esp-tls/esp_tls.h | 22 +++++++++++++++++++++- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/components/esp-tls/esp_tls.c b/components/esp-tls/esp_tls.c index 2cd7a4471..d8411c619 100644 --- a/components/esp-tls/esp_tls.c +++ b/components/esp-tls/esp_tls.c @@ -204,6 +204,9 @@ static void mbedtls_cleanup(esp_tls_t *tls) mbedtls_x509_crt_free(tls->cacert_ptr); } tls->cacert_ptr = NULL; + mbedtls_x509_crt_free(&tls->cacert); + mbedtls_x509_crt_free(&tls->clientcert); + mbedtls_pk_free(&tls->clientkey); mbedtls_entropy_free(&tls->entropy); mbedtls_ssl_config_free(&tls->conf); mbedtls_ctr_drbg_free(&tls->ctr_drbg); @@ -274,7 +277,34 @@ static int create_ssl_handle(esp_tls_t *tls, const char *hostname, size_t hostle } else { mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_NONE); } - + + if (cfg->clientcert_pem_buf != NULL && cfg->clientkey_pem_buf != NULL) { + mbedtls_x509_crt_init(&tls->clientcert); + mbedtls_pk_init(&tls->clientkey); + + ret = mbedtls_x509_crt_parse(&tls->clientcert, cfg->clientcert_pem_buf, cfg->clientcert_pem_bytes); + if (ret < 0) { + ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); + goto exit; + } + + ret = mbedtls_pk_parse_key(&tls->clientkey, cfg->clientkey_pem_buf, cfg->clientkey_pem_bytes, + cfg->clientkey_password, cfg->clientkey_password_len); + if (ret < 0) { + ESP_LOGE(TAG, "mbedtls_pk_parse_keyfile returned -0x%x\n\n", -ret); + goto exit; + } + + ret = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->clientcert, &tls->clientkey); + if (ret < 0) { + ESP_LOGE(TAG, "mbedtls_ssl_conf_own_cert returned -0x%x\n\n", -ret); + goto exit; + } + } else if (cfg->clientcert_pem_buf != NULL || cfg->clientkey_pem_buf != NULL) { + ESP_LOGE(TAG, "You have to provide both clientcert_pem_buf and clientkey_pem_buf for mutual authentication\n\n"); + goto exit; + } + mbedtls_ssl_conf_rng(&tls->conf, mbedtls_ctr_drbg_random, &tls->ctr_drbg); #ifdef CONFIG_MBEDTLS_DEBUG @@ -502,4 +532,4 @@ int esp_tls_conn_http_new_async(const char *url, const esp_tls_cfg_t *cfg, esp_t /* Connect to host */ return esp_tls_conn_new_async(&url[u.field_data[UF_HOST].off], u.field_data[UF_HOST].len, get_port(url, &u), cfg, tls); -} \ No newline at end of file +} diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h index eaa035312..d6982b740 100644 --- a/components/esp-tls/esp_tls.h +++ b/components/esp-tls/esp_tls.h @@ -60,7 +60,22 @@ typedef struct esp_tls_cfg { unsigned int cacert_pem_bytes; /*!< Size of Certificate Authority certificate pointed to by cacert_pem_buf */ + + const unsigned char *clientcert_pem_buf;/*!< Client certificate in a buffer */ + unsigned int clientcert_pem_bytes; /*!< Size of client certificate pointed to by + clientcert_pem_buf */ + + const unsigned char *clientkey_pem_buf; /*!< Client key in a buffer */ + + unsigned int clientkey_pem_bytes; /*!< Size of client key pointed to by + clientkey_pem_buf */ + + const unsigned char *clientkey_password;/*!< Client key decryption password string */ + + unsigned int clientkey_password_len; /*!< String length of the password pointed to by + clientkey_password */ + bool non_block; /*!< Configure non-blocking mode. If set to true the underneath socket will be configured in non blocking mode after tls session is established */ @@ -89,7 +104,12 @@ typedef struct esp_tls { mbedtls_net_context server_fd; /*!< mbedTLS wrapper type for sockets */ - mbedtls_x509_crt cacert; /*!< Container for an X.509 certificate */ + mbedtls_x509_crt cacert; /*!< Container for the X.509 CA certificate */ + + mbedtls_x509_crt clientcert; /*!< Container for the X.509 client certificate */ + + mbedtls_pk_context clientkey; /*!< Container for the private key of the client + certificate */ mbedtls_x509_crt *cacert_ptr; /*!< Pointer to the cacert being used. */ From 9ce8e1e5a11b3980a7e5d083d26afef8d8ad31c1 Mon Sep 17 00:00:00 2001 From: Riccardo Binetti Date: Fri, 28 Sep 2018 18:45:37 +0200 Subject: [PATCH 2/4] transport_ssl: add support for mutual SSL authentication Signed-off-by: David Cermak --- .../tcp_transport/include/esp_transport_ssl.h | 21 +++++++++++++++ components/tcp_transport/transport_ssl.c | 26 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/components/tcp_transport/include/esp_transport_ssl.h b/components/tcp_transport/include/esp_transport_ssl.h index 2065db6b0..87577a7ea 100644 --- a/components/tcp_transport/include/esp_transport_ssl.h +++ b/components/tcp_transport/include/esp_transport_ssl.h @@ -40,6 +40,27 @@ esp_transport_handle_t esp_transport_ssl_init(); */ void esp_transport_ssl_set_cert_data(esp_transport_handle_t t, const char *data, int len); +/** + * @brief Set SSL client certificate data for mutual authentication (as PEM format). + * Note that, this function stores the pointer to data, rather than making a copy. + * So we need to make sure to keep the data lifetime before cleanup the connection + * + * @param t ssl transport + * @param[in] data The pem data + * @param[in] len The length + */ +void esp_transport_ssl_set_client_cert_data(esp_transport_handle_t t, const char *data, int len); + +/** + * @brief Set SSL client key data for mutual authentication (as PEM format). + * Note that, this function stores the pointer to data, rather than making a copy. + * So we need to make sure to keep the data lifetime before cleanup the connection + * + * @param t ssl transport + * @param[in] data The pem data + * @param[in] len The length + */ +void esp_transport_ssl_set_client_key_data(esp_transport_handle_t t, const char *data, int len); #ifdef __cplusplus } diff --git a/components/tcp_transport/transport_ssl.c b/components/tcp_transport/transport_ssl.c index 08afe3c19..f53601ee4 100644 --- a/components/tcp_transport/transport_ssl.c +++ b/components/tcp_transport/transport_ssl.c @@ -40,6 +40,7 @@ typedef struct { esp_tls_cfg_t cfg; bool ssl_initialized; bool verify_server; + bool mutual_authentication; transport_ssl_conn_state_t conn_state; } transport_ssl_t; @@ -52,6 +53,9 @@ static int ssl_connect_async(esp_transport_handle_t t, const char *host, int por if (ssl->cfg.cacert_pem_buf) { ssl->verify_server = true; } + if (ssl->cfg.clientcert_pem_buf && ssl->cfg.clientkey_pem_buf) { + ssl->mutual_authentication = true; + } ssl->cfg.timeout_ms = timeout_ms; ssl->cfg.non_block = true; ssl->ssl_initialized = true; @@ -73,6 +77,9 @@ static int ssl_connect(esp_transport_handle_t t, const char *host, int port, int if (ssl->cfg.cacert_pem_buf) { ssl->verify_server = true; } + if (ssl->cfg.clientcert_pem_buf && ssl->cfg.clientkey_pem_buf) { + ssl->mutual_authentication = true; + } ssl->cfg.timeout_ms = timeout_ms; ssl->ssl_initialized = true; ssl->tls = esp_tls_conn_new(host, strlen(host), port, &ssl->cfg); @@ -147,6 +154,7 @@ static int ssl_close(esp_transport_handle_t t) esp_tls_conn_delete(ssl->tls); ssl->ssl_initialized = false; ssl->verify_server = false; + ssl->mutual_authentication = false; } return ret; } @@ -168,6 +176,24 @@ void esp_transport_ssl_set_cert_data(esp_transport_handle_t t, const char *data, } } +void esp_transport_ssl_set_client_cert_data(esp_transport_handle_t t, const char *data, int len) +{ + transport_ssl_t *ssl = esp_transport_get_context_data(t); + if (t && ssl) { + ssl->cfg.clientcert_pem_buf = (void *)data; + ssl->cfg.clientcert_pem_bytes = len + 1; + } +} + +void esp_transport_ssl_set_client_key_data(esp_transport_handle_t t, const char *data, int len) +{ + transport_ssl_t *ssl = esp_transport_get_context_data(t); + if (t && ssl) { + ssl->cfg.clientkey_pem_buf = (void *)data; + ssl->cfg.clientkey_pem_bytes = len + 1; + } +} + esp_transport_handle_t esp_transport_ssl_init() { esp_transport_handle_t t = esp_transport_init(); From 49df4794863b5342722098193e41b308b01fb5cb Mon Sep 17 00:00:00 2001 From: Riccardo Binetti Date: Mon, 6 Aug 2018 16:35:00 +0200 Subject: [PATCH 3/4] mqtt: Add ssl mutual authentication example Signed-off-by: David Cermak --- examples/mqtt_ssl_mutual_auth/CMakeLists.txt | 19 +++ examples/mqtt_ssl_mutual_auth/Makefile | 13 ++ examples/mqtt_ssl_mutual_auth/README.md | 16 ++ .../main/Kconfig.projbuild | 15 ++ examples/mqtt_ssl_mutual_auth/main/app_main.c | 152 ++++++++++++++++++ .../mqtt_ssl_mutual_auth/main/component.mk | 1 + 6 files changed, 216 insertions(+) create mode 100644 examples/mqtt_ssl_mutual_auth/CMakeLists.txt create mode 100644 examples/mqtt_ssl_mutual_auth/Makefile create mode 100644 examples/mqtt_ssl_mutual_auth/README.md create mode 100644 examples/mqtt_ssl_mutual_auth/main/Kconfig.projbuild create mode 100755 examples/mqtt_ssl_mutual_auth/main/app_main.c create mode 100644 examples/mqtt_ssl_mutual_auth/main/component.mk diff --git a/examples/mqtt_ssl_mutual_auth/CMakeLists.txt b/examples/mqtt_ssl_mutual_auth/CMakeLists.txt new file mode 100644 index 000000000..106b11790 --- /dev/null +++ b/examples/mqtt_ssl_mutual_auth/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.5) + +get_filename_component(DEV_ROOT "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE) + +set(PROJECT_ROOT "${DEV_ROOT}/") + +set(SUBMODULE_ROOT "${DEV_ROOT}/../../../") + +set(PROJECT_NAME "mqtt_ssl_mutual_auth") + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +set(MAIN_SRCS ${PROJECT_ROOT}/main/app_main.c) + +set(EXTRA_COMPONENT_DIRS "${EXTRA_COMPONENT_DIRS} ${SUBMODULE_ROOT}") +set(BUILD_COMPONENTS "${BUILD_COMPONENTS} espmqtt") + +project(${PROJECT_NAME}) + diff --git a/examples/mqtt_ssl_mutual_auth/Makefile b/examples/mqtt_ssl_mutual_auth/Makefile new file mode 100644 index 000000000..c22f41d19 --- /dev/null +++ b/examples/mqtt_ssl_mutual_auth/Makefile @@ -0,0 +1,13 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# +PROJECT_NAME := mqtt_ssl_mutual_auth +EXTRA_COMPONENT_DIRS += $(PROJECT_PATH)/../../../ + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/mqtt_ssl_mutual_auth/README.md b/examples/mqtt_ssl_mutual_auth/README.md new file mode 100644 index 000000000..c415cdffb --- /dev/null +++ b/examples/mqtt_ssl_mutual_auth/README.md @@ -0,0 +1,16 @@ +# ESPMQTT SSL Sample application + +Navigate to the main directory + +``` +cd main +``` + +Generate a client key and a CSR. When you are generating the CSR, do not use the default values. At a minimum, the CSR must include the Country, Organisation and Common Name fields. + +``` +openssl genrsa -out client.key +openssl req -out client.csr -key client.key -new +``` + +Paste the generated CSR in the [Mosquitto test certificate signer](https://test.mosquitto.org/ssl/index.php), click Submit and copy the downloaded `client.crt` in the `main` directory. diff --git a/examples/mqtt_ssl_mutual_auth/main/Kconfig.projbuild b/examples/mqtt_ssl_mutual_auth/main/Kconfig.projbuild new file mode 100644 index 000000000..1c9c2e6cd --- /dev/null +++ b/examples/mqtt_ssl_mutual_auth/main/Kconfig.projbuild @@ -0,0 +1,15 @@ +menu "MQTT Application sample" + +config WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. + +config WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. + +endmenu diff --git a/examples/mqtt_ssl_mutual_auth/main/app_main.c b/examples/mqtt_ssl_mutual_auth/main/app_main.c new file mode 100755 index 000000000..f290d15ec --- /dev/null +++ b/examples/mqtt_ssl_mutual_auth/main/app_main.c @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include "esp_wifi.h" +#include "esp_system.h" +#include "nvs_flash.h" +#include "esp_event_loop.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +#include "freertos/event_groups.h" + +#include "lwip/sockets.h" +#include "lwip/dns.h" +#include "lwip/netdb.h" + +#include "esp_log.h" +#include "mqtt_client.h" + +static const char *TAG = "MQTTS_SAMPLE"; + +static EventGroupHandle_t wifi_event_group; +const static int CONNECTED_BIT = BIT0; + + + +static esp_err_t wifi_event_handler(void *ctx, system_event_t *event) +{ + switch (event->event_id) { + case SYSTEM_EVENT_STA_START: + esp_wifi_connect(); + break; + case SYSTEM_EVENT_STA_GOT_IP: + xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); + + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + esp_wifi_connect(); + xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); + break; + default: + break; + } + return ESP_OK; +} + +static void wifi_init(void) +{ + tcpip_adapter_init(); + wifi_event_group = xEventGroupCreate(); + ESP_ERROR_CHECK(esp_event_loop_init(wifi_event_handler, NULL)); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); + wifi_config_t wifi_config = { + .sta = { + .ssid = CONFIG_WIFI_SSID, + .password = CONFIG_WIFI_PASSWORD, + }, + }; + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); + ESP_LOGI(TAG, "start the WIFI SSID:[%s] password:[%s]", CONFIG_WIFI_SSID, "******"); + ESP_ERROR_CHECK(esp_wifi_start()); + ESP_LOGI(TAG, "Waiting for wifi"); + xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY); +} + +extern const uint8_t client_cert_pem_start[] asm("_binary_client_crt_start"); +extern const uint8_t client_cert_pem_end[] asm("_binary_client_crt_end"); +extern const uint8_t client_key_pem_start[] asm("_binary_client_key_start"); +extern const uint8_t client_key_pem_end[] asm("_binary_client_key_end"); + +static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event) +{ + esp_mqtt_client_handle_t client = event->client; + int msg_id; + // your_context_t *context = event->context; + switch (event->event_id) { + case MQTT_EVENT_CONNECTED: + ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED"); + msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0); + ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); + + msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1); + ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); + + msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1"); + ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id); + break; + case MQTT_EVENT_DISCONNECTED: + ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED"); + break; + + case MQTT_EVENT_SUBSCRIBED: + ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id); + msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0); + ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id); + break; + case MQTT_EVENT_UNSUBSCRIBED: + ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id); + break; + case MQTT_EVENT_PUBLISHED: + ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); + break; + case MQTT_EVENT_DATA: + ESP_LOGI(TAG, "MQTT_EVENT_DATA"); + printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); + printf("DATA=%.*s\r\n", event->data_len, event->data); + break; + case MQTT_EVENT_ERROR: + ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); + break; + } + return ESP_OK; +} + +static void mqtt_app_start(void) +{ + const esp_mqtt_client_config_t mqtt_cfg = { + .uri = "mqtts://test.mosquitto.org:8884", + .event_handle = mqtt_event_handler, + .client_cert_pem = (const char *)client_cert_pem_start, + .client_key_pem = (const char *)client_key_pem_start, + }; + + ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); + esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); + esp_mqtt_client_start(client); +} + +void app_main() +{ + ESP_LOGI(TAG, "[APP] Startup.."); + ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); + ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); + + esp_log_level_set("*", ESP_LOG_INFO); + esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE); + esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE); + esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE); + esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE); + esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE); + + nvs_flash_init(); + wifi_init(); + mqtt_app_start(); + +} diff --git a/examples/mqtt_ssl_mutual_auth/main/component.mk b/examples/mqtt_ssl_mutual_auth/main/component.mk new file mode 100644 index 000000000..01adda5c1 --- /dev/null +++ b/examples/mqtt_ssl_mutual_auth/main/component.mk @@ -0,0 +1 @@ +COMPONENT_EMBED_TXTFILES := client.crt client.key From 0cdb33c9dd4bdb861477627d72ec18ff84440100 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 11 Oct 2018 17:34:09 +0200 Subject: [PATCH 4/4] mqtt: ssl mutual authentication example added per PR from github, corrected cmake build, updated per idf style Merges https://github.com/espressif/esp-idf/pull/2490 --- components/esp-tls/esp_tls.h | 4 +- components/mqtt/esp-mqtt | 2 +- .../tcp_transport/include/esp_transport_ssl.h | 6 +- components/tcp_transport/transport_ssl.c | 17 +--- examples/mqtt_ssl_mutual_auth/CMakeLists.txt | 19 ----- examples/mqtt_ssl_mutual_auth/README.md | 16 ---- .../mqtt/ssl_mutual_auth/CMakeLists.txt | 10 +++ .../mqtt/ssl_mutual_auth}/Makefile | 6 -- .../protocols/mqtt/ssl_mutual_auth/README.md | 81 +++++++++++++++++++ .../mqtt/ssl_mutual_auth/main/CMakeLists.txt | 4 + .../ssl_mutual_auth}/main/Kconfig.projbuild | 2 +- .../mqtt/ssl_mutual_auth}/main/app_main.c | 4 +- .../mqtt/ssl_mutual_auth/main/client.crt | 1 + .../mqtt/ssl_mutual_auth/main/client.key | 1 + .../mqtt/ssl_mutual_auth}/main/component.mk | 0 15 files changed, 107 insertions(+), 66 deletions(-) delete mode 100644 examples/mqtt_ssl_mutual_auth/CMakeLists.txt delete mode 100644 examples/mqtt_ssl_mutual_auth/README.md create mode 100644 examples/protocols/mqtt/ssl_mutual_auth/CMakeLists.txt rename examples/{mqtt_ssl_mutual_auth => protocols/mqtt/ssl_mutual_auth}/Makefile (53%) create mode 100644 examples/protocols/mqtt/ssl_mutual_auth/README.md create mode 100644 examples/protocols/mqtt/ssl_mutual_auth/main/CMakeLists.txt rename examples/{mqtt_ssl_mutual_auth => protocols/mqtt/ssl_mutual_auth}/main/Kconfig.projbuild (90%) rename examples/{mqtt_ssl_mutual_auth => protocols/mqtt/ssl_mutual_auth}/main/app_main.c (97%) mode change 100755 => 100644 create mode 100644 examples/protocols/mqtt/ssl_mutual_auth/main/client.crt create mode 100644 examples/protocols/mqtt/ssl_mutual_auth/main/client.key rename examples/{mqtt_ssl_mutual_auth => protocols/mqtt/ssl_mutual_auth}/main/component.mk (100%) diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h index d6982b740..ed7165e50 100644 --- a/components/esp-tls/esp_tls.h +++ b/components/esp-tls/esp_tls.h @@ -106,12 +106,12 @@ typedef struct esp_tls { mbedtls_x509_crt cacert; /*!< Container for the X.509 CA certificate */ + mbedtls_x509_crt *cacert_ptr; /*!< Pointer to the cacert being used. */ + mbedtls_x509_crt clientcert; /*!< Container for the X.509 client certificate */ mbedtls_pk_context clientkey; /*!< Container for the private key of the client certificate */ - - mbedtls_x509_crt *cacert_ptr; /*!< Pointer to the cacert being used. */ int sockfd; /*!< Underlying socket file descriptor. */ diff --git a/components/mqtt/esp-mqtt b/components/mqtt/esp-mqtt index 85ee406d0..a7b1cea5b 160000 --- a/components/mqtt/esp-mqtt +++ b/components/mqtt/esp-mqtt @@ -1 +1 @@ -Subproject commit 85ee406d03fd84f5613c6dead1ea653e384b9559 +Subproject commit a7b1cea5b3e246298607a8c64447765297626f36 diff --git a/components/tcp_transport/include/esp_transport_ssl.h b/components/tcp_transport/include/esp_transport_ssl.h index 87577a7ea..34045ae77 100644 --- a/components/tcp_transport/include/esp_transport_ssl.h +++ b/components/tcp_transport/include/esp_transport_ssl.h @@ -32,7 +32,7 @@ esp_transport_handle_t esp_transport_ssl_init(); /** * @brief Set SSL certificate data (as PEM format). * Note that, this function stores the pointer to data, rather than making a copy. - * So we need to make sure to keep the data lifetime before cleanup the connection + * So this data must remain valid until after the connection is cleaned up * * @param t ssl transport * @param[in] data The pem data @@ -43,7 +43,7 @@ void esp_transport_ssl_set_cert_data(esp_transport_handle_t t, const char *data, /** * @brief Set SSL client certificate data for mutual authentication (as PEM format). * Note that, this function stores the pointer to data, rather than making a copy. - * So we need to make sure to keep the data lifetime before cleanup the connection + * So this data must remain valid until after the connection is cleaned up * * @param t ssl transport * @param[in] data The pem data @@ -54,7 +54,7 @@ void esp_transport_ssl_set_client_cert_data(esp_transport_handle_t t, const char /** * @brief Set SSL client key data for mutual authentication (as PEM format). * Note that, this function stores the pointer to data, rather than making a copy. - * So we need to make sure to keep the data lifetime before cleanup the connection + * So this data must remain valid until after the connection is cleaned up * * @param t ssl transport * @param[in] data The pem data diff --git a/components/tcp_transport/transport_ssl.c b/components/tcp_transport/transport_ssl.c index f53601ee4..f2d346720 100644 --- a/components/tcp_transport/transport_ssl.c +++ b/components/tcp_transport/transport_ssl.c @@ -39,8 +39,6 @@ typedef struct { esp_tls_t *tls; esp_tls_cfg_t cfg; bool ssl_initialized; - bool verify_server; - bool mutual_authentication; transport_ssl_conn_state_t conn_state; } transport_ssl_t; @@ -50,12 +48,6 @@ static int ssl_connect_async(esp_transport_handle_t t, const char *host, int por { transport_ssl_t *ssl = esp_transport_get_context_data(t); if (ssl->conn_state == TRANS_SSL_INIT) { - if (ssl->cfg.cacert_pem_buf) { - ssl->verify_server = true; - } - if (ssl->cfg.clientcert_pem_buf && ssl->cfg.clientkey_pem_buf) { - ssl->mutual_authentication = true; - } ssl->cfg.timeout_ms = timeout_ms; ssl->cfg.non_block = true; ssl->ssl_initialized = true; @@ -74,12 +66,7 @@ static int ssl_connect_async(esp_transport_handle_t t, const char *host, int por static int ssl_connect(esp_transport_handle_t t, const char *host, int port, int timeout_ms) { transport_ssl_t *ssl = esp_transport_get_context_data(t); - if (ssl->cfg.cacert_pem_buf) { - ssl->verify_server = true; - } - if (ssl->cfg.clientcert_pem_buf && ssl->cfg.clientkey_pem_buf) { - ssl->mutual_authentication = true; - } + ssl->cfg.timeout_ms = timeout_ms; ssl->ssl_initialized = true; ssl->tls = esp_tls_conn_new(host, strlen(host), port, &ssl->cfg); @@ -153,8 +140,6 @@ static int ssl_close(esp_transport_handle_t t) if (ssl->ssl_initialized) { esp_tls_conn_delete(ssl->tls); ssl->ssl_initialized = false; - ssl->verify_server = false; - ssl->mutual_authentication = false; } return ret; } diff --git a/examples/mqtt_ssl_mutual_auth/CMakeLists.txt b/examples/mqtt_ssl_mutual_auth/CMakeLists.txt deleted file mode 100644 index 106b11790..000000000 --- a/examples/mqtt_ssl_mutual_auth/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 3.5) - -get_filename_component(DEV_ROOT "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE) - -set(PROJECT_ROOT "${DEV_ROOT}/") - -set(SUBMODULE_ROOT "${DEV_ROOT}/../../../") - -set(PROJECT_NAME "mqtt_ssl_mutual_auth") - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) - -set(MAIN_SRCS ${PROJECT_ROOT}/main/app_main.c) - -set(EXTRA_COMPONENT_DIRS "${EXTRA_COMPONENT_DIRS} ${SUBMODULE_ROOT}") -set(BUILD_COMPONENTS "${BUILD_COMPONENTS} espmqtt") - -project(${PROJECT_NAME}) - diff --git a/examples/mqtt_ssl_mutual_auth/README.md b/examples/mqtt_ssl_mutual_auth/README.md deleted file mode 100644 index c415cdffb..000000000 --- a/examples/mqtt_ssl_mutual_auth/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# ESPMQTT SSL Sample application - -Navigate to the main directory - -``` -cd main -``` - -Generate a client key and a CSR. When you are generating the CSR, do not use the default values. At a minimum, the CSR must include the Country, Organisation and Common Name fields. - -``` -openssl genrsa -out client.key -openssl req -out client.csr -key client.key -new -``` - -Paste the generated CSR in the [Mosquitto test certificate signer](https://test.mosquitto.org/ssl/index.php), click Submit and copy the downloaded `client.crt` in the `main` directory. diff --git a/examples/protocols/mqtt/ssl_mutual_auth/CMakeLists.txt b/examples/protocols/mqtt/ssl_mutual_auth/CMakeLists.txt new file mode 100644 index 000000000..84bf37525 --- /dev/null +++ b/examples/protocols/mqtt/ssl_mutual_auth/CMakeLists.txt @@ -0,0 +1,10 @@ +# The following four lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +project(mqtt_ssl_mutual_auth) + +target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "main/client.crt" TEXT) +target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "main/client.key" TEXT) diff --git a/examples/mqtt_ssl_mutual_auth/Makefile b/examples/protocols/mqtt/ssl_mutual_auth/Makefile similarity index 53% rename from examples/mqtt_ssl_mutual_auth/Makefile rename to examples/protocols/mqtt/ssl_mutual_auth/Makefile index c22f41d19..cfc04f81b 100644 --- a/examples/mqtt_ssl_mutual_auth/Makefile +++ b/examples/protocols/mqtt/ssl_mutual_auth/Makefile @@ -2,12 +2,6 @@ # This is a project Makefile. It is assumed the directory this Makefile resides in is a # project subdirectory. # -# -# This is a project Makefile. It is assumed the directory this Makefile resides in is a -# project subdirectory. -# PROJECT_NAME := mqtt_ssl_mutual_auth -EXTRA_COMPONENT_DIRS += $(PROJECT_PATH)/../../../ include $(IDF_PATH)/make/project.mk - diff --git a/examples/protocols/mqtt/ssl_mutual_auth/README.md b/examples/protocols/mqtt/ssl_mutual_auth/README.md new file mode 100644 index 000000000..7ffe53704 --- /dev/null +++ b/examples/protocols/mqtt/ssl_mutual_auth/README.md @@ -0,0 +1,81 @@ +# ESP-MQTT SSL Sample application (mutual authentication) + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +This example connects to the broker test.mosquitto.org using ssl transport with client certificate and as a demonstration subscribes/unsubscribes and send a message on certain topic. + +It uses ESP-MQTT library which implements mqtt client to connect to mqtt broker. + +## How to use example + +### Hardware Required + +This example can be executed on any ESP32 board, the only required interface is WiFi and connection to internet. + +### Configure the project + +``` +make menuconfig +``` + +* Set serial port under Serial Flasher Options. + +* Set ssid and password for the board to connect to AP. + +* Generate your client keys and certificate + +Navigate to the main directory + +``` +cd main +``` + +Generate a client key and a CSR. When you are generating the CSR, do not use the default values. At a minimum, the CSR must include the Country, Organisation and Common Name fields. + +``` +openssl genrsa -out client.key +openssl req -out client.csr -key client.key -new +``` + +Paste the generated CSR in the [Mosquitto test certificate signer](https://test.mosquitto.org/ssl/index.php), click Submit and copy the downloaded `client.crt` in the `main` directory. + +Please note, that the supplied files `client.crt` and `client.key` in the `main` directory are only placeholders for your client certificate and key (i.e. the example "as is" would compile but would not connect to the broker) + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +make -j4 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. + +## Example Output + +``` +I (3714) event: sta ip: 192.168.0.139, mask: 255.255.255.0, gw: 192.168.0.2 +I (3714) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE +I (3964) MQTT_CLIENT: Sending MQTT CONNECT message, type: 1, id: 0000 +I (4164) MQTTS_EXAMPLE: MQTT_EVENT_CONNECTED +I (4174) MQTTS_EXAMPLE: sent publish successful, msg_id=41464 +I (4174) MQTTS_EXAMPLE: sent subscribe successful, msg_id=17886 +I (4174) MQTTS_EXAMPLE: sent subscribe successful, msg_id=42970 +I (4184) MQTTS_EXAMPLE: sent unsubscribe successful, msg_id=50241 +I (4314) MQTTS_EXAMPLE: MQTT_EVENT_PUBLISHED, msg_id=41464 +I (4484) MQTTS_EXAMPLE: MQTT_EVENT_SUBSCRIBED, msg_id=17886 +I (4484) MQTTS_EXAMPLE: sent publish successful, msg_id=0 +I (4684) MQTTS_EXAMPLE: MQTT_EVENT_SUBSCRIBED, msg_id=42970 +I (4684) MQTTS_EXAMPLE: sent publish successful, msg_id=0 +I (4884) MQTT_CLIENT: deliver_publish, message_length_read=19, message_length=19 +I (4884) MQTTS_EXAMPLE: MQTT_EVENT_DATA +TOPIC=/topic/qos0 +DATA=data +I (5194) MQTT_CLIENT: deliver_publish, message_length_read=19, message_length=19 +I (5194) MQTTS_EXAMPLE: MQTT_EVENT_DATA +TOPIC=/topic/qos0 +DATA=data +``` + diff --git a/examples/protocols/mqtt/ssl_mutual_auth/main/CMakeLists.txt b/examples/protocols/mqtt/ssl_mutual_auth/main/CMakeLists.txt new file mode 100644 index 000000000..6b0350063 --- /dev/null +++ b/examples/protocols/mqtt/ssl_mutual_auth/main/CMakeLists.txt @@ -0,0 +1,4 @@ +set(COMPONENT_SRCS "app_main.c") +set(COMPONENT_ADD_INCLUDEDIRS ".") + +register_component() diff --git a/examples/mqtt_ssl_mutual_auth/main/Kconfig.projbuild b/examples/protocols/mqtt/ssl_mutual_auth/main/Kconfig.projbuild similarity index 90% rename from examples/mqtt_ssl_mutual_auth/main/Kconfig.projbuild rename to examples/protocols/mqtt/ssl_mutual_auth/main/Kconfig.projbuild index 1c9c2e6cd..176d8fb33 100644 --- a/examples/mqtt_ssl_mutual_auth/main/Kconfig.projbuild +++ b/examples/protocols/mqtt/ssl_mutual_auth/main/Kconfig.projbuild @@ -1,4 +1,4 @@ -menu "MQTT Application sample" +menu "Example Configuration" config WIFI_SSID string "WiFi SSID" diff --git a/examples/mqtt_ssl_mutual_auth/main/app_main.c b/examples/protocols/mqtt/ssl_mutual_auth/main/app_main.c old mode 100755 new mode 100644 similarity index 97% rename from examples/mqtt_ssl_mutual_auth/main/app_main.c rename to examples/protocols/mqtt/ssl_mutual_auth/main/app_main.c index f290d15ec..2ebce48b9 --- a/examples/mqtt_ssl_mutual_auth/main/app_main.c +++ b/examples/protocols/mqtt/ssl_mutual_auth/main/app_main.c @@ -20,7 +20,7 @@ #include "esp_log.h" #include "mqtt_client.h" -static const char *TAG = "MQTTS_SAMPLE"; +static const char *TAG = "MQTTS_EXAMPLE"; static EventGroupHandle_t wifi_event_group; const static int CONNECTED_BIT = BIT0; @@ -63,7 +63,7 @@ static void wifi_init(void) }; ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); - ESP_LOGI(TAG, "start the WIFI SSID:[%s] password:[%s]", CONFIG_WIFI_SSID, "******"); + ESP_LOGI(TAG, "start the WIFI SSID:[%s]", CONFIG_WIFI_SSID); ESP_ERROR_CHECK(esp_wifi_start()); ESP_LOGI(TAG, "Waiting for wifi"); xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY); diff --git a/examples/protocols/mqtt/ssl_mutual_auth/main/client.crt b/examples/protocols/mqtt/ssl_mutual_auth/main/client.crt new file mode 100644 index 000000000..7a3074b90 --- /dev/null +++ b/examples/protocols/mqtt/ssl_mutual_auth/main/client.crt @@ -0,0 +1 @@ +Please paste your client certificate here (follow instructions in README.md) diff --git a/examples/protocols/mqtt/ssl_mutual_auth/main/client.key b/examples/protocols/mqtt/ssl_mutual_auth/main/client.key new file mode 100644 index 000000000..a956f850c --- /dev/null +++ b/examples/protocols/mqtt/ssl_mutual_auth/main/client.key @@ -0,0 +1 @@ +Please paste here your client key (follow instructions in README.md) diff --git a/examples/mqtt_ssl_mutual_auth/main/component.mk b/examples/protocols/mqtt/ssl_mutual_auth/main/component.mk similarity index 100% rename from examples/mqtt_ssl_mutual_auth/main/component.mk rename to examples/protocols/mqtt/ssl_mutual_auth/main/component.mk