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