/ external / libecc / src / tests / ec_self_tests.c
ec_self_tests.c
  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  
 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  
 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  
 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  
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  
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  
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  }