tls_bench.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882
  1. /* tls_bench.c
  2. *
  3. * Copyright (C) 2006-2017 wolfSSL Inc.
  4. *
  5. * This file is part of wolfSSL. (formerly known as CyaSSL)
  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-1301, USA
  20. */
  21. /*
  22. Example gcc build statement
  23. gcc -lwolfssl -lpthread -o tls_bench tls_bench.c
  24. ./tls_bench
  25. Or
  26. #include <examples/benchmark/tls_bench.h>
  27. bench_tls(args);
  28. */
  29. #ifdef HAVE_CONFIG_H
  30. #include <config.h>
  31. #endif
  32. #ifndef WOLFSSL_USER_SETTINGS
  33. #include <wolfssl/options.h>
  34. #endif
  35. #include <wolfssl/wolfcrypt/settings.h>
  36. #include <wolfssl/ssl.h>
  37. #include <wolfssl/test.h>
  38. #include <examples/benchmark/tls_bench.h>
  39. /* force certificate test buffers to be included via headers */
  40. #undef USE_CERT_BUFFERS_2048
  41. #define USE_CERT_BUFFERS_2048
  42. #undef USE_CERT_BUFFERS_256
  43. #define USE_CERT_BUFFERS_256
  44. #include <wolfssl/certs_test.h>
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #include <pthread.h>
  49. #include <unistd.h>
  50. #include <sys/time.h>
  51. /* Defaults for configuration parameters */
  52. #define THREAD_PAIRS 1 /* Thread pairs of server/client */
  53. #define MEM_BUFFER_SZ (1024*16) /* Must be large enough to handle max packet size */
  54. #define MIN_DHKEY_BITS 1024
  55. #define RUNTIME_SEC 1
  56. #define TEST_SIZE_BYTES (1024 * 1024)
  57. #define TEST_PACKET_SIZE 1024
  58. #define SHOW_VERBOSE 0 /* Default output is tab delimited format */
  59. static int argShowPeerInfo = 0; /* Show more info about wolfSSL configuration */
  60. static const char* kTestStr =
  61. "Biodiesel cupidatat marfa, cliche aute put a bird on it incididunt elit\n"
  62. "polaroid. Sunt tattooed bespoke reprehenderit. Sint twee organic id\n"
  63. "marfa. Commodo veniam ad esse gastropub. 3 wolf moon sartorial vero,\n"
  64. "plaid delectus biodiesel squid +1 vice. Post-ironic keffiyeh leggings\n"
  65. "selfies cray fap hoodie, forage anim. Carles cupidatat shoreditch, VHS\n"
  66. "small batch meggings kogi dolore food truck bespoke gastropub.\n"
  67. "\n"
  68. "Terry richardson adipisicing actually typewriter tumblr, twee whatever\n"
  69. "four loko you probably haven't heard of them high life. Messenger bag\n"
  70. "whatever tattooed deep v mlkshk. Brooklyn pinterest assumenda chillwave\n"
  71. "et, banksy ullamco messenger bag umami pariatur direct trade forage.\n"
  72. "Typewriter culpa try-hard, pariatur sint brooklyn meggings. Gentrify\n"
  73. "food truck next level, tousled irony non semiotics PBR ethical anim cred\n"
  74. "readymade. Mumblecore brunch lomo odd future, portland organic terry\n"
  75. "richardson elit leggings adipisicing ennui raw denim banjo hella. Godard\n"
  76. "mixtape polaroid, pork belly readymade organic cray typewriter helvetica\n"
  77. "four loko whatever street art yr farm-to-table.\n"
  78. "\n"
  79. "Vinyl keytar vice tofu. Locavore you probably haven't heard of them pug\n"
  80. "pickled, hella tonx labore truffaut DIY mlkshk elit cosby sweater sint\n"
  81. "et mumblecore. Elit swag semiotics, reprehenderit DIY sartorial nisi ugh\n"
  82. "nesciunt pug pork belly wayfarers selfies delectus. Ethical hoodie\n"
  83. "seitan fingerstache kale chips. Terry richardson artisan williamsburg,\n"
  84. "eiusmod fanny pack irony tonx ennui lo-fi incididunt tofu YOLO\n"
  85. "readymade. 8-bit sed ethnic beard officia. Pour-over iphone DIY butcher,\n"
  86. "ethnic art party qui letterpress nisi proident jean shorts mlkshk\n"
  87. "locavore.\n"
  88. "\n"
  89. "Narwhal flexitarian letterpress, do gluten-free voluptate next level\n"
  90. "banh mi tonx incididunt carles DIY. Odd future nulla 8-bit beard ut\n"
  91. "cillum pickled velit, YOLO officia you probably haven't heard of them\n"
  92. "trust fund gastropub. Nisi adipisicing tattooed, Austin mlkshk 90's\n"
  93. "small batch american apparel. Put a bird on it cosby sweater before they\n"
  94. "sold out pork belly kogi hella. Street art mollit sustainable polaroid,\n"
  95. "DIY ethnic ea pug beard dreamcatcher cosby sweater magna scenester nisi.\n"
  96. "Sed pork belly skateboard mollit, labore proident eiusmod. Sriracha\n"
  97. "excepteur cosby sweater, anim deserunt laborum eu aliquip ethical et\n"
  98. "neutra PBR selvage.\n"
  99. "\n"
  100. "Raw denim pork belly truffaut, irony plaid sustainable put a bird on it\n"
  101. "next level jean shorts exercitation. Hashtag keytar whatever, nihil\n"
  102. "authentic aliquip disrupt laborum. Tattooed selfies deserunt trust fund\n"
  103. "wayfarers. 3 wolf moon synth church-key sartorial, gastropub leggings\n"
  104. "tattooed. Labore high life commodo, meggings raw denim fingerstache pug\n"
  105. "trust fund leggings seitan forage. Nostrud ullamco duis, reprehenderit\n"
  106. "incididunt flannel sustainable helvetica pork belly pug banksy you\n"
  107. "probably haven't heard of them nesciunt farm-to-table. Disrupt nostrud\n"
  108. "mollit magna, sriracha sartorial helvetica.\n"
  109. "\n"
  110. "Nulla kogi reprehenderit, skateboard sustainable duis adipisicing viral\n"
  111. "ad fanny pack salvia. Fanny pack trust fund you probably haven't heard\n"
  112. "of them YOLO vice nihil. Keffiyeh cray lo-fi pinterest cardigan aliqua,\n"
  113. "reprehenderit aute. Culpa tousled williamsburg, marfa lomo actually anim\n"
  114. "skateboard. Iphone aliqua ugh, semiotics pariatur vero readymade\n"
  115. "organic. Marfa squid nulla, in laborum disrupt laboris irure gastropub.\n"
  116. "Veniam sunt food truck leggings, sint vinyl fap.\n"
  117. "\n"
  118. "Hella dolore pork belly, truffaut carles you probably haven't heard of\n"
  119. "them PBR helvetica in sapiente. Fashion axe ugh bushwick american\n"
  120. "apparel. Fingerstache sed iphone, jean shorts blue bottle nisi bushwick\n"
  121. "flexitarian officia veniam plaid bespoke fap YOLO lo-fi. Blog\n"
  122. "letterpress mumblecore, food truck id cray brooklyn cillum ad sed.\n"
  123. "Assumenda chambray wayfarers vinyl mixtape sustainable. VHS vinyl\n"
  124. "delectus, culpa williamsburg polaroid cliche swag church-key synth kogi\n"
  125. "magna pop-up literally. Swag thundercats ennui shoreditch vegan\n"
  126. "pitchfork neutra truffaut etsy, sed single-origin coffee craft beer.\n"
  127. "\n"
  128. "Odio letterpress brooklyn elit. Nulla single-origin coffee in occaecat\n"
  129. "meggings. Irony meggings 8-bit, chillwave lo-fi adipisicing cred\n"
  130. "dreamcatcher veniam. Put a bird on it irony umami, trust fund bushwick\n"
  131. "locavore kale chips. Sriracha swag thundercats, chillwave disrupt\n"
  132. "tousled beard mollit mustache leggings portland next level. Nihil esse\n"
  133. "est, skateboard art party etsy thundercats sed dreamcatcher ut iphone\n"
  134. "swag consectetur et. Irure skateboard banjo, nulla deserunt messenger\n"
  135. "bag dolor terry richardson sapiente.\n";
  136. #ifndef NO_DH
  137. /* dh1024 p */
  138. static const unsigned char p[] =
  139. {
  140. 0xE6, 0x96, 0x9D, 0x3D, 0x49, 0x5B, 0xE3, 0x2C, 0x7C, 0xF1, 0x80, 0xC3,
  141. 0xBD, 0xD4, 0x79, 0x8E, 0x91, 0xB7, 0x81, 0x82, 0x51, 0xBB, 0x05, 0x5E,
  142. 0x2A, 0x20, 0x64, 0x90, 0x4A, 0x79, 0xA7, 0x70, 0xFA, 0x15, 0xA2, 0x59,
  143. 0xCB, 0xD5, 0x23, 0xA6, 0xA6, 0xEF, 0x09, 0xC4, 0x30, 0x48, 0xD5, 0xA2,
  144. 0x2F, 0x97, 0x1F, 0x3C, 0x20, 0x12, 0x9B, 0x48, 0x00, 0x0E, 0x6E, 0xDD,
  145. 0x06, 0x1C, 0xBC, 0x05, 0x3E, 0x37, 0x1D, 0x79, 0x4E, 0x53, 0x27, 0xDF,
  146. 0x61, 0x1E, 0xBB, 0xBE, 0x1B, 0xAC, 0x9B, 0x5C, 0x60, 0x44, 0xCF, 0x02,
  147. 0x3D, 0x76, 0xE0, 0x5E, 0xEA, 0x9B, 0xAD, 0x99, 0x1B, 0x13, 0xA6, 0x3C,
  148. 0x97, 0x4E, 0x9E, 0xF1, 0x83, 0x9E, 0xB5, 0xDB, 0x12, 0x51, 0x36, 0xF7,
  149. 0x26, 0x2E, 0x56, 0xA8, 0x87, 0x15, 0x38, 0xDF, 0xD8, 0x23, 0xC6, 0x50,
  150. 0x50, 0x85, 0xE2, 0x1F, 0x0D, 0xD5, 0xC8, 0x6B,
  151. };
  152. /* dh1024 g */
  153. static const unsigned char g[] =
  154. {
  155. 0x02,
  156. };
  157. #endif
  158. typedef struct {
  159. unsigned char buf[MEM_BUFFER_SZ];
  160. int write_bytes;
  161. int write_idx;
  162. int read_bytes;
  163. int read_idx;
  164. pthread_t tid;
  165. pthread_mutex_t mutex;
  166. pthread_cond_t cond;
  167. int done;
  168. } memBuf_t;
  169. typedef struct {
  170. double connTime;
  171. double rxTime;
  172. double txTime;
  173. int connCount;
  174. int rxTotal;
  175. int txTotal;
  176. } stats_t;
  177. typedef struct {
  178. const char* cipher;
  179. /* The total number of bytes to transfer per connection */
  180. int numBytes;
  181. /* The data payload size in the packet. Will be padded if packet size > buffer size. */
  182. int packetSize;
  183. /* client messages to server in memory */
  184. memBuf_t to_server;
  185. /* server messages to client in memory */
  186. memBuf_t to_client;
  187. /* server */
  188. stats_t server_stats;
  189. /* client */
  190. stats_t client_stats;
  191. int shutdown;
  192. } info_t;
  193. /* Global vars for argument parsing */
  194. int myoptind = 0;
  195. char* myoptarg = NULL;
  196. /* server send callback */
  197. static int ServerSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
  198. {
  199. info_t* info = (info_t*)ctx;
  200. pthread_mutex_lock(&info->to_client.mutex);
  201. /* check for overflow */
  202. if (info->to_client.write_idx + sz > MEM_BUFFER_SZ) {
  203. pthread_mutex_unlock(&info->to_client.mutex);
  204. return -1;
  205. }
  206. memcpy(&info->to_client.buf[info->to_client.write_idx], buf, sz);
  207. info->to_client.write_idx += sz;
  208. info->to_client.write_bytes += sz;
  209. pthread_cond_signal(&info->to_client.cond);
  210. pthread_mutex_unlock(&info->to_client.mutex);
  211. (void)ssl;
  212. return sz;
  213. }
  214. /* server recv callback */
  215. static int ServerRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
  216. {
  217. info_t* info = (info_t*)ctx;
  218. pthread_mutex_lock(&info->to_server.mutex);
  219. while (info->to_server.write_idx - info->to_server.read_idx < sz && !info->to_client.done)
  220. pthread_cond_wait(&info->to_server.cond, &info->to_server.mutex);
  221. memcpy(buf, &info->to_server.buf[info->to_server.read_idx], sz);
  222. info->to_server.read_idx += sz;
  223. info->to_server.read_bytes += sz;
  224. /* if the rx has caught up with pending then reset buffer positions */
  225. if (info->to_server.read_bytes == info->to_server.write_bytes) {
  226. info->to_server.read_bytes = info->to_server.read_idx = 0;
  227. info->to_server.write_bytes = info->to_server.write_idx = 0;
  228. }
  229. pthread_mutex_unlock(&info->to_server.mutex);
  230. if (info->to_client.done != 0)
  231. return -1;
  232. (void)ssl;
  233. return sz;
  234. }
  235. /* client send callback */
  236. static int ClientSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
  237. {
  238. info_t* info = (info_t*)ctx;
  239. pthread_mutex_lock(&info->to_server.mutex);
  240. /* check for overflow */
  241. if (info->to_client.write_idx + sz > MEM_BUFFER_SZ) {
  242. pthread_mutex_unlock(&info->to_server.mutex);
  243. return -1;
  244. }
  245. memcpy(&info->to_server.buf[info->to_server.write_idx], buf, sz);
  246. info->to_server.write_idx += sz;
  247. info->to_server.write_bytes += sz;
  248. pthread_cond_signal(&info->to_server.cond);
  249. pthread_mutex_unlock(&info->to_server.mutex);
  250. (void)ssl;
  251. return sz;
  252. }
  253. /* client recv callback */
  254. static int ClientRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
  255. {
  256. info_t* info = (info_t*)ctx;
  257. pthread_mutex_lock(&info->to_client.mutex);
  258. while (info->to_client.write_idx - info->to_client.read_idx < sz)
  259. pthread_cond_wait(&info->to_client.cond, &info->to_client.mutex);
  260. memcpy(buf, &info->to_client.buf[info->to_client.read_idx], sz);
  261. info->to_client.read_idx += sz;
  262. info->to_client.read_bytes += sz;
  263. /* if the rx has caught up with pending then reset buffer positions */
  264. if (info->to_client.read_bytes == info->to_client.write_bytes) {
  265. info->to_client.read_bytes = info->to_client.read_idx = 0;
  266. info->to_client.write_bytes = info->to_client.write_idx = 0;
  267. }
  268. pthread_mutex_unlock(&info->to_client.mutex);
  269. (void)ssl;
  270. return sz;
  271. }
  272. static double gettime_secs(int reset)
  273. {
  274. struct timeval tv;
  275. gettimeofday(&tv, 0);
  276. (void)reset;
  277. return (double)tv.tv_sec + (double)tv.tv_usec / 1000000;
  278. }
  279. static void* client_thread(void* args)
  280. {
  281. info_t* info = (info_t*)args;
  282. unsigned char* buf;
  283. unsigned char *writeBuf;
  284. double start;
  285. int ret, bufSize;
  286. WOLFSSL_CTX* cli_ctx;
  287. WOLFSSL* cli_ssl;
  288. int haveShownPeerInfo = 0;
  289. /* set up client */
  290. cli_ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
  291. if (cli_ctx == NULL) err_sys("error creating ctx");
  292. #ifndef NO_CERTS
  293. #ifdef HAVE_ECC
  294. if (strstr(info->cipher, "ECDSA")) {
  295. ret = wolfSSL_CTX_load_verify_buffer(cli_ctx, ca_ecc_cert_der_256, sizeof_ca_ecc_cert_der_256, WOLFSSL_FILETYPE_ASN1);
  296. }
  297. else
  298. #endif
  299. {
  300. ret = wolfSSL_CTX_load_verify_buffer(cli_ctx, ca_cert_der_2048, sizeof_ca_cert_der_2048, WOLFSSL_FILETYPE_ASN1);
  301. }
  302. if (ret != WOLFSSL_SUCCESS) err_sys("error loading CA");
  303. #endif
  304. wolfSSL_CTX_SetIOSend(cli_ctx, ClientSend);
  305. wolfSSL_CTX_SetIORecv(cli_ctx, ClientRecv);
  306. /* set cipher suite */
  307. ret = wolfSSL_CTX_set_cipher_list(cli_ctx, info->cipher);
  308. if (ret != WOLFSSL_SUCCESS) err_sys("error setting cipher suite");
  309. #ifndef NO_DH
  310. wolfSSL_CTX_SetMinDhKey_Sz(cli_ctx, MIN_DHKEY_BITS);
  311. #endif
  312. /* Allocate and initialize a packet sized buffer */
  313. writeBuf = (unsigned char*)malloc(info->packetSize);
  314. if (writeBuf != NULL) {
  315. strncpy((char*)writeBuf, kTestStr, info->packetSize);
  316. *(writeBuf + info->packetSize) = '\0';
  317. }
  318. else {
  319. err_sys("failed to allocate memory");
  320. }
  321. while (!info->shutdown) {
  322. cli_ssl = wolfSSL_new(cli_ctx);
  323. if (cli_ssl == NULL) err_sys("error creating client object");
  324. wolfSSL_SetIOReadCtx(cli_ssl, info);
  325. wolfSSL_SetIOWriteCtx(cli_ssl, info);
  326. /* perform connect */
  327. start = gettime_secs(1);
  328. ret = wolfSSL_connect(cli_ssl);
  329. start = gettime_secs(0) - start;
  330. if (ret != WOLFSSL_SUCCESS) {
  331. if (info->shutdown)
  332. break;
  333. err_sys("error connecting client");
  334. }
  335. info->client_stats.connTime += start;
  336. if ((argShowPeerInfo) && (!haveShownPeerInfo)) {
  337. haveShownPeerInfo = 1;
  338. showPeer(cli_ssl);
  339. }
  340. /* Allocate buf after handshake is complete */
  341. bufSize = wolfSSL_GetMaxOutputSize(cli_ssl);
  342. if (bufSize > 0) {
  343. buf = (unsigned char*)malloc(bufSize);
  344. }
  345. else {
  346. buf = NULL;
  347. }
  348. if (buf != NULL) {
  349. /* write test message to server */
  350. while (info->client_stats.rxTotal < info->numBytes) {
  351. start = gettime_secs(1);
  352. ret = wolfSSL_write(cli_ssl, writeBuf, info->packetSize);
  353. info->client_stats.txTime += gettime_secs(0) - start;
  354. if (ret > 0) {
  355. info->client_stats.txTotal += ret;
  356. }
  357. /* read echo of message */
  358. start = gettime_secs(1);
  359. ret = wolfSSL_read(cli_ssl, buf, bufSize-1);
  360. info->client_stats.rxTime += gettime_secs(0) - start;
  361. if (ret > 0) {
  362. info->client_stats.rxTotal += ret;
  363. }
  364. /* validate echo */
  365. if (strncmp((char*)writeBuf, (char*)buf, info->packetSize) != 0) {
  366. err_sys("echo check failed!\n");
  367. }
  368. }
  369. free(buf);
  370. }
  371. else {
  372. err_sys("failed to allocate memory");
  373. }
  374. info->client_stats.connCount++;
  375. wolfSSL_free(cli_ssl);
  376. }
  377. /* clean up */
  378. wolfSSL_CTX_free(cli_ctx);
  379. free(writeBuf);
  380. pthread_cond_signal(&info->to_server.cond);
  381. info->to_client.done = 1;
  382. return NULL;
  383. }
  384. static void* server_thread(void* args)
  385. {
  386. info_t* info = (info_t*)args;
  387. unsigned char *buf;
  388. double start;
  389. int ret, len = 0, bufSize;
  390. WOLFSSL_CTX* srv_ctx;
  391. WOLFSSL* srv_ssl;
  392. /* set up server */
  393. srv_ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method());
  394. if (srv_ctx == NULL) err_sys("error creating server ctx");
  395. #ifndef NO_CERTS
  396. #ifdef HAVE_ECC
  397. if (strstr(info->cipher, "ECDSA")) {
  398. ret = wolfSSL_CTX_use_PrivateKey_buffer(srv_ctx, ecc_key_der_256, sizeof_ecc_key_der_256, WOLFSSL_FILETYPE_ASN1);
  399. }
  400. else
  401. #endif
  402. {
  403. ret = wolfSSL_CTX_use_PrivateKey_buffer(srv_ctx, server_key_der_2048, sizeof_server_key_der_2048, WOLFSSL_FILETYPE_ASN1);
  404. }
  405. if (ret != WOLFSSL_SUCCESS) err_sys("error loading server key");
  406. #ifdef HAVE_ECC
  407. if (strstr(info->cipher, "ECDSA")) {
  408. ret = wolfSSL_CTX_use_certificate_buffer(srv_ctx, serv_ecc_der_256, sizeof_serv_ecc_der_256, WOLFSSL_FILETYPE_ASN1);
  409. }
  410. else
  411. #endif
  412. {
  413. ret = wolfSSL_CTX_use_certificate_buffer(srv_ctx, server_cert_der_2048, sizeof_server_cert_der_2048, WOLFSSL_FILETYPE_ASN1);
  414. }
  415. if (ret != WOLFSSL_SUCCESS) err_sys("error loading server cert");
  416. #endif
  417. wolfSSL_CTX_SetIOSend(srv_ctx, ServerSend);
  418. wolfSSL_CTX_SetIORecv(srv_ctx, ServerRecv);
  419. /* set cipher suite */
  420. ret = wolfSSL_CTX_set_cipher_list(srv_ctx, info->cipher);
  421. if (ret != WOLFSSL_SUCCESS) err_sys("error setting cipher suite");
  422. #ifndef NO_DH
  423. wolfSSL_CTX_SetMinDhKey_Sz(srv_ctx, MIN_DHKEY_BITS);
  424. wolfSSL_CTX_SetTmpDH(srv_ctx, p, sizeof(p), g, sizeof(g));
  425. #endif
  426. while (!info->shutdown) {
  427. srv_ssl = wolfSSL_new(srv_ctx);
  428. if (srv_ssl == NULL) err_sys("error creating server object");
  429. wolfSSL_SetIOReadCtx(srv_ssl, info);
  430. wolfSSL_SetIOWriteCtx(srv_ssl, info);
  431. /* accept tls connection without tcp sockets */
  432. start = gettime_secs(1);
  433. ret = wolfSSL_accept(srv_ssl);
  434. start = gettime_secs(0) - start;
  435. if (ret != WOLFSSL_SUCCESS) {
  436. if (info->shutdown)
  437. break;
  438. err_sys("error on server accept");
  439. }
  440. info->server_stats.connTime += start;
  441. /* Allocate buf after handshake is complete */
  442. bufSize = wolfSSL_GetMaxOutputSize(srv_ssl);
  443. if (bufSize > 0) {
  444. buf = (unsigned char*)malloc(bufSize);
  445. }
  446. else {
  447. buf = NULL;
  448. }
  449. if (buf != NULL) {
  450. while (info->server_stats.txTotal < info->numBytes) {
  451. /* read msg post handshake from client */
  452. memset(buf, 0, bufSize);
  453. start = gettime_secs(1);
  454. ret = wolfSSL_read(srv_ssl, buf, bufSize-1);
  455. info->server_stats.rxTime += gettime_secs(0) - start;
  456. if (ret > 0) {
  457. info->server_stats.rxTotal += ret;
  458. len = ret;
  459. }
  460. /* write message back to client */
  461. start = gettime_secs(1);
  462. ret = wolfSSL_write(srv_ssl, buf, len);
  463. info->server_stats.txTime += gettime_secs(0) - start;
  464. if (ret > 0) {
  465. info->server_stats.txTotal += ret;
  466. }
  467. }
  468. free(buf);
  469. }
  470. else {
  471. err_sys("failed to allocate memory");
  472. }
  473. info->server_stats.connCount++;
  474. wolfSSL_free(srv_ssl);
  475. }
  476. /* clean up */
  477. wolfSSL_CTX_free(srv_ctx);
  478. pthread_cond_signal(&info->to_client.cond);
  479. info->to_server.done = 1;
  480. return NULL;
  481. }
  482. #ifdef __GNUC__
  483. #pragma GCC diagnostic push
  484. #pragma GCC diagnostic ignored "-Wformat-nonliteral"
  485. #endif
  486. static void print_stats(stats_t* wcStat, const char* desc, const char* cipher, int verbose)
  487. {
  488. const char* formatStr;
  489. if (verbose) {
  490. formatStr = "wolfSSL %s Benchmark on %s:\n"
  491. "\tTotal : %9d bytes\n"
  492. "\tNum Conns : %9d\n"
  493. "\tRx Total : %9.3f ms\n"
  494. "\tTx Total : %9.3f ms\n"
  495. "\tRx : %9.3f MB/s\n"
  496. "\tTx : %9.3f MB/s\n"
  497. "\tConnect : %9.3f ms\n"
  498. "\tConnect Avg : %9.3f ms\n";
  499. }
  500. else {
  501. formatStr = "%s\t%s\t%d\t%9d\t%9.3f\t%9.3f\t%9.3f\t%9.3f\t%9.3f\t%9.3f\n";
  502. }
  503. printf(formatStr,
  504. desc,
  505. cipher,
  506. wcStat->txTotal + wcStat->rxTotal,
  507. wcStat->connCount,
  508. wcStat->txTime * 1000,
  509. wcStat->rxTime * 1000,
  510. wcStat->txTotal / wcStat->txTime / 1024 / 1024,
  511. wcStat->rxTotal / wcStat->rxTime / 1024 / 1024,
  512. wcStat->connTime * 1000,
  513. wcStat->connTime * 1000 / wcStat->connCount);
  514. }
  515. static void Usage(void)
  516. {
  517. printf("tls_bench " LIBWOLFSSL_VERSION_STRING
  518. " NOTE: All files relative to wolfSSL home dir\n");
  519. printf("-? Help, print this usage\n");
  520. printf("-b <num> The total <num> bytes transferred per test connection, default %d\n", TEST_SIZE_BYTES);
  521. #ifdef DEBUG_WOLFSSL
  522. printf("-d Enable debug messages\n");
  523. #endif
  524. printf("-e List Every cipher suite available\n");
  525. printf("-i Show peer info\n");
  526. printf("-l <str> Cipher suite list (: delimited)\n");
  527. printf("-t <num> Time <num> (seconds) to run each test, default %d\n", RUNTIME_SEC);
  528. printf("-p <num> The packet size <num> in bytes [1-16kB], default %d\n", TEST_PACKET_SIZE);
  529. printf("-v Show verbose output\n");
  530. printf("-T <num> Thread pairs of server/client, default %d\n", THREAD_PAIRS);
  531. }
  532. static void ShowCiphers(void)
  533. {
  534. char ciphers[4096];
  535. int ret = wolfSSL_get_ciphers(ciphers, (int)sizeof(ciphers));
  536. if (ret == WOLFSSL_SUCCESS)
  537. printf("%s\n", ciphers);
  538. }
  539. #ifdef __GNUC__
  540. #pragma GCC diagnostic pop
  541. #endif
  542. int bench_tls(void* args)
  543. {
  544. info_t *theadInfo, *info;
  545. int i, doShutdown;
  546. char *cipher, *next_cipher, ciphers[4096];
  547. int argc = ((func_args*)args)->argc;
  548. char** argv = ((func_args*)args)->argv;
  549. int ch;
  550. /* Vars configured by command line arguments */
  551. int argRuntimeSec = RUNTIME_SEC;
  552. char *argCipherList = NULL;
  553. int argTestSizeBytes = TEST_SIZE_BYTES;
  554. int argTestPacketSize = TEST_PACKET_SIZE;
  555. int argThreadPairs = THREAD_PAIRS;
  556. int argShowVerbose = SHOW_VERBOSE;
  557. ((func_args*)args)->return_code = -1; /* error state */
  558. /* Initialize wolfSSL */
  559. wolfSSL_Init();
  560. /* Parse command line arguments */
  561. while ((ch = mygetopt(argc, argv, "?" "b:deil:p:t:vT:")) != -1) {
  562. switch (ch) {
  563. case '?' :
  564. Usage();
  565. exit(EXIT_SUCCESS);
  566. case 'b' :
  567. argTestSizeBytes = atoi(myoptarg);
  568. break;
  569. #ifdef DEBUG_WOLFSSL
  570. case 'd' :
  571. wolfSSL_Debugging_ON();
  572. break;
  573. #endif
  574. case 'e' :
  575. ShowCiphers();
  576. exit(EXIT_SUCCESS);
  577. case 'i' :
  578. argShowPeerInfo = 1;
  579. break;
  580. case 'l' :
  581. argCipherList = myoptarg;
  582. break;
  583. case 'p' :
  584. argTestPacketSize = atoi(myoptarg);
  585. break;
  586. case 't' :
  587. argRuntimeSec = atoi(myoptarg);
  588. break;
  589. case 'v' :
  590. argShowVerbose = 1;
  591. break;
  592. case 'T' :
  593. argThreadPairs = atoi(myoptarg);
  594. break;
  595. default:
  596. Usage();
  597. exit(MY_EX_USAGE);
  598. }
  599. }
  600. /* reset for test cases */
  601. myoptind = 0;
  602. if (argCipherList != NULL) {
  603. /* Use the list from CL argument */
  604. cipher = argCipherList;
  605. }
  606. else {
  607. /* Run for each cipher */
  608. wolfSSL_get_ciphers(ciphers, (int)sizeof(ciphers));
  609. cipher = ciphers;
  610. }
  611. /* Allocate test info array */
  612. theadInfo = (info_t*)malloc(sizeof(info_t) * argThreadPairs);
  613. if (theadInfo != NULL) {
  614. memset(theadInfo, 0, sizeof(info_t) * argThreadPairs);
  615. }
  616. /* parse by : */
  617. while ((cipher != NULL) && (cipher[0] != '\0') && (theadInfo != NULL)) {
  618. next_cipher = strchr(cipher, ':');
  619. if (next_cipher != NULL) {
  620. cipher[next_cipher - cipher] = '\0';
  621. }
  622. if (argShowVerbose) {
  623. printf("Cipher: %s\n", cipher);
  624. }
  625. for (i=0; i<argThreadPairs; i++) {
  626. info = (info_t*)memset(&theadInfo[i], 0, sizeof(info_t));
  627. info->cipher = cipher;
  628. info->numBytes = argTestSizeBytes;
  629. info->packetSize = argTestPacketSize;
  630. pthread_mutex_init(&info->to_server.mutex, NULL);
  631. pthread_mutex_init(&info->to_client.mutex, NULL);
  632. pthread_cond_init(&info->to_server.cond, NULL);
  633. pthread_cond_init(&info->to_client.cond, NULL);
  634. pthread_create(&info->to_server.tid, NULL, server_thread, info);
  635. pthread_create(&info->to_client.tid, NULL, client_thread, info);
  636. /* State that we won't be joining this thread */
  637. pthread_detach(info->to_server.tid);
  638. pthread_detach(info->to_client.tid);
  639. }
  640. /* run for x time */
  641. sleep(argRuntimeSec);
  642. /* mark threads to quit */
  643. for (i = 0; i < argThreadPairs; ++i) {
  644. info = &theadInfo[i];
  645. info->shutdown = 1;
  646. }
  647. /* Suspend shutdown until all threads are closed */
  648. do {
  649. doShutdown = 1;
  650. for (i = 0; i < argThreadPairs; ++i) {
  651. info = &theadInfo[i];
  652. if (!info->to_client.done || !info->to_server.done) {
  653. doShutdown = 0;
  654. sleep(1); /* Allow other threads to run */
  655. }
  656. }
  657. } while (!doShutdown);
  658. if (argShowVerbose) {
  659. printf("Shutdown complete\n");
  660. /* print results */
  661. for (i = 0; i < argThreadPairs; ++i) {
  662. info = &theadInfo[i];
  663. printf("\nThread %d\n", i);
  664. print_stats(&info->server_stats, "Server", info->cipher, 1);
  665. print_stats(&info->client_stats, "Server", info->cipher, 1);
  666. }
  667. }
  668. /* print combined results for more than one thread */
  669. stats_t cli_comb;
  670. stats_t srv_comb;
  671. memset(&cli_comb, 0, sizeof(cli_comb));
  672. memset(&srv_comb, 0, sizeof(srv_comb));
  673. for (i = 0; i < argThreadPairs; ++i) {
  674. info = &theadInfo[i];
  675. cli_comb.connCount += info->client_stats.connCount;
  676. srv_comb.connCount += info->server_stats.connCount;
  677. cli_comb.connTime += info->client_stats.connTime;
  678. srv_comb.connTime += info->server_stats.connTime;
  679. cli_comb.rxTotal += info->client_stats.rxTotal;
  680. srv_comb.rxTotal += info->server_stats.rxTotal;
  681. cli_comb.rxTime += info->client_stats.rxTime;
  682. srv_comb.rxTime += info->server_stats.rxTime;
  683. cli_comb.txTotal += info->client_stats.txTotal;
  684. srv_comb.txTotal += info->server_stats.txTotal;
  685. cli_comb.txTime += info->client_stats.txTime;
  686. srv_comb.txTime += info->server_stats.txTime;
  687. }
  688. if (argShowVerbose) {
  689. printf("Totals for %d Threads\n", argThreadPairs);
  690. }
  691. else {
  692. printf("Side\tCipher\tTotal Bytes\tNum Conns\tRx ms\tTx ms\tRx MB/s\tTx MB/s\tConnect Total ms\tConnect Avg ms\n");
  693. print_stats(&srv_comb, "Server", theadInfo[0].cipher, 0);
  694. print_stats(&cli_comb, "Client", theadInfo[0].cipher, 0);
  695. }
  696. /* target next cipher */
  697. cipher = (next_cipher != NULL) ? (next_cipher + 1) : NULL;
  698. }
  699. /* Cleanup the wolfSSL environment */
  700. wolfSSL_Cleanup();
  701. /* Free theadInfo array */
  702. free(theadInfo);
  703. /* Return reporting a success */
  704. return (((func_args*)args)->return_code = 0);
  705. }
  706. #ifndef NO_MAIN_DRIVER
  707. int main(int argc, char** argv)
  708. {
  709. func_args args;
  710. args.argc = argc;
  711. args.argv = argv;
  712. bench_tls(&args);
  713. return(args.return_code);
  714. }
  715. #endif