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 } 303