]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/WolfSSL/tests/suites.c
d1abc19c9985d640703f98fc8c62d0e21628db01
[freertos] / FreeRTOS-Plus / Source / WolfSSL / tests / suites.c
1 /* suites.c
2  *
3  * Copyright (C) 2006-2015 wolfSSL Inc.
4  *
5  * This file is part of wolfSSL. (formerly known as CyaSSL)
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-1301, USA
20  */
21
22 #ifdef HAVE_CONFIG_H
23     #include <config.h>
24 #endif
25
26 #include <wolfssl/wolfcrypt/settings.h>
27
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <wolfssl/ssl.h>
32 #include <tests/unit.h>
33
34
35 #define MAX_ARGS 40
36 #define MAX_COMMAND_SZ 240
37 #define MAX_SUITE_SZ 80 
38 #define NOT_BUILT_IN -123
39 #ifdef NO_OLD_TLS
40     #define VERSION_TOO_OLD -124
41 #endif
42
43 #include "examples/client/client.h"
44 #include "examples/server/server.h"
45
46
47 static WOLFSSL_CTX* cipherSuiteCtx = NULL;
48 static char nonblockFlag[] = "-N";
49 static char noVerifyFlag[] = "-d";
50 static char portFlag[] = "-p";
51 static char flagSep[] = " ";
52 static char svrPort[] = "0";
53
54
55 #ifdef NO_OLD_TLS
56 /* if the protocol version is less than tls 1.2 return 1, else 0 */
57 static int IsOldTlsVersion(const char* line)
58 {
59     const char* find = "-v ";
60     char* begin = strstr(line, find);
61
62     if (begin) {
63         int version = -1;
64
65         begin += 3;
66
67         version = atoi(begin);
68
69         if (version < 3)
70             return 1;
71     }
72
73     return 0;
74
75 #endif /* NO_OLD_TLS */
76
77
78 /* if the cipher suite on line is valid store in suite and return 1, else 0 */
79 static int IsValidCipherSuite(const char* line, char* suite)
80 {
81     int  found = 0;
82     int  valid = 0;
83
84     const char* find = "-l ";
85     const char* begin = strstr(line, find);
86     const char* end;
87
88     suite[0] = '\0';
89
90     if (begin) {
91         begin += 3;
92
93         end = strstr(begin, " ");
94
95         if (end) {
96             long len = end - begin;
97             if (len > MAX_SUITE_SZ) {
98                 printf("suite too long!\n");
99                 return 0;
100             }
101             memcpy(suite, begin, len);
102             suite[len] = '\0';
103         }
104         else
105             strncpy(suite, begin, MAX_SUITE_SZ);
106
107         suite[MAX_SUITE_SZ] = '\0';
108         found = 1;
109     }
110
111     if (found) {
112         if (wolfSSL_CTX_set_cipher_list(cipherSuiteCtx, suite) == SSL_SUCCESS)
113             valid = 1;
114     }
115
116     return valid;
117 }
118
119
120 static int execute_test_case(int svr_argc, char** svr_argv,
121                               int cli_argc, char** cli_argv,
122                               int addNoVerify, int addNonBlocking)
123 {
124 #ifdef WOLFSSL_TIRTOS
125     func_args cliArgs = {0};
126     func_args svrArgs = {0};
127     cliArgs.argc = cli_argc;
128     cliArgs.argv = cli_argv;
129     svrArgs.argc = svr_argc;
130     svrArgs.argv = svr_argv;
131 #else
132     func_args cliArgs = {cli_argc, cli_argv, 0, NULL, NULL};
133     func_args svrArgs = {svr_argc, svr_argv, 0, NULL, NULL};
134 #endif
135
136     tcp_ready   ready;
137     THREAD_TYPE serverThread;
138     char        commandLine[MAX_COMMAND_SZ];
139     char        cipherSuite[MAX_SUITE_SZ+1];
140     int         i;
141     size_t      added = 0;
142     static      int tests = 1;
143
144     commandLine[0] = '\0';
145     for (i = 0; i < svr_argc; i++) {
146         added += strlen(svr_argv[i]) + 2;
147         if (added >= MAX_COMMAND_SZ) {
148             printf("server command line too long\n"); 
149             break;
150         }
151         strcat(commandLine, svr_argv[i]);
152         strcat(commandLine, flagSep);
153     }
154
155     if (IsValidCipherSuite(commandLine, cipherSuite) == 0) {
156         #ifdef DEBUG_SUITE_TESTS
157             printf("cipher suite %s not supported in build\n", cipherSuite);
158         #endif
159         return NOT_BUILT_IN;
160     }
161
162 #ifdef NO_OLD_TLS
163     if (IsOldTlsVersion(commandLine) == 1) {
164         #ifdef DEBUG_SUITE_TESTS
165             printf("protocol version on line %s is too old\n", commandLine);
166         #endif
167         return VERSION_TOO_OLD;
168     }
169 #endif
170
171     if (addNoVerify) {
172         printf("repeating test with client cert request off\n"); 
173         added += 4;   /* -d plus space plus terminator */
174         if (added >= MAX_COMMAND_SZ || svr_argc >= MAX_ARGS)
175             printf("server command line too long\n");
176         else {
177             svr_argv[svr_argc++] = noVerifyFlag;
178             svrArgs.argc = svr_argc;
179             strcat(commandLine, noVerifyFlag);
180             strcat(commandLine, flagSep);
181         }
182     }
183     if (addNonBlocking) {
184         printf("repeating test with non blocking on\n"); 
185         added += 4;   /* -N plus terminator */
186         if (added >= MAX_COMMAND_SZ || svr_argc >= MAX_ARGS)
187             printf("server command line too long\n");
188         else {
189             svr_argv[svr_argc++] = nonblockFlag;
190             svrArgs.argc = svr_argc;
191             strcat(commandLine, nonblockFlag);
192             strcat(commandLine, flagSep);
193         }
194     }
195     #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS)
196         /* add port 0 */
197         if (svr_argc + 2 > MAX_ARGS)
198             printf("cannot add the magic port number flag to server\n");
199         else
200         {
201             svr_argv[svr_argc++] = portFlag;
202             svr_argv[svr_argc++] = svrPort;
203             svrArgs.argc = svr_argc;
204         }
205     #endif
206     printf("trying server command line[%d]: %s\n", tests, commandLine);
207
208     commandLine[0] = '\0';
209     added = 0;
210     for (i = 0; i < cli_argc; i++) {
211         added += strlen(cli_argv[i]) + 2;
212         if (added >= MAX_COMMAND_SZ) {
213             printf("client command line too long\n"); 
214             break;
215         }
216         strcat(commandLine, cli_argv[i]);
217         strcat(commandLine, flagSep);
218     }
219     if (addNonBlocking) {
220         added += 4;   /* -N plus space plus terminator  */
221         if (added >= MAX_COMMAND_SZ)
222             printf("client command line too long\n");
223         else  {
224             cli_argv[cli_argc++] = nonblockFlag;
225             strcat(commandLine, nonblockFlag);
226             strcat(commandLine, flagSep);
227             cliArgs.argc = cli_argc;
228         }
229     }
230     printf("trying client command line[%d]: %s\n", tests++, commandLine);
231
232     InitTcpReady(&ready);
233
234 #ifdef WOLFSSL_TIRTOS
235     fdOpenSession(Task_self());
236 #endif
237
238     /* start server */
239     svrArgs.signal = &ready;
240     start_thread(server_test, &svrArgs, &serverThread);
241     wait_tcp_ready(&svrArgs);
242     #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS)
243         if (ready.port != 0)
244         {
245             if (cli_argc + 2 > MAX_ARGS)
246                 printf("cannot add the magic port number flag to client\n");
247             else {
248                 char portNumber[8];
249                 snprintf(portNumber, sizeof(portNumber), "%d", ready.port);
250                 cli_argv[cli_argc++] = portFlag;
251                 cli_argv[cli_argc++] = portNumber;
252                 cliArgs.argc = cli_argc;
253             }
254         }
255     #endif
256     /* start client */
257     client_test(&cliArgs);
258
259     /* verify results */ 
260     if (cliArgs.return_code != 0) {
261         printf("client_test failed\n");
262         exit(EXIT_FAILURE);
263     }
264
265     join_thread(serverThread);
266     if (svrArgs.return_code != 0) { 
267         printf("server_test failed\n");
268         exit(EXIT_FAILURE);
269     }
270
271 #ifdef WOLFSSL_TIRTOS
272     fdCloseSession(Task_self());
273 #endif
274     FreeTcpReady(&ready);
275     
276     return 0;
277 }
278
279 static void test_harness(void* vargs)
280 {
281     func_args* args = (func_args*)vargs;
282     char* script;
283     long  sz, len;
284     int   cliMode = 0;   /* server or client command flag, server first */
285     int   ret;
286     FILE* file;
287     char* svrArgs[MAX_ARGS];
288     int   svrArgsSz;
289     char* cliArgs[MAX_ARGS];
290     int   cliArgsSz;
291     char* cursor;
292     char* comment;
293     const char* fname = "tests/test.conf";
294
295     if (args->argc == 1) {
296         printf("notice: using default file %s\n", fname);
297     }
298     else if(args->argc != 2) {
299         printf("usage: harness [FILE]\n");
300         args->return_code = 1;
301         return;
302     }
303     else {
304         fname = args->argv[1];
305     }
306
307     file = fopen(fname, "r");
308     if (file == NULL) {
309         fprintf(stderr, "unable to open %s\n", fname);
310         args->return_code = 1;
311         return;
312     }
313     fseek(file, 0, SEEK_END);
314     sz = ftell(file);
315     rewind(file);
316     if (sz <= 0) {
317         fprintf(stderr, "%s is empty\n", fname);
318         fclose(file);
319         args->return_code = 1;
320         return;
321     }
322
323     script = (char*)malloc(sz+1);
324     if (script == 0) {
325         fprintf(stderr, "unable to allocte script buffer\n");
326         fclose(file);
327         args->return_code = 1;
328         return;
329     }
330
331     len = fread(script, 1, sz, file);
332     if (len != sz) {
333         fprintf(stderr, "read error\n");
334         fclose(file);
335         free(script);
336         args->return_code = 1;
337         return;
338     }
339     
340     fclose(file);
341     script[sz] = 0;
342
343     cursor = script;
344     svrArgsSz = 1;
345     svrArgs[0] = args->argv[0];
346     cliArgsSz = 1;
347     cliArgs[0] = args->argv[0];
348
349     while (*cursor != 0) {
350         int do_it = 0;
351
352         switch (*cursor) {
353             case '\n':
354                 /* A blank line triggers test case execution or switches
355                    to client mode if we don't have the client command yet */
356                 if (cliMode == 0)
357                     cliMode = 1;  /* switch to client mode processing */
358                 else
359                     do_it = 1;    /* Do It, we have server and client */
360                 cursor++;
361                 break;
362             case '#':
363                 /* Ignore lines that start with a #. */
364                 comment = strsep(&cursor, "\n");
365 #ifdef DEBUG_SUITE_TESTS
366                 printf("%s\n", comment);
367 #else
368                 (void)comment;
369 #endif
370                 break;
371             case '-':
372                 /* Parameters start with a -. They end in either a newline
373                  * or a space. Capture until either, save in Args list. */
374                 if (cliMode)
375                     cliArgs[cliArgsSz++] = strsep(&cursor, " \n");
376                 else
377                     svrArgs[svrArgsSz++] = strsep(&cursor, " \n");
378                 break;
379             default:
380                 /* Anything from cursor until end of line that isn't the above
381                  * is data for a paramter. Just up until the next newline in
382                  * the Args list. */
383                 if (cliMode)
384                     cliArgs[cliArgsSz++] = strsep(&cursor, "\n");
385                 else
386                     svrArgs[svrArgsSz++] = strsep(&cursor, "\n");
387                 if (*cursor == 0)  /* eof */
388                     do_it = 1; 
389         }
390
391         if (svrArgsSz == MAX_ARGS || cliArgsSz == MAX_ARGS) {
392             fprintf(stderr, "too many arguments, forcing test run\n");
393             do_it = 1;
394         }
395
396         if (do_it) {
397             ret = execute_test_case(svrArgsSz, svrArgs, cliArgsSz, cliArgs,0,0);
398             /* don't repeat if not supported in build */
399             if (ret == 0) {
400                 execute_test_case(svrArgsSz, svrArgs, cliArgsSz, cliArgs, 0, 1);
401                 execute_test_case(svrArgsSz, svrArgs, cliArgsSz, cliArgs, 1, 0);
402                 execute_test_case(svrArgsSz, svrArgs, cliArgsSz, cliArgs, 1, 1);
403             }
404             svrArgsSz = 1;
405             cliArgsSz = 1;
406             cliMode   = 0;
407         }
408     }
409
410     free(script);
411     args->return_code = 0;
412 }
413
414
415 int SuiteTest(void)
416 {
417     func_args args;
418     char argv0[2][80];
419     char* myArgv[2];
420
421     printf(" Begin Cipher Suite Tests\n");
422
423     /* setup */
424     myArgv[0] = argv0[0];
425     myArgv[1] = argv0[1];
426     args.argv = myArgv;
427     strcpy(argv0[0], "SuiteTest");
428
429     (void)test_harness;
430
431     cipherSuiteCtx = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
432     if (cipherSuiteCtx == NULL) {
433         printf("can't get cipher suite ctx\n");
434         exit(EXIT_FAILURE);  
435     }
436
437     /* default case */
438     args.argc = 1;
439     printf("starting default cipher suite tests\n");
440     test_harness(&args);
441     if (args.return_code != 0) {
442         printf("error from script %d\n", args.return_code);
443         exit(EXIT_FAILURE);  
444     }
445
446     /* any extra cases will need another argument */
447     args.argc = 2;
448
449 #ifdef WOLFSSL_DTLS 
450     /* add dtls extra suites */
451     strcpy(argv0[1], "tests/test-dtls.conf");
452     printf("starting dtls extra cipher suite tests\n");
453     test_harness(&args);
454     if (args.return_code != 0) {
455         printf("error from script %d\n", args.return_code);
456         exit(EXIT_FAILURE);  
457     }
458 #endif
459
460     printf(" End Cipher Suite Tests\n");
461
462     wolfSSL_CTX_free(cipherSuiteCtx);
463     wolfSSL_Cleanup();
464
465     return args.return_code;
466 }
467
468