client-tls.c 19 KB

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