testsuite.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. /* testsuite.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. #ifdef HAVE_CONFIG_H
  22. #include <config.h>
  23. #endif
  24. #include <wolfssl/wolfcrypt/settings.h>
  25. #include <wolfssl/ssl.h>
  26. #include <wolfssl/test.h>
  27. #include <wolfcrypt/test/test.h>
  28. #ifndef SINGLE_THREADED
  29. #ifdef OPENSSL_EXTRA
  30. #include <wolfssl/openssl/ssl.h>
  31. #endif
  32. #include <wolfssl/wolfcrypt/sha256.h>
  33. #include <wolfssl/wolfcrypt/ecc.h>
  34. #include <examples/echoclient/echoclient.h>
  35. #include <examples/echoserver/echoserver.h>
  36. #include <examples/server/server.h>
  37. #include <examples/client/client.h>
  38. #ifndef NO_SHA256
  39. void file_test(const char* file, byte* hash);
  40. #endif
  41. #if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT)
  42. #ifdef HAVE_STACK_SIZE
  43. static THREAD_RETURN simple_test(func_args*);
  44. #else
  45. static void simple_test(func_args*);
  46. #endif
  47. static int test_tls(func_args* server_args);
  48. static void show_ciphers(void);
  49. static void cleanup_output(void);
  50. static int validate_cleanup_output(void);
  51. enum {
  52. NUMARGS = 3
  53. };
  54. static const char *outputName;
  55. #endif
  56. int myoptind = 0;
  57. char* myoptarg = NULL;
  58. #ifndef NO_TESTSUITE_MAIN_DRIVER
  59. static int testsuite_test(int argc, char** argv);
  60. int main(int argc, char** argv)
  61. {
  62. return testsuite_test(argc, argv);
  63. }
  64. #endif /* NO_TESTSUITE_MAIN_DRIVER */
  65. #ifdef HAVE_STACK_SIZE
  66. /* Wrap TLS echo client to free thread locals. */
  67. static void *echoclient_test_wrapper(void* args) {
  68. echoclient_test(args);
  69. #if defined(HAVE_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS)
  70. wc_ecc_fp_free(); /* free per thread cache */
  71. #endif
  72. return (void *)0;
  73. }
  74. #endif
  75. int testsuite_test(int argc, char** argv)
  76. {
  77. #if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT)
  78. func_args server_args;
  79. tcp_ready ready;
  80. THREAD_TYPE serverThread;
  81. #ifndef USE_WINDOWS_API
  82. char tempName[] = "/tmp/output-XXXXXX";
  83. int len = 18;
  84. int num = 6;
  85. #else
  86. char tempName[] = "fnXXXXXX";
  87. int len = 8;
  88. int num = 6;
  89. #endif
  90. #ifdef HAVE_STACK_SIZE
  91. void *serverThreadStackContext = NULL;
  92. #endif
  93. int ret;
  94. #ifdef HAVE_WNR
  95. if (wc_InitNetRandom(wnrConfig, NULL, 5000) != 0) {
  96. err_sys("Whitewood netRandom global config failed");
  97. return -1237;
  98. }
  99. #endif /* HAVE_WNR */
  100. StartTCP();
  101. server_args.argc = argc;
  102. server_args.argv = argv;
  103. wolfSSL_Init();
  104. #if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND)
  105. wolfSSL_Debugging_ON();
  106. #endif
  107. #ifdef WC_RNG_SEED_CB
  108. wc_SetSeed_Cb(wc_GenerateSeed);
  109. #endif
  110. #if !defined(WOLFSSL_TIRTOS)
  111. ChangeToWolfRoot();
  112. #endif
  113. #ifdef WOLFSSL_TIRTOS
  114. fdOpenSession(Task_self());
  115. #endif
  116. server_args.signal = &ready;
  117. InitTcpReady(&ready);
  118. #ifndef NO_CRYPT_TEST
  119. /* wc_ test */
  120. #ifdef HAVE_STACK_SIZE
  121. StackSizeCheck(&server_args, wolfcrypt_test);
  122. #else
  123. wolfcrypt_test(&server_args);
  124. #endif
  125. if (server_args.return_code != 0) return server_args.return_code;
  126. #endif
  127. /* Simple wolfSSL client server test */
  128. #ifdef HAVE_STACK_SIZE
  129. StackSizeCheck(&server_args, (THREAD_RETURN (*)(void *))simple_test);
  130. #else
  131. simple_test(&server_args);
  132. #endif
  133. if (server_args.return_code != 0) return server_args.return_code;
  134. #if !defined(NETOS)
  135. /* Echo input wolfSSL client server test */
  136. #ifdef HAVE_STACK_SIZE
  137. StackSizeCheck_launch(&server_args, echoserver_test, &serverThread,
  138. &serverThreadStackContext);
  139. #else
  140. start_thread(echoserver_test, &server_args, &serverThread);
  141. #endif
  142. /* Create unique file name */
  143. outputName = mymktemp(tempName, len, num);
  144. if (outputName == NULL) {
  145. printf("Could not create unique file name");
  146. return EXIT_FAILURE;
  147. }
  148. ret = test_tls(&server_args);
  149. if (ret != 0) {
  150. cleanup_output();
  151. return ret;
  152. }
  153. /* Server won't quit unless TLS test has worked. */
  154. #ifdef HAVE_STACK_SIZE
  155. fputs("reaping echoserver_test: ", stdout);
  156. StackSizeCheck_reap(serverThread, serverThreadStackContext);
  157. #else
  158. join_thread(serverThread);
  159. #endif
  160. if (server_args.return_code != 0) {
  161. cleanup_output();
  162. return server_args.return_code;
  163. }
  164. #endif /* !NETOS */
  165. show_ciphers();
  166. #if !defined(NETOS)
  167. ret = validate_cleanup_output();
  168. if (ret != 0)
  169. return EXIT_FAILURE;
  170. #endif
  171. wolfSSL_Cleanup();
  172. FreeTcpReady(&ready);
  173. #ifdef WOLFSSL_TIRTOS
  174. fdCloseSession(Task_self());
  175. #endif
  176. #ifdef HAVE_WNR
  177. if (wc_FreeNetRandom() < 0)
  178. err_sys("Failed to free netRandom context");
  179. #endif /* HAVE_WNR */
  180. printf("\nAll tests passed!\n");
  181. #else
  182. (void)argc;
  183. (void)argv;
  184. #endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */
  185. return EXIT_SUCCESS;
  186. }
  187. #if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT)
  188. /* Perform a basic TLS handshake.
  189. *
  190. * First connection to echo a file.
  191. * Second to tell TLS server to quit.
  192. *
  193. * @param [in,out] server_args Object sent to server thread.
  194. * @return 0 on success.
  195. * @return echoclient error return code on failure.
  196. */
  197. static int test_tls(func_args* server_args)
  198. {
  199. func_args echo_args;
  200. char* myArgv[NUMARGS];
  201. char arg[3][32];
  202. /* Set up command line arguments for echoclient to send input file
  203. * and write echoed data to temporary output file. */
  204. myArgv[0] = arg[0];
  205. myArgv[1] = arg[1];
  206. myArgv[2] = arg[2];
  207. echo_args.argc = 3;
  208. echo_args.argv = myArgv;
  209. strcpy(arg[0], "testsuite");
  210. strcpy(arg[1], "input");
  211. strcpy(arg[2], outputName);
  212. /* Share the signal, it has the new port number in it. */
  213. echo_args.signal = server_args->signal;
  214. /* Ready to execute client - wait for server to be ready. */
  215. wait_tcp_ready(server_args);
  216. /* Do a client TLS connection. */
  217. #ifdef HAVE_STACK_SIZE
  218. fputs("echoclient_test #1: ", stdout);
  219. StackSizeCheck(&echo_args, echoclient_test_wrapper);
  220. #else
  221. echoclient_test(&echo_args);
  222. #endif
  223. if (echo_args.return_code != 0)
  224. return echo_args.return_code;
  225. #ifdef WOLFSSL_DTLS
  226. /* Ensure server is ready for UDP data. */
  227. wait_tcp_ready(server_args);
  228. #endif
  229. /* Next client connection - send quit to shutdown server. */
  230. echo_args.argc = 2;
  231. strcpy(echo_args.argv[1], "quit");
  232. /* Do a client TLS connection. */
  233. #ifdef HAVE_STACK_SIZE
  234. fputs("echoclient_test #2: ", stdout);
  235. StackSizeCheck(&echo_args, echoclient_test_wrapper);
  236. #else
  237. echoclient_test(&echo_args);
  238. #endif
  239. if (echo_args.return_code != 0)
  240. return echo_args.return_code;
  241. return 0;
  242. }
  243. /* Show cipher suites available. */
  244. static void show_ciphers()
  245. {
  246. char ciphers[WOLFSSL_CIPHER_LIST_MAX_SIZE];
  247. XMEMSET(ciphers, 0, sizeof(ciphers));
  248. wolfSSL_get_ciphers(ciphers, sizeof(ciphers)-1);
  249. printf("ciphers = %s\n", ciphers);
  250. }
  251. /* Cleanup temporary output file. */
  252. static void cleanup_output()
  253. {
  254. remove(outputName);
  255. }
  256. /* Validate output equals input using a hash. Remove temporary output file.
  257. *
  258. * @return 0 on success.
  259. * @return 1 on failure.
  260. */
  261. static int validate_cleanup_output()
  262. {
  263. #ifndef NO_SHA256
  264. byte input[WC_SHA256_DIGEST_SIZE];
  265. byte output[WC_SHA256_DIGEST_SIZE];
  266. file_test("input", input);
  267. file_test(outputName, output);
  268. #endif
  269. cleanup_output();
  270. #ifndef NO_SHA256
  271. if (memcmp(input, output, sizeof(input)) != 0)
  272. return 1;
  273. #endif
  274. return 0;
  275. }
  276. /* Simple server.
  277. *
  278. * @param [in] args Object for server data in thread.
  279. * @return Return code.
  280. */
  281. #ifdef HAVE_STACK_SIZE
  282. static THREAD_RETURN simple_test(func_args* args)
  283. #else
  284. static void simple_test(func_args* args)
  285. #endif
  286. {
  287. THREAD_TYPE serverThread;
  288. int i;
  289. func_args svrArgs;
  290. char *svrArgv[9];
  291. char argvs[9][32];
  292. func_args cliArgs;
  293. char *cliArgv[NUMARGS];
  294. char argvc[3][32];
  295. for (i = 0; i < 9; i++)
  296. svrArgv[i] = argvs[i];
  297. for (i = 0; i < 3; i++)
  298. cliArgv[i] = argvc[i];
  299. strcpy(argvs[0], "SimpleServer");
  300. svrArgs.argc = 1;
  301. svrArgs.argv = svrArgv;
  302. svrArgs.return_code = 0;
  303. #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_SNIFFER) && \
  304. !defined(WOLFSSL_TIRTOS)
  305. strcpy(argvs[svrArgs.argc++], "-p");
  306. strcpy(argvs[svrArgs.argc++], "0");
  307. #endif
  308. /* Set the last arg later, when it is known. */
  309. args->return_code = 0;
  310. svrArgs.signal = args->signal;
  311. start_thread(server_test, &svrArgs, &serverThread);
  312. wait_tcp_ready(&svrArgs);
  313. /* Setting the actual port number. */
  314. strcpy(argvc[0], "SimpleClient");
  315. cliArgs.argv = cliArgv;
  316. cliArgs.return_code = 0;
  317. #ifndef USE_WINDOWS_API
  318. cliArgs.argc = NUMARGS;
  319. strcpy(argvc[1], "-p");
  320. snprintf(argvc[2], sizeof(argvc[2]), "%d", (int)svrArgs.signal->port);
  321. #else
  322. cliArgs.argc = 1;
  323. #endif
  324. client_test(&cliArgs);
  325. if (cliArgs.return_code != 0) {
  326. args->return_code = cliArgs.return_code;
  327. #ifdef HAVE_STACK_SIZE
  328. return (THREAD_RETURN)0;
  329. #else
  330. return;
  331. #endif
  332. }
  333. join_thread(serverThread);
  334. if (svrArgs.return_code != 0) args->return_code = svrArgs.return_code;
  335. #ifdef HAVE_STACK_SIZE
  336. return (THREAD_RETURN)0;
  337. #endif
  338. }
  339. #endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */
  340. /* Wait for the server to be ready for a connection.
  341. *
  342. * @param [in] args Object to send to thread.
  343. */
  344. void wait_tcp_ready(func_args* args)
  345. {
  346. #if defined(_POSIX_THREADS) && !defined(__MINGW32__)
  347. pthread_mutex_lock(&args->signal->mutex);
  348. if (!args->signal->ready)
  349. pthread_cond_wait(&args->signal->cond, &args->signal->mutex);
  350. args->signal->ready = 0; /* reset */
  351. pthread_mutex_unlock(&args->signal->mutex);
  352. #elif defined(NETOS)
  353. (void)tx_mutex_get(&args->signal->mutex, TX_WAIT_FOREVER);
  354. /* TODO:
  355. * if (!args->signal->ready)
  356. * pthread_cond_wait(&args->signal->cond, &args->signal->mutex);
  357. * args->signal->ready = 0; */
  358. (void)tx_mutex_put(&args->signal->mutex);
  359. #else
  360. (void)args;
  361. #endif
  362. }
  363. /* Start a thread.
  364. *
  365. * @param [in] fun Function to executre in thread.
  366. * @param [in] args Object to send to function in thread.
  367. * @param [out] thread Handle to thread.
  368. */
  369. void start_thread(THREAD_FUNC fun, func_args* args, THREAD_TYPE* thread)
  370. {
  371. #if defined(_POSIX_THREADS) && !defined(__MINGW32__)
  372. pthread_create(thread, 0, fun, args);
  373. return;
  374. #elif defined(WOLFSSL_TIRTOS)
  375. /* Initialize the defaults and set the parameters. */
  376. Task_Params taskParams;
  377. Task_Params_init(&taskParams);
  378. taskParams.arg0 = (UArg)args;
  379. taskParams.stackSize = 65535;
  380. *thread = Task_create((Task_FuncPtr)fun, &taskParams, NULL);
  381. if (*thread == NULL) {
  382. printf("Failed to create new Task\n");
  383. }
  384. Task_yield();
  385. #elif defined(NETOS)
  386. /* This can be adjusted by defining in user_settings.h, will default to 65k
  387. * in the event it is undefined */
  388. #ifndef TESTSUITE_THREAD_STACK_SZ
  389. #define TESTSUITE_THREAD_STACK_SZ 65535
  390. #endif
  391. int result;
  392. static void * TestSuiteThreadStack = NULL;
  393. /* Assume only one additional thread is created concurrently. */
  394. if (TestSuiteThreadStack == NULL)
  395. {
  396. TestSuiteThreadStack = (void *)malloc(TESTSUITE_THREAD_STACK_SZ);
  397. if (TestSuiteThreadStack == NULL)
  398. {
  399. printf ("Stack allocation failure.\n");
  400. return;
  401. }
  402. }
  403. memset (thread, 0, sizeof *thread);
  404. /* first create the idle thread:
  405. * ARGS:
  406. * Param1: pointer to thread
  407. * Param2: name
  408. * Param3 and 4: entry function and input
  409. * Param5: pointer to thread stack
  410. * Param6: stack size
  411. * Param7 and 8: priority level and preempt threshold
  412. * Param9 and 10: time slice and auto-start indicator */
  413. result = tx_thread_create(thread,
  414. "WolfSSL TestSuiteThread",
  415. (entry_functionType)fun, (ULONG)args,
  416. TestSuiteThreadStack,
  417. TESTSUITE_THREAD_STACK_SZ,
  418. 2, 2,
  419. 1, TX_AUTO_START);
  420. if (result != TX_SUCCESS)
  421. {
  422. printf("Ethernet Bypass Application: failed to create idle thread!\n");
  423. }
  424. #else
  425. *thread = (THREAD_TYPE)_beginthreadex(0, 0, fun, args, 0, 0);
  426. #endif
  427. }
  428. /* Join thread to wait for completion.
  429. *
  430. * @param [in] thread Handle to thread.
  431. */
  432. void join_thread(THREAD_TYPE thread)
  433. {
  434. #if defined(_POSIX_THREADS) && !defined(__MINGW32__)
  435. pthread_join(thread, 0);
  436. #elif defined(WOLFSSL_TIRTOS)
  437. while(1) {
  438. if (Task_getMode(thread) == Task_Mode_TERMINATED) {
  439. Task_sleep(5);
  440. break;
  441. }
  442. Task_yield();
  443. }
  444. #elif defined(NETOS)
  445. /* TODO: */
  446. #else
  447. int res = WaitForSingleObject((HANDLE)thread, INFINITE);
  448. assert(res == WAIT_OBJECT_0);
  449. res = CloseHandle((HANDLE)thread);
  450. assert(res);
  451. (void)res; /* Suppress un-used variable warning */
  452. #endif
  453. }
  454. #ifndef NO_SHA256
  455. /* Create SHA-256 hash of the file based on filename.
  456. *
  457. * @param [in] file Name of file.
  458. * @parma [out] check Buffer to hold SHA-256 hash.
  459. */
  460. void file_test(const char* file, byte* check)
  461. {
  462. FILE* f;
  463. int i = 0, j, ret;
  464. wc_Sha256 sha256;
  465. byte buf[1024];
  466. byte shasum[WC_SHA256_DIGEST_SIZE];
  467. ret = wc_InitSha256(&sha256);
  468. if (ret != 0) {
  469. printf("Can't wc_InitSha256 %d\n", ret);
  470. return;
  471. }
  472. if( !( f = fopen( file, "rb" ) )) {
  473. printf("Can't open %s\n", file);
  474. return;
  475. }
  476. while( ( i = (int)fread(buf, 1, sizeof(buf), f )) > 0 ) {
  477. ret = wc_Sha256Update(&sha256, buf, i);
  478. if (ret != 0) {
  479. printf("Can't wc_Sha256Update %d\n", ret);
  480. fclose(f);
  481. return;
  482. }
  483. }
  484. ret = wc_Sha256Final(&sha256, shasum);
  485. wc_Sha256Free(&sha256);
  486. if (ret != 0) {
  487. printf("Can't wc_Sha256Final %d\n", ret);
  488. fclose(f);
  489. return;
  490. }
  491. XMEMCPY(check, shasum, sizeof(shasum));
  492. for(j = 0; j < WC_SHA256_DIGEST_SIZE; ++j )
  493. printf( "%02x", shasum[j] );
  494. printf(" %s\n", file);
  495. fclose(f);
  496. }
  497. #endif
  498. #else /* SINGLE_THREADED */
  499. int myoptind = 0;
  500. char* myoptarg = NULL;
  501. int main(int argc, char** argv)
  502. {
  503. func_args wolfcrypt_test_args;
  504. wolfcrypt_test_args.argc = argc;
  505. wolfcrypt_test_args.argv = argv;
  506. wolfSSL_Init();
  507. ChangeToWolfRoot();
  508. /* No TLS - only doing cryptographic algorithm testing. */
  509. wolfcrypt_test(&wolfcrypt_test_args);
  510. if (wolfcrypt_test_args.return_code != 0)
  511. return wolfcrypt_test_args.return_code;
  512. wolfSSL_Cleanup();
  513. printf("\nAll tests passed!\n");
  514. EXIT_TEST(EXIT_SUCCESS);
  515. }
  516. #endif /* SINGLE_THREADED */