From 8950f94ec73cf838ecec5eaa52d9fec54785750b Mon Sep 17 00:00:00 2001 From: Jitin George Date: Tue, 28 May 2019 11:19:02 +0530 Subject: [PATCH 1/3] esp_tls: Add support for server side SSL/TLS connection Currently, esp-tls supports creation of SSL/TLS connection on the client side. This commit includes support for creating SSL/TLS connection on the server side. --- components/esp-tls/Kconfig | 9 ++ components/esp-tls/esp_tls.c | 293 ++++++++++++++++++++++++++++------- components/esp-tls/esp_tls.h | 85 +++++++++- 3 files changed, 328 insertions(+), 59 deletions(-) create mode 100644 components/esp-tls/Kconfig diff --git a/components/esp-tls/Kconfig b/components/esp-tls/Kconfig new file mode 100644 index 0000000000..3208942717 --- /dev/null +++ b/components/esp-tls/Kconfig @@ -0,0 +1,9 @@ +menu "ESP-TLS" + + config ESP_TLS_SERVER + bool "Enable ESP-TLS Server" + help + Enable support for creating server side SSL/TLS session + +endmenu + diff --git a/components/esp-tls/esp_tls.c b/components/esp-tls/esp_tls.c index 8d2c528ae5..c857435ed3 100644 --- a/components/esp-tls/esp_tls.c +++ b/components/esp-tls/esp_tls.c @@ -34,6 +34,17 @@ static mbedtls_x509_crt *global_cacert = NULL; #define ESP_LOGE(TAG, ...) printf(__VA_ARGS__); #endif +typedef struct esp_tls_pki_t { + mbedtls_x509_crt *public_cert; + mbedtls_pk_context *pk_key; + const unsigned char *publiccert_pem_buf; + unsigned int publiccert_pem_bytes; + const unsigned char *privkey_pem_buf; + unsigned int privkey_pem_bytes; + const unsigned char *privkey_password; + unsigned int privkey_password_len; +} esp_tls_pki_t; + static struct addrinfo *resolve_host_name(const char *host, size_t hostlen) { struct addrinfo hints; @@ -169,7 +180,7 @@ esp_err_t esp_tls_set_global_ca_store(const unsigned char *cacert_pem_buf, const } ret = mbedtls_x509_crt_parse(global_cacert, cacert_pem_buf, cacert_pem_bytes); if (ret < 0) { - ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); + ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x", -ret); mbedtls_x509_crt_free(global_cacert); global_cacert = NULL; return ESP_FAIL; @@ -215,6 +226,10 @@ static void mbedtls_cleanup(esp_tls_t *tls) mbedtls_x509_crt_free(tls->cacert_ptr); } tls->cacert_ptr = NULL; +#ifdef CONFIG_ESP_TLS_SERVER + mbedtls_x509_crt_free(&tls->servercert); + mbedtls_pk_free(&tls->serverkey); +#endif mbedtls_x509_crt_free(&tls->cacert); mbedtls_x509_crt_free(&tls->clientcert); mbedtls_pk_free(&tls->clientkey); @@ -224,22 +239,130 @@ static void mbedtls_cleanup(esp_tls_t *tls) mbedtls_ssl_free(&tls->ssl); } -static int create_ssl_handle(esp_tls_t *tls, const char *hostname, size_t hostlen, const esp_tls_cfg_t *cfg) +static int set_global_ca_store(esp_tls_t *tls) { + assert(tls); + if (global_cacert == NULL) { + ESP_LOGE(TAG, "global_cacert is NULL"); + return -1; + } + tls->cacert_ptr = global_cacert; + mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); + mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); + return 0; +} + +static int set_ca_cert(esp_tls_t *tls, const unsigned char *cacert, size_t cacert_len) +{ + assert(tls); + tls->cacert_ptr = &tls->cacert; + mbedtls_x509_crt_init(tls->cacert_ptr); + int ret = mbedtls_x509_crt_parse(tls->cacert_ptr, cacert, cacert_len); + if (ret < 0) { + ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x", -ret); + return ret; + } + mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); + mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); + return 0; +} + +static int set_pki_context(esp_tls_t *tls, const esp_tls_pki_t *pki) +{ + assert(tls); + assert(pki); int ret; - tls->server_fd.fd = tls->sockfd; - mbedtls_ssl_init(&tls->ssl); - mbedtls_ctr_drbg_init(&tls->ctr_drbg); - mbedtls_ssl_config_init(&tls->conf); - mbedtls_entropy_init(&tls->entropy); - - if ((ret = mbedtls_ctr_drbg_seed(&tls->ctr_drbg, - mbedtls_entropy_func, &tls->entropy, NULL, 0)) != 0) { - ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned %d", ret); - goto exit; + if (pki->publiccert_pem_buf != NULL && + pki->privkey_pem_buf != NULL && + pki->public_cert != NULL && + pki->pk_key != NULL) { + + mbedtls_x509_crt_init(pki->public_cert); + mbedtls_pk_init(pki->pk_key); + + ret = mbedtls_x509_crt_parse(pki->public_cert, pki->publiccert_pem_buf, pki->publiccert_pem_bytes); + if (ret < 0) { + ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x", -ret); + return ret; + } + + ret = mbedtls_pk_parse_key(pki->pk_key, pki->privkey_pem_buf, pki->privkey_pem_bytes, + NULL, 0); + if (ret < 0) { + ESP_LOGE(TAG, "mbedtls_pk_parse_keyfile returned -0x%x", -ret); + return ret; + } + + ret = mbedtls_ssl_conf_own_cert(&tls->conf, pki->public_cert, pki->pk_key); + if (ret < 0) { + ESP_LOGE(TAG, "mbedtls_ssl_conf_own_cert returned -0x%x", -ret); + return ret; + } + } else { + return ESP_ERR_INVALID_ARG; } - + return 0; +} + +#ifdef CONFIG_ESP_TLS_SERVER +static int set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls) +{ + assert(cfg != NULL); + assert(tls != NULL); + int ret; + if ((ret = mbedtls_ssl_config_defaults(&tls->conf, + MBEDTLS_SSL_IS_SERVER, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned %d", ret); + return ret; + } + +#ifdef CONFIG_MBEDTLS_SSL_ALPN + if (cfg->alpn_protos) { + mbedtls_ssl_conf_alpn_protocols(&tls->conf, cfg->alpn_protos); + } +#endif + + if (cfg->cacert_pem_buf != NULL) { + ret = set_ca_cert(tls, cfg->cacert_pem_buf, cfg->cacert_pem_bytes); + if (ret != 0) { + return ret; + } + } else { + mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_NONE); + } + + if (cfg->servercert_pem_buf != NULL && cfg->serverkey_pem_buf != NULL) { + esp_tls_pki_t pki = { + .public_cert = &tls->servercert, + .pk_key = &tls->serverkey, + .publiccert_pem_buf = cfg->servercert_pem_buf, + .publiccert_pem_bytes = cfg->servercert_pem_bytes, + .privkey_pem_buf = cfg->serverkey_pem_buf, + .privkey_pem_bytes = cfg->serverkey_pem_bytes, + .privkey_password = cfg->serverkey_password, + .privkey_password_len = cfg->serverkey_password_len, + }; + ret = set_pki_context(tls, &pki); + if (ret != 0) { + ESP_LOGE(TAG, "Failed to set server pki context"); + return ret; + } + } else { + ESP_LOGE(TAG, "Missing server certificate and/or key"); + return -1; + } + return 0; +} +#endif /* ! CONFIG_ESP_TLS_SERVER */ + +static int set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t *cfg, esp_tls_t *tls) +{ + assert(cfg != NULL); + assert(tls != NULL); + int ret; if (!cfg->skip_common_name) { char *use_host = NULL; if (cfg->common_name != NULL) { @@ -249,14 +372,13 @@ static int create_ssl_handle(esp_tls_t *tls, const char *hostname, size_t hostle } if (use_host == NULL) { - goto exit; + return -1; } - /* Hostname set here should match CN in server certificate */ if ((ret = mbedtls_ssl_set_hostname(&tls->ssl, use_host)) != 0) { ESP_LOGE(TAG, "mbedtls_ssl_set_hostname returned -0x%x", -ret); free(use_host); - goto exit; + return ret; } free(use_host); } @@ -266,7 +388,7 @@ static int create_ssl_handle(esp_tls_t *tls, const char *hostname, size_t hostle MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned %d", ret); - goto exit; + return ret; } #ifdef CONFIG_MBEDTLS_SSL_ALPN @@ -276,51 +398,72 @@ static int create_ssl_handle(esp_tls_t *tls, const char *hostname, size_t hostle #endif if (cfg->use_global_ca_store == true) { - if (global_cacert == NULL) { - ESP_LOGE(TAG, "global_cacert is NULL"); - goto exit; - } - tls->cacert_ptr = global_cacert; - mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); - mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); - } else if (cfg->cacert_pem_buf != NULL) { - tls->cacert_ptr = &tls->cacert; - mbedtls_x509_crt_init(tls->cacert_ptr); - ret = mbedtls_x509_crt_parse(tls->cacert_ptr, cfg->cacert_pem_buf, cfg->cacert_pem_bytes); + ret = set_global_ca_store(tls); if (ret < 0) { - ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - goto exit; + return ret; + } + } else if (cfg->cacert_pem_buf != NULL) { + ret = set_ca_cert(tls, cfg->cacert_pem_buf, cfg->cacert_pem_bytes); + if (ret < 0) { + return ret; } - mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); - mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); } 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); + esp_tls_pki_t pki = { + .public_cert = &tls->clientcert, + .pk_key = &tls->clientkey, + .publiccert_pem_buf = cfg->clientcert_pem_buf, + .publiccert_pem_bytes = cfg->clientcert_pem_bytes, + .privkey_pem_buf = cfg->clientkey_pem_buf, + .privkey_pem_bytes = cfg->clientkey_pem_bytes, + .privkey_password = cfg->clientkey_password, + .privkey_password_len = cfg->clientkey_password_len, + }; + ret = set_pki_context(tls, &pki); 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; + ESP_LOGE(TAG, "Failed to set server pki context"); + return ret; } } 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"); + ESP_LOGE(TAG, "You have to provide both clientcert_pem_buf and clientkey_pem_buf for mutual authentication"); + return -1; + } + return 0; +} + +static int create_ssl_handle(const char *hostname, size_t hostlen, const void *cfg, esp_tls_t *tls) +{ + assert(cfg != NULL); + assert(tls != NULL); + int ret; + tls->server_fd.fd = tls->sockfd; + mbedtls_ssl_init(&tls->ssl); + mbedtls_ctr_drbg_init(&tls->ctr_drbg); + mbedtls_ssl_config_init(&tls->conf); + mbedtls_entropy_init(&tls->entropy); + + if (tls->role == ESP_TLS_CLIENT) { + ret = set_client_config(hostname, hostlen, (esp_tls_cfg_t *)cfg, tls); + if (ret != 0) { + ESP_LOGE(TAG, "Failed to set client configurations"); + goto exit; + } +#ifdef CONFIG_ESP_TLS_SERVER + } else if (tls->role == ESP_TLS_SERVER) { + ret = set_server_config((esp_tls_cfg_server_t *) cfg, tls); + if (ret != 0) { + ESP_LOGE(TAG, "Failed to set server configurations"); + goto exit; + } +#endif + } + + if ((ret = mbedtls_ctr_drbg_seed(&tls->ctr_drbg, + mbedtls_entropy_func, &tls->entropy, NULL, 0)) != 0) { + ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned %d", ret); goto exit; } @@ -331,7 +474,7 @@ static int create_ssl_handle(esp_tls_t *tls, const char *hostname, size_t hostle #endif if ((ret = mbedtls_ssl_setup(&tls->ssl, &tls->conf)) != 0) { - ESP_LOGE(TAG, "mbedtls_ssl_setup returned -0x%x\n\n", -ret); + ESP_LOGE(TAG, "mbedtls_ssl_setup returned -0x%x", -ret); goto exit; } mbedtls_ssl_set_bio(&tls->ssl, &tls->server_fd, mbedtls_net_send, mbedtls_net_recv, NULL); @@ -339,7 +482,7 @@ static int create_ssl_handle(esp_tls_t *tls, const char *hostname, size_t hostle return 0; exit: mbedtls_cleanup(tls); - return -1; + return ret; } /** @@ -431,7 +574,7 @@ static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, c } } /* By now, the connection has been established */ - ret = create_ssl_handle(tls, hostname, hostlen, cfg); + ret = create_ssl_handle(hostname, hostlen, cfg, tls); if (ret != 0) { ESP_LOGD(TAG, "create_ssl_handshake failed"); tls->conn_state = ESP_TLS_FAIL; @@ -556,3 +699,43 @@ int esp_tls_conn_http_new_async(const char *url, const esp_tls_cfg_t *cfg, esp_t 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); } + +#ifdef CONFIG_ESP_TLS_SERVER +/** + * @brief Create TLS/SSL server session + */ +int esp_tls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp_tls_t *tls) +{ + if (tls == NULL || cfg == NULL) { + return -1; + } + tls->role = ESP_TLS_SERVER; + tls->sockfd = sockfd; + int ret = create_ssl_handle(NULL, 0, cfg, tls); + if (ret != 0) { + ESP_LOGD(TAG, "create_ssl_handle failed"); + tls->conn_state = ESP_TLS_FAIL; + return ret; + } + tls->read = tls_read; + tls->write = tls_write; + while ((ret = mbedtls_ssl_handshake(&tls->ssl)) != 0) { + if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + ESP_LOGE(TAG, "mbedtls_ssl_handshake returned %d", ret); + tls->conn_state = ESP_TLS_FAIL; + return ret; + } + } + return 0; +} +/** + * @brief Close the server side TLS/SSL connection and free any allocated resources. + */ +void esp_tls_server_session_delete(esp_tls_t *tls) +{ + if (tls != NULL) { + mbedtls_cleanup(tls); + free(tls); + } +}; +#endif /* ! CONFIG_ESP_TLS_SERVER */ diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h index 41faa5b0c8..8a76bf2198 100644 --- a/components/esp-tls/esp_tls.h +++ b/components/esp-tls/esp_tls.h @@ -42,6 +42,11 @@ typedef enum esp_tls_conn_state { ESP_TLS_DONE, } esp_tls_conn_state_t; +typedef enum esp_tls_role { + ESP_TLS_CLIENT = 0, + ESP_TLS_SERVER, +} esp_tls_role_t; + /** * @brief ESP-TLS configuration parameters */ @@ -52,9 +57,8 @@ typedef struct esp_tls_cfg { The format is length followed by protocol name. For the most common cases the following is ok: - "\x02h2" - - where the first '2' is the length of the protocol and - - the subsequent 'h2' is the protocol name */ + const char **alpn_protos = { "h2", NULL }; + - where 'h2' is the protocol name */ const unsigned char *cacert_pem_buf; /*!< Certificate Authority's certificate in a buffer. This buffer should be NULL terminated */ @@ -64,7 +68,7 @@ typedef struct esp_tls_cfg { const unsigned char *clientcert_pem_buf;/*!< Client certificate in a buffer This buffer should be NULL terminated */ - + unsigned int clientcert_pem_bytes; /*!< Size of client certificate pointed to by clientcert_pem_buf */ @@ -94,6 +98,43 @@ typedef struct esp_tls_cfg { bool skip_common_name; /*!< Skip any validation of server certificate CN field */ } esp_tls_cfg_t; +#ifdef CONFIG_ESP_TLS_SERVER +typedef struct esp_tls_cfg_server { + const char **alpn_protos; /*!< Application protocols required for HTTP2. + If HTTP2/ALPN support is required, a list + of protocols that should be negotiated. + The format is length followed by protocol + name. + For the most common cases the following is ok: + const char **alpn_protos = { "h2", NULL }; + - where 'h2' is the protocol name */ + + const unsigned char *cacert_pem_buf; /*!< Client CA certificate in a buffer. + This buffer should be NULL terminated */ + + unsigned int cacert_pem_bytes; /*!< Size of client CA certificate + pointed to by cacert_pem_buf */ + + const unsigned char *servercert_pem_buf; /*!< Server certificate in a buffer + This buffer should be NULL terminated */ + + unsigned int servercert_pem_bytes; /*!< Size of server certificate pointed to by + servercert_pem_buf */ + + const unsigned char *serverkey_pem_buf; /*!< Server key in a buffer + This buffer should be NULL terminated */ + + unsigned int serverkey_pem_bytes; /*!< Size of server key pointed to by + serverkey_pem_buf */ + + const unsigned char *serverkey_password; /*!< Server key decryption password string */ + + unsigned int serverkey_password_len; /*!< String length of the password pointed to by + serverkey_password */ + +} esp_tls_cfg_server_t; +#endif /* ! CONFIG_ESP_TLS_SERVER */ + /** * @brief ESP-TLS Connection Handle */ @@ -120,7 +161,12 @@ typedef struct esp_tls { mbedtls_pk_context clientkey; /*!< Container for the private key of the client certificate */ +#ifdef CONFIG_ESP_TLS_SERVER + mbedtls_x509_crt servercert; /*!< Container for the X.509 server certificate */ + mbedtls_pk_context serverkey; /*!< Container for the private key of the server + certificate */ +#endif int sockfd; /*!< Underlying socket file descriptor. */ ssize_t (*read)(struct esp_tls *tls, char *data, size_t datalen); /*!< Callback function for reading data from TLS/SSL @@ -136,6 +182,10 @@ typedef struct esp_tls { fd_set wset; /*!< write file descriptors */ bool is_tls; /*!< indicates connection type (TLS or NON-TLS) */ + + esp_tls_role_t role; /*!< esp-tls role + - ESP_TLS_CLIENT + - ESP_TLS_SERVER */ } esp_tls_t; /** @@ -323,6 +373,33 @@ mbedtls_x509_crt *esp_tls_get_global_ca_store(); */ void esp_tls_free_global_ca_store(); +#ifdef CONFIG_ESP_TLS_SERVER +/** + * @brief Create TLS/SSL server session + * + * This function creates a TLS/SSL server context for already accepted client connection + * and performs TLS/SSL handshake with the client + * + * @param[in] cfg Pointer to esp_tls_cfg_server_t + * @param[in] sockfd FD of accepted connection + * @param[out] tls Pointer to allocated esp_tls_t + * + * @return + * - 0 if successful + * - <0 in case of error + * + */ +int esp_tls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp_tls_t *tls); + +/** + * @brief Close the server side TLS/SSL connection and free any allocated resources. + * + * This function should be called to close each tls connection opened with esp_tls_server_session_create() + * + * @param[in] tls pointer to esp_tls_t + */ +void esp_tls_server_session_delete(esp_tls_t *tls); +#endif /* ! CONFIG_ESP_TLS_SERVER */ #ifdef __cplusplus } From a8ebde227fdc737bdf7ebdcaca003990a14f6789 Mon Sep 17 00:00:00 2001 From: Jitin George Date: Tue, 28 May 2019 16:55:49 +0530 Subject: [PATCH 2/3] esp_https_server: Add support for esp-tls server APIs --- components/esp_https_server/CMakeLists.txt | 12 +- components/esp_https_server/Kconfig | 9 ++ components/esp_https_server/component.mk | 4 + .../esp_https_server/src/https_server.c | 118 +++++++++--------- 4 files changed, 79 insertions(+), 64 deletions(-) create mode 100644 components/esp_https_server/Kconfig diff --git a/components/esp_https_server/CMakeLists.txt b/components/esp_https_server/CMakeLists.txt index c63549b0e2..0eb83865b5 100644 --- a/components/esp_https_server/CMakeLists.txt +++ b/components/esp_https_server/CMakeLists.txt @@ -1,4 +1,10 @@ -idf_component_register(SRCS "src/https_server.c" - INCLUDE_DIRS "include" - REQUIRES esp_http_server openssl +if (CONFIG_ESP_HTTPS_SERVER_ENABLE) + set(src "src/https_server.c") + set(inc "include") +endif() + +idf_component_register(SRCS ${src} + INCLUDE_DIRS ${inc} + REQUIRES esp_http_server esp-tls PRIV_REQUIRES lwip) + diff --git a/components/esp_https_server/Kconfig b/components/esp_https_server/Kconfig new file mode 100644 index 0000000000..e4085539bb --- /dev/null +++ b/components/esp_https_server/Kconfig @@ -0,0 +1,9 @@ +menu "ESP HTTPS server" + + config ESP_HTTPS_SERVER_ENABLE + bool "Enable ESP_HTTPS_SERVER component" + select ESP_TLS_SERVER + help + Enable ESP HTTPS server component + +endmenu diff --git a/components/esp_https_server/component.mk b/components/esp_https_server/component.mk index be1bffc586..c90f6ee255 100644 --- a/components/esp_https_server/component.mk +++ b/components/esp_https_server/component.mk @@ -1,2 +1,6 @@ +ifdef CONFIG_ESP_HTTPS_SERVER_ENABLE COMPONENT_SRCDIRS := src COMPONENT_ADD_INCLUDEDIRS := include +else +COMPONENT_CONFIG_ONLY := 1 +endif diff --git a/components/esp_https_server/src/https_server.c b/components/esp_https_server/src/https_server.c index 4a0d21792f..f012ffec8e 100644 --- a/components/esp_https_server/src/https_server.c +++ b/components/esp_https_server/src/https_server.c @@ -14,9 +14,9 @@ #include #include "esp_https_server.h" -#include "openssl/ssl.h" #include "esp_log.h" #include "sdkconfig.h" +#include "esp_tls.h" const static char *TAG = "esp_https_server"; @@ -28,8 +28,7 @@ const static char *TAG = "esp_https_server"; static void httpd_ssl_close(void *ctx) { assert(ctx != NULL); - SSL_shutdown(ctx); - SSL_free(ctx); + esp_tls_server_session_delete(ctx); ESP_LOGD(TAG, "Secure socket closed"); } @@ -42,9 +41,9 @@ static void httpd_ssl_close(void *ctx) */ static int httpd_ssl_pending(httpd_handle_t server, int sockfd) { - SSL *ssl = httpd_sess_get_transport_ctx(server, sockfd); - assert(ssl != NULL); - return SSL_pending(ssl); + esp_tls_t *tls = httpd_sess_get_transport_ctx(server, sockfd); + assert(tls != NULL); + return esp_tls_get_bytes_avail(tls); } /** @@ -59,9 +58,9 @@ static int httpd_ssl_pending(httpd_handle_t server, int sockfd) */ static int httpd_ssl_recv(httpd_handle_t server, int sockfd, char *buf, size_t buf_len, int flags) { - SSL *ssl = httpd_sess_get_transport_ctx(server, sockfd); - assert(ssl != NULL); - return SSL_read(ssl, buf, buf_len); + esp_tls_t *tls = httpd_sess_get_transport_ctx(server, sockfd); + assert(tls != NULL); + return esp_tls_conn_read(tls, buf, buf_len); } /** @@ -76,9 +75,9 @@ static int httpd_ssl_recv(httpd_handle_t server, int sockfd, char *buf, size_t b */ static int httpd_ssl_send(httpd_handle_t server, int sockfd, const char *buf, size_t buf_len, int flags) { - SSL *ssl = httpd_sess_get_transport_ctx(server, sockfd); - assert(ssl != NULL); - return SSL_write(ssl, buf, buf_len); + esp_tls_t *tls = httpd_sess_get_transport_ctx(server, sockfd); + assert(tls != NULL); + return esp_tls_conn_write(tls, buf, buf_len); } /** @@ -94,28 +93,22 @@ static esp_err_t httpd_ssl_open(httpd_handle_t server, int sockfd) assert(server != NULL); // Retrieve the SSL context from the global context field (set in config) - SSL_CTX *global_ctx = httpd_get_global_transport_ctx(server); + esp_tls_cfg_server_t *global_ctx = httpd_get_global_transport_ctx(server); assert(global_ctx != NULL); - SSL *ssl = SSL_new(global_ctx); - if (NULL == ssl) { - ESP_LOGE(TAG, "SSL_new ret NULL (out of memory)"); + esp_tls_t *tls = (esp_tls_t *)calloc(1, sizeof(esp_tls_t)); + if (!tls) { return ESP_ERR_NO_MEM; } - - if (1 != SSL_set_fd(ssl, sockfd)) { - ESP_LOGE(TAG, "fail to set SSL fd"); - goto teardown; - } - - ESP_LOGD(TAG, "SSL accept"); - if (1 != SSL_accept(ssl)) { - ESP_LOGW(TAG, "fail to SSL_accept - handshake error"); - goto teardown; + ESP_LOGI(TAG, "performing session handshake"); + int ret = esp_tls_server_session_create(global_ctx, sockfd, tls); + if (ret != 0) { + ESP_LOGE(TAG, "esp_tls_create_server_session failed"); + goto fail; } // Store the SSL session into the context field of the HTTPD session object - httpd_sess_set_transport_ctx(server, sockfd, ssl, httpd_ssl_close); + httpd_sess_set_transport_ctx(server, sockfd, tls, httpd_ssl_close); // Set rx/tx/pending override functions httpd_sess_set_send_override(server, sockfd, httpd_ssl_send); @@ -127,9 +120,8 @@ static esp_err_t httpd_ssl_open(httpd_handle_t server, int sockfd) ESP_LOGD(TAG, "Secure socket open"); return ESP_OK; - -teardown: - SSL_free(ssl); +fail: + esp_tls_server_session_delete(tls); return ESP_FAIL; } @@ -141,38 +133,41 @@ teardown: static void free_secure_context(void *ctx) { assert(ctx != NULL); - + esp_tls_cfg_server_t *cfg = (esp_tls_cfg_server_t *)ctx; ESP_LOGI(TAG, "Server shuts down, releasing SSL context"); - SSL_CTX_free(ctx); + if (cfg->servercert_pem_buf) { + free((void *)cfg->servercert_pem_buf); + } + if (cfg->serverkey_pem_buf) { + free((void *)cfg->serverkey_pem_buf); + } + free(cfg); } -/** -* Create and perform basic init of a SSL_CTX, or return NULL on failure -* -* @return ctx or null -*/ -static SSL_CTX *create_secure_context(const struct httpd_ssl_config *config) +static esp_tls_cfg_server_t *create_secure_context(const struct httpd_ssl_config *config) { - SSL_CTX *ctx = NULL; - - ESP_LOGD(TAG, "SSL server context create"); - ctx = SSL_CTX_new(TLS_server_method()); - if (NULL != ctx) { - //region SSL ctx alloc'd - ESP_LOGD(TAG, "SSL ctx set own cert"); - if (SSL_CTX_use_certificate_ASN1(ctx, config->cacert_len, config->cacert_pem) - && SSL_CTX_use_PrivateKey_ASN1(0, ctx, config->prvtkey_pem, (long) config->prvtkey_len)) { - return ctx; - } - else { - ESP_LOGE(TAG, "Failed to set certificate"); - SSL_CTX_free(ctx); - ctx = NULL; - } - } else { - ESP_LOGE(TAG, "Failed to create SSL context"); + esp_tls_cfg_server_t *cfg = (esp_tls_cfg_server_t *)calloc(1, sizeof(esp_tls_cfg_server_t)); + if (!cfg) { + return NULL; } - return NULL; + cfg->servercert_pem_buf = (unsigned char *)malloc(config->cacert_len); + if (!cfg->servercert_pem_buf) { + free(cfg); + return NULL; + } + memcpy((char *)cfg->servercert_pem_buf, config->cacert_pem, config->cacert_len); + cfg->servercert_pem_bytes = config->cacert_len; + + cfg->serverkey_pem_buf = (unsigned char *)malloc(config->prvtkey_len); + if (!cfg->serverkey_pem_buf) { + free((void *)cfg->servercert_pem_buf); + free(cfg); + return NULL; + } + memcpy((char *)cfg->serverkey_pem_buf, config->prvtkey_pem, config->prvtkey_len); + cfg->serverkey_pem_bytes = config->prvtkey_len; + + return cfg; } /** Start the server */ @@ -184,15 +179,16 @@ esp_err_t httpd_ssl_start(httpd_handle_t *pHandle, struct httpd_ssl_config *conf ESP_LOGI(TAG, "Starting server"); if (HTTPD_SSL_TRANSPORT_SECURE == config->transport_mode) { - SSL_CTX *ctx = create_secure_context(config); - if (!ctx) { - return ESP_FAIL; + + esp_tls_cfg_server_t *esp_tls_cfg = create_secure_context(config); + if (!esp_tls_cfg) { + return -1; } ESP_LOGD(TAG, "SSL context ready"); // set SSL specific config - config->httpd.global_transport_ctx = ctx; + config->httpd.global_transport_ctx = esp_tls_cfg; config->httpd.global_transport_ctx_free_fn = free_secure_context; config->httpd.open_fn = httpd_ssl_open; // the open function configures the created SSL sessions From cdecb67d66fea8d26acf6a79bd97a94e24242c03 Mon Sep 17 00:00:00 2001 From: Jitin George Date: Fri, 21 Jun 2019 14:07:51 +0530 Subject: [PATCH 3/3] example/https_server: Add default sdkconfig --- examples/protocols/https_server/sdkconfig.ci | 1 + examples/protocols/https_server/sdkconfig.defaults | 1 + 2 files changed, 2 insertions(+) create mode 100644 examples/protocols/https_server/sdkconfig.ci create mode 100644 examples/protocols/https_server/sdkconfig.defaults diff --git a/examples/protocols/https_server/sdkconfig.ci b/examples/protocols/https_server/sdkconfig.ci new file mode 100644 index 0000000000..a9595bf0c1 --- /dev/null +++ b/examples/protocols/https_server/sdkconfig.ci @@ -0,0 +1 @@ +CONFIG_ESP_HTTPS_SERVER_ENABLE=y diff --git a/examples/protocols/https_server/sdkconfig.defaults b/examples/protocols/https_server/sdkconfig.defaults new file mode 100644 index 0000000000..a9595bf0c1 --- /dev/null +++ b/examples/protocols/https_server/sdkconfig.defaults @@ -0,0 +1 @@ +CONFIG_ESP_HTTPS_SERVER_ENABLE=y