From 1c72c8d1260036cfd35a1827cf6b2101068ed6bd Mon Sep 17 00:00:00 2001 From: Kedar Sovani Date: Thu, 30 Nov 2017 11:35:34 +0530 Subject: [PATCH] Supports TLS with HTTP2 client --- components/esp-tls/esp-tls.c | 19 +++++++++++++++---- components/esp-tls/esp-tls.h | 28 +++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/components/esp-tls/esp-tls.c b/components/esp-tls/esp-tls.c index 9906fdbf7..59ccd1a81 100644 --- a/components/esp-tls/esp-tls.c +++ b/components/esp-tls/esp-tls.c @@ -95,7 +95,7 @@ err_freeaddr: return -1; } -static int create_ssl_handle(struct esp_tls *tls) +static int create_ssl_handle(struct esp_tls *tls, const char *hostname, size_t hostlen, struct esp_tls_cfg *cfg) { int ret; @@ -108,12 +108,23 @@ static int create_ssl_handle(struct esp_tls *tls) SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY); SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS); #endif + if (cfg->alpn_protos) { + SSL_CTX_set_alpn_protos(ssl_ctx, cfg->alpn_protos, strlen((char *)cfg->alpn_protos)); + } SSL *ssl = SSL_new(ssl_ctx); if (!ssl) { SSL_CTX_free(ssl_ctx); return -1; } + char *use_host = strndup(hostname, hostlen); + if (!use_host) { + SSL_CTX_free(ssl_ctx); + return -1; + } + SSL_set_tlsext_host_name(ssl, use_host); + free(use_host); + SSL_set_fd(ssl, tls->sockfd); ret = SSL_connect(ssl); if (ret < 1) { @@ -155,7 +166,7 @@ static ssize_t tls_write(struct esp_tls *tls, const char *data, size_t datalen) return SSL_write(tls->ssl, data, datalen); } -struct esp_tls *esp_tls_conn_new(const char *hostname, int hostlen, int port, bool is_tls) +struct esp_tls *esp_tls_conn_new(const char *hostname, int hostlen, int port, struct esp_tls_cfg *cfg) { int sockfd = esp_tcp_connect(hostname, hostlen, port); if (sockfd < 0) { @@ -171,8 +182,8 @@ struct esp_tls *esp_tls_conn_new(const char *hostname, int hostlen, int port, bo tls->read = tcp_read; tls->write = tcp_write; - if (is_tls) { - if (create_ssl_handle(tls) != 0) { + if (cfg) { + if (create_ssl_handle(tls, hostname, hostlen, cfg) != 0) { esp_tls_conn_delete(tls); return NULL; } diff --git a/components/esp-tls/esp-tls.h b/components/esp-tls/esp-tls.h index bff2eda4d..08cc63cf2 100644 --- a/components/esp-tls/esp-tls.h +++ b/components/esp-tls/esp-tls.h @@ -5,6 +5,22 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + +struct esp_tls_cfg { + /* 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: + * "\x02h2" + * - where the first '2' is the length of the protocol and + * - the subsequent 'h2' is the protocol name + */ + const unsigned char *alpn_protos; +}; + struct esp_tls { SSL_CTX *ctx; SSL *ssl; @@ -13,7 +29,13 @@ struct esp_tls { ssize_t (*write)(struct esp_tls *tls, const char *data, size_t datalen); }; -struct esp_tls *esp_tls_conn_new(const char *hostname, int hostlen, int port, bool is_tls); +/* + * + * cfg: If you wish to open non-TLS connection, keep this NULL. For TLS + * connection, a pass pointer to 'struct esp_tls_cfg'. At a minimum, this + * structure should be zero-initialized. + */ +struct esp_tls *esp_tls_conn_new(const char *hostname, int hostlen, int port, struct esp_tls_cfg *cfg); static inline ssize_t esp_tls_conn_write(struct esp_tls *tls, const char *data, size_t datalen) { @@ -27,4 +49,8 @@ static inline ssize_t esp_tls_conn_read(struct esp_tls *tls, char *data, size_t void esp_tls_conn_delete(struct esp_tls *tls); +#ifdef __cplusplus +} +#endif + #endif /* ! _ESP_TLS_H_ */