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