xref: /freebsd/crypto/libecc/src/tests/ec_self_tests.c (revision f0865ec9906d5a18fa2a3b61381f22ce16e606ad)
1 /*
2  *  Copyright (C) 2017 - This file is part of libecc project
3  *
4  *  Authors:
5  *      Ryad BENADJILA <ryadbenadjila@gmail.com>
6  *      Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr>
7  *      Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr>
8  *
9  *  Contributors:
10  *      Nicolas VIVET <nicolas.vivet@ssi.gouv.fr>
11  *      Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr>
12  *
13  *  This software is licensed under a dual BSD and GPL v2 license.
14  *  See LICENSE file at the root folder of the project.
15  */
16 #include <libecc/external_deps/print.h>
17 #include <libecc/utils/utils.h>
18 #include <libecc/libsig.h>
19 
20 /*
21  * Use extern declarations to avoid including
22  * ec_self_tests_core.h, which has all fixed
23  * test vectors definitions. We only need the
24  * three functions below.
25  */
26 extern ATTRIBUTE_WARN_UNUSED_RET int perform_known_test_vectors_test(const char *sig, const char *hash, const char *curve);
27 extern ATTRIBUTE_WARN_UNUSED_RET int perform_random_sig_verif_test(const char *sig, const char *hash, const char *curve);
28 extern ATTRIBUTE_WARN_UNUSED_RET int perform_performance_test(const char *sig, const char *hash, const char *curve);
29 
30 /* Tests kinds */
31 #define KNOWN_TEST_VECTORS	(1)
32 #define RANDOM_SIG_VERIF	(1 << 2)
33 #define PERFORMANCE		(1 << 3)
34 
35 typedef struct {
36 	const char *type_name;
37 	const char *type_help;
38 	unsigned int type_mask;
39 } test_type;
40 
41 static const test_type test_types[] = {
42 	{
43 	 .type_name = "vectors",
44 	 .type_help = "Perform known test vectors",
45 	 .type_mask = KNOWN_TEST_VECTORS,
46 	 },
47 	{
48 	 .type_name = "rand",
49 	 .type_help = "Perform random sign/verify tests",
50 	 .type_mask = RANDOM_SIG_VERIF,
51 	 },
52 	{
53 	 .type_name = "perf",
54 	 .type_help = "Performance tests",
55 	 .type_mask = PERFORMANCE,
56 	 },
57 };
58 
perform_tests(unsigned int tests,const char * sig,const char * hash,const char * curve)59 ATTRIBUTE_WARN_UNUSED_RET static int perform_tests(unsigned int tests, const char *sig, const char *hash, const char *curve)
60 {
61 	/* KNOWN_TEST_VECTORS tests */
62 	if (tests & KNOWN_TEST_VECTORS) {
63 		if (perform_known_test_vectors_test(sig, hash, curve)) {
64 			goto err;
65 		}
66 	}
67 	/* RANDOM_SIG_VERIF tests */
68 	if (tests & RANDOM_SIG_VERIF) {
69 		if (perform_random_sig_verif_test(sig, hash, curve)) {
70 			goto err;
71 		}
72 	}
73 	/* PERFORMANCE tests */
74 	if (tests & PERFORMANCE) {
75 		if (perform_performance_test(sig, hash, curve)) {
76 			goto err;
77 		}
78 	}
79 
80 	return 0;
81 
82  err:
83 	return -1;
84 }
85 
print_curves(void)86 static void print_curves(void)
87 {
88        u8 i;
89 
90        /* Print all the available curves */
91        for (i = 0; i < EC_CURVES_NUM; i++) {
92                ext_printf("%s ", (const char *)(ec_maps[i].params->name->buf));
93        }
94 
95        return;
96 }
97 
print_hash_algs(void)98 static void print_hash_algs(void)
99 {
100        int i;
101 
102        /* Print all the available hash functions */
103        for (i = 0; hash_maps[i].type != UNKNOWN_HASH_ALG; i++) {
104                ext_printf("%s ", hash_maps[i].name);
105        }
106 
107        return;
108 }
109 
print_sig_algs(void)110 static void print_sig_algs(void)
111 {
112         int i;
113 
114         /* Print all the available signature schemes */
115         for (i = 0; ec_sig_maps[i].type != UNKNOWN_ALG; i++) {
116                 ext_printf("%s ", ec_sig_maps[i].name);
117         }
118 
119         return;
120 }
121 
print_help(const char * bad_arg)122 static void print_help(const char *bad_arg)
123 {
124 	int j;
125 	if(bad_arg != NULL){
126 		ext_printf("Argument %s is unknown. Possible args are:\n", bad_arg);
127 	}
128 	for (j = 0; j < (int)(sizeof(test_types) / sizeof(test_type)); j++) {
129 		ext_printf("\t%20s:\t%s\n", test_types[j].type_name,
130 			   test_types[j].type_help);
131 	}
132 	ext_printf("-------------------\n");
133 	ext_printf("NOTE: you can filter signatures with 'sign=', hash algorithms with 'hash=', curves with 'curve='\n");
134 	ext_printf("\tExample: sign=ECDSA hash=SHA256 hash=SHA512 curve=FRP256V1\n");
135 	ext_printf("\tPossible signatures: ");
136 	print_sig_algs();
137 	ext_printf("\n\tPossible hash algorithms: ");
138 	print_hash_algs();
139 	ext_printf("\n\tPossible curves: ");
140 	print_curves();
141 	ext_printf("\n");
142 }
143 
144 #if defined(USE_SMALL_STACK)
145 #define MAX_FILTERS 1
146 #else
147 #define MAX_FILTERS 100
148 #endif
149 
150 #ifdef __cplusplus
151 /* In case of a C++ compiler, preserve our "main"
152  * linkage.
153  */
154 extern "C" {
155 int main(int argc, char *argv[]);
156 }
157 #endif
158 
main(int argc,char * argv[])159 int main(int argc, char *argv[])
160 {
161 	int ret;
162 	unsigned int tests_to_do;
163 	const char *sign_filters[MAX_FILTERS]  = { NULL };
164 	const char *hash_filters[MAX_FILTERS]  = { NULL };
165 	const char *curve_filters[MAX_FILTERS] = { NULL };
166 	int sign_filters_num = 0, hash_filters_num = 0, curve_filters_num = 0;
167 	int i, j, k;
168 
169 	/* By default, perform all tests */
170 	tests_to_do = KNOWN_TEST_VECTORS | RANDOM_SIG_VERIF | PERFORMANCE;
171 
172 	/* Sanity check */
173 	if(MAX_FILTERS < 1){
174 		ext_printf("Error: MAX_FILTERS too small\n");
175 		ret = -1;
176 		goto err;
177 	}
178 
179 	/* If we have one or more arguments, only perform specific test */
180 	if (argc > 1) {
181 		unsigned char found = 0, found_filter = 0;
182 		unsigned int found_ops = 0;
183 		int check;
184 		u32 len;
185 		/* Check of the args */
186 		for (i = 1; i < argc; i++) {
187 			found = found_filter = 0;
188 			for (j = 0;
189 			     j < (int)(sizeof(test_types) / sizeof(test_type));
190 			     j++) {
191 				ret = local_strlen(test_types[j].type_name, &len); EG(ret, err);
192 				ret = are_equal(argv[i], test_types[j].type_name, len + 1, &check); EG(ret, err);
193 				if (check) {
194 					found_ops++;
195 					found = 1;
196 					break;
197 				}
198 				ret = are_equal(argv[i], "sign=", sizeof("sign=")-1, &check); EG(ret, err);
199 				if(check){
200 					if(sign_filters_num >= MAX_FILTERS){
201 						ext_printf("Maximum number of sign filters %d exceeded!\n", sign_filters_num);
202 						ret = -1;
203 						goto err;
204 					}
205 					sign_filters[sign_filters_num++] = argv[i]+sizeof("sign=")-1;
206 					found_filter = 1;
207 					break;
208 				}
209 				ret = are_equal(argv[i], "hash=", sizeof("hash=")-1, &check); EG(ret, err);
210 				if(check){
211 					if(hash_filters_num >= MAX_FILTERS){
212 						ext_printf("Maximum number of hash filters %d exceeded!\n", hash_filters_num);
213 						ret = -1;
214 						goto err;
215 					}
216 					hash_filters[hash_filters_num++] = argv[i]+sizeof("hash=")-1;
217 					found_filter = 1;
218 					break;
219 				}
220 				ret = are_equal(argv[i], "curve=", sizeof("curve=")-1, &check); EG(ret, err);
221 				if(check){
222 					if(curve_filters_num >= MAX_FILTERS){
223 						ext_printf("Maximum number of curve filters %d exceeded!\n", curve_filters_num);
224 						return -1;
225 					}
226 					curve_filters[curve_filters_num++] = argv[i]+sizeof("curve=")-1;
227 					found_filter = 1;
228 					break;
229 				}
230 			}
231 			if ((found == 0) && (found_filter == 0)) {
232 				print_help(argv[i]);
233 				ret = -1;
234 				goto err;
235 			}
236 		}
237 		if (found_ops == 0) {
238 			if(found_filter == 0){
239 				ext_printf("Error: no operation asked ...\n");
240 				print_help(NULL);
241 				ret = -1;
242 				goto err;
243 			}
244 		}
245 		else{
246 			tests_to_do = 0;
247 			for (i = 1; i < argc; i++) {
248 				for (j = 0;
249 				     j < (int)(sizeof(test_types) / sizeof(test_type));
250 				     j++) {
251 					ret = local_strlen(test_types[j].type_name, &len); EG(ret, err);
252 					ret = are_equal(argv[i], test_types[j].type_name, len + 1, &check); EG(ret, err);
253 					if (check){
254 						tests_to_do |= test_types[j].type_mask;
255 					}
256 				}
257 			}
258 		}
259 	}
260 	/* If we do not have filters, we put NULL to tell that we do not filter */
261 	if(sign_filters_num == 0){
262 		sign_filters_num = 1;
263 		sign_filters[0] = NULL;
264 	}
265 	if(hash_filters_num == 0){
266 		hash_filters_num = 1;
267 		hash_filters[0] = NULL;
268 	}
269 	if(curve_filters_num == 0){
270 		curve_filters_num = 1;
271 		curve_filters[0] = NULL;
272 	}
273 	for(i = 0; i < sign_filters_num; i++){
274 		for(j = 0; j < hash_filters_num; j++){
275 			for(k = 0; k < curve_filters_num; k++){
276 				if(perform_tests(tests_to_do, sign_filters[i], hash_filters[j], curve_filters[k])){
277 					const char *curr_sign_filters = sign_filters[i];
278 					const char *curr_hash_filters = hash_filters[j];
279 					const char *curr_curve_filters = curve_filters[k];
280 					const char *all = "all";
281 					if(curr_sign_filters == NULL){
282 						curr_sign_filters = all;
283 					}
284 					if(curr_hash_filters == NULL){
285 						curr_hash_filters = all;
286 					}
287 					if(curr_curve_filters == NULL){
288 						curr_curve_filters = all;
289 					}
290 					ext_printf("Test for sign=%s/hash=%s/curve=%s failed!\n", curr_sign_filters, curr_hash_filters, curr_curve_filters);
291 					ret = -1;
292 					goto err;
293 				}
294 			}
295 		}
296 	}
297 
298 	ret = 0;
299 
300 err:
301 	return ret;
302 }
303