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