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