client-tls.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. /* client-tls-callback.c
  2. *
  3. * Copyright (C) 2006-2021 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. /* the usual suspects */
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <errno.h>
  26. /* ESP specific */
  27. #include "wifi_connect.h"
  28. /* socket includes */
  29. #include "lwip/netdb.h"
  30. #include "lwip/sockets.h"
  31. /* wolfSSL */
  32. #include <wolfssl/wolfcrypt/settings.h>
  33. #include <wolfssl/ssl.h>
  34. #include <wolfssl/certs_test.h>
  35. #ifdef WOLFSSL_TRACK_MEMORY
  36. #include <wolfssl/wolfcrypt/mem_track.h>
  37. #endif
  38. static const char* const TAG = "tls_client";
  39. #if defined(DEBUG_WOLFSSL)
  40. static void ShowCiphers(void)
  41. {
  42. char ciphers[4096];
  43. int ret = wolfSSL_get_ciphers(ciphers, (int)sizeof(ciphers));
  44. if (ret == WOLFSSL_SUCCESS)
  45. printf("%s\n", ciphers);
  46. }
  47. #endif
  48. #if defined(WOLFSSL_ESPWROOM32SE) && defined(HAVE_PK_CALLBACKS) \
  49. && defined(WOLFSSL_ATECC508A)
  50. #include "wolfssl/wolfcrypt/port/atmel/atmel.h"
  51. /* when you want to use custom slot allocation */
  52. /* enable the definition CUSTOM_SLOT_ALLOCATION.*/
  53. #if defined(CUSTOM_SLOT_ALLOCATION)
  54. static byte mSlotList[ATECC_MAX_SLOT];
  55. int atmel_set_slot_allocator(atmel_slot_alloc_cb alloc,
  56. atmel_slot_dealloc_cb dealloc);
  57. /* initialize slot array */
  58. void my_atmel_slotInit()
  59. {
  60. int i;
  61. for(i=0;i<ATECC_MAX_SLOT; i++) {
  62. mSlotList[i] = ATECC_INVALID_SLOT;
  63. }
  64. }
  65. /* allocate slot depending on slotType */
  66. int my_atmel_alloc(int slotType)
  67. {
  68. int i, slot = -1;
  69. switch(slotType){
  70. case ATMEL_SLOT_ENCKEY:
  71. slot = 2;
  72. break;
  73. case ATMEL_SLOT_DEVICE:
  74. slot = 0;
  75. break;
  76. case ATMEL_SLOT_ECDHE:
  77. slot = 0;
  78. break;
  79. case ATMEL_SLOT_ECDHE_ENC:
  80. slot = 4;
  81. break;
  82. case ATMEL_SLOT_ANY:
  83. for(i=0;i<ATECC_MAX_SLOT;i++){
  84. if(mSlotList[i] == ATECC_INVALID_SLOT){
  85. slot = i;
  86. break;
  87. }
  88. }
  89. }
  90. return slot;
  91. }
  92. /* free slot array */
  93. void my_atmel_free(int slotId)
  94. {
  95. if(slotId >= 0 && slotId < ATECC_MAX_SLOT){
  96. mSlotList[slotId] = ATECC_INVALID_SLOT;
  97. }
  98. }
  99. #endif /* CUSTOM_SLOT_ALLOCATION */
  100. #endif /* WOLFSSL_ESPWROOM32SE && HAVE_PK_CALLBACK && WOLFSSL_ATECC508A */
  101. /* client task */
  102. void tls_smp_client_task()
  103. {
  104. int ret;
  105. int sockfd;
  106. int doPeerCheck;
  107. int sendGet;
  108. struct sockaddr_in servAddr;
  109. char buff[256];
  110. const char* ch = TLS_SMP_TARGET_HOST;
  111. size_t len;
  112. struct hostent *hp;
  113. struct ip4_addr *ip4_addr;
  114. const char sndMsg[] = "GET /index.html HTTP/1.0\r\n\r\n";
  115. /* declare wolfSSL objects */
  116. WOLFSSL_CTX *ctx;
  117. WOLFSSL *ssl;
  118. WOLFSSL_ENTER("tls_smp_client_task");
  119. doPeerCheck = 0;
  120. sendGet = 0;
  121. #ifdef DEBUG_WOLFSSL
  122. WOLFSSL_MSG("Debug ON");
  123. wolfSSL_Debugging_ON();
  124. ShowCiphers();
  125. #endif
  126. /* Initialize wolfSSL */
  127. wolfSSL_Init();
  128. /* Create a socket that uses an internet IPv4 address,
  129. * Sets the socket to be stream based (TCP),
  130. * 0 means choose the default protocol. */
  131. if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  132. ESP_LOGE(TAG,"ERROR: failed to create the socket\n");
  133. }
  134. ESP_LOGI(TAG, "get target IP address");
  135. hp = gethostbyname(TLS_SMP_TARGET_HOST);
  136. if (!hp) {
  137. ESP_LOGE(TAG, "Failed to get host name.");
  138. ip4_addr = NULL;
  139. } else {
  140. ip4_addr = (struct ip4_addr *)hp->h_addr;
  141. ESP_LOGI(TAG, IPSTR, IP2STR(ip4_addr));
  142. }
  143. /* Create and initialize WOLFSSL_CTX */
  144. if ((ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())) == NULL) {
  145. ESP_LOGE(TAG,"ERROR: failed to create WOLFSSL_CTX\n");
  146. }
  147. WOLFSSL_MSG("Loading...cert");
  148. /* Load client certificates into WOLFSSL_CTX */
  149. if ((ret = wolfSSL_CTX_load_verify_buffer(ctx, ca_cert_der_2048,
  150. sizeof_ca_cert_der_2048, WOLFSSL_FILETYPE_ASN1)) != SSL_SUCCESS) {
  151. ESP_LOGE(TAG,"ERROR: failed to load %d, please check the file.\n",ret);
  152. }
  153. /* not peer check */
  154. if( doPeerCheck == 0 ){
  155. wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, 0);
  156. } else {
  157. WOLFSSL_MSG("Loading... our cert");
  158. /* load our certificate */
  159. if ((ret = wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, client_cert_der_2048,
  160. sizeof_client_cert_der_2048, WOLFSSL_FILETYPE_ASN1)) != SSL_SUCCESS) {
  161. ESP_LOGE(TAG,"ERROR: failed to load chain %d, please check the file.\n",ret);
  162. }
  163. if ((ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx, client_key_der_2048,
  164. sizeof_client_key_der_2048, WOLFSSL_FILETYPE_ASN1)) != SSL_SUCCESS) {
  165. wolfSSL_CTX_free(ctx); ctx = NULL;
  166. ESP_LOGE(TAG,"ERROR: failed to load key %d, please check the file.\n", ret);
  167. }
  168. wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, 0);
  169. }
  170. /* Initialize the server address struct with zeros */
  171. memset(&servAddr, 0, sizeof(servAddr));
  172. /* Fill in the server address */
  173. servAddr.sin_family = AF_INET; /* using IPv4 */
  174. servAddr.sin_port = htons(DEFAULT_PORT); /* on DEFAULT_PORT */
  175. if(*ch >= '1' && *ch <= '9') {
  176. /* Get the server IPv4 address from the command line call */
  177. WOLFSSL_MSG("inet_pton");
  178. if ((ret = inet_pton(AF_INET, TLS_SMP_TARGET_HOST,
  179. &servAddr.sin_addr)) != 1) {
  180. ESP_LOGE(TAG,"ERROR: invalid address ret=%d\n", ret);
  181. }
  182. } else {
  183. servAddr.sin_addr.s_addr = ip4_addr->addr;
  184. }
  185. /* Connect to the server */
  186. sprintf(buff, "Connecting to server....%s(port:%d)", TLS_SMP_TARGET_HOST
  187. , DEFAULT_PORT);
  188. WOLFSSL_MSG(buff);
  189. printf("%s\n",buff);
  190. if ((ret = connect(sockfd, (struct sockaddr *)&servAddr,
  191. sizeof(servAddr))) == -1){
  192. ESP_LOGE(TAG,"ERROR: failed to connect ret=%d\n", ret);
  193. }
  194. WOLFSSL_MSG("Create a WOLFSSL object");
  195. /* Create a WOLFSSL object */
  196. if ((ssl = wolfSSL_new(ctx)) == NULL) {
  197. ESP_LOGE(TAG,"ERROR: failed to create WOLFSSL object\n");
  198. }
  199. /* when using atecc608a on esp32-wroom-32se */
  200. #if defined(WOLFSSL_ESPWROOM32SE) && defined(HAVE_PK_CALLBACKS) \
  201. && defined(WOLFSSL_ATECC508A)
  202. atcatls_set_callbacks(ctx);
  203. /* when using custom slot-allocation */
  204. #if defined(CUSTOM_SLOT_ALLOCATION)
  205. my_atmel_slotInit();
  206. atmel_set_slot_allocator(my_atmel_alloc, my_atmel_free);
  207. #endif
  208. #endif
  209. /* Attach wolfSSL to the socket */
  210. wolfSSL_set_fd(ssl, sockfd);
  211. WOLFSSL_MSG("Connect to wolfSSL on the server side");
  212. /* Connect to wolfSSL on the server side */
  213. if (wolfSSL_connect(ssl) != SSL_SUCCESS) {
  214. ESP_LOGE(TAG,"ERROR: failed to connect to wolfSSL\n");
  215. }
  216. /* Get a message for the server from stdin */
  217. WOLFSSL_MSG("Message for server: ");
  218. memset(buff, 0, sizeof(buff));
  219. if(sendGet){
  220. printf("SSL connect ok, sending GET...\n");
  221. len = XSTRLEN(sndMsg);
  222. strncpy(buff, sndMsg, len);
  223. buff[len] = '\0';
  224. } else {
  225. sprintf(buff, "message from esp32 tls client\n");
  226. len = strnlen(buff, sizeof(buff));
  227. }
  228. /* Send the message to the server */
  229. if (wolfSSL_write(ssl, buff, len) != len) {
  230. ESP_LOGE(TAG,"ERROR: failed to write\n");
  231. }
  232. /* Read the server data into our buff array */
  233. memset(buff, 0, sizeof(buff));
  234. if (wolfSSL_read(ssl, buff, sizeof(buff) - 1) == -1) {
  235. ESP_LOGE(TAG,"ERROR: failed to read\n");
  236. }
  237. /* Print to stdout any data the server sends */
  238. printf("Server:");
  239. printf("%s", buff);
  240. /* Cleanup and return */
  241. wolfSSL_free(ssl); /* Free the wolfSSL object */
  242. wolfSSL_CTX_free(ctx); /* Free the wolfSSL context object */
  243. wolfSSL_Cleanup(); /* Cleanup the wolfSSL environment */
  244. close(sockfd); /* Close the connection to the server */
  245. vTaskDelete(NULL);
  246. return; /* Return reporting a success */
  247. }