Path: blob/main/crypto/libecc/src/arithmetic_tests/arithmetic_tests.c
34889 views
/*1* Copyright (C) 2017 - This file is part of libecc project2*3* Authors:4* Ryad BENADJILA <[email protected]>5* Arnaud EBALARD <[email protected]>6* Jean-Pierre FLORI <[email protected]>7*8* Contributors:9* Nicolas VIVET <[email protected]>10* Karim KHALFALLAH <[email protected]>11*12* This software is licensed under a dual BSD and GPL v2 license.13* See LICENSE file at the root folder of the project.14*/15#include <libecc/libarith.h>16/* Include internal API as it is used in our tests */17#include "../nn/nn_div.h"18#include <sys/types.h>19#include <sys/stat.h>20#include <fcntl.h>21#include <unistd.h>22#include <string.h>23#include <stdio.h>24#include <stdlib.h>25#include <assert.h>2627#ifdef WITH_ASSERT_BACKTRACE28#include <signal.h>29#include <execinfo.h>3031#define BACKTRACE_SIZE 409632static unsigned int backtrace_buffer_ptr = 0;33static char backtrace_buffer[BACKTRACE_SIZE];3435/* assert trapping and backtracing */36static void assert_signal_handler(int sig)37{38if (sig != SIGINT) {39raise(sig);40}41/* Print the recorded backtrace */42printf("**** BACKTRACE *****\n");43printf("(from old to most recent calls)\n");44printf("%s", backtrace_buffer);45exit(-1);46}4748#define ADD_TO_BACKTRACE(...) do {\49int written_size;\50written_size = snprintf(backtrace_buffer + backtrace_buffer_ptr, BACKTRACE_SIZE - 1 - backtrace_buffer_ptr, __VA_ARGS__);\51backtrace_buffer_ptr += written_size;\52if(backtrace_buffer_ptr >= BACKTRACE_SIZE - 1){\53memset(backtrace_buffer, 0, sizeof(backtrace_buffer)-1);\54backtrace_buffer_ptr = 0;\55}\56} while(0)57#else5859#define ADD_TO_BACKTRACE(...) do {\60} while(0)6162#endif6364/*65* Import integer number (found in hexadecimal form in hbuf buffer66* of length hbuflen) into already allocated out_nn. hbuflen is67* expected to be of even size. out_nn parameter is expected to68* have a large enough storage space (i.e. hbuflen / 2) to hold69* imported number.70*/71static int nn_import_from_hexbuf(nn_t out_nn, const char *hbuf, u32 hbuflen)72{73char buf[WORD_BYTES * 2 + 1];74const char *start;75u32 wlen;76u32 k;77int ret;7879ret = nn_check_initialized(out_nn); EG(ret, err);80MUST_HAVE((hbuf != NULL), ret, err);81MUST_HAVE(((hbuflen / 2) / WORD_BYTES) == out_nn->wlen, ret, err);8283wlen = (hbuflen + WORD_BYTES - 1) / (2 * WORD_BYTES);84for (k = wlen; k > 0; k--) {85/*86* Copy current hex encoded word into null terminated87* scratch buffer88*/89memset(buf, 0, WORD_BYTES * 2 + 1);90start = hbuf + ((k - 1) * WORD_BYTES * 2);91memcpy(buf, start, WORD_BYTES * 2);9293/* Let strtoull() convert the value for us */94out_nn->val[wlen - k] = strtoull(buf, NULL, 16);95}9697for (k = NN_MAX_WORD_LEN; k > wlen; k--) {98out_nn->val[k - 1] = 0;99}100101err:102return ret;103}104105#define DISPATCH_TABLE_MAGIC "FEEDBABE"106struct dispatch_table {107const char magic[sizeof(DISPATCH_TABLE_MAGIC)];108const char *op_string;109const char *op_string_helper;110int (*fun) (const char *op, void **, int);111};112113#define ADD_TO_DISPATCH_TABLE(fun, op_string, op_string_helper) \114static const struct dispatch_table entry_##fun \115ATTRIBUTE_SECTION("tests_dispatch_table_section") ATTRIBUTE_USED = \116{ DISPATCH_TABLE_MAGIC, op_string, op_string_helper, fun };117118#define FIND_IN_DISPATCH_TABLE(op, to_find, type) do {\119extern struct dispatch_table __start_tests_dispatch_table_section;\120extern struct dispatch_table __stop_tests_dispatch_table_section;\121struct dispatch_table *dt, *begin, *end;\122char *ptr;\123\124begin = &__start_tests_dispatch_table_section;\125end = &__stop_tests_dispatch_table_section;\126ptr = (char*)begin;\127\128to_find = NULL;\129\130while(ptr < (char*)end){\131dt = (struct dispatch_table*)ptr;\132/* Find the magic */\133while(memcmp(dt->magic, DISPATCH_TABLE_MAGIC, sizeof(DISPATCH_TABLE_MAGIC)) != 0){\134ptr++;\135dt = (struct dispatch_table*)ptr;\136}\137if(strcmp(dt->op_string, op) == 0){ \138to_find = dt->type;\139break;\140}\141ptr += sizeof(struct dispatch_table);\142}\143} while(0)144145#define FIND_FUN_IN_DISPATCH_TABLE(op, function) FIND_IN_DISPATCH_TABLE(op, function, fun)146147#define FIND_HELPER_IN_DISPATCH_TABLE(op, string_helper) FIND_IN_DISPATCH_TABLE(op, string_helper, op_string_helper)148149/*****************/150151#define GENERIC_TEST_FP_DECL_INIT0(name, ctx) \152fp_t name##_ptr[] = {NULL};153154#define GENERIC_TEST_FP_DECL_INIT1(name, ctx) \155fp name##0; \156fp_t name##_ptr[] = { &name##0 };\157ret |= fp_init(&name##0, ctx);\158159#define GENERIC_TEST_FP_DECL_INIT2(name, ctx) \160fp name##0, name##1;\161fp_t name##_ptr[] = { &name##0, &name##1 };\162ret |= fp_init(&name##0, ctx);\163ret |= fp_init(&name##1, ctx);\164165#define GENERIC_TEST_FP_DECL_INIT3(name, ctx) \166fp name##0, name##1, name##2;\167fp_t name##_ptr[] = { &name##0, &name##1, &name##2 };\168ret |= fp_init(&name##0, ctx);\169ret |= fp_init(&name##1, ctx);\170ret |= fp_init(&name##2, ctx);\171172#define GENERIC_TEST_FP_DECL_INIT4(name, ctx) \173fp name##0, name##1, name##2, name##3;\174fp_t name##_ptr[] = { &name##0, &name##1, &name##2, &name##3 };\175ret |= fp_init(&name##0, ctx);\176ret |= fp_init(&name##1, ctx);\177ret |= fp_init(&name##2, ctx);\178ret |= fp_init(&name##3, ctx);\179180#define GENERIC_TEST_FP_DECL_INIT5(name, ctx) \181fp name##0, name##1, name##2, name##3, name##4;\182fp_t name##_ptr[] = { &name##0, &name##1, &name##2, &name##3, &name##4 };\183ret |= fp_init(&name##0, ctx);\184ret |= fp_init(&name##1, ctx);\185ret |= fp_init(&name##2, ctx);\186ret |= fp_init(&name##3, ctx);\187ret |= fp_init(&name##4, ctx);\188189#define GENERIC_TEST_FP_DECL_INIT6(name, ctx) \190fp name##0, name##1, name##2, name##3, name##4, name##5;\191fp_t name##_ptr[] = { &name##0, &name##1, &name##2, &name##3, &name##4, &name##5 };\192ret |= fp_init(&name##0, ctx);\193ret |= fp_init(&name##1, ctx);\194ret |= fp_init(&name##2, ctx);\195ret |= fp_init(&name##3, ctx);\196ret |= fp_init(&name##4, ctx);\197ret |= fp_init(&name##5, ctx);\198199#define GENERIC_TEST_NN_DECL_INIT0(name, size) \200nn_t name##_ptr[] = {NULL};201202#define GENERIC_TEST_NN_DECL_INIT1(name, size) \203nn name##0; \204nn_t name##_ptr[] = { &name##0 }; \205ret |= nn_init(&name##0, size); \206207#define GENERIC_TEST_NN_DECL_INIT2(name, size) \208nn name##0, name##1; \209nn_t name##_ptr[] = { &name##0, &name##1 }; \210ret |= nn_init(&name##0, size); \211ret |= nn_init(&name##1, size); \212213#define GENERIC_TEST_NN_DECL_INIT3(name, size) \214nn name##0, name##1, name##2; \215nn_t name##_ptr[] = { &name##0, &name##1, &name##2 }; \216ret |= nn_init(&name##0, size); \217ret |= nn_init(&name##1, size); \218ret |= nn_init(&name##2, size); \219220#define GENERIC_TEST_NN_DECL_INIT4(name, size) \221nn name##0, name##1, name##2, name##3; \222nn_t name##_ptr[] = { &name##0, &name##1, &name##2, &name##3 }; \223ret |= nn_init(&name##0, size); \224ret |= nn_init(&name##1, size); \225ret |= nn_init(&name##2, size); \226ret |= nn_init(&name##3, size); \227228#define GENERIC_TEST_NN_DECL_INIT5(name, size) \229nn name##0, name##1, name##2, name##3, name##4; \230nn_t name##_ptr[] = { &name##0, &name##1, &name##2, &name##3, &name##4 };\231ret |= nn_init(&name##0, size); \232ret |= nn_init(&name##1, size); \233ret |= nn_init(&name##2, size); \234ret |= nn_init(&name##3, size); \235ret |= nn_init(&name##4, size); \236237#define GENERIC_TEST_NN_DECL_INIT6(name, size) \238nn name##0, name##1, name##2, name##3, name##4, name##5; \239nn_t name##_ptr[] = { &name##0, &name##1, &name##2, &name##3, &name##4, &name##5 };\240ret |= nn_init(&name##0, size); \241ret |= nn_init(&name##1, size); \242ret |= nn_init(&name##2, size); \243ret |= nn_init(&name##3, size); \244ret |= nn_init(&name##4, size); \245ret |= nn_init(&name##5, size); \246247#define GENERIC_TEST_FP_CLEAR0(name)248249#define GENERIC_TEST_FP_CLEAR1(name) \250fp_uninit(&name##0);\251252#define GENERIC_TEST_FP_CLEAR2(name) \253fp_uninit(&name##0);\254fp_uninit(&name##1);\255256#define GENERIC_TEST_FP_CLEAR3(name) \257fp_uninit(&name##0);\258fp_uninit(&name##1);\259fp_uninit(&name##2);\260261#define GENERIC_TEST_FP_CLEAR4(name) \262fp_uninit(&name##0);\263fp_uninit(&name##1);\264fp_uninit(&name##2);\265fp_uninit(&name##3);\266267#define GENERIC_TEST_FP_CLEAR5(name) \268fp_uninit(&name##0);\269fp_uninit(&name##1);\270fp_uninit(&name##2);\271fp_uninit(&name##3);\272fp_uninit(&name##4);\273274#define GENERIC_TEST_FP_CLEAR6(name) \275fp_uninit(&name##0);\276fp_uninit(&name##1);\277fp_uninit(&name##2);\278fp_uninit(&name##3);\279fp_uninit(&name##4);\280fp_uninit(&name##5);\281282#define GENERIC_TEST_nn_uninit0(name)283284#define GENERIC_TEST_nn_uninit1(name) \285nn_uninit(&name##0);\286287#define GENERIC_TEST_nn_uninit2(name) \288nn_uninit(&name##0);\289nn_uninit(&name##1);\290291#define GENERIC_TEST_nn_uninit3(name) \292nn_uninit(&name##0);\293nn_uninit(&name##1);\294nn_uninit(&name##2);\295296#define GENERIC_TEST_nn_uninit4(name) \297nn_uninit(&name##0);\298nn_uninit(&name##1);\299nn_uninit(&name##2);\300nn_uninit(&name##3);\301302#define GENERIC_TEST_nn_uninit5(name) \303nn_uninit(&name##0);\304nn_uninit(&name##1);\305nn_uninit(&name##2);\306nn_uninit(&name##3);\307nn_uninit(&name##4);\308309#define GENERIC_TEST_nn_uninit6(name) \310nn_uninit(&name##0);\311nn_uninit(&name##1);\312nn_uninit(&name##2);\313nn_uninit(&name##3);\314nn_uninit(&name##4);\315nn_uninit(&name##5);\316317#define FP_CTX_T_GENERIC_IN(num) ((fp_ctx_t)params[num])318#define FP_T_GENERIC_IN(num) ((fp_t)params[num])319#define NN_T_GENERIC_IN(num) ((nn_t)params[num])320#define UINT_GENERIC_IN(num) ((u64)*((u64*)params[num]))321#define WORD_T_GENERIC_IN(num) ((word_t)*((word_t*)params[num]))322#define INT_GENERIC_IN(num) ((int)*((int*)params[num]))323324#define FP_T_GENERIC_OUT(num) (&fp_out##num)325#define NN_T_GENERIC_OUT(num) (&nn_out##num)326#define WORD_T_GENERIC_OUT(num) (&(word_out[num]))327#define INT_GENERIC_OUT(num) (&(int_out[num]))328329#define CHECK_FUN_RET there_is_output = 1; fun_out_value = (int)330331#define CHECK_FUN_NO_RET there_is_output = 0; fun_out_value = (int)332333/* Number of pre-allocated */334#define NUM_PRE_ALLOCATED_NN 6335#define NUM_PRE_ALLOCATED_FP 6336#define MAX_PARAMS 6337338#define GENERIC_TEST_NN_DECL_INIT_MAX(name, n) GENERIC_TEST_NN_DECL_INIT6(name, n)339#define GENERIC_TEST_FP_DECL_INIT_MAX(name, ctx) GENERIC_TEST_FP_DECL_INIT6(name, ctx)340341/* Check that the string of parameters types only containes 'c', 'f', 'n' and 'u'342* Check that the string of parameters I/O only contains 'i', 'o' and 'O'343*344*/345#define PARAMETERS_SANITY_CHECK(test_num, param_types, param_io) do {\346unsigned int i, real_output = 0;\347assert(sizeof(param_types) == sizeof(param_io));\348for(i = 0; i < sizeof(param_types)-1; i++){\349if((param_types[i] != 'c') && (param_types[i] != 'f') && (param_types[i] != 'n') && (param_types[i] != 'u') && (param_types[i] != 's')){ \350printf("Error: types parameters of test %d mismatch!\n", test_num);\351return 0;\352}\353if((param_io[i] != 'i') && (param_io[i] != 'o') && (param_io[i] != 'O')){\354printf("Error: I/O parameters of test %d mismatch!\n", test_num);\355return 0;\356}\357if((param_io[i] == 'O') && (param_types[i] != 'u') && (param_types[i] != 's')){\358printf("Error: types and I/O parameters of test %d mismatch!\n", test_num);\359return 0;\360}\361if(param_io[i] == 'O'){\362real_output++;\363}\364}\365/* Check that we only have one function output */\366if(real_output > 1){\367printf("Error: multiple function output defined in I/O parameters of test %d!\n", test_num);\368return 0;\369}\370} while(0);371372#define SET_PARAMETER_PRETTY_NAME1(a) a373#define SET_PARAMETER_PRETTY_NAME2(a, b) SET_PARAMETER_PRETTY_NAME1(a) "\0" b374#define SET_PARAMETER_PRETTY_NAME3(a, b, c) SET_PARAMETER_PRETTY_NAME2(a, b) "\0" c375#define SET_PARAMETER_PRETTY_NAME4(a, b, c, d) SET_PARAMETER_PRETTY_NAME3(a, b, c) "\0" d376#define SET_PARAMETER_PRETTY_NAME5(a, b, c, d, e) SET_PARAMETER_PRETTY_NAME4(a, b, c, d) "\0" e377#define SET_PARAMETER_PRETTY_NAME6(a, b, c, d, e, f) SET_PARAMETER_PRETTY_NAME5(a, b, c, d, e) "\0" f378379#define SET_PARAMETER_PRETTY_NAME(num, ...) SET_PARAMETER_PRETTY_NAME##num(__VA_ARGS__)380381/* Parse the helper string to get the pretty print names */382#define GET_PARAMETER_PRETTY_NAME(parameters_string_names_, parameters_string_names, num, out) do {\383unsigned int cnt = 0;\384out = 0;\385\386/* Find the proper position */\387while(out < sizeof(parameters_string_names_)-1){\388if(cnt == num){\389break;\390}\391if(parameters_string_names[out] == '\0'){\392cnt++;\393}\394out++;\395}\396} while(0);397398/* Print for a given test all the inputs, outpus and expected outputs */399#define PRINT_ALL(parameters_types, parameters_io, params, nn_out_ptr, fp_out_ptr, fun_output, there_is_output, parameters_string_names_, bad_num) do { \400unsigned int j;\401unsigned int nn_out_local_cnt = 0, fp_out_local_cnt = 0;\402unsigned int str_pos;\403const char parameters_string_names[] = parameters_string_names_;\404const char real[] = "Real ";\405const char expected[] = "Expected ";\406char expected_modified_string_names[sizeof(expected)+sizeof(parameters_string_names_)];\407char real_modified_string_names[sizeof(real)+sizeof(parameters_string_names_)];\408/* First print the inputs */\409for(j=0; j<sizeof(parameters_types)-1; j++){\410GET_PARAMETER_PRETTY_NAME(parameters_string_names_, parameters_string_names, j, str_pos);\411if(parameters_io[j] == 'i'){\412/* This is an input */\413if(parameters_types[j] == 'c'){\414nn_print(&(parameters_string_names[str_pos]), &(FP_CTX_T_GENERIC_IN(j)->p)); \415}\416if(parameters_types[j] == 'f'){\417nn_print(&(parameters_string_names[str_pos]), &(FP_T_GENERIC_IN(j)->fp_val)); \418}\419if(parameters_types[j] == 'n'){\420nn_print(&(parameters_string_names[str_pos]), NN_T_GENERIC_IN(j));\421}\422if(parameters_types[j] == 'u'){\423printf("%16s: 0x", &(parameters_string_names[str_pos])); \424printf(PRINTF_WORD_HEX_FMT, WORD_T_GENERIC_IN(j)); \425printf("\n"); \426}\427if(parameters_types[j] == 's'){\428printf("%16s:", &(parameters_string_names[str_pos])); \429printf("%d", INT_GENERIC_IN(j)); \430printf("\n"); \431}\432}\433}\434/* Then print the outputs */\435for(j=0; j<sizeof(parameters_types)-1; j++){\436GET_PARAMETER_PRETTY_NAME(parameters_string_names_, parameters_string_names, j, str_pos);\437memset(expected_modified_string_names, 0, sizeof(expected_modified_string_names));\438strcat(expected_modified_string_names, expected);\439strcat(expected_modified_string_names, &(parameters_string_names[str_pos]));\440memset(real_modified_string_names, 0, sizeof(real_modified_string_names));\441strcat(real_modified_string_names, real);\442strcat(real_modified_string_names, &(parameters_string_names[str_pos]));\443if(parameters_io[j] == 'o'){\444/* This is an input that is an output */\445if(parameters_types[j] == 'f'){\446nn_print(real_modified_string_names, &(fp_out_ptr[j]->fp_val)); \447nn_print(expected_modified_string_names, &(FP_T_GENERIC_IN(j)->fp_val)); \448fp_out_local_cnt++;\449}\450if(parameters_types[j] == 'n'){\451nn_print(real_modified_string_names, nn_out_ptr[j]);\452nn_print(expected_modified_string_names, NN_T_GENERIC_IN(j));\453nn_out_local_cnt++;\454}\455if(parameters_types[j] == 'u'){\456printf("%16s: 0x", real_modified_string_names); \457printf(PRINTF_WORD_HEX_FMT, *(WORD_T_GENERIC_OUT(j))); \458printf("\n"); \459printf("%16s: 0x", expected_modified_string_names); \460printf(PRINTF_WORD_HEX_FMT, WORD_T_GENERIC_IN(j)); \461printf("\n"); \462}\463if(parameters_types[j] == 's'){\464printf("%16s: ", real_modified_string_names); \465printf("%d", *(INT_GENERIC_OUT(j))); \466printf("\n"); \467printf("%16s: ", expected_modified_string_names); \468printf("%d", INT_GENERIC_IN(j)); \469printf("\n"); \470}\471}\472if((parameters_io[j] == 'O') && (there_is_output == 1)){\473/* This is a real function output */\474if(parameters_types[j] == 'u'){\475printf("%16s: 0x", real_modified_string_names); \476printf(PRINTF_WORD_HEX_FMT, (word_t)fun_output); \477printf("\n"); \478printf("%16s: 0x", expected_modified_string_names); \479printf(PRINTF_WORD_HEX_FMT, WORD_T_GENERIC_IN(j)); \480printf("\n"); \481}\482if(parameters_types[j] == 's'){\483printf("%16s: ", real_modified_string_names); \484printf("%d", (int)fun_output); \485printf("\n"); \486printf("%16s: ", expected_modified_string_names); \487printf("%d", INT_GENERIC_IN(j)); \488printf("\n"); \489}\490}\491}\492} while(0)493494/* Generic testing framework. Seems ugly but does the job! */495#define GENERIC_TEST(test_name, operation_, given_string_helper, fun_name, parameters_types_, parameters_io_, parameters_string_names, fun_output, nn_out_num, fp_out_num, ...) \496int test_##test_name(const char ATTRIBUTE_UNUSED *op, void **params, int test_num);\497int test_##test_name(const char ATTRIBUTE_UNUSED *op, void **params, int test_num){\498unsigned int i;\499int ret = 0, cmp, mismatch = 0; \500const char *op_string = NULL;\501unsigned int n_len ATTRIBUTE_UNUSED = 0;\502int fun_out_value = 0;\503u8 there_is_output = 0;\504unsigned int nn_out_local_cnt = 0, fp_out_local_cnt = 0;\505fp_ctx_t fp_ctx_param ATTRIBUTE_UNUSED = NULL;\506int fp_ctx_initialized ATTRIBUTE_UNUSED = 0;\507\508const char parameters_types[] = parameters_types_;\509const char parameters_io[] = parameters_io_;\510\511const char operation[] = #operation_;\512\513/* Our words used as output of functions */\514word_t word_out[MAX_PARAMS] ATTRIBUTE_UNUSED = { 0 };\515int int_out[MAX_PARAMS] ATTRIBUTE_UNUSED = { 0 };\516\517assert(memcmp(operation, op, sizeof(operation)) == 0);\518\519/* Sanity check: check that the parameters passed from the file are the same as the ones declared in the test */\520if(memcmp(global_parameters, parameters_types, LOCAL_MIN(MAX_PARAMS, strlen(parameters_types))) != 0){\521printf("Error: parameters %s given in the test file differ from the test expected parameters (%s)\n", parameters_types, global_parameters);\522return -1;\523}\524\525PARAMETERS_SANITY_CHECK(test_num, parameters_types, parameters_io);\526\527/* If we find an fp or nn, assume its length is the common length. */\528for(i=0; i<sizeof(parameters_io)-1; i++){\529if((parameters_io[i] == 'o') && (parameters_types[i] == 'f')){\530n_len = (FP_T_GENERIC_IN(i))->fp_val.wlen;\531break;\532}\533if((parameters_io[i] == 'o') && (parameters_types[i] == 'n')){\534n_len = (NN_T_GENERIC_IN(i))->wlen;\535break;\536}\537}\538for(i=0; i<sizeof(parameters_io)-1; i++){\539if(parameters_types[i] == 'c'){\540fp_ctx_param = (FP_CTX_T_GENERIC_IN(i));\541fp_ctx_initialized = 1;\542break;\543}\544}\545GENERIC_TEST_NN_DECL_INIT##nn_out_num(nn_out, n_len * WORD_BYTES);\546assert(fp_out_num == 0 || fp_ctx_initialized != 0);\547GENERIC_TEST_FP_DECL_INIT##fp_out_num(fp_out, fp_ctx_param);\548if(ret){\549goto err;\550}\551\552CHECK_FUN_##fun_output fun_name(__VA_ARGS__);\553/* Check generic value return is 0 */\554if(there_is_output == 0){\555assert(fun_out_value == 0);\556}\557\558/* Check result is what we expect */\559FIND_HELPER_IN_DISPATCH_TABLE(operation, op_string);\560assert(op_string != NULL);\561\562for(i=0; i<sizeof(parameters_io)-1; i++){\563if(parameters_io[i] == 'o'){\564/* We have an input that is an output, check it */\565if (parameters_types[i] == 'f') {\566ret = fp_cmp(fp_out_ptr[i], FP_T_GENERIC_IN(i), &cmp); \567if(ret || cmp){\568printf("[-] Test %d (%s): result mismatch\n", test_num, op_string);\569/* Print the expected outputs */\570PRINT_ALL(parameters_types, parameters_io, params, nn_out_ptr, fp_out_ptr, fun_out_value, there_is_output, parameters_string_names, i);\571mismatch = 1;\572break;\573}\574fp_out_local_cnt++;\575}\576if (parameters_types[i] == 'n') {\577ret = nn_cmp(nn_out_ptr[i], NN_T_GENERIC_IN(i), &cmp); \578if(ret || cmp){\579printf("[-] Test %d (%s): result mismatch\n", test_num, op_string);\580/* Print the expected outputs */\581PRINT_ALL(parameters_types, parameters_io, params, nn_out_ptr, fp_out_ptr, fun_out_value, there_is_output, parameters_string_names, i);\582mismatch = 1;\583break;\584}\585nn_out_local_cnt++;\586}\587if (parameters_types[i] == 'u') {\588if((*(WORD_T_GENERIC_OUT(i))) != WORD_T_GENERIC_IN(i)){\589printf("[-] Test %d (%s): result mismatch\n", test_num, op_string);\590/* Print the expected outputs */\591PRINT_ALL(parameters_types, parameters_io, params, nn_out_ptr, fp_out_ptr, fun_out_value, there_is_output, parameters_string_names, i);\592mismatch = 1;\593break;\594}\595}\596if (parameters_types[i] == 's') {\597if((*(INT_GENERIC_OUT(i))) != INT_GENERIC_IN(i)){\598printf("[-] Test %d (%s): result mismatch\n", test_num, op_string);\599/* Print the expected outputs */\600PRINT_ALL(parameters_types, parameters_io, params, nn_out_ptr, fp_out_ptr, fun_out_value, there_is_output, parameters_string_names, i);\601mismatch = 1;\602break;\603}\604}\605}\606if(parameters_io[i] == 'O'){\607/* We have a function output, check it */\608if(fun_out_value != INT_GENERIC_IN(i)){\609printf("[-] Test %d (%s): result mismatch\n", test_num, op_string);\610/* Print the expected outputs */\611PRINT_ALL(parameters_types, parameters_io, params, nn_out_ptr, fp_out_ptr, fun_out_value, there_is_output, parameters_string_names, i);\612mismatch = 1;\613break;\614}\615}\616}\617\618GENERIC_TEST_nn_uninit##nn_out_num(nn_out);\619GENERIC_TEST_FP_CLEAR##fp_out_num(fp_out);\620\621return !mismatch;\622err:\623printf("[-] Error: general error when initializing variables ...\n");\624exit(-1);\625}\626ADD_TO_DISPATCH_TABLE(test_##test_name, #operation_, given_string_helper)627628#define GENERIC_TEST_NN(test_name, operation_, given_string_helper, fun_name, parameters_types_, parameters_io_, parameters_string_names, fun_output, nn_out_num, ...) \629GENERIC_TEST(test_name, operation_, given_string_helper, fun_name, parameters_types_, parameters_io_, parameters_string_names, fun_output, nn_out_num, 0, __VA_ARGS__)630631#define GENERIC_TEST_FP(test_name, operation_, given_string_helper, fun_name, parameters_types_, parameters_io_, parameters_string_names, fun_output, nn_out_num, ...) \632GENERIC_TEST(test_name, operation_, given_string_helper, fun_name, parameters_types_, parameters_io_, parameters_string_names, fun_output, nn_out_num, __VA_ARGS__)633634635/* Global variable to keep track of parameters */636static char global_parameters[MAX_PARAMS];637638/*********** NN layer tests ************************************************/639/* Testing shifts and rotates */640GENERIC_TEST_NN(nn_lshift_fixedlen, NN_SHIFT_LEFT_FIXEDLEN, "(fixed)<<", nn_lshift_fixedlen, "nnu", "oii",641SET_PARAMETER_PRETTY_NAME(3, "output", "input", "fixed lshift"), NO_RET, 1,642NN_T_GENERIC_OUT(0), NN_T_GENERIC_IN(1), (bitcnt_t)UINT_GENERIC_IN(2))643GENERIC_TEST_NN(nn_rshift_fixedlen, NN_SHIFT_RIGHT_FIXEDLEN, "(fixed)>>", nn_rshift_fixedlen, "nnu", "oii",644SET_PARAMETER_PRETTY_NAME(3, "output", "input", "fixed rshift"), NO_RET, 1,645NN_T_GENERIC_OUT(0), NN_T_GENERIC_IN(1), (bitcnt_t)UINT_GENERIC_IN(2))646GENERIC_TEST_NN(nn_lshift, NN_SHIFT_LEFT, "<<", nn_lshift, "nnu", "oii",647SET_PARAMETER_PRETTY_NAME(3, "output", "input", "lshift"), NO_RET, 1,648NN_T_GENERIC_OUT(0), NN_T_GENERIC_IN(1), (bitcnt_t)UINT_GENERIC_IN(2))649GENERIC_TEST_NN(nn_rshift, NN_SHIFT_RIGHT, ">>", nn_rshift, "nnu", "oii",650SET_PARAMETER_PRETTY_NAME(3, "output", "input", "rshift"), NO_RET, 1,651NN_T_GENERIC_OUT(0), NN_T_GENERIC_IN(1), (bitcnt_t)UINT_GENERIC_IN(2))652GENERIC_TEST_NN(nn_lrot, NN_ROTATE_LEFT, "lrot", nn_lrot, "nnuu", "oiii",653SET_PARAMETER_PRETTY_NAME(4, "output", "input", "lrot", "bitlen_base"), NO_RET, 1,654NN_T_GENERIC_OUT(0), NN_T_GENERIC_IN(1), (bitcnt_t)UINT_GENERIC_IN(2), (bitcnt_t)UINT_GENERIC_IN(3))655GENERIC_TEST_NN(nn_rrot, NN_ROTATE_RIGHT, "rrot", nn_rrot, "nnuu", "oiii",656SET_PARAMETER_PRETTY_NAME(4, "output", "input", "rrot", "bitlen_base"), NO_RET, 1,657NN_T_GENERIC_OUT(0), NN_T_GENERIC_IN(1), (bitcnt_t)UINT_GENERIC_IN(2), (bitcnt_t)UINT_GENERIC_IN(3))658659660/* Testing xor, or, and, not */661GENERIC_TEST_NN(nn_xor, NN_XOR, "^", nn_xor, "nnn", "iio",662SET_PARAMETER_PRETTY_NAME(3, "input1", "input2", "output"), NO_RET, 3,663NN_T_GENERIC_OUT(2), NN_T_GENERIC_IN(0), NN_T_GENERIC_IN(1))664GENERIC_TEST_NN(nn_or, NN_OR, "|", nn_or, "nnn", "iio",665SET_PARAMETER_PRETTY_NAME(3, "input1", "input2", "output"), NO_RET, 3,666NN_T_GENERIC_OUT(2), NN_T_GENERIC_IN(0), NN_T_GENERIC_IN(1))667GENERIC_TEST_NN(nn_and, NN_AND, "&", nn_and, "nnn", "iio",668SET_PARAMETER_PRETTY_NAME(3, "input1", "input2", "output"), NO_RET, 3,669NN_T_GENERIC_OUT(2), NN_T_GENERIC_IN(0), NN_T_GENERIC_IN(1))670GENERIC_TEST_NN(nn_not, NN_NOT, "~", nn_not, "nn", "io",671SET_PARAMETER_PRETTY_NAME(2, "input", "output"), NO_RET, 2,672NN_T_GENERIC_OUT(1), NN_T_GENERIC_IN(0))673674/* Testing add and sub */675GENERIC_TEST_NN(nn_add, NN_ADD, "+", nn_add, "nnn", "iio",676SET_PARAMETER_PRETTY_NAME(3, "input1", "input2", "output"),677NO_RET, 3, NN_T_GENERIC_OUT(2), NN_T_GENERIC_IN(0),678NN_T_GENERIC_IN(1))679GENERIC_TEST_NN(nn_sub, NN_SUB, "-", nn_sub, "nnn", "iio",680SET_PARAMETER_PRETTY_NAME(3, "input1", "input2", "output"),681NO_RET, 3, NN_T_GENERIC_OUT(2), NN_T_GENERIC_IN(0),682NN_T_GENERIC_IN(1))683684/* Testing inc and dec */685GENERIC_TEST_NN(nn_inc, NN_INC, "++", nn_inc, "nn", "io",686SET_PARAMETER_PRETTY_NAME(2, "input", "output"), NO_RET, 2,687NN_T_GENERIC_OUT(1), NN_T_GENERIC_IN(0))688GENERIC_TEST_NN(nn_dec, NN_DEC, "--", nn_dec, "nn", "io",689SET_PARAMETER_PRETTY_NAME(2, "input", "output"), NO_RET, 2,690NN_T_GENERIC_OUT(1), NN_T_GENERIC_IN(0))691692/* Testing modular add, sub, inc, dec, mul, exp (inputs are supposed < p except for exp) */693GENERIC_TEST_NN(nn_mod_add, NN_MOD_ADD, "+%", nn_mod_add, "nnnn", "iiio",694SET_PARAMETER_PRETTY_NAME(4, "input1", "input2", "modulo", "output"),695NO_RET, 4, NN_T_GENERIC_OUT(3), NN_T_GENERIC_IN(0),696NN_T_GENERIC_IN(1), NN_T_GENERIC_IN(2))697GENERIC_TEST_NN(nn_mod_sub, NN_MOD_SUB, "-%", nn_mod_sub, "nnnn", "iiio",698SET_PARAMETER_PRETTY_NAME(4, "input1", "input2", "modulo", "output"),699NO_RET, 4, NN_T_GENERIC_OUT(3), NN_T_GENERIC_IN(0),700NN_T_GENERIC_IN(1), NN_T_GENERIC_IN(2))701GENERIC_TEST_NN(nn_mod_inc, NN_MOD_INC, "++%", nn_mod_inc, "nnn", "iio",702SET_PARAMETER_PRETTY_NAME(3, "input1", "modulo", "output"),703NO_RET, 3, NN_T_GENERIC_OUT(2), NN_T_GENERIC_IN(0),704NN_T_GENERIC_IN(1))705GENERIC_TEST_NN(nn_mod_dec, NN_MOD_DEC, "--%", nn_mod_dec, "nnn", "iio",706SET_PARAMETER_PRETTY_NAME(3, "input1", "modulo", "output"),707NO_RET, 3, NN_T_GENERIC_OUT(2), NN_T_GENERIC_IN(0),708NN_T_GENERIC_IN(1))709GENERIC_TEST_NN(nn_mod_mul, NN_MOD_MUL, "*%", nn_mod_mul, "nnnn", "iiio",710SET_PARAMETER_PRETTY_NAME(4, "input1", "input2", "modulo", "output"),711NO_RET, 4, NN_T_GENERIC_OUT(3), NN_T_GENERIC_IN(0),712NN_T_GENERIC_IN(1), NN_T_GENERIC_IN(2))713GENERIC_TEST_NN(nn_mod_pow, NN_MOD_POW, "exp%", nn_mod_pow, "nnnn", "iiio",714SET_PARAMETER_PRETTY_NAME(4, "base", "exp", "modulo", "output"),715NO_RET, 4, NN_T_GENERIC_OUT(3), NN_T_GENERIC_IN(0),716NN_T_GENERIC_IN(1), NN_T_GENERIC_IN(2))717718719/* Testing mul */720GENERIC_TEST_NN(nn_mul, NN_MUL, "*", nn_mul, "nnn", "oii",721SET_PARAMETER_PRETTY_NAME(3, "output1", "input1", "input2"),722NO_RET, 1, NN_T_GENERIC_OUT(0), NN_T_GENERIC_IN(1),723NN_T_GENERIC_IN(2))724GENERIC_TEST_NN(nn_sqr, NN_SQR, "(^2)", nn_sqr, "nn", "oi",725SET_PARAMETER_PRETTY_NAME(2, "output1", "input1"),726NO_RET, 1, NN_T_GENERIC_OUT(0), NN_T_GENERIC_IN(1))727728/* Testing division */729GENERIC_TEST_NN(nn_divrem, NN_DIVREM, "/", nn_divrem, "nnnn", "ooii",730SET_PARAMETER_PRETTY_NAME(4, "quotient", "remainder", "input1", "input2"),731NO_RET, 2, NN_T_GENERIC_OUT(0), NN_T_GENERIC_OUT(1),732NN_T_GENERIC_IN(2), NN_T_GENERIC_IN(3))733GENERIC_TEST_NN(nn_xgcd, NN_XGCD, "xgcd", nn_xgcd, "nnnnns", "oooiio",734SET_PARAMETER_PRETTY_NAME(6, "xgcd", "u", "v", "input1", "input2", "sign"),735NO_RET, 3, NN_T_GENERIC_OUT(0), NN_T_GENERIC_OUT(1), NN_T_GENERIC_OUT(2),736NN_T_GENERIC_IN(3), NN_T_GENERIC_IN(4), INT_GENERIC_OUT(5))737GENERIC_TEST_NN(nn_gcd, NN_GCD, "gcd", nn_gcd, "nnns", "oiio",738SET_PARAMETER_PRETTY_NAME(4, "gcd", "input1", "input2", "sign"),739NO_RET, 1, NN_T_GENERIC_OUT(0),740NN_T_GENERIC_IN(1), NN_T_GENERIC_IN(2), INT_GENERIC_OUT(3))741GENERIC_TEST_NN(nn_mod, NN_MOD, "%", nn_mod, "nnn", "oii",742SET_PARAMETER_PRETTY_NAME(3, "output", "input1", "input2"),743NO_RET, 1, NN_T_GENERIC_OUT(0),744NN_T_GENERIC_IN(1), NN_T_GENERIC_IN(2))745746/* Testing modular inversion */747GENERIC_TEST_NN(nn_modinv, NN_MODINV, "(^-1%)", nn_modinv, "nnns", "oiiO",748SET_PARAMETER_PRETTY_NAME(4, "output", "input1", "input2", "ret"),749RET, 1, NN_T_GENERIC_OUT(0),750NN_T_GENERIC_IN(1), NN_T_GENERIC_IN(2))751752/* Testing modular inversion modulo a 2**n */753GENERIC_TEST_NN(nn_modinv_2exp, NN_MODINV_2EXP, "(^-1%)(2exp)", nn_modinv_2exp, "nnus", "oiio",754SET_PARAMETER_PRETTY_NAME(4, "output", "input1", "input2", "isodd"),755NO_RET, 1, NN_T_GENERIC_OUT(0), NN_T_GENERIC_IN(1),756UINT_GENERIC_IN(2), INT_GENERIC_OUT(3))757758/* Check Montgomery multiplication redcify primitives */759GENERIC_TEST_NN(nn_compute_redc1_coefs, NN_COEF_REDC1, "coef_redc1", nn_compute_redc1_coefs, "nnnu", "ooio",760SET_PARAMETER_PRETTY_NAME(4, "r", "r_square", "p", "mpinv"),761NO_RET, 3, NN_T_GENERIC_OUT(0), NN_T_GENERIC_OUT(1), NN_T_GENERIC_IN(2), WORD_T_GENERIC_OUT(3))762GENERIC_TEST_NN(nn_compute_div_coefs, NN_COEF_DIV, "coef_div", nn_compute_div_coefs, "nuun", "oooi",763SET_PARAMETER_PRETTY_NAME(4, "p_normalized", "p_shift", "p_reciprocal", "p"),764NO_RET, 3, NN_T_GENERIC_OUT(0), WORD_T_GENERIC_OUT(1), WORD_T_GENERIC_OUT(2), NN_T_GENERIC_IN(3))765GENERIC_TEST_NN(nn_mul_redc1, NN_MUL_REDC1, "*_redc1", nn_mul_redc1, "nnnnu", "oiiii",766SET_PARAMETER_PRETTY_NAME(5, "output", "input1", "input2", "p", "mpinv"),767NO_RET, 1, NN_T_GENERIC_OUT(0), NN_T_GENERIC_IN(1), NN_T_GENERIC_IN(2),768NN_T_GENERIC_IN(3), WORD_T_GENERIC_IN(4))769770771772/*********** Fp layer tests ************************************************/773/* Testing addition in F_p */774GENERIC_TEST_FP(fp_add, FP_ADD, "+", fp_add, "cfff", "ioii",775SET_PARAMETER_PRETTY_NAME(4, "p", "sum", "input1", "input2"),776NO_RET, 0, 2,777FP_T_GENERIC_OUT(1), FP_T_GENERIC_IN(2), FP_T_GENERIC_IN(3))778779/* Testing subtraction in F_p */780GENERIC_TEST_FP(fp_sub, FP_SUB, "-", fp_sub, "cfff", "ioii",781SET_PARAMETER_PRETTY_NAME(4, "p", "diff", "input1", "input2"),782NO_RET, 0, 2,783FP_T_GENERIC_OUT(1), FP_T_GENERIC_IN(2), FP_T_GENERIC_IN(3))784785/* Testing multiplication in F_p */786GENERIC_TEST_FP(fp_mul, FP_MUL, "*", fp_mul, "cfff", "ioii",787SET_PARAMETER_PRETTY_NAME(4, "p", "prod", "input1", "input2"),788NO_RET, 0, 2,789FP_T_GENERIC_OUT(1), FP_T_GENERIC_IN(2), FP_T_GENERIC_IN(3))790GENERIC_TEST_FP(fp_sqr, FP_SQR, "(^2)", fp_sqr, "cff", "ioi",791SET_PARAMETER_PRETTY_NAME(3, "p", "prod", "input1"),792NO_RET, 0, 2,793FP_T_GENERIC_OUT(1), FP_T_GENERIC_IN(2))794795/* Testing division in F_p */796GENERIC_TEST_FP(fp_div, FP_DIV, "/", fp_div, "cfff", "ioii",797SET_PARAMETER_PRETTY_NAME(4, "p", "quo", "input1", "input2"),798NO_RET, 0, 2,799FP_T_GENERIC_OUT(1), FP_T_GENERIC_IN(2), FP_T_GENERIC_IN(3))800801/* Testing Montgomery multiplication in F_p */802GENERIC_TEST_FP(fp_mul_monty, FP_MUL_MONTY, "*_monty", fp_mul_monty, "cfff", "ioii",803SET_PARAMETER_PRETTY_NAME(4, "p", "prod", "input1", "input2"),804NO_RET, 0, 2,805FP_T_GENERIC_OUT(1), FP_T_GENERIC_IN(2), FP_T_GENERIC_IN(3))806GENERIC_TEST_FP(fp_sqr_monty, FP_SQR_MONTY, "(^2)_monty", fp_sqr_monty, "cff", "ioi",807SET_PARAMETER_PRETTY_NAME(3, "p", "prod", "input1"),808NO_RET, 0, 2,809FP_T_GENERIC_OUT(1), FP_T_GENERIC_IN(2))810811/* Testing exponentiation in F_p */812GENERIC_TEST_FP(fp_pow, FP_POW, "exp", fp_pow, "cffn", "ioii",813SET_PARAMETER_PRETTY_NAME(4, "p", "pow", "input", "exp"),814NO_RET, 0, 2,815FP_T_GENERIC_OUT(1), FP_T_GENERIC_IN(2), NN_T_GENERIC_IN(3))816817/* Testing square residue in F_p */818GENERIC_TEST_FP(fp_sqrt, FP_SQRT, "sqrt", fp_sqrt, "cfffs", "iooiO",819SET_PARAMETER_PRETTY_NAME(4, "sqrt1", "sqrt2", "p", "ret"),820RET, 0, 3,821FP_T_GENERIC_OUT(1), FP_T_GENERIC_OUT(2), FP_T_GENERIC_IN(3))822823/*****************************************************************/824825/*826* Read data on given fd until first newline character and put it in buf827* followed by a null character. buffer size is passed via buflen. The828* length of read line is returned to the caller in buflen on success829* (not including null character terminating read string).830*831* 0 is returned on success.832* -1 is returned on end of file.833* -2 is returned on error (buffer not sufficient, etc)834*/835int read_string(int fd, char *buf, unsigned int *buflen);836int read_string(int fd, char *buf, unsigned int *buflen)837{838unsigned int pos = 0, len;839int ret = -1;840char c;841842MUST_HAVE((buf != NULL) && (buflen != NULL), ret, err);843844len = *buflen;845846if (len < 2) {847ret = -2;848goto err;849}850851len -= 1; /* keep some space to terminate the string */852853while ((len > 0) && ((ret = read(fd, &c, 1)) != 0) && (c != '\n')) {854buf[pos++] = c;855len -= 1;856}857858if (len == 0) {859ret = -2;860goto err;861}862863if (!ret) {864ret = -1;865goto err;866}867868/* Terminate the string */869buf[pos] = 0;870*buflen = pos;871ret = 0;872873err:874return ret;875}876877878/*879* Parse a test file and perform the tests it provides, one880* by one, in order.881*/882int main(int argc, char *argv[])883{884nn fp_ctx_modulus, fp_ctx_r, fp_ctx_r_square, fp_ctx_mpinv;885nn fp_ctx_pshift, fp_ctx_pnorm, fp_ctx_prec;886fp_ctx fp_ctx_param;887int ret, cmp;888u64 u_params[MAX_PARAMS];889void *params[MAX_PARAMS];890unsigned int ibuflen = BIT_LEN_WORDS(NN_MAX_BIT_LEN) * WORD_BYTES * 10;891unsigned long int test_num, line = 0, oktests = 0;892int test_ret;893unsigned int len = ibuflen;894int nrecs;895int fd = 0, nn_local_cnt = 0, fp_local_cnt = 0, fp_ctx_local_cnt = 0;896unsigned int nn_len;897char op[1024];898char *ibuf = NULL, *rec = NULL;899nn *tmp;900fp *fp_tmp;901int (*curr_test_fun) (const char *, void **, int);902unsigned long p_tmp;903904ret = nn_init(&fp_ctx_modulus, 0);905ret |= nn_init(&fp_ctx_r, 0);906ret |= nn_init(&fp_ctx_r_square, 0);907ret |= nn_init(&fp_ctx_mpinv, 0);908ret |= nn_init(&fp_ctx_pshift, 0);909ret |= nn_init(&fp_ctx_pnorm, 0);910ret |= nn_init(&fp_ctx_prec, 0);911912/* First "fake" context initialization with junk value913* one as prime number914*/915ret |= nn_one(&fp_ctx_modulus);916ret |= fp_ctx_init_from_p(&fp_ctx_param, &fp_ctx_modulus);917GENERIC_TEST_FP_DECL_INIT_MAX(fp_params, &fp_ctx_param)918GENERIC_TEST_NN_DECL_INIT_MAX(nn_params, 0)919920if(ret){921goto err;922}923924#ifdef WITH_ASSERT_BACKTRACE925memset(backtrace_buffer, 0, sizeof(backtrace_buffer) - 1);926if (signal(SIGINT, assert_signal_handler) == SIG_ERR) {927printf("Error: can't catch SIGINT signal ...\n");928return -1;929}930#endif931932if (argc > 2) {933printf("Usage: %s [test_file]\n", argv[0]);934printf(" If no test_file provided, stdin is taken\n");935return -1;936}937938/* Special case where we want to dump information */939if (argc == 2) {940if (memcmp(argv[1], "-info", sizeof("-info")) == 0){941printf("%d %d\n", WORDSIZE, NN_MAX_BASE);942return 0;943}944}945946ibuf = (char*)malloc(ibuflen);947if (!ibuf) {948return -1;949}950memset(ibuf, 0, ibuflen);951952if(argc == 2){953fd = open(argv[1], O_RDONLY);954}955else{956fd = STDIN_FILENO;957}958while (read_string(fd, ibuf, &len) == 0) {959char *t, *s = ibuf;960int i;961962/* Find end of first record (the test number) */963t = strchr(s, ' ');964if (t == NULL) {965printf("\nLine %lu: unable to find record #1\n", line);966return -1;967}968*t = 0; /* mark end of record */969test_num = strtoul(s, NULL, 10);970assert(line == test_num);971s = t + 1; /* jump to beginning of next record */972973/* Find end of second record (operation type) */974t = strchr(s, ' ');975if (t == NULL) {976printf("\nLine %lu: unable to find record #2\n", line);977return -1;978}979*t = 0; /* mark end of record */980strncpy(op, s, sizeof(op) - 1); /* Copy opcode */981s = t + 1; /* jump to beginning of next record */982983/* Pretty print the evolution of our tests */984if((line % 1000 == 0) && (line != 0)){985printf("\r%*s", 40, "");986printf("\rTest %lu on the go [%s]", line, op);987fflush(stdout);988}989990/* Find end of third record (str of types for next records) */991t = strchr(s, ' ');992if (t == NULL) {993printf("\nLine %lu: unable to find record #3\n", line);994return -1;995}996*t = 0; /* mark end of record */997nrecs = (int)(t - s);998999rec = t + 1;1000ADD_TO_BACKTRACE("--------------\n");1001for (i = 0; i < nrecs; i++) {1002/* Find end of record */1003t = strchr(rec, ' ');1004if (t == NULL) {1005t = ibuf + len;1006}1007*t = 0;1008switch (s[i]) {1009case 'c': /* fp_ctx */1010if (fp_ctx_local_cnt > 0) {1011printf("\nLine %lu: Only one fp_ctx allowed\n", line);1012ret = -1;1013goto err;1014}1015/*1016* We expect a 3 nn of the same size (p, r, r^2)1017* followed by a single word providing mpinv1018* and an additional nn and two words.1019*/1020assert(((t - rec) % 2) == 0);1021nn_len = (unsigned int)(t - rec -10223 * (WORD_BYTES * 2)) /1023(2 * 4);1024assert((nn_len % WORD_BYTES) == 0);1025fp_ctx_local_cnt++;1026tmp = &fp_ctx_modulus;1027ret = nn_set_wlen(tmp, (u8)(nn_len / WORD_BYTES)); EG(ret, err);1028ret = nn_import_from_hexbuf(tmp, rec, 2 * nn_len); EG(ret, err);10291030/* Initialize fp context from the prime modulus */1031ret = fp_ctx_init_from_p(&fp_ctx_param, &fp_ctx_modulus); EG(ret, err);1032/* Now get the other Fp context values and check that1033* everything is OK1034*/1035tmp = &fp_ctx_r;1036ret = nn_set_wlen(tmp, (u8)(nn_len / WORD_BYTES)); EG(ret, err);1037ret = nn_import_from_hexbuf(tmp, rec + (2 * nn_len),10382 * nn_len); EG(ret, err);10391040/* Compare r */1041ret = nn_cmp(&fp_ctx_r, &(fp_ctx_param.r), &cmp);1042if(ret || cmp){1043printf("\nLine %lu: Fp context import failed\n", line);1044nn_print("Imported r from file =", &fp_ctx_r);1045nn_print("Computed r from modulus=", &(fp_ctx_param.r));1046ret = -1;1047goto err;1048}1049tmp = &fp_ctx_r_square;1050ret = nn_set_wlen(tmp, (u8)(nn_len / WORD_BYTES)); EG(ret, err);1051ret = nn_import_from_hexbuf(tmp, rec + (4 * nn_len),10522 * nn_len); EG(ret, err);10531054/* Compare r_square */1055ret = nn_cmp(&fp_ctx_r_square, &(fp_ctx_param.r_square), &cmp);1056if(ret || cmp){1057printf("\nLine %lu: Fp context import failed\n", line);1058nn_print("Imported r_square from file =", &fp_ctx_r_square);1059nn_print("Computed r_square from modulus=", &(fp_ctx_param.r_square));1060ret = -1;1061goto err;1062}1063tmp = &fp_ctx_mpinv;1064ret = nn_set_wlen(tmp, 1); EG(ret, err);1065ret = nn_import_from_hexbuf(tmp, rec + (6 * nn_len),1066WORD_BYTES * 2); EG(ret, err);10671068/* Compare mpinv */1069if(fp_ctx_mpinv.val[0] != fp_ctx_param.mpinv){1070printf("\nLine %lu: Fp context import failed\n", line);1071printf("Imported mpinv from modulus=" PRINTF_WORD_HEX_FMT, fp_ctx_mpinv.val[0]);1072printf("Computed mpiv from file =" PRINTF_WORD_HEX_FMT, fp_ctx_param.mpinv);1073ret = -1;1074goto err;1075}1076tmp = &fp_ctx_pshift;1077ret = nn_set_wlen(tmp, 1); EG(ret, err);1078ret = nn_import_from_hexbuf(tmp, rec + (6 * nn_len + 2 * WORD_BYTES),1079WORD_BYTES * 2); EG(ret, err);10801081/* Compare p_shift */1082if((bitcnt_t)fp_ctx_pshift.val[0] != fp_ctx_param.p_shift){1083printf("\nLine %lu: Fp context import failed\n", line);1084printf("Imported mpinv from modulus=%d", (bitcnt_t)fp_ctx_pshift.val[0]);1085printf("Computed mpiv from file =%d", fp_ctx_param.p_shift);1086ret = -1;1087goto err;1088}1089tmp = &fp_ctx_pnorm;1090ret = nn_set_wlen(tmp, (u8)(nn_len / WORD_BYTES)); EG(ret, err);1091ret = nn_import_from_hexbuf(tmp, rec + (6 * nn_len + 4 * WORD_BYTES),1092nn_len * 2); EG(ret, err);10931094/* Compare p_normalized */1095ret = nn_cmp(&fp_ctx_pnorm, &(fp_ctx_param.p_normalized), &cmp);1096if(ret || (cmp != 0)){1097printf("\nLine %lu: Fp context import failed\n", line);1098nn_print("Imported r_square from file =", &fp_ctx_pnorm);1099nn_print("Computed r_square from modulus=", &(fp_ctx_param.p_normalized));1100return -1;1101}1102tmp = &fp_ctx_prec;1103ret = nn_set_wlen(tmp, 1); EG(ret, err);1104ret = nn_import_from_hexbuf(tmp, rec + (8 * nn_len + 4 * WORD_BYTES),1105WORD_BYTES * 2); EG(ret, err);11061107/* Compare p_reciprocal */1108if(fp_ctx_prec.val[0] != fp_ctx_param.p_reciprocal){1109printf("\nLine %lu: Fp context import failed\n", line);1110printf("Imported mpinv from modulus=" PRINTF_WORD_HEX_FMT, fp_ctx_prec.val[0]);1111printf("Computed mpiv from file =" PRINTF_WORD_HEX_FMT, fp_ctx_param.p_reciprocal);1112ret = -1;1113goto err;1114}1115params[i] = &fp_ctx_param;1116ADD_TO_BACKTRACE("'c' param: %s\n", rec);1117break;1118case 'f': /* fp */1119if (fp_ctx_local_cnt != 1) {1120printf("\nLine %lu: No fp_ctx available\n", line);1121ret = -1;1122goto err;1123}1124if (fp_local_cnt >= NUM_PRE_ALLOCATED_FP) {1125printf("\nLine %lu: Not enough fp\n",1126line);1127ret = -1;1128goto err;1129}1130assert(((t - rec) % 2) == 0);1131nn_len = (unsigned int)(t - rec) / 2;1132assert((nn_len / WORD_BYTES) <=1133fp_ctx_param.p.wlen);1134fp_tmp = fp_params_ptr[fp_local_cnt++];1135fp_tmp->ctx = &fp_ctx_param;1136tmp = &(fp_tmp->fp_val);1137ret = nn_set_wlen(tmp, (u8)(nn_len / WORD_BYTES)); EG(ret, err);1138ret = nn_import_from_hexbuf(tmp, rec, 2 * nn_len); EG(ret, err);1139ret = nn_set_wlen(tmp, fp_ctx_param.p.wlen); EG(ret, err);1140params[i] = fp_tmp;1141ADD_TO_BACKTRACE("'f' param: %s\n", rec);1142break;1143case 'p': /* raw pointer value. Useful for NULL */1144p_tmp = strtoull(rec, NULL, 10);1145params[i] = (void *)p_tmp;1146ADD_TO_BACKTRACE("'p' param: %s\n", rec);1147/* If this is not a NULL pointer, this is weird!1148* Abort ...1149*/1150if(params[i] != NULL){1151printf("\nLine %lu: imported a pointer (type 'p') non NULL\n",1152line);1153ret = -1;1154goto err;1155}1156break;1157case 'n': /* nn */1158if (nn_local_cnt >= NUM_PRE_ALLOCATED_NN) {1159printf("\nLine %lu: Not enough nn\n",1160line);1161return -1;1162}1163assert(((t - rec) % 2) == 0);1164nn_len = (unsigned int)(t - rec) / 2;1165assert((nn_len % WORD_BYTES) == 0);1166tmp = nn_params_ptr[nn_local_cnt++];1167ret = nn_set_wlen(tmp, (u8)(nn_len / WORD_BYTES)); EG(ret, err);1168ret = nn_import_from_hexbuf(tmp, rec, 2 * nn_len); EG(ret, err);1169params[i] = tmp;1170ADD_TO_BACKTRACE("'n' param: %s\n", rec);1171break;1172case 'u': /* unsigned long int (in base 10) */1173u_params[i] = (u64)strtoull(rec, NULL, 10);1174params[i] = &u_params[i];1175ADD_TO_BACKTRACE("'u' param: %s\n", rec);1176break;1177case 's': /* signed long int (in base 10) */1178u_params[i] = (u64)strtoll(rec, NULL, 10);1179params[i] = &u_params[i];1180ADD_TO_BACKTRACE("'s' param: %s\n", rec);1181break;1182default:1183printf("\nUnknown record type '%c'\n", s[i]);1184ret = -1;1185goto err;1186}1187rec = t + 1;1188}1189/* Save current parameters format in the global variable */1190memcpy(global_parameters, s, LOCAL_MIN(nrecs, MAX_PARAMS));1191curr_test_fun = NULL;1192FIND_FUN_IN_DISPATCH_TABLE(op, curr_test_fun);1193if (curr_test_fun == NULL) {1194printf("\nLine %lu: unknown opcode %s\n", line, op);1195} else {1196ADD_TO_BACKTRACE("\nLine %lu: testing opcode %s\n", line, op);1197test_ret = curr_test_fun(op, params, (int)test_num);1198if (test_ret == 1) {1199ADD_TO_BACKTRACE("-- TEST OK ---\n");1200oktests += (unsigned long)test_ret;1201} else {1202ADD_TO_BACKTRACE("-- TEST NOK --\n");1203}1204}1205line += 1;1206len = ibuflen;1207nn_local_cnt = 0;1208fp_local_cnt = 0;1209fp_ctx_local_cnt = 0;1210}12111212printf("\n%lu/%lu tests passed successfully (%lu on error)\n",1213oktests, line, line - oktests);12141215if(fd != 0){1216close(fd);1217}1218if(ibuf != NULL){1219free(ibuf);1220}12211222return 0;1223err:1224printf("Error: critical error occured! Leaving ...\n");1225if(fd != 0){1226close(fd);1227}1228if(ibuf != NULL){1229free(ibuf);1230}1231return -1;1232}123312341235