1 /*shell.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
23 /*** tiny Shell for wolfSSL apps ***/
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29
30 #include "wolfssl/internal.h"
31 #include <wolfssl/wolfcrypt/logging.h>
32
33 #if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET)
34 #include <stdio.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #if defined(WOLFSSL_MDK5) || defined(WOLFSSL_KEIL_TCP_NET)
38 #include "cmsis_os.h"
39 #include "rl_fs.h"
40 #else
41 #include <rtl.h>
42 #endif
43 #endif
44
45 #ifdef WOLFSSL_KEIL_TCP_NET
46 #include "wolfssl/test.h"
47 #else
48 typedef struct func_args {
49 int argc;
50 char** argv;
51 int return_code;
52 } func_args;
53 #endif
54
55 #if defined(WOLFSSL_CMSIS_RTOS)
56 #define HAVE_KEIL_RTX
57 #endif
58
59 #ifdef NO_ECHOCLIENT
60 #define echoclient_test command_not_found
61 #endif
62 #ifdef NO_ECHOSERVER
63 #define echoserver_test command_not_found
64 #endif
65 #ifdef NO_SIMPLE_CLIENT
66 #define client_test command_not_found
67 #endif
68 #ifdef NO_SIMPLE_SERVER
69 #define server_test command_not_found
70 #endif
71 #ifdef NO_CRYPT_BENCHMARK
72 #define benchmark_test command_not_found
73 #endif
74 #ifdef NO_CRYPT_TEST
75 #define ctaocrypt_test command_not_found
76 #endif
77
78 #ifndef WOLFSSL_KEIL_TCP_NET
79 #define ipaddr_comm command_not_found
80 #endif
81
82 #if !defined(HAVE_KEIL_RTX)
83 #define stack_comm command_not_found
84 #endif
85
86
87 #if !defined(DEBUG_WOLFSSL)
88 #define dbg_comm command_not_found
89 #endif
90
91
command_not_found(void * argv)92 void command_not_found(void *argv) {
93 printf("Command not found\n") ;
94 }
95
96 extern void echoclient_test(void *args) ;
97 extern void echoserver_test(void *args) ;
98 extern void benchmark_test(void *args) ;
99 extern void wolfcrypt_test(void *args) ;
100 extern void client_test(void *args) ;
101 extern void server_test(void *args) ;
102 extern void kill_task(void *args) ;
103 extern void ipaddr_comm(void *args) ;
104 extern void stack_comm(void *args) ;
105 extern void for_command(void *args) ;
106 extern void dbg_comm(void *arg) ;
107 extern void help_comm(void *arg) ;
108
109 #if !defined(NO_CRYPT_TEST)
110
111 #ifndef NO_MD5
112 extern void md5_test(void *arg) ;
113 #endif
114 #ifdef WOLFSSL_MD2
115 extern void md2_test(void *arg) ;
116 #endif
117 #ifndef NO_MD4
118 extern void md4_test(void *arg) ;
119 #endif
120
121 extern void sha_test(void *arg) ;
122
123 #ifndef NO_SHA256
124 extern void sha256_test(void *arg) ;
125 #endif
126 #ifdef WOLFSSL_SHA384
127 extern void sha384_test(void *arg) ;
128 #endif
129
130 #ifdef WOLFSSL_SHA512
131 extern void sha512_test(void *arg) ;
132 #endif
133
134 #ifdef WOLFSSL_RIPEMD
135 extern void ripemd_test(void *arg) ;
136 #endif
137 #ifndef NO_HMAC
138 #ifndef NO_MD5
139 extern void hmac_md5_test(void *arg) ;
140 #endif
141 extern void hmac_sha_test(void *arg) ;
142
143 #ifndef NO_SHA256
144 extern void hmac_sha256_test(void *arg) ;
145 #endif
146
147 #ifdef WOLFSSL_SHA384
148 extern void hmac_sha384_test(void *arg) ;
149 #endif
150 #endif
151 #ifndef NO_RC4
152 extern void arc4_test(void *arg) ;
153 #endif
154
155 #ifndef NO_HC128
156 extern void hc128_test(void *arg) ;
157 #endif
158
159 #ifndef NO_RABBIT
160 extern void rabbit_test(void *arg) ;
161 #endif
162
163 #ifndef NO_DES3
164 extern void des_test(void *arg) ;
165 extern void des3_test(void *arg) ;
166 #endif
167
168 #ifndef NO_AES
169 extern void aes_test(void *arg) ;
170 #ifdef HAVE_AESGCM
171 extern void aesgcm_test(void *arg) ;
172 #endif
173
174 #ifdef HAVE_AESCCM
175 extern void aesccm_test(void *arg) ;
176 #endif
177 #endif
178
179 #ifdef HAVE_CAMELLIA
180 extern void camellia_test(void *arg) ;
181 #endif
182 extern void random_test(void *arg) ;
183
184 #ifndef NO_RSA
185 extern void rsa_test(void *arg) ;
186 #endif
187
188 #ifndef NO_DH
189 extern void dh_test(void *arg) ;
190 #endif
191
192 #ifndef NO_DSA
193 extern void dsa_test(void *arg) ;
194 #endif
195
196 #ifndef NO_PWDBASED
197 extern void pwdbased_test(void *arg) ;
198 #endif
199
200 #ifdef OPENSSL_EXTRA
201 extern void openssl_test(void *arg) ;
202 #endif
203
204 #ifdef HAVE_ECC
205 extern void ecc_test(void *arg) ;
206 #endif
207
208 #endif /* NO_CRYPT_TEST */
209
210 static struct {
211 const char *command ;
212 void (*func)(void *args) ;
213 } commandTable[] = {
214 "echoclient", echoclient_test,
215 "echoserver", echoserver_test,
216 "benchmark", benchmark_test,
217 "test", wolfcrypt_test,
218 "client", client_test,
219 "server", server_test,
220 "ipaddr", ipaddr_comm, /* TBD */
221 "stack", stack_comm, /* On/Off check stack size */
222 "for", for_command, /* iterate next command X times */
223 "debug", dbg_comm, /* On/Off debug message */
224 "help", help_comm, /* Brief description about the commands */
225
226 /** short name **/
227 "ec", echoclient_test,
228 "es", echoserver_test,
229 "bm", benchmark_test,
230 "te", wolfcrypt_test,
231 "cl", client_test,
232 "sv", server_test,
233 "ip", ipaddr_comm,
234 "st", stack_comm,
235 "dbg", dbg_comm,
236 "?", help_comm,
237
238 /*** test suites ****/
239 #if !defined(NO_CRYPT_TEST)
240 #ifndef NO_MD5
241 "md5", md5_test,
242 #endif
243 #ifdef WOLFSSL_MD2
244 "md2", md2_test,
245 #endif
246 #ifndef NO_MD4
247 "md4", md4_test,
248 #endif
249 "sha", sha_test,
250 #ifndef NO_SHA256
251 "sha256", sha256_test,
252 #endif
253 #ifdef WOLFSSL_SHA384
254 "sha384", sha384_test,
255 #endif
256 #ifdef WOLFSSL_SHA512
257 "sha512", sha512_test,
258 #endif
259 #ifdef WOLFSSL_RIPEMD
260 "ripemd", ripemd_test,
261 #endif
262 #ifndef NO_HMAC
263 #ifndef NO_MD5
264 "hmac_md5", hmac_md5_test,
265 #endif
266 "hmac_sha", hmac_sha_test,
267 #ifndef NO_SHA256
268 "hmac_sha256", hmac_sha256_test,
269 #endif
270 #ifdef WOLFSSL_SHA384
271 "hmac_sha384", hmac_sha384_test,
272 #endif
273 #endif
274 #ifndef NO_RC4
275 "arc4", arc4_test,
276 #endif
277 #ifndef NO_HC128
278 "hc128", hc128_test,
279 #endif
280 #ifndef NO_RABBIT
281 "rabbit", rabbit_test,
282 #endif
283 #ifndef NO_DES3
284 "des", des_test,
285 "des3", des3_test,
286 #endif
287 #ifndef NO_AES
288 "aes", aes_test,
289 #ifdef HAVE_AESGCM
290 "aesgcm", aesgcm_test,
291 #endif
292 #ifdef HAVE_AESCCM
293 "aesccm", aesccm_test,
294 #endif
295 #endif
296
297 #ifdef HAVE_CAMELLIA
298 "camellia", camellia_test,
299 #endif
300 "random", random_test,
301 #ifndef NO_RSA
302 "rsa", rsa_test,
303 #endif
304 #ifndef NO_DH
305 "dh", dh_test,
306 #endif
307 #ifndef NO_DSA
308 "dsa", dsa_test,
309 #endif
310 #ifndef NO_PWDBASED
311 "pwdbased", pwdbased_test,
312 #endif
313 #ifdef OPENSSL_EXTRA
314 "openssl", openssl_test,
315 #endif
316 #ifdef HAVE_ECC
317 "ecc", ecc_test,
318 #endif
319
320 #endif /* NO_CRYPT_TEST */
321
322 "", NULL
323 } ;
324
325 enum jobtype { FORGROUND, BACKGROUND } ;
326
327 #define IF_DELIMITER(ch) ((ch) == ' ' || (ch) == '\n')
328
329 static int BackGround = 0 ; /* 1: background job is running */
330
wolfssl_fgets(char * str,int num,FILE * f)331 char * wolfssl_fgets ( char * str, int num, FILE * f )
332 {
333 int i ;
334
335 for(i = 0 ; i< num ; i++) {
336 while((str[i] = getchar()) == 0) {
337 #if defined (HAVE_KEIL_RTX) && !defined(WOLFSSL_CMSIS_RTOS)
338 os_tsk_pass ();
339 #else
340 osThreadYield ();
341 #endif
342 }
343 if(str[i] == '\n' || str[i] == '\012' || str[i] == '\015') {
344 putchar('\n') ;
345 str[i++] = '\n' ;
346 str[i] = '\0' ;
347 break ;
348 } else if(str[i] == '\010') { /* BS */
349 if(i) { /* erace one char */
350 putchar('\010') ; putchar(' ') ; putchar('\010') ;
351 i = (i>0 ? (i-2) : -1 ) ;
352 continue ;
353 }
354 } else if(str[i] == '\033' || str[i] == '\004' ) { /* ESC or ^D */
355 str[i] = '\0' ;
356 return(0) ;
357 }
358 putchar(str[i]) ;
359 }
360 return(str) ;
361 }
362
363 /******* Get Command Line *****************************/
getline(char * line,int sz,func_args * args,int * bf_flg)364 static int getline(char * line, int sz, func_args *args, int*bf_flg)
365 {
366 char * ret ;
367 int i ;
368
369 #define MAXARGS 10
370 #define MAXARGLEN 30
371 static char *argv[MAXARGS] ;
372 args->argv = argv ;
373
374 putchar('>') ;
375 fflush(stdout) ;
376 ret = wolfssl_fgets(line, sz, stdin) ;
377
378 #define SHELL_ERROR_FGETS -102
379 if(ret != line) return(SHELL_ERROR_FGETS) ;
380
381 if(line[strlen(line)-2] == '&') {
382 (*bf_flg) = BACKGROUND ;
383 line[strlen(line)-2] = '\n' ;
384 } else {
385 (*bf_flg) = FORGROUND ;
386 }
387 args->argc = 0 ;
388 for(i=0; i<sz; i++) {
389 args->argv[args->argc] = &(line[i]) ;
390 while(!IF_DELIMITER(line[i])) i++ ;
391 args->argc++ ;
392 if(line[i] == '\n') {
393 line[i] = '\0' ;
394 break ;
395 } else {
396 line[i] = '\0' ;
397 }
398 }
399 return i ;
400 }
401
402
403 /************* Embedded Shell Commands **********************************/
404 #define IP_SIZE 16
405
406 #ifdef WOLFSSL_KEIL_TCP_NET
ipaddr_comm(void * args)407 static void ipaddr_comm(void *args)
408 {
409 if(((func_args *)args)->argc == 1) {
410 printf("IP addr: %s, port %d\n", wolfSSLIP, wolfSSLPort) ;
411 } else {
412 if(BackGround != 0) {
413 printf("Cannot change IP addr while background server is running\n") ;
414 } else if(((func_args *)args)->argc == 3 &&
415 ((func_args *)args)->argv[1][0] == '-'&&
416 ((func_args *)args)->argv[1][1] == 'a' ) {
417 /* strcpy(yasslIP, ((func_args *)args)->argv[2]) ; */
418 } else if(((func_args *)args)->argc == 3 &&
419 ((func_args *)args)->argv[1][0] == '-' &&
420 ((func_args *)args)->argv[1][1] == 'p' ) {
421 /* yasslPort = atoi(((func_args *)args)->argv[2]) ; */
422 } else printf("Invalid argument\n") ;
423 }
424 }
425
426 #endif
427
428
429
430 #if defined(HAVE_KEIL_RTX)
431 static int stack_ck = 0 ;
432
stack_comm(void * args)433 void stack_comm(void *args)
434 {
435 if(stack_ck) {
436 printf("Stack Check: Off\n") ;
437 stack_ck = 0 ;
438 } else {
439 printf("Stack Check: On\n") ;
440 stack_ck = 1 ;
441 }
442 }
443
444 #define FILL_PATTERN 0xa596695a
stack_fill(char * stack,int size)445 void stack_fill(char * stack, int size)
446 {
447 int i ;
448
449 if(stack_ck == 0)return ;
450 for(i=1; i<size/4-10; i++)
451 ((int *)stack)[i] = FILL_PATTERN ;
452 }
453
stack_check(char * stack,int size)454 void stack_check(char * stack, int size)
455 {
456 int i ;
457
458 if(stack_ck == 0)return ;
459 if(stack_ck == 1) {
460 stack_ck ++ ; return ;
461 }
462 for(i=1; i<size/4 ; i++) {
463 if(((int *)stack)[i] != FILL_PATTERN) break ;
464 }
465 if(i < size/4) {
466 printf("Stack is used %d bytes out of %d\n", size - i*4, size) ;
467 } else {
468 printf("Stack overflow. Stack size: %d\n", size) ;
469 }
470 }
471
472 #endif /* HAVE_KEIL_RTX */
473
474 static int for_iteration = 1 ;
475
for_command(void * args)476 static void for_command(void *args)
477 {
478 if( args == NULL || ((func_args *)args)->argc == 1) {
479 printf("For %d times\n", for_iteration) ;
480 } else if(((func_args *)args)->argc == 2) {
481 for_iteration = atoi(((func_args *)args)->argv[1]) ;
482 } else printf("Invalid argument\n") ;
483 }
484
485
486 #if defined(DEBUG_WOLFSSL)
487
488 static int wolfsslDebug = 1 ;
489
dbg_comm(void * args)490 static void dbg_comm(void *args)
491 {
492 if(wolfsslDebug == 1) {
493 wolfsslDebug = 0 ;
494 printf("Turning OFF Debug message\n") ;
495 wolfSSL_Debugging_OFF() ;
496 } else {
497 wolfasslDebug = 1 ;
498 printf("Turning ON Debug message\n") ;
499 wolfSSL_Debugging_ON() ;
500 }
501 }
502 #endif
503
help_comm(void * args)504 static void help_comm(void *args)
505 {
506 static char *commands[] = {
507 "test",
508 "benchmark",
509 "echoserver& : simple echo server in background mode",
510 "echoclient : simple echo client followed by any input string, or \"quit\", \"break\"",
511 "server& : simple server in background mode",
512 "client : simple client",
513 "client -g -v [0123] -h xxx.xxx.xxx.xxx -p 443 : usage example",
514 "server/client -h : help for server/client command",
515 "help",
516 ""
517 } ;
518
519 int i ;
520 printf("Commands:\n") ;
521 for(i=0; commands[i][0] ; i++)
522 printf(" %s\n", commands[i]) ;
523
524 }
525
526
527
528 #define BG_JOB_STACK_SIZE 16000
529 #if (!defined(NO_SIMPLE_SERVER) && !defined(NO_ECHOSERVER)) && \
530 defined(HAVE_KEIL_RTX)
531 #if !defined(WOLFSSL_CMSIS_RTOS)
532 static char bg_job_stack[BG_JOB_STACK_SIZE] ;
533 #endif
534
535 #endif
536
537 #define COMMAND_STACK_SIZE 24000
538 #if defined(HAVE_KEIL_RTX) && !defined(WOLFSSL_CMSIS_RTOS)
539 static char command_stack[COMMAND_STACK_SIZE] ;
540 #endif
541
542
543 #if defined(HAVE_KEIL_RTX) || defined(WOLFSSL_CMSIS_RTOS)
544 static wolfSSL_Mutex command_mutex ;
545 #endif
546
exit_command(void)547 void exit_command(void) {
548 printf("Command Aborted\n") ;
549 #ifdef WOLFSSL_CMSIS_RTOS
550 osThreadTerminate(osThreadGetId()) ;
551 #else
552 os_tsk_delete_self() ;
553 #endif
554 }
555
556
557 /*********** Invoke Foreground Command *********************/
command_invoke(void const * args)558 static void command_invoke(void const *args)
559 {
560 void (*func)(void const * ) ;
561 int i,iteration ;
562
563 func = (void(*)(void const *))((func_args *)args)->argv[0] ;
564 #if defined(HAVE_KEIL_RTX)
565 wc_LockMutex((wolfSSL_Mutex *)&command_mutex) ;
566 #endif
567 iteration = for_iteration ;
568 for(i=0; i< iteration; i++) {
569 if(iteration > 1) printf("--- Start for %d ---->\n", i) ;
570 #if defined(HAVE_KEIL_RTX) && !defined(WOLFSSL_CMSIS_RTOS)
571 stack_fill(command_stack, COMMAND_STACK_SIZE) ;
572 #endif
573
574 func(args) ; /* invoke command */
575
576 #if defined(HAVE_KEIL_RTX)&& !defined(WOLFSSL_CMSIS_RTOS)
577 stack_check(command_stack, COMMAND_STACK_SIZE) ;
578 #endif
579 }
580
581 if(iteration > 1)
582 for_iteration = 1 ;
583 osDelay(20000) ;
584 #ifdef HAVE_KEIL_RTX
585 wc_UnLockMutex((wolfSSL_Mutex *)&command_mutex) ;
586 #ifdef WOLFSSL_CMSIS_RTOS
587 osThreadTerminate(osThreadGetId()) ;
588 #else
589 os_tsk_delete_self() ;
590 #endif
591 #endif
592 }
593
594 #if defined(HAVE_KEIL_RTX) || defined(WOLFSSL_CMSIS_RTOS)
595 /******* Invoke Background Job *******************************/
bg_job_invoke(void const * args)596 static void bg_job_invoke(void const *args)
597 {
598 void (*func)(void const * ) ;
599 BackGround = 1 ;
600 #if defined(HAVE_KEIL_RTX)&& !defined(WOLFSSL_CMSIS_RTOS)
601 stack_fill(bg_job_stack, BG_JOB_STACK_SIZE) ;
602 #endif
603
604 func = (void(*)(void const *))((func_args *)args)->argv[0] ;
605 func(args) ; /* invoke command */
606 #if defined(HAVE_KEIL_RTX) && !defined(WOLFSSL_CMSIS_RTOS)
607 stack_check(bg_job_stack, BG_JOB_STACK_SIZE) ;
608 #endif
609
610 osDelay(20000) ;
611 BackGround = 0 ;
612
613 #ifdef WOLFSSL_CMSIS_RTOS
614 osThreadTerminate(osThreadGetId()) ;
615 #else
616 os_tsk_delete_self() ; ;
617 #endif
618 }
619 #endif
620
621 #define LINESIZE 100
622 static char line[LINESIZE] ;
623
624 #if defined(WOLFSSL_CMSIS_RTOS)
625 osThreadDef (command_invoke, osPriorityAboveNormal , 1, COMMAND_STACK_SIZE) ;
626 osThreadDef (bg_job_invoke, osPriorityNormal , 1 , BG_JOB_STACK_SIZE) ;
627 #endif
628 /********* SHEULL MAIN LOOP ***********************************/
shell_main(void * arg)629 void shell_main(void *arg) {
630 int i ;
631 func_args args ;
632 int bf_flg ;
633 #if defined(WOLFSSL_CMSIS_RTOS)
634 osThreadId cmd ;
635 #endif
636 i = BackGround ;
637 /* Dummy for avoiding warning: BackGround is defined but not used. */
638
639 #if defined(HAVE_KEIL_RTX)
640 wc_InitMutex(&command_mutex) ;
641 #endif
642 help_comm(NULL) ;
643
644 printf("Starting Shell\n") ;
645 while(1) {
646 if(getline(line, LINESIZE, &args, &bf_flg) > 0) {
647 for(i=0; commandTable[i].func != NULL; i++) {
648 if(strcmp(commandTable[i].command, args.argv[0]) == 0) {
649 args.argv[0] = (char *) commandTable[i].func ;
650 if(bf_flg == FORGROUND) {
651 #if defined(HAVE_KEIL_RTX) && !defined(WOLFSSL_CMSIS_RTOS)
652 wc_UnLockMutex((wolfSSL_Mutex *)&command_mutex) ;
653 os_tsk_create_user_ex( (void(*)(void *))&command_invoke, 7,
654 command_stack, COMMAND_STACK_SIZE, &args) ;
655 os_tsk_pass ();
656 #else
657 #if defined(WOLFSSL_CMSIS_RTOS)
658 wc_UnLockMutex((wolfSSL_Mutex *)&command_mutex) ;
659 cmd = osThreadCreate (osThread (command_invoke) , &args);
660 if(cmd == NULL) {
661 printf("Cannon create command thread\n") ;
662 }
663 osThreadYield ();
664 #else
665 command_invoke(&args) ;
666 #endif
667 #endif
668 #ifdef HAVE_KEIL_RTX
669 wc_LockMutex((wolfSSL_Mutex *)&command_mutex) ;
670 #endif
671 } else {
672 #if (!defined(NO_SIMPLE_SERVER) && \
673 !defined(NO_ECHOSERVER)) && \
674 defined(HAVE_KEIL_RTX)
675 if(BackGround != 0) {
676 printf("Multiple background servers not supported.\n") ;
677 } else {
678 printf("\"%s\" is running with the background mode.\n",
679 commandTable[i].command) ;
680 #if defined(HAVE_KEIL_RTX) && !defined(WOLFSSL_CMSIS_RTOS)
681 os_tsk_create_user_ex( (void(*)(void *))&bg_job_invoke,
682 6, bg_job_stack, BG_JOB_STACK_SIZE, &args) ;
683 #else
684 osThreadCreate (osThread (bg_job_invoke), &args);
685 osDelay (500) ;
686 #endif
687 }
688 #else
689 printf("Invalid Command: no background job\n") ;
690 #endif
691 }
692 break ;
693 }
694 }
695 if(commandTable[i].func == NULL)
696 printf("Command not found\n") ;
697 }
698 }
699 }
700
701