memory-tls.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. /* memory-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. /* IoT-safe client side demo
  22. - server uses software crypto and buffers
  23. - client uses IoT-Safe
  24. Client and server communicates in a cooperative
  25. scheduling mechanism within the same thread.
  26. Two buffers in memory are used for client<=>server communication.
  27. */
  28. #include <wolfssl/wolfcrypt/settings.h>
  29. #include <wolfssl/ssl.h>
  30. #include <wolfssl/error-ssl.h>
  31. #include <wolfssl/wolfcrypt/port/iotsafe/iotsafe.h>
  32. #include <stdio.h>
  33. #include <string.h>
  34. #include "ca-cert.c"
  35. /* The following define
  36. * activates mutual authentication */
  37. #define CLIENT_AUTH
  38. #define CLIENT_IOTSAFE
  39. #define CA_ECC
  40. static int client_state = 0;
  41. static int server_state = 0;
  42. static uint8_t cert_buffer[2048];
  43. static uint32_t cert_buffer_size;
  44. static WOLFSSL_CTX* srv_ctx = NULL;
  45. static WOLFSSL* srv_ssl = NULL;
  46. static WOLFSSL_CTX *cli_ctx = NULL;
  47. static WOLFSSL *cli_ssl = NULL;
  48. /* client messages to server in memory */
  49. #define TLS_BUFFERS_SZ (1024 * 8)
  50. static unsigned char to_server[TLS_BUFFERS_SZ];
  51. static int server_bytes;
  52. static int server_write_idx;
  53. static int server_read_idx;
  54. /* server messages to client in memory */
  55. static unsigned char to_client[TLS_BUFFERS_SZ];
  56. static int client_bytes;
  57. static int client_write_idx;
  58. static int client_read_idx;
  59. /* server send callback */
  60. int ServerSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
  61. {
  62. if (client_write_idx + sz > TLS_BUFFERS_SZ) {
  63. return WOLFSSL_CBIO_ERR_WANT_WRITE;
  64. }
  65. printf("=== Srv-Cli: %d\n", sz);
  66. XMEMCPY(&to_client[client_write_idx], buf, sz);
  67. client_write_idx += sz;
  68. client_bytes += sz;
  69. return sz;
  70. }
  71. /* server recv callback */
  72. int ServerRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
  73. {
  74. if (server_bytes - server_read_idx < sz) {
  75. return WOLFSSL_CBIO_ERR_WANT_READ;
  76. }
  77. XMEMCPY(buf, &to_server[server_read_idx], sz);
  78. server_read_idx += sz;
  79. if (server_read_idx == server_write_idx) {
  80. server_read_idx = server_write_idx = 0;
  81. server_bytes = 0;
  82. }
  83. printf("=== Srv RX: %d\n", sz);
  84. return sz;
  85. }
  86. /* client send callback */
  87. int ClientSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
  88. {
  89. if (server_write_idx + sz > TLS_BUFFERS_SZ)
  90. return WOLFSSL_CBIO_ERR_WANT_WRITE;
  91. printf("=== Cli->Srv: %d\n", sz);
  92. XMEMCPY(&to_server[server_write_idx], buf, sz);
  93. server_write_idx += sz;
  94. server_bytes += sz;
  95. return sz;
  96. }
  97. /* client recv callback */
  98. int ClientRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
  99. {
  100. if (client_bytes - client_read_idx < sz) {
  101. return WOLFSSL_CBIO_ERR_WANT_READ;
  102. }
  103. XMEMCPY(buf, &to_client[client_read_idx], sz);
  104. client_read_idx += sz;
  105. if (client_read_idx == client_write_idx) {
  106. client_read_idx = client_write_idx = 0;
  107. client_bytes = 0;
  108. }
  109. printf("=== Cli RX: %d\n", sz);
  110. return sz;
  111. }
  112. /* wolfSSL Client loop */
  113. static int client_loop(void)
  114. {
  115. /* set up client */
  116. int ret;
  117. const char* helloStr = "hello iot-safe wolfSSL";
  118. #if (IOTSAFE_ID_SIZE == 1)
  119. byte cert_file_id, privkey_id, keypair_id, peer_pubkey_id, peer_cert_id, serv_cert_id;
  120. byte ca_cert_id;
  121. #elif (IOTSAFE_ID_SIZE == 2)
  122. word16 cert_file_id, privkey_id, keypair_id, peer_pubkey_id, peer_cert_id, serv_cert_id;
  123. word16 ca_cert_id;
  124. #else
  125. word32 cert_file_id, privkey_id, keypair_id, peer_pubkey_id, peer_cert_id, serv_cert_id;
  126. word32 ca_cert_id;
  127. #endif
  128. cert_file_id = CRT_CLIENT_FILE_ID;
  129. privkey_id = PRIVKEY_ID;
  130. keypair_id = ECDH_KEYPAIR_ID;
  131. peer_pubkey_id = PEER_PUBKEY_ID;
  132. peer_cert_id = PEER_CERT_ID;
  133. ca_cert_id = CRT_SERVER_FILE_ID;
  134. serv_cert_id = CRT_SERVER_FILE_ID;
  135. printf("=== CLIENT step %d ===\n", client_state);
  136. if (client_state == 0) {
  137. printf("Client: Creating new CTX\n");
  138. #ifdef WOLFSSL_TLS13
  139. cli_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
  140. #else
  141. cli_ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
  142. #endif
  143. if (cli_ctx == NULL) {
  144. printf("Bad client ctx new");
  145. return 0;
  146. }
  147. printf("Client: Enabling IoT Safe in CTX\n");
  148. wolfSSL_CTX_iotsafe_enable(cli_ctx);
  149. printf("Loading CA\n");
  150. #ifdef SOFT_SERVER_CA
  151. ret = wolfSSL_CTX_load_verify_buffer(cli_ctx, ca_ecc_cert_der_256,
  152. sizeof_ca_ecc_cert_der_256, WOLFSSL_FILETYPE_ASN1);
  153. if (ret != WOLFSSL_SUCCESS) {
  154. printf("Bad CA\n");
  155. return -1;
  156. }
  157. #else
  158. cert_buffer_size = wolfIoTSafe_GetCert_ex(&ca_cert_id, IOTSAFE_ID_SIZE,
  159. cert_buffer,
  160. sizeof(cert_buffer));
  161. if (cert_buffer_size < 1) {
  162. printf("Bad server cert\n");
  163. return -1;
  164. }
  165. printf("Loaded Server CA from IoT-Safe, size = %lu\n",
  166. cert_buffer_size);
  167. ret = wolfSSL_CTX_load_verify_buffer(cli_ctx, cert_buffer,
  168. cert_buffer_size, WOLFSSL_FILETYPE_ASN1);
  169. #endif
  170. printf("Loading Server Certificate\n");
  171. #ifdef SOFT_SERVER_CERT
  172. /*
  173. ret = wolfSSL_CTX_load_verify_buffer(cli_ctx, serv_ecc_der_256,
  174. sizeof_serv_ecc_der_256, WOLFSSL_FILETYPE_ASN1);
  175. if (ret != WOLFSSL_SUCCESS) {
  176. printf("Bad Server certificate!\n");
  177. return -1;
  178. }
  179. */
  180. #else
  181. cert_buffer_size = wolfIoTSafe_GetCert_ex(&serv_cert_id,IOTSAFE_ID_SIZE,
  182. cert_buffer,
  183. sizeof(cert_buffer));
  184. if (cert_buffer_size < 1) {
  185. printf("Bad server certificate!\n");
  186. return -1;
  187. }
  188. printf("Loaded Server certificate from IoT-Safe, size = %lu\n",
  189. cert_buffer_size);
  190. if (wolfSSL_CTX_load_verify_buffer(cli_ctx, cert_buffer, cert_buffer_size,
  191. WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) {
  192. printf("Cannot load server cert\n");
  193. return -1;
  194. }
  195. #endif
  196. printf("Server certificate successfully imported.\n");
  197. wolfSSL_CTX_set_verify(cli_ctx, WOLFSSL_VERIFY_PEER, NULL);
  198. #ifdef CLIENT_AUTH
  199. cert_buffer_size = wolfIoTSafe_GetCert_ex(&cert_file_id, IOTSAFE_ID_SIZE,
  200. cert_buffer,
  201. sizeof(cert_buffer));
  202. if (cert_buffer_size < 1) {
  203. printf("Bad client cert\n");
  204. return -1;
  205. }
  206. printf("Loaded Client certificate from IoT-Safe, size = %lu\n",
  207. cert_buffer_size);
  208. if (wolfSSL_CTX_use_certificate_buffer(cli_ctx, cert_buffer,
  209. cert_buffer_size, WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) {
  210. printf("Cannot load client cert\n");
  211. return -1;
  212. }
  213. printf("Client certificate successfully imported.\n");
  214. #endif
  215. /* Setting IO Send/Receive functions to local memory-based message
  216. * passing (ClientSend, ClientRecv) */
  217. wolfSSL_CTX_SetIOSend(cli_ctx, ClientSend);
  218. wolfSSL_CTX_SetIORecv(cli_ctx, ClientRecv);
  219. printf("Creating new SSL object\n");
  220. cli_ssl = wolfSSL_new(cli_ctx);
  221. if (cli_ssl == NULL) {
  222. printf("bad client new");
  223. return 0;
  224. }
  225. printf("Setting TLS options: turn on IoT-safe for this socket\n");
  226. wolfSSL_iotsafe_on_ex(cli_ssl, &privkey_id, &keypair_id,
  227. &peer_pubkey_id, &peer_cert_id, IOTSAFE_ID_SIZE);
  228. #ifdef WOLFSSL_TLS13
  229. printf("Setting TLSv1.3 for SECP256R1 key share\n");
  230. wolfSSL_UseKeyShare(cli_ssl, WOLFSSL_ECC_SECP256R1);
  231. #endif
  232. client_state++;
  233. }
  234. if (client_state == 1) {
  235. printf("Connecting to server...\n");
  236. ret = wolfSSL_connect(cli_ssl);
  237. if (ret != WOLFSSL_SUCCESS) {
  238. if (wolfSSL_want_read(cli_ssl) || wolfSSL_want_write(cli_ssl)) {
  239. return 0;
  240. }
  241. printf("Error in client tls connect: %d\n",
  242. wolfSSL_get_error(cli_ssl, ret));
  243. client_state = 0;
  244. return -1;
  245. }
  246. printf("Client connected!\n");
  247. client_state++;
  248. }
  249. if (client_state == 2) {
  250. printf("Sending message: %s\n", helloStr);
  251. ret = wolfSSL_write(cli_ssl, helloStr, XSTRLEN(helloStr));
  252. if (ret >= 0) {
  253. printf("wolfSSL client test success!\n");
  254. wolfSSL_free(cli_ssl); cli_ssl = NULL;
  255. wolfSSL_CTX_free(cli_ctx); cli_ctx = NULL;
  256. client_state = 0;
  257. }
  258. else if (wolfSSL_get_error(cli_ssl, ret) != WOLFSSL_ERROR_WANT_WRITE) {
  259. printf("Error in client tls write");
  260. client_state = 0;
  261. return -1;
  262. }
  263. }
  264. return ret;
  265. }
  266. /* wolfSSL Server Loop */
  267. static int server_loop(void)
  268. {
  269. int ret;
  270. unsigned char buf[80];
  271. printf("=== SERVER step %d ===\n", server_state);
  272. if (server_state == 0) {
  273. #ifdef WOLFSSL_TLS13
  274. srv_ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method());
  275. #else
  276. srv_ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method());
  277. #endif
  278. if (srv_ctx == NULL) {
  279. printf("bad server ctx new");
  280. return -1;
  281. }
  282. #ifdef CLIENT_AUTH
  283. ret = wolfSSL_CTX_load_verify_buffer(srv_ctx, ca_ecc_cert_der_256,
  284. sizeof_ca_ecc_cert_der_256, WOLFSSL_FILETYPE_ASN1);
  285. if (ret != WOLFSSL_SUCCESS) {
  286. printf("Bad CA load: %d\n", ret);
  287. }
  288. ret = wolfSSL_CTX_load_verify_buffer(srv_ctx, cliecc_cert_der_256,
  289. sizeof_cliecc_cert_der_256, WOLFSSL_FILETYPE_ASN1);
  290. if (ret != WOLFSSL_SUCCESS) {
  291. printf("Bad Client cert load: %d\n", ret);
  292. }
  293. wolfSSL_CTX_set_verify(srv_ctx, WOLFSSL_VERIFY_PEER, NULL);
  294. #endif
  295. if (wolfSSL_CTX_use_PrivateKey_buffer(srv_ctx, ecc_key_der_256,
  296. sizeof_ecc_key_der_256, WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) {
  297. printf("Cannot load server private key\n");
  298. }
  299. if (wolfSSL_CTX_use_certificate_buffer(srv_ctx, serv_ecc_der_256,
  300. sizeof_serv_ecc_der_256, WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) {
  301. printf("Cannot load server cert\n");
  302. }
  303. wolfSSL_CTX_SetIOSend(srv_ctx, ServerSend);
  304. wolfSSL_CTX_SetIORecv(srv_ctx, ServerRecv);
  305. srv_ssl = wolfSSL_new(srv_ctx);
  306. if (srv_ssl == NULL) {
  307. printf("bad server new");
  308. return -1;
  309. }
  310. #ifdef WOLFSSL_TLS13
  311. printf("Setting TLSv1.3 for SECP256R1 key share\n");
  312. wolfSSL_UseKeyShare(srv_ssl, WOLFSSL_ECC_SECP256R1);
  313. #endif
  314. server_state++;
  315. }
  316. if (server_state == 1) {
  317. /* accept tls connection without tcp sockets */
  318. ret = wolfSSL_accept(srv_ssl);
  319. if (ret != WOLFSSL_SUCCESS) {
  320. if (wolfSSL_want_read(srv_ssl) || wolfSSL_want_write(srv_ssl)) {
  321. return 0;
  322. }
  323. printf("Error in server tls accept: %d\n",
  324. wolfSSL_get_error(srv_ssl, ret));
  325. server_state = 0;
  326. return -1;
  327. }
  328. printf("wolfSSL accept success!\n");
  329. server_state++;
  330. }
  331. if (server_state == 2) {
  332. ret = wolfSSL_read(srv_ssl, buf, sizeof(buf)-1);
  333. if (wolfSSL_get_error(srv_ssl, ret) == WOLFSSL_ERROR_WANT_READ) {
  334. return 0;
  335. }
  336. if (ret < 0) {
  337. printf("SERVER READ ERROR: %d\n", wolfSSL_get_error(srv_ssl, ret));
  338. return -1;
  339. }
  340. if (ret > 0) {
  341. printf("++++++ Server received msg from client: '%s'\n", buf);
  342. printf("IoT-Safe TEST SUCCESSFUL\n");
  343. wolfSSL_free(srv_ssl); srv_ssl = NULL;
  344. wolfSSL_CTX_free(srv_ctx); srv_ctx = NULL;
  345. server_state = 0;
  346. return -1; /* exit test loop, so it doesn't keep running forever */
  347. }
  348. }
  349. return 0;
  350. }
  351. int memory_tls_test(void)
  352. {
  353. int ret_s, ret_c;
  354. printf("Starting memory-tls test...\n");
  355. do {
  356. ret_s = server_loop();
  357. if (ret_s >= 0)
  358. ret_c = client_loop();
  359. } while ((ret_s >= 0) && (ret_c >= 0));
  360. /* clean up */
  361. wolfSSL_free(cli_ssl);
  362. wolfSSL_CTX_free(cli_ctx);
  363. wolfSSL_free(srv_ssl);
  364. wolfSSL_CTX_free(srv_ctx);
  365. return 0;
  366. }