1
0

wolfExamples.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <stdarg.h>
  5. #include <rt.h>
  6. #include <sys/types.h>
  7. #include <sys/socket.h>
  8. #include <netdb.h>
  9. #include <netinet/in.h>
  10. #include <arpa/inet.h>
  11. #include <io.h>
  12. #include "wolfExamples.h"
  13. #include <wolfssl/wolfcrypt/settings.h>
  14. #include <wolfssl/ssl.h>
  15. #include <wolfssl/certs_test.h>
  16. #include <wolfcrypt/test/test.h>
  17. #include <wolfcrypt/benchmark/benchmark.h>
  18. /*****************************************************************************
  19. * Globals
  20. ****************************************************************************/
  21. RTHANDLE hRootProcess;
  22. DWORD dwKtickInUsecs;
  23. INIT_STRUCT gInit;
  24. static int gServerExit = 0;
  25. static int gServerReady = 0;
  26. static const char menu1[] = "\r\n"
  27. "\tt. WolfCrypt Test\r\n"
  28. "\tb. WolfCrypt Benchmark\r\n"
  29. "\tc. WolfSSL Client Example\r\n"
  30. "\ts. WolfSSL Server Example\r\n"
  31. "\tl. WolfSSL Localhost Client/Server Example\r\n";
  32. /*****************************************************************************
  33. * Configuration
  34. ****************************************************************************/
  35. #define TLS_MAXDATASIZE 4096 /* maximum acceptable amount of data */
  36. #define TLS_PORT 11111 /* define default port number */
  37. #define TLS_HOST_LOCAL "127.0.0.1"
  38. #define TLS_HOST_REMOTE "192.168.0.112"
  39. #define SOCK_MAX_PENDING 5
  40. #define THREAD_BASE_PRIO 150
  41. /*****************************************************************************
  42. * TLS Client
  43. ****************************************************************************/
  44. int wolfExample_TLSClient(const char* ip, int port)
  45. {
  46. int ret = 0;
  47. WOLFSSL_CTX* ctx = NULL;
  48. WOLFSSL* ssl = NULL; /* create WOLFSSL object */
  49. int sockFd = -1; /* socket file descriptor */
  50. struct sockaddr_in servAddr; /* struct for server address */
  51. char sendBuff[TLS_MAXDATASIZE], rcvBuff[TLS_MAXDATASIZE];
  52. sockFd = socket(AF_INET, SOCK_STREAM, 0);
  53. if (sockFd < 0) {
  54. printf("Failed to create socket. Error: %d\n", errno);
  55. return errno;
  56. }
  57. memset(&servAddr, 0, sizeof(servAddr)); /* clears memory block for use */
  58. servAddr.sin_family = AF_INET; /* sets addressfamily to internet*/
  59. servAddr.sin_port = htons(port); /* sets port to defined port */
  60. /* looks for the server at the entered address (ip in the command line) */
  61. if (inet_pton(AF_INET, ip, &servAddr.sin_addr) < 1) {
  62. /* checks validity of address */
  63. ret = errno;
  64. printf("Invalid Address. Error: %d\n", ret);
  65. goto exit;
  66. }
  67. if (connect(sockFd, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0) {
  68. /* if socket fails to connect to the server*/
  69. ret = errno;
  70. printf("Connect error. Error: %d\n", ret);
  71. goto exit;
  72. }
  73. /* create and initialize WOLFSSL_CTX structure */
  74. if ((ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method())) == NULL) {
  75. printf("SSL_CTX_new error.\n");
  76. goto exit;
  77. }
  78. /* load CA certificates into wolfSSL_CTX. which will verify the server */
  79. ret = wolfSSL_CTX_load_verify_buffer(ctx, ca_cert_der_2048,
  80. sizeof_ca_cert_der_2048, SSL_FILETYPE_ASN1);
  81. if (ret != SSL_SUCCESS) {
  82. printf("Error %d loading CA cert\n", ret);
  83. goto exit;
  84. }
  85. if ((ssl = wolfSSL_new(ctx)) == NULL) {
  86. printf("wolfSSL_new error.\n");
  87. goto exit;
  88. }
  89. wolfSSL_set_fd(ssl, sockFd);
  90. ret = wolfSSL_connect(ssl);
  91. if (ret == SSL_SUCCESS) {
  92. printf("Message for server:\t");
  93. fgets(sendBuff, TLS_MAXDATASIZE, stdin);
  94. if (wolfSSL_write(ssl, sendBuff, strlen(sendBuff)) != strlen(sendBuff)) {
  95. /* the message is not able to send, or error trying */
  96. ret = wolfSSL_get_error(ssl, 0);
  97. printf("Write error: Error: %d\n", ret);
  98. goto exit;
  99. }
  100. memset(rcvBuff, 0, TLS_MAXDATASIZE);
  101. if (wolfSSL_read(ssl, rcvBuff, TLS_MAXDATASIZE) < 0) {
  102. /* the server failed to send data, or error trying */
  103. ret = wolfSSL_get_error(ssl, 0);
  104. printf("Read error. Error: %d\n", ret);
  105. goto exit;
  106. }
  107. printf("Received: \t%s\n", rcvBuff);
  108. }
  109. exit:
  110. /* frees all data before client termination */
  111. if (sockFd != -1)
  112. close(sockFd);
  113. wolfSSL_free(ssl);
  114. wolfSSL_CTX_free(ctx);
  115. gServerExit = 1;
  116. return ret;
  117. }
  118. /*****************************************************************************
  119. * TLS Server
  120. ****************************************************************************/
  121. int wolfExample_TLSServer(int port)
  122. {
  123. int ret = 0;
  124. WOLFSSL_CTX* ctx = NULL;
  125. WOLFSSL* ssl = NULL;
  126. int sockFd = -1, clientFd = -1;
  127. struct sockaddr_in serverAddr = {0}, clientAddr = {0};
  128. const char reply[] = "I hear ya fa shizzle!\n";
  129. int addrSize = sizeof(clientAddr);
  130. char buff[256];
  131. sockFd = socket(AF_INET, SOCK_STREAM, 0);
  132. if (sockFd < 0) {
  133. printf("Failed to create socket. Error: %d\n", errno);
  134. return errno;
  135. }
  136. /* create and initialize WOLFSSL_CTX structure */
  137. if ((ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method())) == NULL) {
  138. fprintf(stderr, "wolfSSL_CTX_new error.\n");
  139. goto exit;
  140. }
  141. /* Load server certificate into WOLFSSL_CTX */
  142. ret = wolfSSL_CTX_use_certificate_buffer(ctx, server_cert_der_2048,
  143. sizeof_server_cert_der_2048, SSL_FILETYPE_ASN1);
  144. if (ret != SSL_SUCCESS) {
  145. fprintf(stderr, "Error %d loading server-cert!\n", ret);
  146. goto exit;
  147. }
  148. /* Load server key into WOLFSSL_CTX */
  149. ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx, server_key_der_2048,
  150. sizeof_server_key_der_2048, SSL_FILETYPE_ASN1);
  151. if (ret != SSL_SUCCESS) {
  152. fprintf(stderr, "Error %d loading server-key!\n", ret);
  153. goto exit;
  154. }
  155. /* Initialize the server address struct to zero */
  156. memset((char *)&serverAddr, 0, sizeof(serverAddr));
  157. /* Fill the server's address family */
  158. serverAddr.sin_family = AF_INET;
  159. serverAddr.sin_addr.s_addr = INADDR_ANY;
  160. serverAddr.sin_port = htons(port);
  161. /* Attach the server socket to our port */
  162. if (bind(sockFd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) {
  163. printf("ERROR: failed to bind\n");
  164. goto exit;
  165. }
  166. printf("Waiting for a connection...\n");
  167. gServerReady = 1;
  168. /* Continuously accept connects while not in an active connection */
  169. while (gServerExit == 0) {
  170. /* listen for a new connection */
  171. ret = listen(sockFd, SOCK_MAX_PENDING);
  172. if (ret == 0) {
  173. /* Wait until a client connects */
  174. clientFd = accept(sockFd, (struct sockaddr*)&clientAddr, &addrSize);
  175. /* If fails to connect, loop back up and wait for a new connection */
  176. if (clientFd == -1) {
  177. printf("failed to accept the connection..\n");
  178. }
  179. /* If it connects, read in and reply to the client */
  180. else {
  181. printf("Client connected successfully\n");
  182. ssl = wolfSSL_new(ctx);
  183. if (ssl == NULL) {
  184. fprintf(stderr, "wolfSSL_new error.\n");
  185. break;
  186. }
  187. /* direct our ssl to our clients connection */
  188. wolfSSL_set_fd(ssl, clientFd);
  189. printf("Using Non-Blocking I/O: %d\n",
  190. wolfSSL_get_using_nonblock(ssl));
  191. for ( ; ; ) {
  192. /* Clear the buffer memory for anything possibly left over */
  193. memset(&buff, 0, sizeof(buff));
  194. /* Read the client data into our buff array */
  195. ret = wolfSSL_read(ssl, buff, sizeof(buff) - 1);
  196. if (ret > 0) {
  197. /* Print any data the client sends to the console */
  198. printf("Client: %s\n", buff);
  199. /* Reply back to the client */
  200. ret = wolfSSL_write(ssl, reply, sizeof(reply) - 1);
  201. if (ret < 0) {
  202. printf("wolfSSL_write error = %d\n",
  203. wolfSSL_get_error(ssl, ret));
  204. gServerExit = 1;
  205. break;
  206. }
  207. }
  208. /* if the client disconnects break the loop */
  209. else {
  210. if (ret < 0)
  211. printf("wolfSSL_read error = %d\n",
  212. wolfSSL_get_error(ssl, ret));
  213. else if (ret == 0)
  214. printf("The client has closed the connection.\n");
  215. gServerExit = 1;
  216. break;
  217. }
  218. }
  219. wolfSSL_free(ssl); /* Free the WOLFSSL object */
  220. ssl = NULL;
  221. }
  222. close(clientFd); /* close the connected socket */
  223. clientFd = -1;
  224. }
  225. } /* while */
  226. exit:
  227. if (clientFd != -1)
  228. close(clientFd);
  229. if (sockFd != -1)
  230. close(sockFd);
  231. wolfSSL_free(ssl); /* Free the WOLFSSL object */
  232. wolfSSL_CTX_free(ctx); /* Free WOLFSSL_CTX */
  233. return ret;
  234. }
  235. /*****************************************************************************
  236. * TLS Local Test
  237. ****************************************************************************/
  238. static void wolfSSLLocalServerThread(void* param)
  239. {
  240. int port = (int)((int*)param);
  241. wolfExample_TLSServer(port);
  242. }
  243. int wolfExample_TLSLocal(int port)
  244. {
  245. int ret;
  246. RTHANDLE srvHandle;
  247. /* start server thread */
  248. srvHandle = CreateRtThread(THREAD_BASE_PRIO + 10,
  249. (LPPROC)wolfSSLLocalServerThread, WOLF_EXAMPLES_STACK, (void*)port);
  250. if (srvHandle == BAD_RTHANDLE) {
  251. Fail("Cannot create server thread");
  252. return -1;
  253. }
  254. /* wait for server to be ready */
  255. while (gServerReady != 1) {
  256. RtSleep(0);
  257. }
  258. /* run client */
  259. ret = wolfExample_TLSClient(TLS_HOST_LOCAL, port);
  260. return ret;
  261. }
  262. /*****************************************************************************
  263. * Thread
  264. memset(&args, 0, sizeof(args));
  265. ****************************************************************************/
  266. typedef struct func_args {
  267. int argc;
  268. char** argv;
  269. int return_code;
  270. } func_args;
  271. static void wolfExampleThread(void* param)
  272. {
  273. func_args args;
  274. #ifdef DEBUG_WOLFSSL
  275. wolfSSL_Debugging_ON();
  276. #endif
  277. /* initialize wolfSSL */
  278. wolfSSL_Init();
  279. while (1) {
  280. char rc;
  281. gServerExit = 0;
  282. gServerReady = 0;
  283. printf("\r\n\t\t\t\tMENU\r\n");
  284. printf(menu1);
  285. printf("Please select one of the above options: ");
  286. rc = getchar();
  287. switch (rc) {
  288. case 't':
  289. printf("\nCrypt Test\n");
  290. wolfcrypt_test(&args);
  291. printf("Crypt Test: Return code %d\n", args.return_code);
  292. break;
  293. case 'b':
  294. printf("\nBenchmark Test\n");
  295. benchmark_test(&args);
  296. printf("Benchmark Test: Return code %d\n", args.return_code);
  297. break;
  298. case 'c':
  299. wolfExample_TLSClient(TLS_HOST_REMOTE, TLS_PORT);
  300. break;
  301. case 's':
  302. wolfExample_TLSServer(TLS_PORT);
  303. break;
  304. case 'l':
  305. wolfExample_TLSLocal(TLS_PORT);
  306. break;
  307. // All other cases go here
  308. default:
  309. if (rc != '\r' && rc != '\n')
  310. printf("\r\nSelection %c out of range\r\n", rc);
  311. break;
  312. }
  313. }
  314. wolfSSL_Cleanup();
  315. }
  316. /*****************************************************************************
  317. * FUNCTION: Catalog
  318. *
  319. * PARAMETERS: 1. handle of the process whose object directory must be used
  320. * 2. the object whose handle must be cataloged
  321. * 3. the name to be used (upto 14 characters)
  322. *
  323. * RETURNS: TRUE on success
  324. *
  325. * DESCRIPTION: If the given name already exists,
  326. * and the existing name refers to a non-existing object,
  327. * then the existing name is removed before cataloging.
  328. \*****************************************************************************/
  329. BOOLEAN Catalog(
  330. RTHANDLE hProcess,
  331. RTHANDLE hObject,
  332. LPSTR lpszName)
  333. {
  334. RTHANDLE hOld;
  335. if (CatalogRtHandle(hProcess, hObject, lpszName))
  336. return TRUE;
  337. // something wrong: check for the case mentioned above
  338. if (((hOld = LookupRtHandle(hProcess, lpszName, NO_WAIT)) != BAD_RTHANDLE) &&
  339. (GetRtHandleType(hOld) == INVALID_TYPE))
  340. {
  341. // this is the case mentioned above: remove the old entry and try again
  342. if (UncatalogRtHandle(hProcess, lpszName))
  343. return (CatalogRtHandle(hProcess, hObject, lpszName));
  344. }
  345. return FALSE;
  346. }
  347. /*****************************************************************************
  348. * FUNCTION: Cleanup (local function)
  349. *
  350. * DESCRIPTION:
  351. * Tell threads to delete themselves and wait a while;
  352. * if any thread still exists, kill it.
  353. * Remove all other objects as far as they have been created.
  354. \*****************************************************************************/
  355. void Cleanup(void)
  356. {
  357. // indicate that we are cleaning up
  358. gInit.state = CLEANUP_BUSY;
  359. gInit.bShutdown = TRUE;
  360. #ifdef _DEBUG
  361. fprintf(stderr, "wolfExamples started cleaning up\n");
  362. #endif
  363. // remove our name from the root process
  364. if (gInit.bCataloged) {
  365. if (!UncatalogRtHandle(hRootProcess, "wolfExample"))
  366. Fail("Cannot remove my own name");
  367. }
  368. #ifdef _DEBUG
  369. fprintf(stderr, "wolfExamples finished cleaning up\n");
  370. #endif
  371. // lie down
  372. exit(0);
  373. }
  374. /*****************************************************************************
  375. * FUNCTION: Fail
  376. *
  377. * PARAMETERS: same parameters as expected by printf
  378. *
  379. * DESCRIPTION:
  380. * If in debug mode, prints the message, appending a new line and the error number.
  381. * Then the current process is killed graciously:
  382. * If the current thread is the main thread, this is done directly.
  383. * if the current thread is another one, a terminate request is sent and
  384. * the function returns to the calling thread.
  385. \*****************************************************************************/
  386. void Fail(LPSTR lpszMessage, ...)
  387. {
  388. EXCEPTION eh;
  389. RTHANDLE hDelMbx;
  390. DWORD dwTerminate;
  391. #ifdef _DEBUG
  392. va_list ap;
  393. va_start(ap, lpszMessage);
  394. vfprintf(stderr, lpszMessage, ap);
  395. va_end(ap);
  396. fprintf(stderr, "\nError nr=%x %s\n", GetLastRtError(), GetRtErrorText(GetLastRtError()));
  397. #endif
  398. // make sure that exceptions are returned for inline handling
  399. GetRtExceptionHandlerInfo(THREAD_HANDLER, &eh);
  400. eh.ExceptionMode = 0;
  401. SetRtExceptionHandler(&eh);
  402. // if we had not started initializing yet, just get out
  403. if (BEFORE_INIT == gInit.state)
  404. exit(0);
  405. if (gInit.hMain == GetRtThreadHandles(THIS_THREAD))
  406. {
  407. // this is the main thread:
  408. // if we are busy initializing, then do Cleanup
  409. if (INIT_BUSY == gInit.state)
  410. Cleanup(); // does not return
  411. // this is the main thread, but we are not initializing: just return
  412. return;
  413. }
  414. // this is not the main thread:
  415. // ask main thread to do cleanup
  416. // (allow some time to setup the deletion mailbox, ignore errors)
  417. hDelMbx = LookupRtHandle(NULL_RTHANDLE, "R?EXIT_MBOX", 5000);
  418. dwTerminate = TERMINATE;
  419. SendRtData(hDelMbx, &dwTerminate, 4);
  420. }
  421. /*****************************************************************************
  422. *
  423. * FUNCTION: UsecsToKticks
  424. *
  425. * PARAMETERS: 1. number of usecs
  426. *
  427. * RETURNS: number of low level ticks
  428. *
  429. * DESCRIPTION: returns the parameter if it is WAIT_FOREVER
  430. * otherwise rounds up to number of low level ticks
  431. \*****************************************************************************/
  432. DWORD UsecsToKticks(DWORD dwUsecs)
  433. {
  434. if (dwUsecs == WAIT_FOREVER)
  435. return WAIT_FOREVER;
  436. return (dwUsecs + dwKtickInUsecs - 1) / dwKtickInUsecs;
  437. }
  438. /*****************************************************************************
  439. * FUNCTION: main
  440. *
  441. * DESCRIPTION:
  442. * This is the main program module.
  443. * It creates global objects and all threads.
  444. * The main thread then waits for notifications and acts accordingly
  445. \*****************************************************************************/
  446. int main(int argc, char* argv[])
  447. {
  448. SYSINFO sysinfo;
  449. EVENTINFO eiEventInfo;
  450. RTHANDLE taskHandle;
  451. #ifdef _DEBUG
  452. fprintf(stderr, "wolfExamples started\n");
  453. #endif
  454. // obtain handle of root process (cannot fail)
  455. hRootProcess = GetRtThreadHandles(ROOT_PROCESS);
  456. // initialize the structure for cleaning up
  457. memset(&gInit, 0, sizeof(gInit));
  458. gInit.state = BEFORE_INIT;
  459. // get low level tick length in usecs
  460. if (!CopyRtSystemInfo(&sysinfo))
  461. Fail("Cannot copy system info");
  462. dwKtickInUsecs = 10000 / sysinfo.KernelTickRatio;
  463. if (dwKtickInUsecs == 0)
  464. Fail("Invalid low level tick length");
  465. // adjust process max priority (ignore error)
  466. // TODO adjust the 2nd parameter to a value closer to zero if you want to allow more priorities
  467. SetRtProcessMaxPriority(NULL_RTHANDLE, THREAD_BASE_PRIO);
  468. // obtain main thread's handle
  469. gInit.hMain = GetRtThreadHandles(THIS_THREAD);
  470. gInit.state = INIT_BUSY;
  471. // attempt to catalog the thread but ignore error
  472. Catalog(NULL_RTHANDLE, gInit.hMain, "TMain");
  473. // catalog the handle of this process in the root process
  474. if (!Catalog(hRootProcess, GetRtThreadHandles(THIS_PROCESS), "wolfExample")) {
  475. Fail("Cannot catalog process name");
  476. }
  477. gInit.bCataloged = TRUE;
  478. // create thread
  479. taskHandle = CreateRtThread(THREAD_BASE_PRIO + 20,
  480. (LPPROC)wolfExampleThread, WOLF_EXAMPLES_STACK, 0);
  481. if (taskHandle == BAD_RTHANDLE) {
  482. Fail("Cannot create thread");
  483. }
  484. // indicate that initialization has finished
  485. gInit.state = INIT_DONE;
  486. #ifdef _DEBUG
  487. fprintf(stderr, "wolfExamples finished initialization\n");
  488. #endif
  489. // wait for notifications
  490. while (RtNotifyEvent(RT_SYSTEM_NOTIFICATIONS | RT_EXIT_NOTIFICATIONS,
  491. WAIT_FOREVER, &eiEventInfo))
  492. {
  493. switch(eiEventInfo.dwNotifyType)
  494. {
  495. case TERMINATE:
  496. // TODO: this process should terminate
  497. // cleanup the environment
  498. Cleanup(); // does not return
  499. case NT_HOST_UP:
  500. // TODO: react to a Windows host that has come back
  501. break;
  502. case NT_BLUESCREEN:
  503. // TODO: react to a Windows blue screen
  504. break;
  505. case KERNEL_STOPPING:
  506. // TODO: react to the INtime kernel stopping
  507. break;
  508. case NT_HOST_HIBERNATE:
  509. // TODO: react to the Windows host going in hibernation
  510. break;
  511. case NT_HOST_STANDBY:
  512. // TODO: react to the Windows host going in standby mode
  513. break;
  514. case NT_HOST_SHUTDOWN_PENDING:
  515. // TODO: react to a Windows host that is about to shutdown
  516. break;
  517. }
  518. }
  519. Fail("Notify failed");
  520. return 0;
  521. }