1 // Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
18 #include "freertos/FreeRTOS.h"
19 #include "freertos/task.h"
22 #include "esp_system.h"
24 #include "esp_transport.h"
25 #include "esp_transport_ssl.h"
26 #include "esp_transport_utils.h"
27 #include "esp_transport_ssl_internal.h"
29 static const char *TAG = "TRANS_SSL";
34 } transport_ssl_conn_state_t;
37 * mbedtls specific transport data
43 transport_ssl_conn_state_t conn_state;
46 static int ssl_close(esp_transport_handle_t t);
48 static int ssl_connect_async(esp_transport_handle_t t, const char *host, int port, int timeout_ms)
50 transport_ssl_t *ssl = esp_transport_get_context_data(t);
51 if (ssl->conn_state == TRANS_SSL_INIT) {
52 ssl->cfg.timeout_ms = timeout_ms;
53 ssl->cfg.non_block = true;
54 ssl->ssl_initialized = true;
55 ssl->tls = esp_tls_init();
59 ssl->conn_state = TRANS_SSL_CONNECTING;
61 if (ssl->conn_state == TRANS_SSL_CONNECTING) {
62 return esp_tls_conn_new_async(host, strlen(host), port, &ssl->cfg, ssl->tls);
67 static int ssl_connect(esp_transport_handle_t t, const char *host, int port, int timeout_ms)
69 transport_ssl_t *ssl = esp_transport_get_context_data(t);
71 ssl->cfg.timeout_ms = timeout_ms;
72 ssl->ssl_initialized = true;
73 ssl->tls = esp_tls_init();
74 if (esp_tls_conn_new_sync(host, strlen(host), port, &ssl->cfg, ssl->tls) < 0) {
75 ESP_LOGE(TAG, "Failed to open a new connection");
76 esp_transport_set_errors(t, ssl->tls->error_handle);
77 esp_tls_conn_delete(ssl->tls);
85 static int ssl_poll_read(esp_transport_handle_t t, int timeout_ms)
87 transport_ssl_t *ssl = esp_transport_get_context_data(t);
93 FD_SET(ssl->tls->sockfd, &readset);
94 FD_SET(ssl->tls->sockfd, &errset);
95 struct timeval timeout;
96 esp_transport_utils_ms_to_timeval(timeout_ms, &timeout);
98 ret = select(ssl->tls->sockfd + 1, &readset, NULL, &errset, &timeout);
99 if (ret > 0 && FD_ISSET(ssl->tls->sockfd, &errset)) {
101 uint32_t optlen = sizeof(sock_errno);
102 getsockopt(ssl->tls->sockfd, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen);
103 ESP_LOGE(TAG, "ssl_poll_read select error %d, errno = %s, fd = %d", sock_errno, strerror(sock_errno), ssl->tls->sockfd);
109 static int ssl_poll_write(esp_transport_handle_t t, int timeout_ms)
111 transport_ssl_t *ssl = esp_transport_get_context_data(t);
117 FD_SET(ssl->tls->sockfd, &writeset);
118 FD_SET(ssl->tls->sockfd, &errset);
119 struct timeval timeout;
120 esp_transport_utils_ms_to_timeval(timeout_ms, &timeout);
121 ret = select(ssl->tls->sockfd + 1, NULL, &writeset, &errset, &timeout);
122 if (ret > 0 && FD_ISSET(ssl->tls->sockfd, &errset)) {
124 uint32_t optlen = sizeof(sock_errno);
125 getsockopt(ssl->tls->sockfd, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen);
126 ESP_LOGE(TAG, "ssl_poll_write select error %d, errno = %s, fd = %d", sock_errno, strerror(sock_errno), ssl->tls->sockfd);
132 static int ssl_write(esp_transport_handle_t t, const char *buffer, int len, int timeout_ms)
135 transport_ssl_t *ssl = esp_transport_get_context_data(t);
137 if ((poll = esp_transport_poll_write(t, timeout_ms)) <= 0) {
138 ESP_LOGW(TAG, "Poll timeout or error, errno=%s, fd=%d, timeout_ms=%d", strerror(errno), ssl->tls->sockfd, timeout_ms);
141 ret = esp_tls_conn_write(ssl->tls, (const unsigned char *) buffer, len);
143 ESP_LOGE(TAG, "esp_tls_conn_write error, errno=%s", strerror(errno));
144 esp_transport_set_errors(t, ssl->tls->error_handle);
149 static int ssl_read(esp_transport_handle_t t, char *buffer, int len, int timeout_ms)
152 transport_ssl_t *ssl = esp_transport_get_context_data(t);
154 if (esp_tls_get_bytes_avail(ssl->tls) <= 0) {
155 if ((poll = esp_transport_poll_read(t, timeout_ms)) <= 0) {
159 ret = esp_tls_conn_read(ssl->tls, (unsigned char *)buffer, len);
161 ESP_LOGE(TAG, "esp_tls_conn_read error, errno=%s", strerror(errno));
162 esp_transport_set_errors(t, ssl->tls->error_handle);
170 static int ssl_close(esp_transport_handle_t t)
173 transport_ssl_t *ssl = esp_transport_get_context_data(t);
174 if (ssl->ssl_initialized) {
175 esp_tls_conn_delete(ssl->tls);
176 ssl->ssl_initialized = false;
181 static int ssl_destroy(esp_transport_handle_t t)
183 transport_ssl_t *ssl = esp_transport_get_context_data(t);
184 esp_transport_close(t);
189 void esp_transport_ssl_enable_global_ca_store(esp_transport_handle_t t)
191 transport_ssl_t *ssl = esp_transport_get_context_data(t);
193 ssl->cfg.use_global_ca_store = true;
197 void esp_transport_ssl_set_psk_key_hint(esp_transport_handle_t t, const psk_hint_key_t* psk_hint_key)
199 transport_ssl_t *ssl = esp_transport_get_context_data(t);
201 ssl->cfg.psk_hint_key = psk_hint_key;
205 void esp_transport_ssl_set_cert_data(esp_transport_handle_t t, const char *data, int len)
207 transport_ssl_t *ssl = esp_transport_get_context_data(t);
209 ssl->cfg.cacert_pem_buf = (void *)data;
210 ssl->cfg.cacert_pem_bytes = len + 1;
214 void esp_transport_ssl_set_cert_data_der(esp_transport_handle_t t, const char *data, int len)
216 transport_ssl_t *ssl = esp_transport_get_context_data(t);
218 ssl->cfg.cacert_buf = (void *)data;
219 ssl->cfg.cacert_bytes = len;
223 void esp_transport_ssl_set_client_cert_data(esp_transport_handle_t t, const char *data, int len)
225 transport_ssl_t *ssl = esp_transport_get_context_data(t);
227 ssl->cfg.clientcert_pem_buf = (void *)data;
228 ssl->cfg.clientcert_pem_bytes = len + 1;
232 void esp_transport_ssl_set_client_cert_data_der(esp_transport_handle_t t, const char *data, int len)
234 transport_ssl_t *ssl = esp_transport_get_context_data(t);
236 ssl->cfg.clientcert_buf = (void *)data;
237 ssl->cfg.clientcert_bytes = len;
241 void esp_transport_ssl_set_client_key_data(esp_transport_handle_t t, const char *data, int len)
243 transport_ssl_t *ssl = esp_transport_get_context_data(t);
245 ssl->cfg.clientkey_pem_buf = (void *)data;
246 ssl->cfg.clientkey_pem_bytes = len + 1;
250 void esp_transport_ssl_set_client_key_data_der(esp_transport_handle_t t, const char *data, int len)
252 transport_ssl_t *ssl = esp_transport_get_context_data(t);
254 ssl->cfg.clientkey_buf = (void *)data;
255 ssl->cfg.clientkey_bytes = len;
259 void esp_transport_ssl_skip_common_name_check(esp_transport_handle_t t)
261 transport_ssl_t *ssl = esp_transport_get_context_data(t);
263 ssl->cfg.skip_common_name = true;
267 esp_transport_handle_t esp_transport_ssl_init(void)
269 esp_transport_handle_t t = esp_transport_init();
270 transport_ssl_t *ssl = calloc(1, sizeof(transport_ssl_t));
271 ESP_TRANSPORT_MEM_CHECK(TAG, ssl, return NULL);
272 esp_transport_set_context_data(t, ssl);
273 esp_transport_set_func(t, ssl_connect, ssl_read, ssl_write, ssl_close, ssl_poll_read, ssl_poll_write, ssl_destroy);
274 esp_transport_set_async_connect_func(t, ssl_connect_async);