esp_tls.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  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. free(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 = calloc(1, sizeof(esp_tls_last_error_t));
  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, 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. } else if (addrinfo->ai_family == AF_INET6) {
  191. struct sockaddr_in6 *p = (struct sockaddr_in6 *)addrinfo->ai_addr;
  192. p->sin6_port = htons(port);
  193. p->sin6_family = AF_INET6;
  194. addr_ptr = p;
  195. } else {
  196. ESP_LOGE(TAG, "Unsupported protocol family %d", addrinfo->ai_family);
  197. ret = ESP_ERR_ESP_TLS_UNSUPPORTED_PROTOCOL_FAMILY;
  198. goto err_freesocket;
  199. }
  200. if (cfg) {
  201. if (cfg->timeout_ms >= 0) {
  202. struct timeval tv;
  203. ms_to_timeval(cfg->timeout_ms, &tv);
  204. setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
  205. setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
  206. if (cfg->keep_alive_cfg && cfg->keep_alive_cfg->keep_alive_enable) {
  207. if (esp_tls_tcp_enable_keep_alive(fd, cfg->keep_alive_cfg) < 0) {
  208. ESP_LOGE(TAG, "Error setting keep-alive");
  209. goto err_freesocket;
  210. }
  211. }
  212. }
  213. if (cfg->non_block) {
  214. int flags = fcntl(fd, F_GETFL, 0);
  215. ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
  216. if (ret < 0) {
  217. ESP_LOGE(TAG, "Failed to configure the socket as non-blocking (errno %d)", errno);
  218. goto err_freesocket;
  219. }
  220. }
  221. }
  222. ret = connect(fd, addr_ptr, addrinfo->ai_addrlen);
  223. if (ret < 0 && !(errno == EINPROGRESS && cfg && cfg->non_block)) {
  224. ESP_LOGE(TAG, "Failed to connnect to host (errno %d)", errno);
  225. ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_SYSTEM, errno);
  226. ret = ESP_ERR_ESP_TLS_FAILED_CONNECT_TO_HOST;
  227. goto err_freesocket;
  228. }
  229. *sockfd = fd;
  230. freeaddrinfo(addrinfo);
  231. return ESP_OK;
  232. err_freesocket:
  233. close(fd);
  234. err_freeaddr:
  235. freeaddrinfo(addrinfo);
  236. return ret;
  237. }
  238. static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_t *tls)
  239. {
  240. if (!tls) {
  241. ESP_LOGE(TAG, "empty esp_tls parameter");
  242. return -1;
  243. }
  244. esp_err_t esp_ret;
  245. /* These states are used to keep a tab on connection progress in case of non-blocking connect,
  246. and in case of blocking connect these cases will get executed one after the other */
  247. switch (tls->conn_state) {
  248. case ESP_TLS_INIT:
  249. tls->sockfd = -1;
  250. if (cfg != NULL) {
  251. #ifdef CONFIG_ESP_TLS_USING_MBEDTLS
  252. mbedtls_net_init(&tls->server_fd);
  253. #endif
  254. tls->is_tls = true;
  255. }
  256. if ((esp_ret = esp_tcp_connect(hostname, hostlen, port, &tls->sockfd, tls, cfg)) != ESP_OK) {
  257. ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, esp_ret);
  258. return -1;
  259. }
  260. if (!cfg) {
  261. tls->read = tcp_read;
  262. tls->write = tcp_write;
  263. ESP_LOGD(TAG, "non-tls connection established");
  264. return 1;
  265. }
  266. if (cfg->non_block) {
  267. FD_ZERO(&tls->rset);
  268. FD_SET(tls->sockfd, &tls->rset);
  269. tls->wset = tls->rset;
  270. }
  271. tls->conn_state = ESP_TLS_CONNECTING;
  272. /* falls through */
  273. case ESP_TLS_CONNECTING:
  274. if (cfg->non_block) {
  275. ESP_LOGD(TAG, "connecting...");
  276. struct timeval tv;
  277. ms_to_timeval(cfg->timeout_ms, &tv);
  278. /* In case of non-blocking I/O, we use the select() API to check whether
  279. connection has been established or not*/
  280. if (select(tls->sockfd + 1, &tls->rset, &tls->wset, NULL,
  281. cfg->timeout_ms>0 ? &tv : NULL) == 0) {
  282. ESP_LOGD(TAG, "select() timed out");
  283. return 0;
  284. }
  285. if (FD_ISSET(tls->sockfd, &tls->rset) || FD_ISSET(tls->sockfd, &tls->wset)) {
  286. int error;
  287. unsigned int len = sizeof(error);
  288. /* pending error check */
  289. if (getsockopt(tls->sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
  290. ESP_LOGD(TAG, "Non blocking connect failed");
  291. ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_SYSTEM, errno);
  292. ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED);
  293. tls->conn_state = ESP_TLS_FAIL;
  294. return -1;
  295. }
  296. }
  297. }
  298. /* By now, the connection has been established */
  299. esp_ret = create_ssl_handle(hostname, hostlen, cfg, tls);
  300. if (esp_ret != ESP_OK) {
  301. ESP_LOGE(TAG, "create_ssl_handle failed");
  302. ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, esp_ret);
  303. tls->conn_state = ESP_TLS_FAIL;
  304. return -1;
  305. }
  306. tls->read = _esp_tls_read;
  307. tls->write = _esp_tls_write;
  308. tls->conn_state = ESP_TLS_HANDSHAKE;
  309. /* falls through */
  310. case ESP_TLS_HANDSHAKE:
  311. ESP_LOGD(TAG, "handshake in progress...");
  312. return esp_tls_handshake(tls, cfg);
  313. break;
  314. case ESP_TLS_FAIL:
  315. ESP_LOGE(TAG, "failed to open a new connection");;
  316. break;
  317. default:
  318. ESP_LOGE(TAG, "invalid esp-tls state");
  319. break;
  320. }
  321. return -1;
  322. }
  323. /**
  324. * @brief Create a new TLS/SSL connection
  325. */
  326. esp_tls_t *esp_tls_conn_new(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg)
  327. {
  328. esp_tls_t *tls = esp_tls_init();
  329. if (!tls) {
  330. return NULL;
  331. }
  332. /* esp_tls_conn_new() API establishes connection in a blocking manner thus this loop ensures that esp_tls_conn_new()
  333. API returns only after connection is established unless there is an error*/
  334. size_t start = xTaskGetTickCount();
  335. while (1) {
  336. int ret = esp_tls_low_level_conn(hostname, hostlen, port, cfg, tls);
  337. if (ret == 1) {
  338. return tls;
  339. } else if (ret == -1) {
  340. esp_tls_conn_delete(tls);
  341. ESP_LOGE(TAG, "Failed to open new connection");
  342. return NULL;
  343. } else if (ret == 0 && cfg->timeout_ms >= 0) {
  344. size_t timeout_ticks = pdMS_TO_TICKS(cfg->timeout_ms);
  345. uint32_t expired = xTaskGetTickCount() - start;
  346. if (expired >= timeout_ticks) {
  347. esp_tls_conn_delete(tls);
  348. ESP_LOGE(TAG, "Failed to open new connection in specified timeout");
  349. return NULL;
  350. }
  351. }
  352. }
  353. return NULL;
  354. }
  355. int esp_tls_conn_new_sync(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_t *tls)
  356. {
  357. /* esp_tls_conn_new_sync() is a sync alternative to esp_tls_conn_new_async() with symmetric function prototype
  358. it is an alternative to esp_tls_conn_new() which is left for compatibility reasons */
  359. size_t start = xTaskGetTickCount();
  360. while (1) {
  361. int ret = esp_tls_low_level_conn(hostname, hostlen, port, cfg, tls);
  362. if (ret == 1) {
  363. return ret;
  364. } else if (ret == -1) {
  365. ESP_LOGE(TAG, "Failed to open new connection");
  366. return -1;
  367. } else if (ret == 0 && cfg->timeout_ms >= 0) {
  368. size_t timeout_ticks = pdMS_TO_TICKS(cfg->timeout_ms);
  369. uint32_t expired = xTaskGetTickCount() - start;
  370. if (expired >= timeout_ticks) {
  371. ESP_LOGW(TAG, "Failed to open new connection in specified timeout");
  372. ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT);
  373. return 0;
  374. }
  375. }
  376. }
  377. return 0;
  378. }
  379. /*
  380. * @brief Create a new TLS/SSL non-blocking connection
  381. */
  382. int esp_tls_conn_new_async(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_t *tls)
  383. {
  384. return esp_tls_low_level_conn(hostname, hostlen, port, cfg, tls);
  385. }
  386. static int get_port(const char *url, struct http_parser_url *u)
  387. {
  388. if (u->field_data[UF_PORT].len) {
  389. return strtol(&url[u->field_data[UF_PORT].off], NULL, 10);
  390. } else {
  391. if (strncasecmp(&url[u->field_data[UF_SCHEMA].off], "http", u->field_data[UF_SCHEMA].len) == 0) {
  392. return 80;
  393. } else if (strncasecmp(&url[u->field_data[UF_SCHEMA].off], "https", u->field_data[UF_SCHEMA].len) == 0) {
  394. return 443;
  395. }
  396. }
  397. return 0;
  398. }
  399. /**
  400. * @brief Create a new TLS/SSL connection with a given "HTTP" url
  401. */
  402. esp_tls_t *esp_tls_conn_http_new(const char *url, const esp_tls_cfg_t *cfg)
  403. {
  404. /* Parse URI */
  405. struct http_parser_url u;
  406. http_parser_url_init(&u);
  407. http_parser_parse_url(url, strlen(url), 0, &u);
  408. esp_tls_t *tls = esp_tls_init();
  409. if (!tls) {
  410. return NULL;
  411. }
  412. /* Connect to host */
  413. if (esp_tls_conn_new_sync(&url[u.field_data[UF_HOST].off], u.field_data[UF_HOST].len,
  414. get_port(url, &u), cfg, tls) == 1) {
  415. return tls;
  416. }
  417. esp_tls_conn_delete(tls);
  418. return NULL;
  419. }
  420. /**
  421. * @brief Create a new non-blocking TLS/SSL connection with a given "HTTP" url
  422. */
  423. int esp_tls_conn_http_new_async(const char *url, const esp_tls_cfg_t *cfg, esp_tls_t *tls)
  424. {
  425. /* Parse URI */
  426. struct http_parser_url u;
  427. http_parser_url_init(&u);
  428. http_parser_parse_url(url, strlen(url), 0, &u);
  429. /* Connect to host */
  430. return esp_tls_conn_new_async(&url[u.field_data[UF_HOST].off], u.field_data[UF_HOST].len,
  431. get_port(url, &u), cfg, tls);
  432. }
  433. #ifdef CONFIG_ESP_TLS_USING_MBEDTLS
  434. mbedtls_x509_crt *esp_tls_get_global_ca_store(void)
  435. {
  436. return _esp_tls_get_global_ca_store();
  437. }
  438. #endif /* CONFIG_ESP_TLS_USING_MBEDTLS */
  439. #ifdef CONFIG_ESP_TLS_SERVER
  440. /**
  441. * @brief Create a server side TLS/SSL connection
  442. */
  443. int esp_tls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp_tls_t *tls)
  444. {
  445. return _esp_tls_server_session_create(cfg, sockfd, tls);
  446. }
  447. /**
  448. * @brief Close the server side TLS/SSL connection and free any allocated resources.
  449. */
  450. void esp_tls_server_session_delete(esp_tls_t *tls)
  451. {
  452. return _esp_tls_server_session_delete(tls);
  453. }
  454. #endif /* CONFIG_ESP_TLS_SERVER */
  455. ssize_t esp_tls_get_bytes_avail(esp_tls_t *tls)
  456. {
  457. return _esp_tls_get_bytes_avail(tls);
  458. }
  459. esp_err_t esp_tls_get_conn_sockfd(esp_tls_t *tls, int *sockfd)
  460. {
  461. if (!tls || !sockfd) {
  462. ESP_LOGE(TAG, "Invalid arguments passed");
  463. return ESP_ERR_INVALID_ARG;
  464. }
  465. *sockfd = tls->sockfd;
  466. return ESP_OK;
  467. }
  468. esp_err_t esp_tls_get_and_clear_last_error(esp_tls_error_handle_t h, int *esp_tls_code, int *esp_tls_flags)
  469. {
  470. if (!h) {
  471. return ESP_ERR_INVALID_STATE;
  472. }
  473. esp_err_t last_err = h->last_error;
  474. if (esp_tls_code) {
  475. *esp_tls_code = h->esp_tls_error_code;
  476. }
  477. if (esp_tls_flags) {
  478. *esp_tls_flags = h->esp_tls_flags;
  479. }
  480. memset(h, 0, sizeof(esp_tls_last_error_t));
  481. return last_err;
  482. }
  483. esp_err_t esp_tls_init_global_ca_store(void)
  484. {
  485. return _esp_tls_init_global_ca_store();
  486. }
  487. esp_err_t esp_tls_set_global_ca_store(const unsigned char *cacert_pem_buf, const unsigned int cacert_pem_bytes)
  488. {
  489. return _esp_tls_set_global_ca_store(cacert_pem_buf, cacert_pem_bytes);
  490. }
  491. void esp_tls_free_global_ca_store(void)
  492. {
  493. return _esp_tls_free_global_ca_store();
  494. }