client-tls.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. /* client-tls.c
  2. *
  3. * Copyright (C) 2006-2024 wolfSSL Inc.
  4. *
  5. * This file is part of wolfSSL.
  6. *
  7. * wolfSSL is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * wolfSSL is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
  20. */
  21. #include "client-tls.h"
  22. /* Espressif FreeRTOS */
  23. #ifndef SINGLE_THREADED
  24. #include <freertos/FreeRTOS.h>
  25. #include <freertos/task.h>
  26. #include <freertos/event_groups.h>
  27. #endif
  28. /* Espressif */
  29. #include <esp_log.h>
  30. /* socket includes */
  31. #include <lwip/netdb.h>
  32. #include <lwip/sockets.h>
  33. /* wolfSSL */
  34. #include <wolfssl/wolfcrypt/settings.h>
  35. #include <wolfssl/ssl.h>
  36. #if defined(WOLFSSL_WC_KYBER)
  37. #include <wolfssl/wolfcrypt/kyber.h>
  38. #include <wolfssl/wolfcrypt/wc_kyber.h>
  39. #endif
  40. #if defined(USE_CERT_BUFFERS_2048) || defined(USE_CERT_BUFFERS_1024)
  41. #include <wolfssl/certs_test.h>
  42. #endif
  43. #ifdef WOLFSSL_TRACK_MEMORY
  44. #include <wolfssl/wolfcrypt/mem_track.h>
  45. #endif
  46. #ifndef NO_DH
  47. /* see also wolfssl/test.h */
  48. #undef DEFAULT_MIN_DHKEY_BITS
  49. #define DEFAULT_MIN_DHKEY_BITS 1024
  50. #undef DEFAULT_MAX_DHKEY_BITS
  51. #define DEFAULT_MAX_DHKEY_BITS 2048
  52. #endif
  53. /* Project */
  54. #include "wifi_connect.h"
  55. #include "time_helper.h"
  56. /* working TLS 1.2 VS client app commandline param:
  57. *
  58. * -h 192.168.1.128 -v 3 -l ECDHE-ECDSA-SM4-CBC-SM3 -c ./certs/sm2/client-sm2.pem -k ./certs/sm2/client-sm2-priv.pem -A ./certs/sm2/root-sm2.pem -C
  59. *
  60. * working Linux, non-working VS c app
  61. *
  62. * -h 192.168.1.128 -v 4 -l TLS13-SM4-CCM-SM3 -c ./certs/sm2/client-sm2.pem -k ./certs/sm2/client-sm2-priv.pem -A ./certs/sm2/root-sm2.pem -C
  63. *
  64. **/
  65. #define TAG "client-tls"
  66. #if defined(DEBUG_WOLFSSL)
  67. int stack_start = -1;
  68. int ShowCiphers(WOLFSSL* ssl)
  69. {
  70. #define CLIENT_TLS_MAX_CIPHER_LENGTH 4096
  71. char ciphers[CLIENT_TLS_MAX_CIPHER_LENGTH];
  72. const char* cipher_used;
  73. int ret = 0;
  74. if (ssl == NULL) {
  75. ESP_LOGI(TAG, "WOLFSSL* ssl is NULL, so no cipher in use");
  76. ret = wolfSSL_get_ciphers(ciphers, (int)sizeof(ciphers));
  77. if (ret == WOLFSSL_SUCCESS) {
  78. for (int i = 0; i < CLIENT_TLS_MAX_CIPHER_LENGTH; i++) {
  79. if (ciphers[i] == ':') {
  80. ciphers[i] = '\n';
  81. }
  82. }
  83. ESP_LOGI(TAG, "Available Ciphers:\n%s\n", ciphers);
  84. }
  85. else {
  86. ESP_LOGE(TAG, "Failed to call wolfSSL_get_ciphers. Error %d", ret);
  87. }
  88. }
  89. else {
  90. cipher_used = wolfSSL_get_cipher_name(ssl);
  91. ESP_LOGI(TAG, "WOLFSSL* ssl using %s", cipher_used);
  92. }
  93. return ret;
  94. }
  95. #endif
  96. #if defined(WOLFSSL_ESPWROOM32SE) && defined(HAVE_PK_CALLBACKS) \
  97. && defined(WOLFSSL_ATECC508A)
  98. #include "wolfssl/wolfcrypt/port/atmel/atmel.h"
  99. /* when you want to use custom slot allocation */
  100. /* enable the definition CUSTOM_SLOT_ALLOCATION.*/
  101. #if defined(CUSTOM_SLOT_ALLOCATION)
  102. static byte mSlotList[ATECC_MAX_SLOT];
  103. int atmel_set_slot_allocator(atmel_slot_alloc_cb alloc,
  104. atmel_slot_dealloc_cb dealloc);
  105. /* initialize slot array */
  106. void my_atmel_slotInit()
  107. {
  108. int i;
  109. for (i = 0; i < ATECC_MAX_SLOT; i++) {
  110. mSlotList[i] = ATECC_INVALID_SLOT;
  111. }
  112. }
  113. /* allocate slot depending on slotType */
  114. int my_atmel_alloc(int slotType)
  115. {
  116. int i, slot = -1;
  117. switch (slotType) {
  118. case ATMEL_SLOT_ENCKEY:
  119. slot = 2;
  120. break;
  121. case ATMEL_SLOT_DEVICE:
  122. slot = 0;
  123. break;
  124. case ATMEL_SLOT_ECDHE:
  125. slot = 0;
  126. break;
  127. case ATMEL_SLOT_ECDHE_ENC:
  128. slot = 4;
  129. break;
  130. case ATMEL_SLOT_ANY:
  131. for (i = 0; i < ATECC_MAX_SLOT; i++) {
  132. if (mSlotList[i] == ATECC_INVALID_SLOT) {
  133. slot = i;
  134. break;
  135. }
  136. }
  137. }
  138. return slot;
  139. }
  140. /* free slot array */
  141. void my_atmel_free(int slotId)
  142. {
  143. if (slotId >= 0 && slotId < ATECC_MAX_SLOT) {
  144. mSlotList[slotId] = ATECC_INVALID_SLOT;
  145. }
  146. }
  147. #endif /* CUSTOM_SLOT_ALLOCATION */
  148. #endif /* WOLFSSL_ESPWROOM32SE && HAVE_PK_CALLBACK && WOLFSSL_ATECC508A */
  149. /* client task */
  150. WOLFSSL_ESP_TASK tls_smp_client_task(void* args)
  151. {
  152. #if defined(SINGLE_THREADED)
  153. int ret = ESP_OK;
  154. #define TLS_SMP_CLIENT_TASK_RET ret
  155. #else
  156. #define TLS_SMP_CLIENT_TASK_RET
  157. #endif
  158. char buff[256];
  159. const char sndMsg[] = "GET /index.html HTTP/1.0\r\n\r\n";
  160. const char* ch = TLS_SMP_TARGET_HOST; /* see wifi_connect.h */
  161. struct sockaddr_in servAddr;
  162. struct hostent *hp;
  163. struct ip4_addr *ip4_addr;
  164. int ret_i; /* interim return values */
  165. int err; /* interim return values */
  166. int sockfd;
  167. int doPeerCheck;
  168. int sendGet;
  169. #ifdef DEBUG_WOLFSSL
  170. int this_heap = 0;
  171. #endif
  172. #ifndef NO_DH
  173. int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS;
  174. #endif
  175. /* declare wolfSSL objects */
  176. WOLFSSL_CTX* ctx;
  177. WOLFSSL* ssl;
  178. size_t len;
  179. wolfSSL_Debugging_ON();
  180. WOLFSSL_ENTER(TLS_SMP_CLIENT_TASK_NAME);
  181. doPeerCheck = 1;
  182. sendGet = 0;
  183. #ifdef DEBUG_WOLFSSL
  184. WOLFSSL_MSG("Debug ON");
  185. ShowCiphers(NULL);
  186. #endif
  187. /* Initialize wolfSSL */
  188. wolfSSL_Init();
  189. /* Create a socket that uses an Internet IPv4 address,
  190. * Sets the socket to be stream based (TCP),
  191. * 0 means choose the default protocol. */
  192. if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  193. ESP_LOGE(TAG, "ERROR: failed to create the socket\n");
  194. }
  195. ESP_LOGI(TAG, "get target IP address");
  196. hp = gethostbyname(TLS_SMP_TARGET_HOST);
  197. if (!hp) {
  198. ESP_LOGE(TAG, "Failed to get host name.");
  199. ip4_addr = NULL;
  200. }
  201. else {
  202. ip4_addr = (struct ip4_addr *)hp->h_addr;
  203. }
  204. /* Create and initialize WOLFSSL_CTX */
  205. ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); /* SSL 3.0 - TLS 1.3. */
  206. /* options: */
  207. /* ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); only TLS 1.2 */
  208. /* ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()); only TLS 1.3 */
  209. /* wolfSSL_CTX_NoTicketTLSv12(); */
  210. /* wolfSSL_NoTicketTLSv12(); */
  211. if (ctx == NULL) {
  212. ESP_LOGE(TAG, "ERROR: failed to create WOLFSSL_CTX\n");
  213. }
  214. #if defined(WOLFSSL_ESP32_CIPHER_SUITE)
  215. ESP_LOGI(TAG, "Start SM2\n");
  216. /*
  217. *
  218. * reference code for SM Ciphers:
  219. *
  220. #if defined(HAVE_AESGCM) && !defined(NO_DH)
  221. #ifdef WOLFSSL_TLS13
  222. defaultCipherList = "TLS13-AES128-GCM-SHA256"
  223. #ifndef WOLFSSL_NO_TLS12
  224. ":DHE-PSK-AES128-GCM-SHA256"
  225. #endif
  226. ;
  227. #else
  228. defaultCipherList = "DHE-PSK-AES128-GCM-SHA256";
  229. #endif
  230. #elif defined(HAVE_AESGCM) && defined(WOLFSSL_TLS13)
  231. defaultCipherList = "TLS13-AES128-GCM-SHA256:PSK-AES128-GCM-SHA256"
  232. #ifndef WOLFSSL_NO_TLS12
  233. ":PSK-AES128-GCM-SHA256"
  234. #endif
  235. ;
  236. #elif defined(HAVE_NULL_CIPHER)
  237. defaultCipherList = "PSK-NULL-SHA256";
  238. #elif !defined(NO_AES_CBC)
  239. defaultCipherList = "PSK-AES128-CBC-SHA256";
  240. #else
  241. defaultCipherList = "PSK-AES128-GCM-SHA256";
  242. #endif
  243. */
  244. ret = wolfSSL_CTX_set_cipher_list(ctx, WOLFSSL_ESP32_CIPHER_SUITE);
  245. if (ret == WOLFSSL_SUCCESS) {
  246. ESP_LOGI(TAG, "Set cipher list: %s\n", WOLFSSL_ESP32_CIPHER_SUITE);
  247. }
  248. else {
  249. ESP_LOGE(TAG, "ERROR: failed to set cipher list: %s\n",
  250. WOLFSSL_ESP32_CIPHER_SUITE);
  251. }
  252. #endif
  253. #ifdef DEBUG_WOLFSSL
  254. ShowCiphers(NULL);
  255. ESP_LOGI(TAG, "Stack used: %d\n",
  256. CONFIG_ESP_MAIN_TASK_STACK_SIZE
  257. - uxTaskGetStackHighWaterMark(NULL));
  258. #endif
  259. /* see user_settings PROJECT_DH for HAVE_DH and HAVE_FFDHE_2048 */
  260. #ifndef NO_DH
  261. ret = wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits);
  262. if (ret != WOLFSSL_SUCCESS) {
  263. ESP_LOGE(TAG, "Error setting minimum DH key size");
  264. }
  265. #endif
  266. /* no peer check */
  267. if (doPeerCheck == 0) {
  268. ESP_LOGW(TAG, "doPeerCheck == 0");
  269. wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, 0);
  270. }
  271. else {
  272. ESP_LOGW(TAG, "doPeerCheck != 0");
  273. WOLFSSL_MSG("Loading... our cert");
  274. /* load our certificate */
  275. ret_i = wolfSSL_CTX_use_certificate_chain_buffer_format(ctx,
  276. CTX_CLIENT_CERT,
  277. CTX_CLIENT_CERT_SIZE,
  278. CTX_CLIENT_CERT_TYPE);
  279. if (ret_i != WOLFSSL_SUCCESS) {
  280. ESP_LOGE(TAG, "ERROR: failed to load our cert chain %d, "
  281. "please check the file.", ret_i);
  282. }
  283. /* Load client certificates into WOLFSSL_CTX */
  284. WOLFSSL_MSG("Loading... CA cert");
  285. ret_i = wolfSSL_CTX_load_verify_buffer(ctx,
  286. CTX_CA_CERT,
  287. CTX_CA_CERT_SIZE,
  288. CTX_CA_CERT_TYPE);
  289. if (ret_i != WOLFSSL_SUCCESS) {
  290. ESP_LOGE(TAG, "ERROR: failed to load CA cert %d, "
  291. "please check the file.\n", ret_i) ;
  292. }
  293. WOLFSSL_MSG("Loading... our key");
  294. ret_i = wolfSSL_CTX_use_PrivateKey_buffer(ctx,
  295. CTX_CLIENT_KEY,
  296. CTX_CLIENT_KEY_SIZE,
  297. CTX_CLIENT_KEY_TYPE);
  298. if (ret_i != WOLFSSL_SUCCESS) {
  299. ESP_LOGE(TAG, "ERROR: failed to load key %d, "
  300. "please check the file.\n", ret_i) ;
  301. }
  302. wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, 0);
  303. }
  304. /* Initialize the server address struct with zeros */
  305. memset(&servAddr, 0, sizeof(servAddr));
  306. /* Fill in the server address */
  307. servAddr.sin_family = AF_INET; /* using IPv4 */
  308. servAddr.sin_port = htons(TLS_SMP_DEFAULT_PORT); /* on DEFAULT_PORT */
  309. if (*ch >= '1' && *ch <= '9') {
  310. /* Get the server IPv4 address from the command line call */
  311. WOLFSSL_MSG("inet_pton");
  312. if ((ret_i = inet_pton(AF_INET,
  313. TLS_SMP_TARGET_HOST,
  314. &servAddr.sin_addr)) != 1) {
  315. ESP_LOGE(TAG, "ERROR: invalid address ret=%d\n", ret_i);
  316. }
  317. }
  318. else {
  319. servAddr.sin_addr.s_addr = ip4_addr->addr;
  320. }
  321. /* Connect to the server */
  322. sprintf(buff,
  323. "Connecting to server....%s (port:%d)",
  324. TLS_SMP_TARGET_HOST,
  325. TLS_SMP_DEFAULT_PORT);
  326. ESP_LOGI(TAG, "%s\n", buff);
  327. if ((ret_i = connect(sockfd,
  328. (struct sockaddr *)&servAddr,
  329. sizeof(servAddr))) == -1) {
  330. ESP_LOGE(TAG, "ERROR: failed to connect ret=%d\n", ret_i);
  331. }
  332. #if defined(WOLFSSL_EXPERIMENTAL_SETTINGS)
  333. ESP_LOGW(TAG, "WOLFSSL_EXPERIMENTAL_SETTINGS is enabled");
  334. #endif
  335. WOLFSSL_MSG("Create a WOLFSSL object");
  336. /* Create a WOLFSSL object */
  337. if ((ssl = wolfSSL_new(ctx)) == NULL) {
  338. ESP_LOGE(TAG, "ERROR: failed to create WOLFSSL object\n");
  339. }
  340. else {
  341. #ifdef DEBUG_WOLFSSL
  342. ESP_LOGI(TAG, "\nCreated WOLFSSL object:");
  343. ShowCiphers(ssl);
  344. this_heap = esp_get_free_heap_size();
  345. ESP_LOGI(TAG, "tls_smp_client_task heap @ %p = %d",
  346. &this_heap, this_heap);
  347. #endif
  348. #if defined(WOLFSSL_HAVE_KYBER)
  349. #if defined(WOLFSSL_KYBER1024)
  350. ESP_LOGI(TAG, "WOLFSSL_HAVE_KYBER is enabled, setting key share: "
  351. "WOLFSSL_P256_KYBER_LEVEL5");
  352. ret_i = wolfSSL_UseKeyShare(ssl, WOLFSSL_P521_KYBER_LEVEL5);
  353. #elif defined(WOLFSSL_KYBER768)
  354. ESP_LOGI(TAG, "WOLFSSL_HAVE_KYBER is enabled, setting key share: "
  355. "WOLFSSL_P256_KYBER_LEVEL3");
  356. ret_i = wolfSSL_UseKeyShare(ssl, WOLFSSL_P256_KYBER_LEVEL3);
  357. #elif defined(WOLFSSL_KYBER512)
  358. /* This will typically be a low memory situation, such as ESP8266 */
  359. ESP_LOGI(TAG, "WOLFSSL_HAVE_KYBER is enabled, setting key share: "
  360. "WOLFSSL_P256_KYBER_LEVEL1");
  361. ret_i = wolfSSL_UseKeyShare(ssl, WOLFSSL_P256_KYBER_LEVEL1);
  362. #else
  363. ESP_LOGW(TAG, "WOLFSSL_HAVE_KYBER enabled but no key size available.");
  364. ret_i = ESP_FAIL;
  365. #endif
  366. if (ret_i == WOLFSSL_SUCCESS) {
  367. ESP_LOGI(TAG, "UseKeyShare Kyber success");
  368. }
  369. else {
  370. ESP_LOGE(TAG, "UseKeyShare Kyber failed");
  371. }
  372. #else
  373. ESP_LOGI(TAG, "WOLFSSL_HAVE_KYBER is not enabled");
  374. #endif
  375. }
  376. #if defined(WOLFSSL_SM2)
  377. /* SM TLS1.3 Cipher needs to have key share explicitly set. */
  378. ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SM2P256V1);
  379. if (ret == WOLFSSL_SUCCESS) {
  380. ESP_LOGI(TAG, "Successfully set WOLFSSL_ECC_SM2P256V1");
  381. }
  382. else {
  383. ESP_LOGE(TAG, "FAILED to set WOLFSSL_ECC_SM2P256V1");
  384. }
  385. #endif
  386. /* when using atecc608a on esp32-wroom-32se */
  387. #if defined(WOLFSSL_ESPWROOM32SE) && defined(HAVE_PK_CALLBACKS) \
  388. && defined(WOLFSSL_ATECC508A)
  389. atcatls_set_callbacks(ctx);
  390. /* when using custom slot-allocation */
  391. #if defined(CUSTOM_SLOT_ALLOCATION)
  392. my_atmel_slotInit();
  393. atmel_set_slot_allocator(my_atmel_alloc, my_atmel_free);
  394. #endif
  395. #endif
  396. #ifdef DEBUG_WOLFSSL
  397. this_heap = esp_get_free_heap_size();
  398. ESP_LOGI(TAG, "tls_smp_client_task heap(2) @ %p = %d",
  399. &this_heap, this_heap);
  400. #endif
  401. /* Attach wolfSSL to the socket */
  402. ret_i = wolfSSL_set_fd(ssl, sockfd);
  403. if (ret_i == WOLFSSL_SUCCESS) {
  404. ESP_LOGI(TAG, "wolfSSL_set_fd success");
  405. }
  406. else {
  407. ESP_LOGE(TAG, "ERROR: failed wolfSSL_set_fd. Error: %d\n", ret_i);
  408. }
  409. ESP_LOGI(TAG, "Connect to wolfSSL server...");
  410. ret_i = wolfSSL_connect(ssl);
  411. #ifdef DEBUG_WOLFSSL
  412. this_heap = esp_get_free_heap_size();
  413. ESP_LOGI(TAG, "tls_smp_client_task heap(3) @ %p = %d",
  414. &this_heap, this_heap);
  415. #endif
  416. if (ret_i == WOLFSSL_SUCCESS) {
  417. #ifdef DEBUG_WOLFSSL
  418. ShowCiphers(ssl);
  419. #endif
  420. ESP_LOGI(TAG, "Connect success! Sending message...");
  421. /* Get a message for the server from stdin */
  422. WOLFSSL_MSG("Message for server: ");
  423. memset(buff, 0, sizeof(buff));
  424. if (sendGet) {
  425. len = XSTRLEN(sndMsg);
  426. strncpy(buff, sndMsg, len);
  427. }
  428. else {
  429. sprintf(buff, "Hello from Espressif wolfSSL TLS client!\n");
  430. len = strnlen(buff, sizeof(buff));
  431. }
  432. buff[len] = '\0';
  433. ESP_LOGI(TAG, "SSL connect ok, sending message:\n\n%s\n", buff);
  434. /* Send the message to the server */
  435. do {
  436. err = 0; /* reset error */
  437. ret_i = wolfSSL_write(ssl, buff, len);
  438. if (ret_i <= 0) {
  439. err = wolfSSL_get_error(ssl, 0);
  440. }
  441. } while (err == WOLFSSL_ERROR_WANT_WRITE ||
  442. err == WOLFSSL_ERROR_WANT_READ);
  443. if (ret_i != len) {
  444. ESP_LOGE(TAG, "ERROR: failed to write\n");
  445. }
  446. else {
  447. ESP_LOGI(TAG, "Message sent! Awaiting response...");
  448. }
  449. /* Read the server data into our buff array */
  450. memset(buff, 0, sizeof(buff));
  451. do {
  452. err = 0; /* reset error */
  453. ret_i =wolfSSL_read(ssl, buff, sizeof(buff));
  454. if (ret_i <= 0) {
  455. err = wolfSSL_get_error(ssl, 0);
  456. }
  457. } while ((err == WOLFSSL_ERROR_WANT_READ) ||
  458. (err == WOLFSSL_ERROR_WANT_WRITE) );
  459. if (ret_i < 0) {
  460. ESP_LOGE(TAG, "ERROR: failed to read\n");
  461. }
  462. /* Show any data the server sends */
  463. ESP_LOGI(TAG, "Server response: \n\n%s\n", buff);
  464. ret_i = wolfSSL_shutdown(ssl);
  465. while (ret_i == WOLFSSL_SHUTDOWN_NOT_DONE) {
  466. ret_i = wolfSSL_shutdown(ssl); /* bidirectional shutdown */
  467. if (ret_i == WOLFSSL_SUCCESS) {
  468. ESP_LOGI(TAG, "Bidirectional shutdown complete\n");
  469. break;
  470. }
  471. else if (ret_i != WOLFSSL_SHUTDOWN_NOT_DONE) {
  472. ESP_LOGE(TAG, "Bidirectional shutdown failed\n");
  473. break;
  474. }
  475. }
  476. if (ret_i != WOLFSSL_SUCCESS) {
  477. ESP_LOGE(TAG, "Bidirectional shutdown failed\n");
  478. }
  479. } /* wolfSSL_connect(ssl) == WOLFSSL_SUCCESS) */
  480. else {
  481. ESP_LOGE(TAG, "ERROR: failed to connect to wolfSSL. "
  482. "Error: %d\n", ret_i);
  483. }
  484. #ifdef DEBUG_WOLFSSL
  485. ShowCiphers(ssl);
  486. #endif
  487. ESP_LOGI(TAG, "Cleanup and exit");
  488. wolfSSL_free(ssl); /* Release the wolfSSL object memory */
  489. wolfSSL_CTX_free(ctx); /* Free the wolfSSL context object */
  490. wolfSSL_Cleanup(); /* Cleanup the wolfSSL environment */
  491. close(sockfd); /* Close the connection to the server */
  492. vTaskDelete(NULL);
  493. return TLS_SMP_CLIENT_TASK_RET;
  494. }
  495. #if defined(SINGLE_THREADED)
  496. /* we don't initialize a single thread, so no init function here */
  497. #else
  498. /* create task */
  499. WOLFSSL_ESP_TASK tls_smp_client_init(void* args)
  500. {
  501. int ret;
  502. #if ESP_IDF_VERSION_MAJOR >= 4
  503. TaskHandle_t _handle;
  504. #else
  505. xTaskHandle _handle;
  506. #endif
  507. /* See https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos_idf.html#functions */
  508. if (TLS_SMP_CLIENT_TASK_BYTES < (6 * 1024)) {
  509. /* Observed approximately 6KB limit for the RTOS task stack size.
  510. * Reminder parameter is bytes, not words as with generic FreeRTOS. */
  511. ESP_LOGW(TAG, "Warning: TLS_SMP_CLIENT_TASK_BYTES < 6KB");
  512. }
  513. #ifndef WOLFSSL_SMALL_STACK
  514. ESP_LOGW(TAG, "WARNING: WOLFSSL_SMALL_STACK is not defined. Consider "
  515. "defining that to reduce embedded memory usage.");
  516. #endif
  517. /* Note that despite vanilla FreeRTOS using WORDS for a parameter,
  518. * Espressif uses BYTES for the task stack size here.
  519. * See https://docs.espressif.com/projects/esp-idf/en/v4.3/esp32/api-reference/system/freertos.html */
  520. ret = xTaskCreate(tls_smp_client_task,
  521. TLS_SMP_CLIENT_TASK_NAME,
  522. TLS_SMP_CLIENT_TASK_BYTES,
  523. NULL,
  524. TLS_SMP_CLIENT_TASK_PRIORITY,
  525. &_handle);
  526. if (ret != pdPASS) {
  527. ESP_LOGI(TAG, "Create thread %s failed.", TLS_SMP_CLIENT_TASK_NAME);
  528. }
  529. return TLS_SMP_CLIENT_TASK_RET;
  530. }
  531. #endif