1 /* wolfssl_example.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
22 #include "wolfssl_example.h"
23
24 /* force certificate test buffers to be included via headers */
25 #undef USE_CERT_BUFFERS_2048
26 #define USE_CERT_BUFFERS_2048
27 #undef USE_CERT_BUFFERS_256
28 #define USE_CERT_BUFFERS_256
29 #include <wolfssl/certs_test.h>
30
31 #include <wolfssl/wolfcrypt/hash.h> /* WC_MAX_DIGEST_SIZE */
32
33 #ifndef SINGLE_THREADED
34 #include <cmsis_os.h>
35
36 #ifdef WOLFSSL_DEBUG_MEMORY
37 /* for memory debugging */
38 #include <task.h>
39 #endif
40 #endif
41
42 #include <stdio.h>
43 #include <string.h>
44
45 /*****************************************************************************
46 * Configuration
47 ****************************************************************************/
48
49 /* Defaults for configuration parameters */
50 #define BENCH_DEFAULT_HOST "localhost"
51 #define BENCH_DEFAULT_PORT 11112
52 #define BENCH_RUNTIME_SEC 20
53 #define BENCH_SHOW_PEER_INFO 1
54 #define TEST_PACKET_SIZE (2 * 1024) /* TLS packet size */
55 #ifdef BENCH_EMBEDDED
56 #define TEST_MAX_SIZE (4 * 1024)
57 #else
58 #define TEST_MAX_SIZE (32 * 1024) /* Total bytes to benchmark */
59 #endif
60 /* Must be large enough to handle max packet size - TLS header MAX_MSG_EXTRA + MAX DIGEST */
61 #define MEM_BUFFER_SZ (TEST_PACKET_SIZE + 38 + WC_MAX_DIGEST_SIZE)
62 /* make sure memory buffer size is large enough */
63 #if MEM_BUFFER_SZ < 2048
64 #undef MEM_BUFFER_SZ
65 #define MEM_BUFFER_SZ 2048
66 #endif
67 #define SHOW_VERBOSE 0 /* 0=tab del (minimal), 1=info, 2=debug, 3=debug w/wolf logs */
68 #ifndef WOLFSSL_CIPHER_LIST_MAX_SIZE
69 #define WOLFSSL_CIPHER_LIST_MAX_SIZE 2048
70 #endif
71 #if 0
72 /* define this to test only a specific cipher suite(s) (colon separated) */
73 #define TEST_CIPHER_SUITE "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256"
74 #endif
75 #if 0
76 /* use non-blocking mode for read/write IO */
77 #define BENCH_USE_NONBLOCK
78 #endif
79 #ifndef RECV_WAIT_TIMEOUT
80 #define RECV_WAIT_TIMEOUT 10000
81 #endif
82
83 /*****************************************************************************
84 * Private types/enumerations/variables
85 ****************************************************************************/
86
87 #ifdef WOLFSSL_STATIC_MEMORY
88 #if 1 /* on-chip RAM */
89 #define RAM_STATIC
90 #else /* external RAM */
91 /* requires .ld to be updated with ".extram" section */
92 #define RAM_STATIC __attribute__ ((section (".extram")))
93 #endif
94 #define WOLF_GEN_MEM (20*1024)
95 #define WOLF_TLS_GEN_MEM (90*1024)
96 #define WOLF_TLS_IO_POOL_MEM (35*1024)
97
98 RAM_STATIC static byte gWolfMem[WOLF_GEN_MEM];
99 RAM_STATIC static byte gWolfCTXCli[WOLF_TLS_GEN_MEM];
100 RAM_STATIC static byte gWolfIOCli[WOLF_TLS_IO_POOL_MEM];
101 RAM_STATIC static byte gWolfCTXSrv[WOLF_TLS_GEN_MEM];
102 RAM_STATIC static byte gWolfIOSrv[WOLF_TLS_IO_POOL_MEM];
103
104 WOLFSSL_HEAP_HINT* HEAP_HINT = NULL;
105 #endif /* WOLFSSL_STATIC_MEMORY */
106
107
108 /* UART definitions */
109 #ifndef HAL_CONSOLE_UART
110 #define HAL_CONSOLE_UART huart4
111 #endif
112 extern UART_HandleTypeDef HAL_CONSOLE_UART;
113
114 /*****************************************************************************
115 * Public types/enumerations/variables
116 ****************************************************************************/
117 typedef struct func_args {
118 int argc;
119 char** argv;
120 int return_code;
121 } func_args;
122
123 const char menu1[] = "\n"
124 "\tt. WolfCrypt Test\n"
125 "\tb. WolfCrypt Benchmark\n"
126 "\tl. WolfSSL TLS Bench\n"
127 "\te. Show Cipher List\n";
128
129 static void PrintMemStats(void);
130 double current_time(void);
131
132
133 #if (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && \
134 !defined(WOLFCRYPT_ONLY) && !defined(SINGLE_THREADED)
135
136 static const char* kShutdown = "shutdown";
137
138 static const char* kTestStr =
139 "Biodiesel cupidatat marfa, cliche aute put a bird on it incididunt elit\n"
140 "polaroid. Sunt tattooed bespoke reprehenderit. Sint twee organic id\n"
141 "marfa. Commodo veniam ad esse gastropub. 3 wolf moon sartorial vero,\n"
142 "plaid delectus biodiesel squid +1 vice. Post-ironic keffiyeh leggings\n"
143 "selfies cray fap hoodie, forage anim. Carles cupidatat shoreditch, VHS\n"
144 "small batch meggings kogi dolore food truck bespoke gastropub.\n"
145 "\n"
146 "Terry richardson adipisicing actually typewriter tumblr, twee whatever\n"
147 "four loko you probably haven't heard of them high life. Messenger bag\n"
148 "whatever tattooed deep v mlkshk. Brooklyn pinterest assumenda chillwave\n"
149 "et, banksy ullamco messenger bag umami pariatur direct trade forage.\n"
150 "Typewriter culpa try-hard, pariatur sint brooklyn meggings. Gentrify\n"
151 "food truck next level, tousled irony non semiotics PBR ethical anim cred\n"
152 "readymade. Mumblecore brunch lomo odd future, portland organic terry\n"
153 "richardson elit leggings adipisicing ennui raw denim banjo hella. Godard\n"
154 "mixtape polaroid, pork belly readymade organic cray typewriter helvetica\n"
155 "four loko whatever street art yr farm-to-table.\n"
156 "\n"
157 "Vinyl keytar vice tofu. Locavore you probably haven't heard of them pug\n"
158 "pickled, hella tonx labore truffaut DIY mlkshk elit cosby sweater sint\n"
159 "et mumblecore. Elit swag semiotics, reprehenderit DIY sartorial nisi ugh\n"
160 "nesciunt pug pork belly wayfarers selfies delectus. Ethical hoodie\n"
161 "seitan fingerstache kale chips. Terry richardson artisan williamsburg,\n"
162 "eiusmod fanny pack irony tonx ennui lo-fi incididunt tofu YOLO\n"
163 "readymade. 8-bit sed ethnic beard officia. Pour-over iphone DIY butcher,\n"
164 "ethnic art party qui letterpress nisi proident jean shorts mlkshk\n"
165 "locavore.\n"
166 "\n"
167 "Narwhal flexitarian letterpress, do gluten-free voluptate next level\n"
168 "banh mi tonx incididunt carles DIY. Odd future nulla 8-bit beard ut\n"
169 "cillum pickled velit, YOLO officia you probably haven't heard of them\n"
170 "trust fund gastropub. Nisi adipisicing tattooed, Austin mlkshk 90's\n"
171 "small batch american apparel. Put a bird on it cosby sweater before they\n"
172 "sold out pork belly kogi hella. Street art mollit sustainable polaroid,\n"
173 "DIY ethnic ea pug beard dreamcatcher cosby sweater magna scenester nisi.\n"
174 "Sed pork belly skateboard mollit, labore proident eiusmod. Sriracha\n"
175 "excepteur cosby sweater, anim deserunt laborum eu aliquip ethical et\n"
176 "neutra PBR selvage.\n"
177 "\n"
178 "Raw denim pork belly truffaut, irony plaid sustainable put a bird on it\n"
179 "next level jean shorts exercitation. Hashtag keytar whatever, nihil\n"
180 "authentic aliquip disrupt laborum. Tattooed selfies deserunt trust fund\n"
181 "wayfarers. 3 wolf moon synth church-key sartorial, gastropub leggings\n"
182 "tattooed. Labore high life commodo, meggings raw denim fingerstache pug\n"
183 "trust fund leggings seitan forage. Nostrud ullamco duis, reprehenderit\n"
184 "incididunt flannel sustainable helvetica pork belly pug banksy you\n"
185 "probably haven't heard of them nesciunt farm-to-table. Disrupt nostrud\n"
186 "mollit magna, sriracha sartorial helvetica.\n"
187 "\n"
188 "Nulla kogi reprehenderit, skateboard sustainable duis adipisicing viral\n"
189 "ad fanny pack salvia. Fanny pack trust fund you probably haven't heard\n"
190 "of them YOLO vice nihil. Keffiyeh cray lo-fi pinterest cardigan aliqua,\n"
191 "reprehenderit aute. Culpa tousled williamsburg, marfa lomo actually anim\n"
192 "skateboard. Iphone aliqua ugh, semiotics pariatur vero readymade\n"
193 "organic. Marfa squid nulla, in laborum disrupt laboris irure gastropub.\n"
194 "Veniam sunt food truck leggings, sint vinyl fap.\n"
195 "\n"
196 "Hella dolore pork belly, truffaut carles you probably haven't heard of\n"
197 "them PBR helvetica in sapiente. Fashion axe ugh bushwick american\n"
198 "apparel. Fingerstache sed iphone, jean shorts blue bottle nisi bushwick\n"
199 "flexitarian officia veniam plaid bespoke fap YOLO lo-fi. Blog\n"
200 "letterpress mumblecore, food truck id cray brooklyn cillum ad sed.\n"
201 "Assumenda chambray wayfarers vinyl mixtape sustainable. VHS vinyl\n"
202 "delectus, culpa williamsburg polaroid cliche swag church-key synth kogi\n"
203 "magna pop-up literally. Swag thundercats ennui shoreditch vegan\n"
204 "pitchfork neutra truffaut etsy, sed single-origin coffee craft beer.\n"
205 "\n"
206 "Odio letterpress brooklyn elit. Nulla single-origin coffee in occaecat\n"
207 "meggings. Irony meggings 8-bit, chillwave lo-fi adipisicing cred\n"
208 "dreamcatcher veniam. Put a bird on it irony umami, trust fund bushwick\n"
209 "locavore kale chips. Sriracha swag thundercats, chillwave disrupt\n"
210 "tousled beard mollit mustache leggings portland next level. Nihil esse\n"
211 "est, skateboard art party etsy thundercats sed dreamcatcher ut iphone\n"
212 "swag consectetur et. Irure skateboard banjo, nulla deserunt messenger\n"
213 "bag dolor terry richardson sapiente.\n";
214
215 #if !defined(NO_DH)
216 #define MIN_DHKEY_BITS 1024
217
218 /* dh2048 p */
219 static const unsigned char p[] =
220 {
221 0xb0, 0xa1, 0x08, 0x06, 0x9c, 0x08, 0x13, 0xba, 0x59, 0x06, 0x3c, 0xbc, 0x30,
222 0xd5, 0xf5, 0x00, 0xc1, 0x4f, 0x44, 0xa7, 0xd6, 0xef, 0x4a, 0xc6, 0x25, 0x27,
223 0x1c, 0xe8, 0xd2, 0x96, 0x53, 0x0a, 0x5c, 0x91, 0xdd, 0xa2, 0xc2, 0x94, 0x84,
224 0xbf, 0x7d, 0xb2, 0x44, 0x9f, 0x9b, 0xd2, 0xc1, 0x8a, 0xc5, 0xbe, 0x72, 0x5c,
225 0xa7, 0xe7, 0x91, 0xe6, 0xd4, 0x9f, 0x73, 0x07, 0x85, 0x5b, 0x66, 0x48, 0xc7,
226 0x70, 0xfa, 0xb4, 0xee, 0x02, 0xc9, 0x3d, 0x9a, 0x4a, 0xda, 0x3d, 0xc1, 0x46,
227 0x3e, 0x19, 0x69, 0xd1, 0x17, 0x46, 0x07, 0xa3, 0x4d, 0x9f, 0x2b, 0x96, 0x17,
228 0x39, 0x6d, 0x30, 0x8d, 0x2a, 0xf3, 0x94, 0xd3, 0x75, 0xcf, 0xa0, 0x75, 0xe6,
229 0xf2, 0x92, 0x1f, 0x1a, 0x70, 0x05, 0xaa, 0x04, 0x83, 0x57, 0x30, 0xfb, 0xda,
230 0x76, 0x93, 0x38, 0x50, 0xe8, 0x27, 0xfd, 0x63, 0xee, 0x3c, 0xe5, 0xb7, 0xc8,
231 0x09, 0xae, 0x6f, 0x50, 0x35, 0x8e, 0x84, 0xce, 0x4a, 0x00, 0xe9, 0x12, 0x7e,
232 0x5a, 0x31, 0xd7, 0x33, 0xfc, 0x21, 0x13, 0x76, 0xcc, 0x16, 0x30, 0xdb, 0x0c,
233 0xfc, 0xc5, 0x62, 0xa7, 0x35, 0xb8, 0xef, 0xb7, 0xb0, 0xac, 0xc0, 0x36, 0xf6,
234 0xd9, 0xc9, 0x46, 0x48, 0xf9, 0x40, 0x90, 0x00, 0x2b, 0x1b, 0xaa, 0x6c, 0xe3,
235 0x1a, 0xc3, 0x0b, 0x03, 0x9e, 0x1b, 0xc2, 0x46, 0xe4, 0x48, 0x4e, 0x22, 0x73,
236 0x6f, 0xc3, 0x5f, 0xd4, 0x9a, 0xd6, 0x30, 0x07, 0x48, 0xd6, 0x8c, 0x90, 0xab,
237 0xd4, 0xf6, 0xf1, 0xe3, 0x48, 0xd3, 0x58, 0x4b, 0xa6, 0xb9, 0xcd, 0x29, 0xbf,
238 0x68, 0x1f, 0x08, 0x4b, 0x63, 0x86, 0x2f, 0x5c, 0x6b, 0xd6, 0xb6, 0x06, 0x65,
239 0xf7, 0xa6, 0xdc, 0x00, 0x67, 0x6b, 0xbb, 0xc3, 0xa9, 0x41, 0x83, 0xfb, 0xc7,
240 0xfa, 0xc8, 0xe2, 0x1e, 0x7e, 0xaf, 0x00, 0x3f, 0x93
241 };
242
243 /* dh2048 g */
244 static const unsigned char g[] =
245 {
246 0x02,
247 };
248 #endif /* !NO_DH */
249
250 typedef struct {
251 unsigned char buf[MEM_BUFFER_SZ];
252 int write_bytes;
253 int write_idx;
254 int read_bytes;
255 int read_idx;
256 } memBuf_t;
257
258 typedef struct {
259 double connTime;
260 double rxTime;
261 double txTime;
262 int connCount;
263 int rxTotal;
264 int txTotal;
265 } stats_t;
266
267 typedef struct {
268 int ret;
269
270 osThreadId threadId;
271 #ifdef CMSIS_OS2_H_
272 osSemaphoreId_t mutex;
273 #else
274 osThreadDef_t threadDef;
275 osSemaphoreDef_t mutexDef;
276 osSemaphoreId mutex;
277 #endif
278
279 byte shutdown:1;
280 byte done:1;
281 } side_t;
282
283 typedef struct {
284 const char* cipher;
285 const char* host;
286 word32 port;
287 int packetSize; /* The data payload size in the packet */
288 int maxSize;
289 int runTimeSec;
290 int showPeerInfo;
291 int showVerbose;
292 int doShutdown;
293
294 side_t client;
295 side_t server;
296
297 /* client messages to server in memory */
298 memBuf_t to_server;
299
300 /* server messages to client in memory */
301 memBuf_t to_client;
302
303 /* server */
304 stats_t server_stats;
305
306 /* client */
307 stats_t client_stats;
308 } info_t;
309
310
311 /*****************************************************************************
312 * Private functions
313 ****************************************************************************/
gettime_secs(int reset)314 static double gettime_secs(int reset)
315 {
316 return current_time();
317 }
318
PrintTlsStats(stats_t * wcStat,const char * desc,const char * cipher,int verbose)319 static void PrintTlsStats(stats_t* wcStat, const char* desc, const char* cipher, int verbose)
320 {
321 const char* formatStr;
322
323 if (verbose) {
324 formatStr = "wolfSSL %s Benchmark on %s:\n"
325 "\tTotal : %9d bytes\n"
326 "\tNum Conns : %9d\n"
327 "\tRx Total : %9.3f ms\n"
328 "\tTx Total : %9.3f ms\n"
329 "\tRx : %9.3f MB/s\n"
330 "\tTx : %9.3f MB/s\n"
331 "\tConnect : %9.3f ms\n"
332 "\tConnect Avg : %9.3f ms\n";
333 }
334 else {
335 formatStr = "%-6s %-33s %11d %9d %9.3f %9.3f %9.3f %9.3f %17.3f %15.3f\n";
336 }
337
338 printf(formatStr,
339 desc,
340 cipher,
341 wcStat->txTotal + wcStat->rxTotal,
342 wcStat->connCount,
343 wcStat->rxTime * 1000,
344 wcStat->txTime * 1000,
345 wcStat->rxTotal / wcStat->rxTime / 1024 / 1024,
346 wcStat->txTotal / wcStat->txTime / 1024 / 1024,
347 wcStat->connTime * 1000,
348 wcStat->connTime * 1000 / wcStat->connCount);
349 }
350
351
352 #if defined(KEEP_PEER_CERT) || defined(KEEP_OUR_CERT)
353 static const char* client_showx509_msg[] = {
354 "issuer",
355 "subject",
356 "altname",
357 "serial number",
358 NULL
359 };
360
ShowX509(WOLFSSL_X509 * x509,const char * hdr)361 static void ShowX509(WOLFSSL_X509* x509, const char* hdr)
362 {
363 char* altName;
364 char* issuer;
365 char* subject;
366 byte serial[32];
367 int ret;
368 int sz = sizeof(serial);
369 const char** words = client_showx509_msg;
370
371 if (x509 == NULL) {
372 printf("%s No Cert\n", hdr);
373 return;
374 }
375
376 issuer = wolfSSL_X509_NAME_oneline(
377 wolfSSL_X509_get_issuer_name(x509), 0, 0);
378 subject = wolfSSL_X509_NAME_oneline(
379 wolfSSL_X509_get_subject_name(x509), 0, 0);
380
381 printf("%s\n %s : %s\n %s: %s\n", hdr, words[0], issuer, words[1], subject);
382
383 while ( (altName = wolfSSL_X509_get_next_altname(x509)) != NULL)
384 printf(" %s = %s\n", words[2], altName);
385
386 ret = wolfSSL_X509_get_serial_number(x509, serial, &sz);
387 if (ret == WOLFSSL_SUCCESS) {
388 int i;
389 int strLen;
390 char serialMsg[80];
391
392 /* testsuite has multiple threads writing to stdout, get output
393 message ready to write once */
394 strLen = sprintf(serialMsg, " %s", words[3]);
395 for (i = 0; i < sz; i++)
396 sprintf(serialMsg + strLen + (i*3), ":%02x ", serial[i]);
397 printf("%s\n", serialMsg);
398 }
399
400 XFREE(subject, 0, DYNAMIC_TYPE_OPENSSL);
401 XFREE(issuer, 0, DYNAMIC_TYPE_OPENSSL);
402
403 #if defined(OPENSSL_EXTRA)
404 {
405 WOLFSSL_BIO* bio;
406 char buf[256]; /* should be size of ASN_NAME_MAX */
407 int textSz;
408
409 /* print out domain component if certificate has it */
410 textSz = wolfSSL_X509_NAME_get_text_by_NID(
411 wolfSSL_X509_get_subject_name(x509), NID_domainComponent,
412 buf, sizeof(buf));
413 if (textSz > 0) {
414 printf("Domain Component = %s\n", buf);
415 }
416
417 bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
418 if (bio != NULL) {
419 wolfSSL_BIO_set_fp(bio, stdout, BIO_NOCLOSE);
420 wolfSSL_X509_print(bio, x509);
421 wolfSSL_BIO_free(bio);
422 }
423 }
424 #endif /* OPENSSL_EXTRA */
425 }
426 #endif
427
428
429 static const char* client_showpeer_msg[] = {
430 "SSL version is",
431 "SSL cipher suite is",
432 "SSL curve name is",
433 "SSL DH size is",
434 "SSL reused session",
435 "Alternate cert chain used",
436 "peer's cert info:",
437 NULL
438 };
439
ShowPeer(WOLFSSL * ssl)440 static void ShowPeer(WOLFSSL* ssl)
441 {
442 WOLFSSL_CIPHER* cipher;
443 const char** words = client_showpeer_msg;
444 #if defined(HAVE_ECC) || !defined(NO_DH)
445 const char *name;
446 #endif
447 #ifndef NO_DH
448 int bits;
449 #endif
450 #ifdef KEEP_PEER_CERT
451 WOLFSSL_X509* peer = wolfSSL_get_peer_certificate(ssl);
452 if (peer)
453 ShowX509(peer, words[6]);
454 else
455 printf("peer has no cert!\n");
456 wolfSSL_FreeX509(peer);
457 #endif
458 #if defined(KEEP_OUR_CERT) && \
459 (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
460 ShowX509(wolfSSL_get_certificate(ssl), "our cert info:");
461 printf("Peer verify result = %lu\n", wolfSSL_get_verify_result(ssl));
462 #endif /* SHOW_CERTS && KEEP_OUR_CERT */
463 printf("%s %s\n", words[0], wolfSSL_get_version(ssl));
464
465 cipher = wolfSSL_get_current_cipher(ssl);
466 printf("%s %s\n", words[1], wolfSSL_CIPHER_get_name(cipher));
467 #if defined(HAVE_ECC) || !defined(NO_DH)
468 if ((name = wolfSSL_get_curve_name(ssl)) != NULL)
469 printf("%s %s\n", words[2], name);
470 #endif
471 #ifndef NO_DH
472 else if ((bits = wolfSSL_GetDhKey_Sz(ssl)) > 0)
473 printf("%s %d bits\n", words[3], bits);
474 #endif
475 if (wolfSSL_session_reused(ssl))
476 printf("%s\n", words[4]);
477 #ifdef WOLFSSL_ALT_CERT_CHAINS
478 if (wolfSSL_is_peer_alt_cert_chain(ssl))
479 printf("%s\n", words[5]);
480 #endif
481
482 (void)ssl;
483 }
484
485
486
487 /* server send callback */
ServerMemSend(info_t * info,char * buf,int sz)488 static int ServerMemSend(info_t* info, char* buf, int sz)
489 {
490 #ifdef CMSIS_OS2_H_
491 osSemaphoreAcquire(info->client.mutex, osWaitForever);
492 #else
493 osSemaphoreWait(info->client.mutex, osWaitForever);
494 #endif
495
496 #ifndef BENCH_USE_NONBLOCK
497 /* check for overflow */
498 if (info->to_client.write_idx + sz > MEM_BUFFER_SZ) {
499 osSemaphoreRelease(info->client.mutex);
500 printf("ServerMemSend overflow\n");
501 return -1;
502 }
503 #else
504 if (info->to_client.write_idx + sz > MEM_BUFFER_SZ)
505 sz = MEM_BUFFER_SZ - info->to_client.write_idx;
506 #endif
507
508 if (info->showVerbose >= 2)
509 printf("Server Send: %d\n", sz);
510 XMEMCPY(&info->to_client.buf[info->to_client.write_idx], buf, sz);
511 info->to_client.write_idx += sz;
512 info->to_client.write_bytes += sz;
513
514 #ifdef CMSIS_OS2_H_
515 osThreadFlagsSet(info->client.threadId, 1);
516 #else
517 osSignalSet(info->client.threadId, 1);
518 #endif
519 osSemaphoreRelease(info->client.mutex);
520
521 #ifdef BENCH_USE_NONBLOCK
522 if (sz == 0)
523 return WOLFSSL_CBIO_ERR_WANT_WRITE;
524 #endif
525 return sz;
526 }
527
528 /* server recv callback */
ServerMemRecv(info_t * info,char * buf,int sz)529 static int ServerMemRecv(info_t* info, char* buf, int sz)
530 {
531 #ifdef CMSIS_OS2_H_
532 osSemaphoreAcquire(info->server.mutex, osWaitForever);
533 #else
534 osSemaphoreWait(info->server.mutex, osWaitForever);
535 #endif
536
537 #ifndef BENCH_USE_NONBLOCK
538 while (info->to_server.write_idx - info->to_server.read_idx < sz &&
539 !info->client.done) {
540 osSemaphoreRelease(info->server.mutex);
541 #ifdef CMSIS_OS2_H_
542 if (osThreadFlagsWait(1, osFlagsWaitAny, RECV_WAIT_TIMEOUT) == osFlagsErrorTimeout) {
543 printf("Server Recv: Timeout!\n");
544 return WOLFSSL_CBIO_ERR_TIMEOUT;
545 }
546 osSemaphoreAcquire(info->server.mutex, osWaitForever);
547 #else
548 if (osSignalWait(1, RECV_WAIT_TIMEOUT) == osEventTimeout) {
549 printf("Server Recv: Timeout!\n");
550 return WOLFSSL_CBIO_ERR_TIMEOUT;
551 }
552 osSemaphoreWait(info->server.mutex, osWaitForever);
553 #endif
554 }
555 #else
556 if (info->to_server.write_idx - info->to_server.read_idx < sz)
557 sz = info->to_server.write_idx - info->to_server.read_idx;
558 #endif
559
560 XMEMCPY(buf, &info->to_server.buf[info->to_server.read_idx], sz);
561 info->to_server.read_idx += sz;
562 info->to_server.read_bytes += sz;
563
564 /* if the rx has caught up with pending then reset buffer positions */
565 if (info->to_server.read_bytes == info->to_server.write_bytes) {
566 info->to_server.read_bytes = info->to_server.read_idx = 0;
567 info->to_server.write_bytes = info->to_server.write_idx = 0;
568 }
569 if (info->showVerbose >= 2)
570 printf("Server Recv: %d\n", sz);
571
572 osSemaphoreRelease(info->server.mutex);
573
574
575 #ifdef BENCH_USE_NONBLOCK
576 if (sz == 0)
577 return WOLFSSL_CBIO_ERR_WANT_READ;
578 #endif
579 return sz;
580 }
581
582 /* client send callback */
ClientMemSend(info_t * info,char * buf,int sz)583 static int ClientMemSend(info_t* info, char* buf, int sz)
584 {
585 #ifdef CMSIS_OS2_H_
586 osSemaphoreAcquire(info->server.mutex, osWaitForever);
587 #else
588 osSemaphoreWait(info->server.mutex, osWaitForever);
589 #endif
590
591 #ifndef BENCH_USE_NONBLOCK
592 /* check for overflow */
593 if (info->to_server.write_idx + sz > MEM_BUFFER_SZ) {
594 printf("ClientMemSend overflow %d %d %d\n",
595 info->to_server.write_idx, sz, MEM_BUFFER_SZ);
596 osSemaphoreRelease(info->server.mutex);
597 return -1;
598 }
599 #else
600 if (info->to_server.write_idx + sz > MEM_BUFFER_SZ)
601 sz = MEM_BUFFER_SZ - info->to_server.write_idx;
602 #endif
603
604 if (info->showVerbose >= 2)
605 printf("Client Send: %d\n", sz);
606 XMEMCPY(&info->to_server.buf[info->to_server.write_idx], buf, sz);
607 info->to_server.write_idx += sz;
608 info->to_server.write_bytes += sz;
609
610 #ifdef CMSIS_OS2_H_
611 osThreadFlagsSet(info->server.threadId, 1);
612 #else
613 osSignalSet(info->server.threadId, 1);
614 #endif
615 osSemaphoreRelease(info->server.mutex);
616
617 #ifdef BENCH_USE_NONBLOCK
618 if (sz == 0)
619 return WOLFSSL_CBIO_ERR_WANT_WRITE;
620 #endif
621 return sz;
622 }
623
624 /* client recv callback */
ClientMemRecv(info_t * info,char * buf,int sz)625 static int ClientMemRecv(info_t* info, char* buf, int sz)
626 {
627 #ifdef CMSIS_OS2_H_
628 osSemaphoreAcquire(info->client.mutex, osWaitForever);
629 #else
630 osSemaphoreWait(info->client.mutex, osWaitForever);
631 #endif
632
633 #ifndef BENCH_USE_NONBLOCK
634 while (info->to_client.write_idx - info->to_client.read_idx < sz &&
635 !info->server.done) {
636 osSemaphoreRelease(info->client.mutex);
637 #ifdef CMSIS_OS2_H_
638 if (osThreadFlagsWait(1, osFlagsWaitAny, RECV_WAIT_TIMEOUT) == osFlagsErrorTimeout) {
639 printf("Client Recv: Timeout!\n");
640 return WOLFSSL_CBIO_ERR_TIMEOUT;
641 }
642 osSemaphoreAcquire(info->client.mutex, osWaitForever);
643 #else
644 if (osSignalWait(1, RECV_WAIT_TIMEOUT) == osEventTimeout) {
645 printf("Client Recv: Timeout!\n");
646 return WOLFSSL_CBIO_ERR_TIMEOUT;
647 }
648 osSemaphoreWait(info->client.mutex, osWaitForever);
649 #endif
650 }
651 #else
652 if (info->to_client.write_idx - info->to_client.read_idx < sz)
653 sz = info->to_client.write_idx - info->to_client.read_idx;
654 #endif
655
656 XMEMCPY(buf, &info->to_client.buf[info->to_client.read_idx], sz);
657 info->to_client.read_idx += sz;
658 info->to_client.read_bytes += sz;
659
660 /* if the rx has caught up with pending then reset buffer positions */
661 if (info->to_client.read_bytes == info->to_client.write_bytes) {
662 info->to_client.read_bytes = info->to_client.read_idx = 0;
663 info->to_client.write_bytes = info->to_client.write_idx = 0;
664 }
665 if (info->showVerbose >= 2)
666 printf("Client Recv: %d\n", sz);
667
668 osSemaphoreRelease(info->client.mutex);
669
670 #ifdef BENCH_USE_NONBLOCK
671 if (sz == 0)
672 return WOLFSSL_CBIO_ERR_WANT_READ;
673 #endif
674 return sz;
675 }
676
ServerSend(WOLFSSL * ssl,char * buf,int sz,void * ctx)677 static int ServerSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
678 {
679 info_t* info = (info_t*)ctx;
680 (void)ssl;
681
682 return ServerMemSend(info, buf, sz);
683 }
ServerRecv(WOLFSSL * ssl,char * buf,int sz,void * ctx)684 static int ServerRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
685 {
686 info_t* info = (info_t*)ctx;
687 (void)ssl;
688 return ServerMemRecv(info, buf, sz);
689 }
690
ClientSend(WOLFSSL * ssl,char * buf,int sz,void * ctx)691 static int ClientSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
692 {
693 info_t* info = (info_t*)ctx;
694 (void)ssl;
695 return ClientMemSend(info, buf, sz);
696 }
ClientRecv(WOLFSSL * ssl,char * buf,int sz,void * ctx)697 static int ClientRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
698 {
699 info_t* info = (info_t*)ctx;
700 (void)ssl;
701 return ClientMemRecv(info, buf, sz);
702 }
703
704
bench_tls_client(info_t * info)705 static int bench_tls_client(info_t* info)
706 {
707 byte *writeBuf = NULL, *readBuf = NULL;
708 double start, total = 0;
709 int ret = 0, readBufSz;
710 WOLFSSL_CTX* cli_ctx = NULL;
711 WOLFSSL* cli_ssl = NULL;
712 int haveShownPeerInfo = 0;
713 int tls13 = XSTRNCMP(info->cipher, "TLS13", 5) == 0;
714 int total_sz;
715
716 total = gettime_secs(0);
717
718 /* set up client */
719 #ifdef WOLFSSL_TLS13
720 if (tls13) {
721 #ifdef WOLFSSL_STATIC_MEMORY
722 ret = wolfSSL_CTX_load_static_memory(&cli_ctx, wolfTLSv1_3_client_method_ex,
723 gWolfCTXCli, sizeof(gWolfCTXCli), WOLFMEM_GENERAL , 10);
724 #else
725 cli_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
726 #endif
727 }
728 #endif
729 if (!tls13) {
730 #if !defined(WOLFSSL_TLS13)
731 #ifdef WOLFSSL_STATIC_MEMORY
732 ret = wolfSSL_CTX_load_static_memory(&cli_ctx, wolfSSLv23_client_method_ex,
733 gWolfCTXCli, sizeof(gWolfCTXCli), WOLFMEM_GENERAL , 10);
734 #else
735 cli_ctx = wolfSSL_CTX_new(wolfSSLv23_client_method());
736 #endif
737 #elif !defined(WOLFSSL_NO_TLS12)
738 #ifdef WOLFSSL_STATIC_MEMORY
739 ret = wolfSSL_CTX_load_static_memory(&cli_ctx, wolfTLSv1_2_client_method_ex,
740 gWolfCTXCli, sizeof(gWolfCTXCli), WOLFMEM_GENERAL , 10);
741 #else
742 cli_ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
743 #endif
744 #endif
745 }
746
747 if (cli_ctx == NULL || ret != 0) {
748 printf("error creating ctx: ret %d\n", ret);
749 ret = MEMORY_E; goto exit;
750 }
751
752 #ifdef WOLFSSL_STATIC_MEMORY
753 ret = wolfSSL_CTX_load_static_memory(&cli_ctx, 0, gWolfIOCli, sizeof(gWolfIOCli),
754 WOLFMEM_IO_POOL, 10 );
755 #endif
756
757 #ifndef NO_CERTS
758 #ifdef HAVE_ECC
759 if (XSTRSTR(info->cipher, "ECDSA")) {
760 ret = wolfSSL_CTX_load_verify_buffer(cli_ctx, ca_ecc_cert_der_256,
761 sizeof_ca_ecc_cert_der_256, WOLFSSL_FILETYPE_ASN1);
762 }
763 else
764 #endif
765 {
766 ret = wolfSSL_CTX_load_verify_buffer(cli_ctx, ca_cert_der_2048,
767 sizeof_ca_cert_der_2048, WOLFSSL_FILETYPE_ASN1);
768 }
769 if (ret != WOLFSSL_SUCCESS) {
770 printf("error loading CA\n");
771 goto exit;
772 }
773 #endif /* !NO_CERTS */
774
775 wolfSSL_CTX_SetIOSend(cli_ctx, ClientSend);
776 wolfSSL_CTX_SetIORecv(cli_ctx, ClientRecv);
777
778 /* set cipher suite */
779 ret = wolfSSL_CTX_set_cipher_list(cli_ctx, info->cipher);
780 if (ret != WOLFSSL_SUCCESS) {
781 printf("error setting cipher suite\n");
782 goto exit;
783 }
784
785 #ifndef NO_DH
786 ret = wolfSSL_CTX_SetMinDhKey_Sz(cli_ctx, MIN_DHKEY_BITS);
787 if (ret != WOLFSSL_SUCCESS) {
788 printf("Error setting minimum DH key size\n");
789 goto exit;
790 }
791 #endif /* !NO_DH */
792
793 /* Allocate and initialize a packet sized buffer */
794 writeBuf = (unsigned char*)XMALLOC(info->packetSize, NULL,
795 DYNAMIC_TYPE_TMP_BUFFER);
796 if (writeBuf == NULL) {
797 printf("failed to allocate write memory\n");
798 ret = MEMORY_E; goto exit;
799 }
800
801 /* Allocate read buffer */
802 readBufSz = info->packetSize;
803 readBuf = (unsigned char*)XMALLOC(readBufSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
804 if (readBuf == NULL) {
805 printf("failed to allocate read memory\n");
806 ret = MEMORY_E; goto exit;
807 }
808
809 /* BENCHMARK CONNECTIONS LOOP */
810 while (!info->client.shutdown) {
811 int writeSz = info->packetSize;
812 #ifdef BENCH_USE_NONBLOCK
813 int err;
814 #endif
815
816 cli_ssl = wolfSSL_new(cli_ctx);
817 if (cli_ssl == NULL) {
818 printf("error creating client object\n");
819 ret = MEMORY_E; goto exit;
820 }
821
822 wolfSSL_SetIOReadCtx(cli_ssl, info);
823 wolfSSL_SetIOWriteCtx(cli_ssl, info);
824
825 /* perform connect */
826 start = gettime_secs(1);
827 #ifndef BENCH_USE_NONBLOCK
828 ret = wolfSSL_connect(cli_ssl);
829 #else
830 do
831 {
832 ret = wolfSSL_connect(cli_ssl);
833 err = wolfSSL_get_error(cli_ssl, ret);
834 }
835 while (err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE);
836 #endif
837 start = gettime_secs(0) - start;
838 if (ret != WOLFSSL_SUCCESS) {
839 ret = wolfSSL_get_error(cli_ssl, ret);
840 printf("error %d connecting client\n", ret);
841 goto exit;
842 }
843 info->client_stats.connTime += start;
844 info->client_stats.connCount++;
845
846 if ((info->showPeerInfo) && (!haveShownPeerInfo)) {
847 haveShownPeerInfo = 1;
848 ShowPeer(cli_ssl);
849 }
850
851 /* check for run time completion and issue shutdown */
852 if (gettime_secs(0) - total >= info->runTimeSec) {
853 info->client.shutdown = 1;
854
855 writeSz = (int)XSTRLEN(kShutdown) + 1;
856 XMEMCPY(writeBuf, kShutdown, writeSz); /* include null term */
857 if (info->showVerbose) {
858 printf("Sending shutdown\n");
859 }
860
861 ret = wolfSSL_write(cli_ssl, writeBuf, writeSz);
862 if (ret < 0) {
863 ret = wolfSSL_get_error(cli_ssl, ret);
864 printf("error %d on client write\n", ret);
865 goto exit;
866 }
867 }
868 else {
869 XMEMSET(writeBuf, 0, info->packetSize);
870 XSTRNCPY((char*)writeBuf, kTestStr, info->packetSize);
871 }
872
873 /* write / read echo loop */
874 ret = 0;
875 total_sz = 0;
876 while (ret == 0 && total_sz < info->maxSize && !info->client.shutdown) {
877 /* write test message to server */
878 start = gettime_secs(1);
879 #ifndef BENCH_USE_NONBLOCK
880 ret = wolfSSL_write(cli_ssl, writeBuf, writeSz);
881 #else
882 do {
883 ret = wolfSSL_write(cli_ssl, writeBuf, writeSz);
884 err = wolfSSL_get_error(cli_ssl, ret);
885 }
886 while (err == WOLFSSL_ERROR_WANT_WRITE);
887 #endif
888 info->client_stats.txTime += gettime_secs(0) - start;
889 if (ret < 0) {
890 ret = wolfSSL_get_error(cli_ssl, ret);
891 printf("error %d on client write\n", ret);
892 goto exit;
893 }
894 info->client_stats.txTotal += ret;
895 total_sz += ret;
896
897 /* read echo of message from server */
898 XMEMSET(readBuf, 0, readBufSz);
899 start = gettime_secs(1);
900 #ifndef BENCH_USE_NONBLOCK
901 ret = wolfSSL_read(cli_ssl, readBuf, readBufSz);
902 #else
903 do {
904 ret = wolfSSL_read(cli_ssl, readBuf, readBufSz);
905 err = wolfSSL_get_error(cli_ssl, ret);
906 }
907 while (err == WOLFSSL_ERROR_WANT_READ);
908 #endif
909 info->client_stats.rxTime += gettime_secs(0) - start;
910 if (ret < 0) {
911 ret = wolfSSL_get_error(cli_ssl, ret);
912 printf("error %d on client read\n", ret);
913 goto exit;
914 }
915 info->client_stats.rxTotal += ret;
916 ret = 0; /* reset return code */
917
918 /* validate echo */
919 if (XMEMCMP((char*)writeBuf, (char*)readBuf, writeSz) != 0) {
920 printf("echo check failed!\n");
921 goto exit;
922 }
923 }
924
925 wolfSSL_free(cli_ssl);
926 cli_ssl = NULL;
927 }
928
929 exit:
930
931 if (ret != 0 && ret != WOLFSSL_SUCCESS) {
932 info->doShutdown = 1;
933 printf("Client Error: %d (%s)\n", ret,
934 wolfSSL_ERR_reason_error_string(ret));
935 }
936
937 /* cleanup */
938 if (cli_ssl != NULL)
939 wolfSSL_free(cli_ssl);
940 if (cli_ctx != NULL)
941 wolfSSL_CTX_free(cli_ctx);
942 XFREE(readBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
943 XFREE(writeBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
944 info->client.ret = ret;
945
946 return ret;
947 }
948
949 #ifdef CMSIS_OS2_H_
client_thread(void * args)950 static void client_thread(void* args)
951 #else
952 static void client_thread(const void* args)
953 #endif
954 {
955 int ret;
956 info_t* info = (info_t*)args;
957
958 #ifdef CMSIS_OS2_H_
959 info->client.threadId = osThreadGetId();
960 #endif
961 do {
962 ret = bench_tls_client(info);
963
964 /* signal server */
965 if (!info->server.done && info->server.threadId != 0) {
966 #ifdef CMSIS_OS2_H_
967 osThreadFlagsSet(info->server.threadId, 1);
968 #else
969 osSignalSet(info->server.threadId, 1);
970 #endif
971 }
972 info->client.ret = ret;
973 info->client.done = 1;
974 osThreadSuspend(info->client.threadId);
975
976 if (info->doShutdown)
977 info->client.done = 1;
978 } while (!info->doShutdown);
979
980 osThreadTerminate(info->client.threadId);
981 info->client.threadId = NULL;
982 }
983
bench_tls_server(info_t * info)984 static int bench_tls_server(info_t* info)
985 {
986 byte *readBuf = NULL;
987 double start;
988 int ret = 0, len = 0, readBufSz;
989 WOLFSSL_CTX* srv_ctx = NULL;
990 WOLFSSL* srv_ssl = NULL;
991 int tls13 = XSTRNCMP(info->cipher, "TLS13", 5) == 0;
992 int total_sz;
993
994 /* set up server */
995 #ifdef WOLFSSL_TLS13
996 if (tls13) {
997 #ifdef WOLFSSL_STATIC_MEMORY
998 ret = wolfSSL_CTX_load_static_memory(&srv_ctx, wolfTLSv1_3_server_method_ex,
999 gWolfCTXSrv, sizeof(gWolfCTXSrv), WOLFMEM_GENERAL , 10);
1000 #else
1001 srv_ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method());
1002 #endif
1003 }
1004 #endif
1005 if (!tls13) {
1006 #if !defined(WOLFSSL_TLS13)
1007 #ifdef WOLFSSL_STATIC_MEMORY
1008 ret = wolfSSL_CTX_load_static_memory(&srv_ctx, wolfSSLv23_server_method_ex,
1009 gWolfCTXSrv, sizeof(gWolfCTXSrv), WOLFMEM_GENERAL , 10);
1010 #else
1011 srv_ctx = wolfSSL_CTX_new(wolfSSLv23_server_method());
1012 #endif
1013 #elif !defined(WOLFSSL_NO_TLS12)
1014 #ifdef WOLFSSL_STATIC_MEMORY
1015 ret = wolfSSL_CTX_load_static_memory(&srv_ctx, wolfTLSv1_2_server_method_ex,
1016 gWolfCTXSrv, sizeof(gWolfCTXSrv), WOLFMEM_GENERAL , 10);
1017 #else
1018 srv_ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method());
1019 #endif
1020 #endif
1021 }
1022
1023 if (srv_ctx == NULL || ret != 0) {
1024 printf("error creating server ctx: ret %d\n", ret);
1025 ret = MEMORY_E; goto exit;
1026 }
1027
1028 #ifdef WOLFSSL_STATIC_MEMORY
1029 ret = wolfSSL_CTX_load_static_memory(&srv_ctx, 0, gWolfIOSrv, sizeof(gWolfIOSrv),
1030 WOLFMEM_IO_POOL, 10 );
1031 #endif
1032
1033 #ifndef NO_CERTS
1034 #ifdef HAVE_ECC
1035 if (XSTRSTR(info->cipher, "ECDSA")) {
1036 ret = wolfSSL_CTX_use_PrivateKey_buffer(srv_ctx, ecc_key_der_256,
1037 sizeof_ecc_key_der_256, WOLFSSL_FILETYPE_ASN1);
1038 }
1039 else
1040 #endif
1041 {
1042 ret = wolfSSL_CTX_use_PrivateKey_buffer(srv_ctx, server_key_der_2048,
1043 sizeof_server_key_der_2048, WOLFSSL_FILETYPE_ASN1);
1044 }
1045 if (ret != WOLFSSL_SUCCESS) {
1046 printf("error loading server key\n");
1047 goto exit;
1048 }
1049
1050 #ifdef HAVE_ECC
1051 if (XSTRSTR(info->cipher, "ECDSA")) {
1052 ret = wolfSSL_CTX_use_certificate_buffer(srv_ctx, serv_ecc_der_256,
1053 sizeof_serv_ecc_der_256, WOLFSSL_FILETYPE_ASN1);
1054 }
1055 else
1056 #endif
1057 {
1058 ret = wolfSSL_CTX_use_certificate_buffer(srv_ctx, server_cert_der_2048,
1059 sizeof_server_cert_der_2048, WOLFSSL_FILETYPE_ASN1);
1060 }
1061 if (ret != WOLFSSL_SUCCESS) {
1062 printf("error loading server cert\n");
1063 goto exit;
1064 }
1065 #endif /* !NO_CERTS */
1066
1067 wolfSSL_CTX_SetIOSend(srv_ctx, ServerSend);
1068 wolfSSL_CTX_SetIORecv(srv_ctx, ServerRecv);
1069
1070 /* set cipher suite */
1071 ret = wolfSSL_CTX_set_cipher_list(srv_ctx, info->cipher);
1072 if (ret != WOLFSSL_SUCCESS) {
1073 printf("error setting cipher suite\n");
1074 goto exit;
1075 }
1076
1077 #ifndef NO_DH
1078 ret = wolfSSL_CTX_SetMinDhKey_Sz(srv_ctx, MIN_DHKEY_BITS);
1079 if (ret != WOLFSSL_SUCCESS) {
1080 printf("Error setting minimum DH key size\n");
1081 goto exit;
1082 }
1083 #endif
1084
1085 /* Allocate read buffer */
1086 readBufSz = info->packetSize;
1087 readBuf = (unsigned char*)XMALLOC(readBufSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1088 if (readBuf == NULL) {
1089 printf("failed to allocate read memory\n");
1090 ret = MEMORY_E; goto exit;
1091 }
1092
1093 /* BENCHMARK CONNECTIONS LOOP */
1094 while (!info->server.shutdown) {
1095 #ifdef BENCH_USE_NONBLOCK
1096 int err;
1097 #endif
1098
1099 #ifdef BENCH_USE_NONBLOCK
1100 if (ret == -2) {
1101 osDelay(0);
1102 continue;
1103 }
1104 #endif
1105
1106 srv_ssl = wolfSSL_new(srv_ctx);
1107 if (srv_ssl == NULL) {
1108 printf("error creating server object\n");
1109 ret = MEMORY_E; goto exit;
1110 }
1111
1112 wolfSSL_SetIOReadCtx(srv_ssl, info);
1113 wolfSSL_SetIOWriteCtx(srv_ssl, info);
1114
1115 #ifndef NO_DH
1116 wolfSSL_SetTmpDH(srv_ssl, p, sizeof(p), g, sizeof(g));
1117 #endif
1118
1119 /* accept TLS connection */
1120 start = gettime_secs(1);
1121 #ifndef BENCH_USE_NONBLOCK
1122 ret = wolfSSL_accept(srv_ssl);
1123 #else
1124 do {
1125 ret = wolfSSL_accept(srv_ssl);
1126 err = wolfSSL_get_error(srv_ssl, ret);
1127 }
1128 while (err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE);
1129 #endif
1130 start = gettime_secs(0) - start;
1131 if (ret != WOLFSSL_SUCCESS) {
1132 ret = wolfSSL_get_error(srv_ssl, ret);
1133 printf("error %d on server accept\n", ret);
1134 goto exit;
1135 }
1136
1137 info->server_stats.connTime += start;
1138 info->server_stats.connCount++;
1139
1140 /* echo loop */
1141 ret = 0;
1142 total_sz = 0;
1143 while (ret == 0 && total_sz < info->maxSize) {
1144 double rxTime;
1145
1146 /* read message from client */
1147 XMEMSET(readBuf, 0, readBufSz);
1148 start = gettime_secs(1);
1149 #ifndef BENCH_USE_NONBLOCK
1150 ret = wolfSSL_read(srv_ssl, readBuf, readBufSz);
1151 #else
1152 do {
1153 ret = wolfSSL_read(srv_ssl, readBuf, readBufSz);
1154 err = wolfSSL_get_error(srv_ssl, ret);
1155 }
1156 while (err == WOLFSSL_ERROR_WANT_READ);
1157 #endif
1158 rxTime = gettime_secs(0) - start;
1159
1160 /* shutdown signals, no more connections for this cipher */
1161 if (XSTRSTR((const char*)readBuf, kShutdown) != NULL) {
1162 info->server.shutdown = 1;
1163 if (info->showVerbose) {
1164 printf("Server shutdown done\n");
1165 }
1166 ret = 0; /* success */
1167 break;
1168 }
1169
1170 info->server_stats.rxTime += rxTime;
1171 if (ret < 0) {
1172 ret = wolfSSL_get_error(srv_ssl, ret);
1173 printf("error %d on server read\n", ret);
1174 goto exit;
1175 }
1176 info->server_stats.rxTotal += ret;
1177 len = ret;
1178 total_sz += ret;
1179
1180 /* write message back to client */
1181 start = gettime_secs(1);
1182 #ifndef BENCH_USE_NONBLOCK
1183 ret = wolfSSL_write(srv_ssl, readBuf, len);
1184 #else
1185 do {
1186 ret = wolfSSL_write(srv_ssl, readBuf, len);
1187 err = wolfSSL_get_error(srv_ssl, ret);
1188 }
1189 while (err == WOLFSSL_ERROR_WANT_WRITE);
1190 #endif
1191 info->server_stats.txTime += gettime_secs(0) - start;
1192 if (ret < 0) {
1193 ret = wolfSSL_get_error(srv_ssl, ret);
1194 printf("error %d on server write\n", ret);
1195 goto exit;
1196 }
1197 info->server_stats.txTotal += ret;
1198 ret = 0; /* reset return code */
1199 }
1200
1201 wolfSSL_free(srv_ssl);
1202 srv_ssl = NULL;
1203 }
1204
1205 exit:
1206
1207 if (ret != 0 && ret != WOLFSSL_SUCCESS) {
1208 info->doShutdown = 1;
1209 printf("Server Error: %d (%s)\n", ret,
1210 wolfSSL_ERR_reason_error_string(ret));
1211 }
1212
1213 /* clean up */
1214 if (srv_ssl != NULL)
1215 wolfSSL_free(srv_ssl);
1216 if (srv_ctx != NULL)
1217 wolfSSL_CTX_free(srv_ctx);
1218 XFREE(readBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1219 info->server.ret = ret;
1220
1221 return ret;
1222 }
1223
1224 #ifdef CMSIS_OS2_H_
server_thread(void * args)1225 static void server_thread(void* args)
1226 #else
1227 static void server_thread(const void* args)
1228 #endif
1229 {
1230 int ret;
1231 info_t* info = (info_t*)args;
1232
1233 #ifdef CMSIS_OS2_H_
1234 info->server.threadId = osThreadGetId();
1235 #endif
1236 do {
1237 ret = bench_tls_server(info);
1238
1239 /* signal client */
1240 if (!info->client.done && info->client.threadId != 0) {
1241 #ifdef CMSIS_OS2_H_
1242 osThreadFlagsSet(info->client.threadId, 1);
1243 #else
1244 osSignalSet(info->client.threadId, 1);
1245 #endif
1246 }
1247 info->server.ret = ret;
1248 info->server.done = 1;
1249 osThreadSuspend(info->server.threadId);
1250
1251 if (info->doShutdown)
1252 info->server.done = 1;
1253 } while (!info->doShutdown);
1254
1255 osThreadTerminate(info->server.threadId);
1256 info->server.threadId = NULL;
1257 }
1258
1259 #ifdef CMSIS_OS2_H_
1260 static const osThreadAttr_t server_thread_attributes = {
1261 .name = "server_thread",
1262 .priority = (osPriority_t) osPriorityNormal,
1263 .stack_size = WOLF_EXAMPLES_STACK
1264 };
1265 static const osThreadAttr_t client_thread_attributes = {
1266 .name = "client_thread",
1267 .priority = (osPriority_t) osPriorityNormal,
1268 .stack_size = WOLF_EXAMPLES_STACK
1269 };
1270 #endif
1271
bench_tls(void * args)1272 int bench_tls(void* args)
1273 {
1274 int ret = 0;
1275 info_t *info = NULL;
1276 char *cipher, *next_cipher, *ciphers;
1277
1278 /* Runtime variables */
1279 int argRuntimeSec = BENCH_RUNTIME_SEC;
1280 int argTestPacketSize = TEST_PACKET_SIZE;
1281 int argTestMaxSize = TEST_MAX_SIZE;
1282 int argShowVerbose = SHOW_VERBOSE;
1283 const char* argHost = BENCH_DEFAULT_HOST;
1284 int argPort = BENCH_DEFAULT_PORT;
1285 int argShowPeerInfo = BENCH_SHOW_PEER_INFO;
1286
1287 #ifdef DEBUG_WOLFSSL
1288 if (argShowVerbose >= 3) {
1289 wolfSSL_Debugging_ON();
1290 }
1291 else {
1292 wolfSSL_Debugging_OFF();
1293 }
1294 #endif
1295
1296 #ifdef TEST_CIPHER_SUITE
1297 ciphers = TEST_CIPHER_SUITE;
1298 #else
1299 /* Get cipher suite list */
1300 ciphers = (char*)XMALLOC(WOLFSSL_CIPHER_LIST_MAX_SIZE, NULL,
1301 DYNAMIC_TYPE_TMP_BUFFER);
1302 if (ciphers == NULL) {
1303 ret = MEMORY_E; goto exit;
1304 }
1305 wolfSSL_get_ciphers(ciphers, WOLFSSL_CIPHER_LIST_MAX_SIZE);
1306 #endif
1307 cipher = ciphers;
1308
1309 /* Allocate test info */
1310 info = (info_t*)XMALLOC(sizeof(info_t), NULL, DYNAMIC_TYPE_TMP_BUFFER);
1311 if (info == NULL) {
1312 ret = MEMORY_E; goto exit;
1313 }
1314 XMEMSET(info, 0, sizeof(info_t));
1315
1316 info->host = argHost;
1317 info->port = argPort;
1318 info->packetSize = argTestPacketSize;
1319 info->runTimeSec = argRuntimeSec;
1320 info->maxSize = argTestMaxSize;
1321 info->showPeerInfo = argShowPeerInfo;
1322 info->showVerbose = argShowVerbose;
1323
1324 #ifdef CMSIS_OS2_H_
1325 info->server.mutex = osSemaphoreNew(1, 0, NULL);
1326 info->client.mutex = osSemaphoreNew(1, 0, NULL);
1327 #else
1328 info->server.mutex = osSemaphoreCreate(&info->server.mutexDef, 1);
1329 info->client.mutex = osSemaphoreCreate(&info->client.mutexDef, 1);
1330
1331 /* threads */
1332 info->server.threadDef.name = "server_thread";
1333 info->server.threadDef.pthread = server_thread;
1334 info->server.threadDef.tpriority = osPriorityNormal;
1335 info->server.threadDef.stacksize = WOLF_EXAMPLES_STACK;
1336
1337 info->client.threadDef.name = "client_thread";
1338 info->client.threadDef.pthread = client_thread;
1339 info->client.threadDef.tpriority = osPriorityNormal;
1340 info->client.threadDef.stacksize = WOLF_EXAMPLES_STACK;
1341 #endif
1342
1343 /* parse by : */
1344 while ((cipher != NULL) && (cipher[0] != '\0')) {
1345 next_cipher = strchr(cipher, ':');
1346 if (next_cipher != NULL) {
1347 cipher[next_cipher - cipher] = '\0';
1348 }
1349
1350 if (argShowVerbose) {
1351 printf("Cipher: %s\n", cipher);
1352 }
1353
1354 /* set cipher suite */
1355 info->cipher = cipher;
1356
1357 /* reset thread info */
1358 info->server.ret = info->client.ret = 0;
1359 info->server.done = info->client.done = 0;
1360 info->server.shutdown = info->client.shutdown = 0;
1361 XMEMSET(&info->server_stats, 0, sizeof(info->server_stats));
1362 XMEMSET(&info->client_stats, 0, sizeof(info->client_stats));
1363 XMEMSET(&info->to_server, 0, sizeof(info->to_server));
1364 XMEMSET(&info->to_client, 0, sizeof(info->to_client));
1365
1366 /* make sure nothing is locking it */
1367 osSemaphoreRelease(info->server.mutex);
1368 osSemaphoreRelease(info->client.mutex);
1369
1370 /* start threads */
1371 if (info->server.threadId == 0) {
1372 #ifdef CMSIS_OS2_H_
1373 osThreadNew(server_thread, info, &server_thread_attributes);
1374 #else
1375 info->server.threadId = osThreadCreate(&info->server.threadDef, info);
1376 #endif
1377 }
1378 else {
1379 osThreadResume(info->server.threadId);
1380 }
1381 if (info->client.threadId == 0) {
1382 #ifdef CMSIS_OS2_H_
1383 osThreadNew(client_thread, info, &client_thread_attributes);
1384 #else
1385 info->client.threadId = osThreadCreate(&info->client.threadDef, info);
1386 #endif
1387 }
1388 else {
1389 osThreadResume(info->client.threadId);
1390 }
1391
1392 /* Wait until threads are marked done */
1393 while (!info->client.done || !info->server.done) {
1394 osThreadYield(); /* Allow other threads to run */
1395 }
1396
1397 if (argShowVerbose) {
1398 /* print results */
1399 PrintTlsStats(&info->server_stats, "Server", info->cipher, 1);
1400 PrintTlsStats(&info->client_stats, "Client", info->cipher, 1);
1401 }
1402
1403 printf("%-6s %-33s %11s %9s %9s %9s %9s %9s %17s %15s\n",
1404 "Side", "Cipher", "Total Bytes", "Num Conns", "Rx ms", "Tx ms",
1405 "Rx MB/s", "Tx MB/s", "Connect Total ms", "Connect Avg ms");
1406 PrintTlsStats(&info->server_stats, "Server", info->cipher, 0);
1407 PrintTlsStats(&info->client_stats, "Client", info->cipher, 0);
1408
1409 PrintMemStats();
1410
1411 /* target next cipher */
1412 cipher = (next_cipher != NULL) ? (next_cipher + 1) : NULL;
1413 } /* while */
1414
1415 /* do thread shutdown */
1416 info->doShutdown = 1;
1417 info->server.done = 0;
1418 info->client.done = 0;
1419 osThreadResume(info->server.threadId);
1420 osThreadResume(info->client.threadId);
1421 /* Wait until threads are marked done */
1422 while (!info->client.done || !info->server.done) {
1423 osThreadYield(); /* Allow other threads to run */
1424 }
1425
1426 exit:
1427
1428 /* cleanup thread info */
1429 osSemaphoreDelete(info->server.mutex);
1430 osSemaphoreDelete(info->client.mutex);
1431 XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1432
1433 #ifndef TEST_CIPHER_SUITE
1434 /* Free cipher list */
1435 XFREE(ciphers, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1436 #endif
1437
1438 /* set return code */
1439 if (args)
1440 ((func_args*)args)->return_code = ret;
1441
1442 return ret;
1443 }
1444 #endif /* (!NO_WOLFSSL_CLIENT || !NO_WOLFSSL_SERVER) && !WOLFCRYPT_ONLY && !SINGLE_THREADED */
1445
1446 #ifndef WOLFCRYPT_ONLY
ShowCiphers(void)1447 static void ShowCiphers(void)
1448 {
1449 int ret;
1450 char* ciphers = (char*)XMALLOC(WOLFSSL_CIPHER_LIST_MAX_SIZE, NULL,
1451 DYNAMIC_TYPE_TMP_BUFFER);
1452 if (ciphers) {
1453 ret = wolfSSL_get_ciphers(ciphers, WOLFSSL_CIPHER_LIST_MAX_SIZE);
1454 if (ret == WOLFSSL_SUCCESS)
1455 printf("%s\n", ciphers);
1456 XFREE(ciphers, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1457 }
1458 }
1459 #endif
1460
PrintMemStats(void)1461 static void PrintMemStats(void)
1462 {
1463 #ifdef WOLFSSL_DEBUG_MEMORY
1464 printf("\nHeap MinEver %d, Free %d, Stack %lu\n",
1465 xPortGetMinimumEverFreeHeapSize(),
1466 xPortGetFreeHeapSize(),
1467 uxTaskGetStackHighWaterMark(NULL));
1468 #endif
1469 }
1470
1471 #if 0
1472 static void* wolfMallocCb(size_t size)
1473 {
1474 void* ptr = malloc(size);
1475 if (ptr == NULL) {
1476 printf("BREAK!\n");
1477 }
1478 return ptr;
1479 }
1480 static void wolfFreeCb(void *ptr)
1481 {
1482 free(ptr);
1483 }
1484 static void* wolfReallocCb(void *ptr, size_t size)
1485 {
1486 return realloc(ptr, size);
1487 }
1488 #endif
1489
1490 /*****************************************************************************
1491 * Public functions
1492 ****************************************************************************/
1493 #ifdef HAL_RTC_MODULE_ENABLED
1494 extern RTC_HandleTypeDef hrtc;
current_time(void)1495 double current_time(void)
1496 {
1497 RTC_TimeTypeDef time;
1498 RTC_DateTypeDef date;
1499 uint32_t subsec = 0;
1500
1501 /* must get time and date here due to STM32 HW bug */
1502 HAL_RTC_GetTime(&hrtc, &time, FORMAT_BIN);
1503 HAL_RTC_GetDate(&hrtc, &date, FORMAT_BIN);
1504 /* Not all STM32 RTCs have subseconds in the struct */
1505 #ifdef RTC_ALARMSUBSECONDMASK_ALL
1506 subsec = (255 - time.SubSeconds) * 1000 / 255;
1507 #endif
1508
1509 (void) date;
1510
1511 /* return seconds.milliseconds */
1512 return ((double) time.Hours * 24) + ((double) time.Minutes * 60)
1513 + (double) time.Seconds + ((double) subsec / 1000);
1514 }
1515 #endif /* HAL_RTC_MODULE_ENABLED */
1516
1517 #ifdef CMSIS_OS2_H_
wolfCryptDemo(void * argument)1518 void wolfCryptDemo(void* argument)
1519 #else
1520 void wolfCryptDemo(const void* argument)
1521 #endif
1522 {
1523 HAL_StatusTypeDef halRet;
1524 uint8_t buffer[2];
1525 func_args args;
1526
1527 #ifdef DEBUG_WOLFSSL
1528 wolfSSL_Debugging_ON();
1529 #endif
1530
1531 /* initialize wolfSSL */
1532 #ifdef WOLFCRYPT_ONLY
1533 wolfCrypt_Init();
1534 #else
1535 wolfSSL_Init();
1536 #endif
1537
1538 #ifdef WOLFSSL_STATIC_MEMORY
1539 if (wc_LoadStaticMemory(&HEAP_HINT, gWolfMem, sizeof(gWolfMem),
1540 WOLFMEM_GENERAL, 10) != 0) {
1541 printf("unable to load static memory");
1542 }
1543 #endif
1544
1545 //wolfSSL_SetAllocators(wolfMallocCb, wolfFreeCb, wolfReallocCb);
1546
1547 while (1) {
1548 memset(&args, 0, sizeof(args));
1549 args.return_code = NOT_COMPILED_IN; /* default */
1550
1551 printf("\n\t\t\t\tMENU\n");
1552 printf(menu1);
1553 printf("Please select one of the above options:\n");
1554
1555 do {
1556 halRet = HAL_UART_Receive(&HAL_CONSOLE_UART, buffer, sizeof(buffer), 100);
1557 } while (halRet != HAL_OK || buffer[0] == '\n' || buffer[0] == '\r');
1558
1559 switch (buffer[0]) {
1560 case 't':
1561 printf("Running wolfCrypt Tests...\n");
1562 #ifndef NO_CRYPT_TEST
1563 args.return_code = 0;
1564 wolfcrypt_test(&args);
1565 #else
1566 args.return_code = NOT_COMPILED_IN;
1567 #endif
1568 printf("Crypt Test: Return code %d\n", args.return_code);
1569 break;
1570
1571 case 'b':
1572 printf("Running wolfCrypt Benchmarks...\n");
1573 #ifndef NO_CRYPT_BENCHMARK
1574 args.return_code = 0;
1575 benchmark_test(&args);
1576 #else
1577 args.return_code = NOT_COMPILED_IN;
1578 #endif
1579 printf("Benchmark Test: Return code %d\n", args.return_code);
1580 break;
1581
1582 case 'l':
1583 printf("Running TLS Benchmarks...\n");
1584 #if (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && !defined(WOLFCRYPT_ONLY) && !defined(SINGLE_THREADED)
1585 bench_tls(&args);
1586 #else
1587 args.return_code = NOT_COMPILED_IN;
1588 #endif
1589 printf("TLS Benchmarks: Return code %d\n", args.return_code);
1590 break;
1591
1592 case 'e':
1593 #ifndef WOLFCRYPT_ONLY
1594 ShowCiphers();
1595 #else
1596 printf("Not compiled in\n");
1597 #endif
1598 break;
1599
1600 // All other cases go here
1601 default:
1602 printf("\nSelection out of range\n");
1603 break;
1604 }
1605
1606 PrintMemStats();
1607 }
1608
1609 #ifdef WOLFCRYPT_ONLY
1610 wolfCrypt_Cleanup();
1611 #else
1612 wolfSSL_Cleanup();
1613 #endif
1614 }
1615