echoclient.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. /* echoclient.c
  2. *
  3. * Copyright (C) 2006-2023 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. #ifdef HAVE_CONFIG_H
  22. #include <config.h>
  23. #endif
  24. #include <wolfssl/wolfcrypt/settings.h>
  25. /* let's use cyassl layer AND cyassl openssl layer */
  26. #undef TEST_OPENSSL_COEXIST /* can't use this option with this example */
  27. #include <wolfssl/ssl.h>
  28. /* Force enable the compatibility macros for this example */
  29. #ifdef WOLFSSL_DTLS
  30. #include <wolfssl/error-ssl.h>
  31. #endif
  32. #if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET)
  33. #include <stdio.h>
  34. #include <string.h>
  35. #include "cmsis_os.h"
  36. #include "rl_fs.h"
  37. #include "rl_net.h"
  38. #include "wolfssl_MDK_ARM.h"
  39. #endif
  40. #include <wolfssl/test.h>
  41. #ifndef OPENSSL_EXTRA_X509_SMALL
  42. #define OPENSSL_EXTRA_X509_SMALL
  43. #endif
  44. #include <wolfssl/openssl/ssl.h>
  45. #include <examples/echoclient/echoclient.h>
  46. #ifndef NO_WOLFSSL_CLIENT
  47. #ifdef NO_FILESYSTEM
  48. #ifdef NO_RSA
  49. #error currently the example only tries to load in a RSA buffer
  50. #endif
  51. #undef USE_CERT_BUFFERS_2048
  52. #define USE_CERT_BUFFERS_2048
  53. #include <wolfssl/certs_test.h>
  54. #endif
  55. #ifdef WOLFSSL_ASYNC_CRYPT
  56. static int devId = INVALID_DEVID;
  57. #endif
  58. void echoclient_test(void* args)
  59. {
  60. SOCKET_T sockfd = 0;
  61. FILE* fin = stdin ;
  62. FILE* fout = stdout;
  63. #ifndef WOLFSSL_MDK_SHELL
  64. int inCreated = 0;
  65. int outCreated = 0;
  66. #endif
  67. char msg[1024];
  68. char reply[1024+1];
  69. SSL_METHOD* method = 0;
  70. SSL_CTX* ctx = 0;
  71. SSL* ssl = 0;
  72. int ret = 0, err = 0;
  73. int doDTLS = 0;
  74. int doPSK = 0;
  75. int sendSz;
  76. #ifndef WOLFSSL_MDK_SHELL
  77. int argc = 0;
  78. char** argv = 0;
  79. #endif
  80. word16 port;
  81. char buffer[WOLFSSL_MAX_ERROR_SZ];
  82. ((func_args*)args)->return_code = -1; /* error state */
  83. #ifndef WOLFSSL_MDK_SHELL
  84. argc = ((func_args*)args)->argc;
  85. argv = ((func_args*)args)->argv;
  86. if (argc >= 2) {
  87. fin = fopen(argv[1], "r");
  88. inCreated = 1;
  89. }
  90. if (argc >= 3) {
  91. fout = fopen(argv[2], "w");
  92. outCreated = 1;
  93. }
  94. #endif
  95. if (!fin) err_sys("can't open input file");
  96. if (!fout) err_sys("can't open output file");
  97. #ifdef WOLFSSL_DTLS
  98. doDTLS = 1;
  99. #endif
  100. #ifdef WOLFSSL_LEANPSK
  101. doPSK = 1;
  102. #endif
  103. #if defined(NO_RSA) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \
  104. !defined(HAVE_ED448)
  105. doPSK = 1;
  106. #endif
  107. (void)doPSK;
  108. #if defined(NO_MAIN_DRIVER) && !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_SHELL)
  109. port = ((func_args*)args)->signal->port;
  110. #else
  111. port = wolfSSLPort;
  112. #endif
  113. #if defined(WOLFSSL_DTLS)
  114. #ifdef WOLFSSL_DTLS13
  115. method = wolfDTLSv1_3_client_method();
  116. #elif !defined(WOLFSSL_NO_TLS12)
  117. method = DTLSv1_2_client_method();
  118. #endif
  119. #elif !defined(NO_TLS)
  120. #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_SNIFFER)
  121. method = wolfTLSv1_2_client_method();
  122. #else
  123. method = wolfSSLv23_client_method();
  124. #endif
  125. #elif defined(WOLFSSL_ALLOW_SSLV3)
  126. method = SSLv3_client_method();
  127. #else
  128. #error "no valid client method type"
  129. #endif
  130. ctx = SSL_CTX_new(method);
  131. #ifndef NO_FILESYSTEM
  132. #ifndef NO_RSA
  133. if (SSL_CTX_load_verify_locations(ctx, caCertFile, 0) != WOLFSSL_SUCCESS)
  134. err_sys("can't load ca file, Please run from wolfSSL home dir");
  135. #endif
  136. #ifdef HAVE_ECC
  137. if (SSL_CTX_load_verify_locations(ctx, caEccCertFile, 0) != WOLFSSL_SUCCESS)
  138. err_sys("can't load ca file, Please run from wolfSSL home dir");
  139. #elif defined(HAVE_ED25519)
  140. if (SSL_CTX_load_verify_locations(ctx, caEdCertFile, 0) != WOLFSSL_SUCCESS)
  141. err_sys("can't load ca file, Please run from wolfSSL home dir");
  142. #elif defined(HAVE_ED448)
  143. if (SSL_CTX_load_verify_locations(ctx, caEd448CertFile, 0) != WOLFSSL_SUCCESS)
  144. err_sys("can't load ca file, Please run from wolfSSL home dir");
  145. #endif
  146. #elif !defined(NO_CERTS)
  147. if (!doPSK)
  148. if (wolfSSL_CTX_load_verify_buffer(ctx, ca_cert_der_2048,
  149. sizeof_ca_cert_der_2048, WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS)
  150. err_sys("can't load ca buffer");
  151. #endif
  152. #if defined(WOLFSSL_SNIFFER)
  153. /* Only set if not running testsuite */
  154. if (XSTRSTR(argv[0], "testsuite") == NULL) {
  155. /* don't use EDH, can't sniff tmp keys */
  156. SSL_CTX_set_cipher_list(ctx, "AES256-SHA");
  157. }
  158. #endif
  159. #ifndef NO_PSK
  160. if (doPSK) {
  161. const char *defaultCipherList;
  162. wolfSSL_CTX_set_psk_client_callback(ctx, my_psk_client_cb);
  163. #ifdef HAVE_NULL_CIPHER
  164. defaultCipherList = "PSK-NULL-SHA256";
  165. #elif defined(HAVE_AESGCM) && !defined(NO_DH)
  166. #ifdef WOLFSSL_TLS13
  167. defaultCipherList = "TLS13-AES128-GCM-SHA256"
  168. #ifndef WOLFSSL_NO_TLS12
  169. ":DHE-PSK-AES128-GCM-SHA256"
  170. #endif
  171. ;
  172. #else
  173. defaultCipherList = "DHE-PSK-AES128-GCM-SHA256";
  174. #endif
  175. #elif defined(HAVE_AESGCM) && defined(WOLFSSL_TLS13)
  176. defaultCipherList = "TLS13-AES128-GCM-SHA256"
  177. #ifndef WOLFSSL_NO_TLS12
  178. ":DHE-PSK-AES128-GCM-SHA256"
  179. #endif
  180. ;
  181. #else
  182. defaultCipherList = "PSK-AES128-CBC-SHA256";
  183. #endif
  184. if (wolfSSL_CTX_set_cipher_list(ctx,defaultCipherList) !=WOLFSSL_SUCCESS)
  185. err_sys("client can't set cipher list 2");
  186. wolfSSL_CTX_set_psk_callback_ctx(ctx, (void*)defaultCipherList);
  187. }
  188. #endif
  189. #ifdef WOLFSSL_ENCRYPTED_KEYS
  190. SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
  191. #endif
  192. #if defined(WOLFSSL_MDK_ARM)
  193. wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, 0);
  194. #endif
  195. #ifdef WOLFSSL_ASYNC_CRYPT
  196. ret = wolfAsync_DevOpen(&devId);
  197. if (ret < 0) {
  198. fprintf(stderr, "Async device open failed\nRunning without async\n");
  199. }
  200. wolfSSL_CTX_SetDevId(ctx, devId);
  201. #endif /* WOLFSSL_ASYNC_CRYPT */
  202. ssl = SSL_new(ctx);
  203. tcp_connect(&sockfd, wolfSSLIP, port, doDTLS, 0, ssl);
  204. SSL_set_fd(ssl, sockfd);
  205. #if defined(USE_WINDOWS_API) && defined(WOLFSSL_DTLS) && defined(NO_MAIN_DRIVER)
  206. /* let echoserver bind first, TODO: add Windows signal like pthreads does */
  207. Sleep(100);
  208. #endif
  209. do {
  210. err = 0; /* Reset error */
  211. ret = SSL_connect(ssl);
  212. if (ret != WOLFSSL_SUCCESS) {
  213. err = SSL_get_error(ssl, 0);
  214. #ifdef WOLFSSL_ASYNC_CRYPT
  215. if (err == WC_PENDING_E) {
  216. ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
  217. if (ret < 0) break;
  218. }
  219. #endif
  220. }
  221. } while (err == WC_PENDING_E);
  222. if (ret != WOLFSSL_SUCCESS) {
  223. fprintf(stderr, "SSL_connect error %d, %s\n", err,
  224. ERR_error_string(err, buffer));
  225. err_sys("SSL_connect failed");
  226. }
  227. while (fgets(msg, sizeof(msg), fin) != 0) {
  228. sendSz = (int)XSTRLEN(msg);
  229. do {
  230. err = 0; /* reset error */
  231. ret = SSL_write(ssl, msg, sendSz);
  232. if (ret <= 0) {
  233. err = SSL_get_error(ssl, 0);
  234. #ifdef WOLFSSL_ASYNC_CRYPT
  235. if (err == WC_PENDING_E) {
  236. ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
  237. if (ret < 0) break;
  238. }
  239. #endif
  240. }
  241. } while (err == WC_PENDING_E);
  242. if (ret != sendSz) {
  243. fprintf(stderr, "SSL_write msg error %d, %s\n", err,
  244. ERR_error_string(err, buffer));
  245. err_sys("SSL_write failed");
  246. }
  247. if (strncmp(msg, "quit", 4) == 0) {
  248. LIBCALL_CHECK_RET(fputs("sending server shutdown command: quit!\n",
  249. fout));
  250. break;
  251. }
  252. if (strncmp(msg, "break", 5) == 0) {
  253. LIBCALL_CHECK_RET(fputs("sending server session close: break!\n",
  254. fout));
  255. break;
  256. }
  257. #ifndef WOLFSSL_MDK_SHELL
  258. while (sendSz)
  259. #endif
  260. {
  261. do {
  262. err = 0; /* reset error */
  263. ret = SSL_read(ssl, reply, sizeof(reply)-1);
  264. if (ret <= 0) {
  265. err = SSL_get_error(ssl, 0);
  266. #ifdef WOLFSSL_ASYNC_CRYPT
  267. if (err == WC_PENDING_E) {
  268. ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
  269. if (ret < 0) break;
  270. }
  271. #endif
  272. }
  273. } while (err == WC_PENDING_E);
  274. if (ret > 0) {
  275. reply[ret] = 0;
  276. LIBCALL_CHECK_RET(fputs(reply, fout));
  277. LIBCALL_CHECK_RET(fflush(fout));
  278. sendSz -= ret;
  279. }
  280. #ifdef WOLFSSL_DTLS
  281. else if (wolfSSL_dtls(ssl) && err == DECRYPT_ERROR) {
  282. /* This condition is OK. The packet should be dropped
  283. * silently when there is a decrypt or MAC error on
  284. * a DTLS record. */
  285. sendSz = 0;
  286. }
  287. #endif
  288. else {
  289. fprintf(stderr, "SSL_read msg error %d, %s\n", err,
  290. ERR_error_string(err, buffer));
  291. err_sys("SSL_read failed");
  292. }
  293. }
  294. }
  295. #ifdef WOLFSSL_DTLS
  296. strncpy(msg, "break", 6);
  297. sendSz = (int)strlen(msg);
  298. /* try to tell server done */
  299. do {
  300. err = 0; /* reset error */
  301. ret = SSL_write(ssl, msg, sendSz);
  302. if (ret <= 0) {
  303. err = SSL_get_error(ssl, 0);
  304. #ifdef WOLFSSL_ASYNC_CRYPT
  305. if (err == WC_PENDING_E) {
  306. ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
  307. if (ret < 0) break;
  308. }
  309. #endif
  310. }
  311. } while (err == WC_PENDING_E);
  312. #else
  313. SSL_shutdown(ssl);
  314. #endif
  315. SSL_free(ssl);
  316. SSL_CTX_free(ctx);
  317. #ifdef WOLFSSL_ASYNC_CRYPT
  318. wolfAsync_DevClose(&devId);
  319. #endif
  320. LIBCALL_CHECK_RET(fflush(fout));
  321. #ifndef WOLFSSL_MDK_SHELL
  322. if (inCreated) fclose(fin);
  323. if (outCreated) fclose(fout);
  324. #endif
  325. CloseSocket(sockfd);
  326. ((func_args*)args)->return_code = 0;
  327. }
  328. #endif /* !NO_WOLFSSL_CLIENT */
  329. /* so overall tests can pull in test function */
  330. #ifndef NO_MAIN_DRIVER
  331. int main(int argc, char** argv)
  332. {
  333. func_args args;
  334. #ifdef HAVE_WNR
  335. if (wc_InitNetRandom(wnrConfig, NULL, 5000) != 0)
  336. err_sys("Whitewood netRandom global config failed");
  337. #endif
  338. StartTCP();
  339. args.argc = argc;
  340. args.argv = argv;
  341. args.return_code = 0;
  342. wolfSSL_Init();
  343. #if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_MDK_SHELL)
  344. wolfSSL_Debugging_ON();
  345. #endif
  346. #ifndef WOLFSSL_TIRTOS
  347. ChangeToWolfRoot();
  348. #endif
  349. #ifndef NO_WOLFSSL_CLIENT
  350. echoclient_test(&args);
  351. #endif
  352. wolfSSL_Cleanup();
  353. #ifdef HAVE_WNR
  354. if (wc_FreeNetRandom() < 0)
  355. err_sys("Failed to free netRandom context");
  356. #endif /* HAVE_WNR */
  357. return args.return_code;
  358. }
  359. #endif /* NO_MAIN_DRIVER */