esp_tls.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. // Copyright 2019 Espressif Systems (Shanghai) PTE LTD
  2. //
  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
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <stdlib.h>
  16. #include <unistd.h>
  17. #include <sys/types.h>
  18. #include <sys/socket.h>
  19. #include <netdb.h>
  20. #include <http_parser.h>
  21. #include "esp_tls.h"
  22. #include "esp_tls_error_capture_internal.h"
  23. #include <errno.h>
  24. static const char *TAG = "esp-tls";
  25. #ifdef CONFIG_ESP_TLS_USING_MBEDTLS
  26. #include "esp_tls_mbedtls.h"
  27. #elif CONFIG_ESP_TLS_USING_WOLFSSL
  28. #include "esp_tls_wolfssl.h"
  29. #endif
  30. #ifdef ESP_PLATFORM
  31. #include <esp_log.h>
  32. #else
  33. #define ESP_LOGD(TAG, ...) //printf(__VA_ARGS__);
  34. #define ESP_LOGE(TAG, ...) printf(__VA_ARGS__);
  35. #endif
  36. #ifdef CONFIG_ESP_TLS_USING_MBEDTLS
  37. #define _esp_create_ssl_handle esp_create_mbedtls_handle
  38. #define _esp_tls_handshake esp_mbedtls_handshake
  39. #define _esp_tls_read esp_mbedtls_read
  40. #define _esp_tls_write esp_mbedtls_write
  41. #define _esp_tls_conn_delete esp_mbedtls_conn_delete
  42. #ifdef CONFIG_ESP_TLS_SERVER
  43. #define _esp_tls_server_session_create esp_mbedtls_server_session_create
  44. #define _esp_tls_server_session_delete esp_mbedtls_server_session_delete
  45. #endif /* CONFIG_ESP_TLS_SERVER */
  46. #define _esp_tls_get_bytes_avail esp_mbedtls_get_bytes_avail
  47. #define _esp_tls_init_global_ca_store esp_mbedtls_init_global_ca_store
  48. #define _esp_tls_set_global_ca_store esp_mbedtls_set_global_ca_store /*!< Callback function for setting global CA store data for TLS/SSL */
  49. #define _esp_tls_get_global_ca_store esp_mbedtls_get_global_ca_store
  50. #define _esp_tls_free_global_ca_store esp_mbedtls_free_global_ca_store /*!< Callback function for freeing global ca store for TLS/SSL */
  51. #elif CONFIG_ESP_TLS_USING_WOLFSSL /* CONFIG_ESP_TLS_USING_MBEDTLS */
  52. #define _esp_create_ssl_handle esp_create_wolfssl_handle
  53. #define _esp_tls_handshake esp_wolfssl_handshake
  54. #define _esp_tls_read esp_wolfssl_read
  55. #define _esp_tls_write esp_wolfssl_write
  56. #define _esp_tls_conn_delete esp_wolfssl_conn_delete
  57. #ifdef CONFIG_ESP_TLS_SERVER
  58. #define _esp_tls_server_session_create esp_wolfssl_server_session_create
  59. #define _esp_tls_server_session_delete esp_wolfssl_server_session_delete
  60. #endif /* CONFIG_ESP_TLS_SERVER */
  61. #define _esp_tls_get_bytes_avail esp_wolfssl_get_bytes_avail
  62. #define _esp_tls_init_global_ca_store esp_wolfssl_init_global_ca_store
  63. #define _esp_tls_set_global_ca_store esp_wolfssl_set_global_ca_store /*!< Callback function for setting global CA store data for TLS/SSL */
  64. #define _esp_tls_free_global_ca_store esp_wolfssl_free_global_ca_store /*!< Callback function for freeing global ca store for TLS/SSL */
  65. #else /* ESP_TLS_USING_WOLFSSL */
  66. #error "No TLS stack configured"
  67. #endif
  68. static esp_err_t create_ssl_handle(const char *hostname, size_t hostlen, const void *cfg, esp_tls_t *tls)
  69. {
  70. return _esp_create_ssl_handle(hostname, hostlen, cfg, tls);
  71. }
  72. static esp_err_t esp_tls_handshake(esp_tls_t *tls, const esp_tls_cfg_t *cfg)
  73. {
  74. return _esp_tls_handshake(tls, cfg);
  75. }
  76. static ssize_t tcp_read(esp_tls_t *tls, char *data, size_t datalen)
  77. {
  78. return recv(tls->sockfd, data, datalen, 0);
  79. }
  80. static ssize_t tcp_write(esp_tls_t *tls, const char *data, size_t datalen)
  81. {
  82. return send(tls->sockfd, data, datalen, 0);
  83. }
  84. /**
  85. * @brief Close the TLS connection and free any allocated resources.
  86. */
  87. void esp_tls_conn_delete(esp_tls_t *tls)
  88. {
  89. esp_tls_conn_destroy(tls);
  90. }
  91. int esp_tls_conn_destroy(esp_tls_t *tls)
  92. {
  93. if (tls != NULL) {
  94. int ret = 0;
  95. _esp_tls_conn_delete(tls);
  96. if (tls->sockfd >= 0) {
  97. ret = close(tls->sockfd);
  98. }
  99. esp_tls_internal_event_tracker_destroy(tls->error_handle);
  100. free(tls);
  101. return ret;
  102. }
  103. return -1; // invalid argument
  104. }
  105. esp_tls_t *esp_tls_init(void)
  106. {
  107. esp_tls_t *tls = (esp_tls_t *)calloc(1, sizeof(esp_tls_t));
  108. if (!tls) {
  109. return NULL;
  110. }
  111. tls->error_handle = esp_tls_internal_event_tracker_create();
  112. if (!tls->error_handle) {
  113. free(tls);
  114. return NULL;
  115. }
  116. #ifdef CONFIG_ESP_TLS_USING_MBEDTLS
  117. tls->server_fd.fd = -1;
  118. #endif
  119. tls->sockfd = -1;
  120. return tls;
  121. }
  122. static esp_err_t resolve_host_name(const char *host, size_t hostlen, struct addrinfo **address_info)
  123. {
  124. struct addrinfo hints;
  125. memset(&hints, 0, sizeof(hints));
  126. hints.ai_family = AF_UNSPEC;
  127. hints.ai_socktype = SOCK_STREAM;
  128. char *use_host = strndup(host, hostlen);
  129. if (!use_host) {
  130. return ESP_ERR_NO_MEM;
  131. }
  132. ESP_LOGD(TAG, "host:%s: strlen %lu", use_host, (unsigned long)hostlen);
  133. if (getaddrinfo(use_host, NULL, &hints, address_info)) {
  134. ESP_LOGE(TAG, "couldn't get hostname for :%s:", use_host);
  135. free(use_host);
  136. return ESP_ERR_ESP_TLS_CANNOT_RESOLVE_HOSTNAME;
  137. }
  138. free(use_host);
  139. return ESP_OK;
  140. }
  141. static void ms_to_timeval(int timeout_ms, struct timeval *tv)
  142. {
  143. tv->tv_sec = timeout_ms / 1000;
  144. tv->tv_usec = (timeout_ms % 1000) * 1000;
  145. }
  146. static int esp_tls_tcp_enable_keep_alive(int fd, tls_keep_alive_cfg_t *cfg)
  147. {
  148. int keep_alive_enable = 1;
  149. int keep_alive_idle = cfg->keep_alive_idle;
  150. int keep_alive_interval = cfg->keep_alive_interval;
  151. int keep_alive_count = cfg->keep_alive_count;
  152. ESP_LOGD(TAG, "Enable TCP keep alive. idle: %d, interval: %d, count: %d", keep_alive_idle, keep_alive_interval, keep_alive_count);
  153. if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keep_alive_enable, sizeof(keep_alive_enable)) != 0) {
  154. ESP_LOGE(TAG, "Fail to setsockopt SO_KEEPALIVE");
  155. return -1;
  156. }
  157. if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &keep_alive_idle, sizeof(keep_alive_idle)) != 0) {
  158. ESP_LOGE(TAG, "Fail to setsockopt TCP_KEEPIDLE");
  159. return -1;
  160. }
  161. if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &keep_alive_interval, sizeof(keep_alive_interval)) != 0) {
  162. ESP_LOGE(TAG, "Fail to setsockopt TCP_KEEPINTVL");
  163. return -1;
  164. }
  165. if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &keep_alive_count, sizeof(keep_alive_count)) != 0) {
  166. ESP_LOGE(TAG, "Fail to setsockopt TCP_KEEPCNT");
  167. return -1;
  168. }
  169. return 0;
  170. }
  171. static esp_err_t esp_tcp_connect(const char *host, int hostlen, int port, int *sockfd, const esp_tls_t *tls, const esp_tls_cfg_t *cfg)
  172. {
  173. esp_err_t ret;
  174. struct addrinfo *addrinfo;
  175. if ((ret = resolve_host_name(host, hostlen, &addrinfo)) != ESP_OK) {
  176. return ret;
  177. }
  178. int fd = socket(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol);
  179. if (fd < 0) {
  180. ESP_LOGE(TAG, "Failed to create socket (family %d socktype %d protocol %d)", addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol);
  181. ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_SYSTEM, errno);
  182. ret = ESP_ERR_ESP_TLS_CANNOT_CREATE_SOCKET;
  183. goto err_freeaddr;
  184. }
  185. void *addr_ptr;
  186. if (addrinfo->ai_family == AF_INET) {
  187. struct sockaddr_in *p = (struct sockaddr_in *)addrinfo->ai_addr;
  188. p->sin_port = htons(port);
  189. addr_ptr = p;
  190. }
  191. #if CONFIG_LWIP_IPV6
  192. else if (addrinfo->ai_family == AF_INET6) {
  193. struct sockaddr_in6 *p = (struct sockaddr_in6 *)addrinfo->ai_addr;
  194. p->sin6_port = htons(port);
  195. p->sin6_family = AF_INET6;
  196. addr_ptr = p;
  197. }
  198. #endif
  199. else {
  200. ESP_LOGE(TAG, "Unsupported protocol family %d", addrinfo->ai_family);
  201. ret = ESP_ERR_ESP_TLS_UNSUPPORTED_PROTOCOL_FAMILY;
  202. goto err_freesocket;
  203. }
  204. if (cfg) {
  205. if (cfg->timeout_ms >= 0) {
  206. struct timeval tv;
  207. ms_to_timeval(cfg->timeout_ms, &tv);
  208. setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
  209. setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
  210. if (cfg->keep_alive_cfg && cfg->keep_alive_cfg->keep_alive_enable) {
  211. if (esp_tls_tcp_enable_keep_alive(fd, cfg->keep_alive_cfg) < 0) {
  212. ESP_LOGE(TAG, "Error setting keep-alive");
  213. goto err_freesocket;
  214. }
  215. }
  216. }
  217. if (cfg->non_block) {
  218. int flags = fcntl(fd, F_GETFL, 0);
  219. ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
  220. if (ret < 0) {
  221. ESP_LOGE(TAG, "Failed to configure the socket as non-blocking (errno %d)", errno);
  222. goto err_freesocket;
  223. }
  224. }
  225. }
  226. ret = connect(fd, addr_ptr, addrinfo->ai_addrlen);
  227. if (ret < 0 && !(errno == EINPROGRESS && cfg && cfg->non_block)) {
  228. ESP_LOGE(TAG, "Failed to connnect to host (errno %d)", errno);
  229. ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_SYSTEM, errno);
  230. ret = ESP_ERR_ESP_TLS_FAILED_CONNECT_TO_HOST;
  231. goto err_freesocket;
  232. }
  233. *sockfd = fd;
  234. freeaddrinfo(addrinfo);
  235. return ESP_OK;
  236. err_freesocket:
  237. close(fd);
  238. err_freeaddr:
  239. freeaddrinfo(addrinfo);
  240. return ret;
  241. }
  242. static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_t *tls)
  243. {
  244. if (!tls) {
  245. ESP_LOGE(TAG, "empty esp_tls parameter");
  246. return -1;
  247. }
  248. esp_err_t esp_ret;
  249. /* These states are used to keep a tab on connection progress in case of non-blocking connect,
  250. and in case of blocking connect these cases will get executed one after the other */
  251. switch (tls->conn_state) {
  252. case ESP_TLS_INIT:
  253. tls->sockfd = -1;
  254. if (cfg != NULL) {
  255. #ifdef CONFIG_ESP_TLS_USING_MBEDTLS
  256. mbedtls_net_init(&tls->server_fd);
  257. #endif
  258. tls->is_tls = true;
  259. }
  260. if ((esp_ret = esp_tcp_connect(hostname, hostlen, port, &tls->sockfd, tls, cfg)) != ESP_OK) {
  261. ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, esp_ret);
  262. return -1;
  263. }
  264. if (!cfg) {
  265. tls->read = tcp_read;
  266. tls->write = tcp_write;
  267. ESP_LOGD(TAG, "non-tls connection established");
  268. return 1;
  269. }
  270. if (cfg->non_block) {
  271. FD_ZERO(&tls->rset);
  272. FD_SET(tls->sockfd, &tls->rset);
  273. tls->wset = tls->rset;
  274. }
  275. tls->conn_state = ESP_TLS_CONNECTING;
  276. /* falls through */
  277. case ESP_TLS_CONNECTING:
  278. if (cfg->non_block) {
  279. ESP_LOGD(TAG, "connecting...");
  280. struct timeval tv;
  281. ms_to_timeval(cfg->timeout_ms, &tv);
  282. /* In case of non-blocking I/O, we use the select() API to check whether
  283. connection has been established or not*/
  284. if (select(tls->sockfd + 1, &tls->rset, &tls->wset, NULL,
  285. cfg->timeout_ms>0 ? &tv : NULL) == 0) {
  286. ESP_LOGD(TAG, "select() timed out");
  287. return 0;
  288. }
  289. if (FD_ISSET(tls->sockfd, &tls->rset) || FD_ISSET(tls->sockfd, &tls->wset)) {
  290. int error;
  291. socklen_t len = sizeof(error);
  292. /* pending error check */
  293. if (getsockopt(tls->sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
  294. ESP_LOGD(TAG, "Non blocking connect failed");
  295. ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_SYSTEM, errno);
  296. ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED);
  297. tls->conn_state = ESP_TLS_FAIL;
  298. return -1;
  299. }
  300. }
  301. }
  302. /* By now, the connection has been established */
  303. esp_ret = create_ssl_handle(hostname, hostlen, cfg, tls);
  304. if (esp_ret != ESP_OK) {
  305. ESP_LOGE(TAG, "create_ssl_handle failed");
  306. ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, esp_ret);
  307. tls->conn_state = ESP_TLS_FAIL;
  308. return -1;
  309. }
  310. tls->read = _esp_tls_read;
  311. tls->write = _esp_tls_write;
  312. tls->conn_state = ESP_TLS_HANDSHAKE;
  313. /* falls through */
  314. case ESP_TLS_HANDSHAKE:
  315. ESP_LOGD(TAG, "handshake in progress...");
  316. return esp_tls_handshake(tls, cfg);
  317. break;
  318. case ESP_TLS_FAIL:
  319. ESP_LOGE(TAG, "failed to open a new connection");;
  320. break;
  321. default:
  322. ESP_LOGE(TAG, "invalid esp-tls state");
  323. break;
  324. }
  325. return -1;
  326. }
  327. /**
  328. * @brief Create a new TLS/SSL connection
  329. */
  330. esp_tls_t *esp_tls_conn_new(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg)
  331. {
  332. esp_tls_t *tls = esp_tls_init();
  333. if (!tls) {
  334. return NULL;
  335. }
  336. /* esp_tls_conn_new() API establishes connection in a blocking manner thus this loop ensures that esp_tls_conn_new()
  337. API returns only after connection is established unless there is an error*/
  338. size_t start = xTaskGetTickCount();
  339. while (1) {
  340. int ret = esp_tls_low_level_conn(hostname, hostlen, port, cfg, tls);
  341. if (ret == 1) {
  342. return tls;
  343. } else if (ret == -1) {
  344. esp_tls_conn_delete(tls);
  345. ESP_LOGE(TAG, "Failed to open new connection");
  346. return NULL;
  347. } else if (ret == 0 && cfg->timeout_ms >= 0) {
  348. size_t timeout_ticks = pdMS_TO_TICKS(cfg->timeout_ms);
  349. uint32_t expired = xTaskGetTickCount() - start;
  350. if (expired >= timeout_ticks) {
  351. esp_tls_conn_delete(tls);
  352. ESP_LOGE(TAG, "Failed to open new connection in specified timeout");
  353. return NULL;
  354. }
  355. }
  356. }
  357. return NULL;
  358. }
  359. int esp_tls_conn_new_sync(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_t *tls)
  360. {
  361. /* esp_tls_conn_new_sync() is a sync alternative to esp_tls_conn_new_async() with symmetric function prototype
  362. it is an alternative to esp_tls_conn_new() which is left for compatibility reasons */
  363. size_t start = xTaskGetTickCount();
  364. while (1) {
  365. int ret = esp_tls_low_level_conn(hostname, hostlen, port, cfg, tls);
  366. if (ret == 1) {
  367. return ret;
  368. } else if (ret == -1) {
  369. ESP_LOGE(TAG, "Failed to open new connection");
  370. return -1;
  371. } else if (ret == 0 && cfg->timeout_ms >= 0) {
  372. size_t timeout_ticks = pdMS_TO_TICKS(cfg->timeout_ms);
  373. uint32_t expired = xTaskGetTickCount() - start;
  374. if (expired >= timeout_ticks) {
  375. ESP_LOGW(TAG, "Failed to open new connection in specified timeout");
  376. ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT);
  377. return 0;
  378. }
  379. }
  380. }
  381. return 0;
  382. }
  383. /*
  384. * @brief Create a new TLS/SSL non-blocking connection
  385. */
  386. int esp_tls_conn_new_async(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_t *tls)
  387. {
  388. return esp_tls_low_level_conn(hostname, hostlen, port, cfg, tls);
  389. }
  390. static int get_port(const char *url, struct http_parser_url *u)
  391. {
  392. if (u->field_data[UF_PORT].len) {
  393. return strtol(&url[u->field_data[UF_PORT].off], NULL, 10);
  394. } else {
  395. if (strncasecmp(&url[u->field_data[UF_SCHEMA].off], "http", u->field_data[UF_SCHEMA].len) == 0) {
  396. return 80;
  397. } else if (strncasecmp(&url[u->field_data[UF_SCHEMA].off], "https", u->field_data[UF_SCHEMA].len) == 0) {
  398. return 443;
  399. }
  400. }
  401. return 0;
  402. }
  403. /**
  404. * @brief Create a new TLS/SSL connection with a given "HTTP" url
  405. */
  406. esp_tls_t *esp_tls_conn_http_new(const char *url, const esp_tls_cfg_t *cfg)
  407. {
  408. /* Parse URI */
  409. struct http_parser_url u;
  410. http_parser_url_init(&u);
  411. http_parser_parse_url(url, strlen(url), 0, &u);
  412. esp_tls_t *tls = esp_tls_init();
  413. if (!tls) {
  414. return NULL;
  415. }
  416. /* Connect to host */
  417. if (esp_tls_conn_new_sync(&url[u.field_data[UF_HOST].off], u.field_data[UF_HOST].len,
  418. get_port(url, &u), cfg, tls) == 1) {
  419. return tls;
  420. }
  421. esp_tls_conn_delete(tls);
  422. return NULL;
  423. }
  424. /**
  425. * @brief Create a new non-blocking TLS/SSL connection with a given "HTTP" url
  426. */
  427. int esp_tls_conn_http_new_async(const char *url, const esp_tls_cfg_t *cfg, esp_tls_t *tls)
  428. {
  429. /* Parse URI */
  430. struct http_parser_url u;
  431. http_parser_url_init(&u);
  432. http_parser_parse_url(url, strlen(url), 0, &u);
  433. /* Connect to host */
  434. return esp_tls_conn_new_async(&url[u.field_data[UF_HOST].off], u.field_data[UF_HOST].len,
  435. get_port(url, &u), cfg, tls);
  436. }
  437. #ifdef CONFIG_ESP_TLS_USING_MBEDTLS
  438. mbedtls_x509_crt *esp_tls_get_global_ca_store(void)
  439. {
  440. return _esp_tls_get_global_ca_store();
  441. }
  442. #endif /* CONFIG_ESP_TLS_USING_MBEDTLS */
  443. #ifdef CONFIG_ESP_TLS_SERVER
  444. /**
  445. * @brief Create a server side TLS/SSL connection
  446. */
  447. int esp_tls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp_tls_t *tls)
  448. {
  449. return _esp_tls_server_session_create(cfg, sockfd, tls);
  450. }
  451. /**
  452. * @brief Close the server side TLS/SSL connection and free any allocated resources.
  453. */
  454. void esp_tls_server_session_delete(esp_tls_t *tls)
  455. {
  456. return _esp_tls_server_session_delete(tls);
  457. }
  458. #endif /* CONFIG_ESP_TLS_SERVER */
  459. ssize_t esp_tls_get_bytes_avail(esp_tls_t *tls)
  460. {
  461. return _esp_tls_get_bytes_avail(tls);
  462. }
  463. esp_err_t esp_tls_get_conn_sockfd(esp_tls_t *tls, int *sockfd)
  464. {
  465. if (!tls || !sockfd) {
  466. ESP_LOGE(TAG, "Invalid arguments passed");
  467. return ESP_ERR_INVALID_ARG;
  468. }
  469. *sockfd = tls->sockfd;
  470. return ESP_OK;
  471. }
  472. esp_err_t esp_tls_get_and_clear_last_error(esp_tls_error_handle_t h, int *esp_tls_code, int *esp_tls_flags)
  473. {
  474. if (!h) {
  475. return ESP_ERR_INVALID_STATE;
  476. }
  477. esp_err_t last_err = h->last_error;
  478. if (esp_tls_code) {
  479. *esp_tls_code = h->esp_tls_error_code;
  480. }
  481. if (esp_tls_flags) {
  482. *esp_tls_flags = h->esp_tls_flags;
  483. }
  484. memset(h, 0, sizeof(esp_tls_last_error_t));
  485. return last_err;
  486. }
  487. esp_err_t esp_tls_init_global_ca_store(void)
  488. {
  489. return _esp_tls_init_global_ca_store();
  490. }
  491. esp_err_t esp_tls_set_global_ca_store(const unsigned char *cacert_pem_buf, const unsigned int cacert_pem_bytes)
  492. {
  493. return _esp_tls_set_global_ca_store(cacert_pem_buf, cacert_pem_bytes);
  494. }
  495. void esp_tls_free_global_ca_store(void)
  496. {
  497. return _esp_tls_free_global_ca_store();
  498. }