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