xref: /freebsd-src/crypto/libecc/src/arithmetic_tests/arithmetic_tests.c (revision f0865ec9906d5a18fa2a3b61381f22ce16e606ad)
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/libarith.h>
17*f0865ec9SKyle Evans /* Include internal API as it is used in our tests */
18*f0865ec9SKyle Evans #include "../nn/nn_div.h"
19*f0865ec9SKyle Evans #include <sys/types.h>
20*f0865ec9SKyle Evans #include <sys/stat.h>
21*f0865ec9SKyle Evans #include <fcntl.h>
22*f0865ec9SKyle Evans #include <unistd.h>
23*f0865ec9SKyle Evans #include <string.h>
24*f0865ec9SKyle Evans #include <stdio.h>
25*f0865ec9SKyle Evans #include <stdlib.h>
26*f0865ec9SKyle Evans #include <assert.h>
27*f0865ec9SKyle Evans 
28*f0865ec9SKyle Evans #ifdef WITH_ASSERT_BACKTRACE
29*f0865ec9SKyle Evans #include <signal.h>
30*f0865ec9SKyle Evans #include <execinfo.h>
31*f0865ec9SKyle Evans 
32*f0865ec9SKyle Evans #define BACKTRACE_SIZE 4096
33*f0865ec9SKyle Evans static unsigned int backtrace_buffer_ptr = 0;
34*f0865ec9SKyle Evans static char backtrace_buffer[BACKTRACE_SIZE];
35*f0865ec9SKyle Evans 
36*f0865ec9SKyle Evans /* assert trapping and backtracing */
37*f0865ec9SKyle Evans static void assert_signal_handler(int sig)
38*f0865ec9SKyle Evans {
39*f0865ec9SKyle Evans 	if (sig != SIGINT) {
40*f0865ec9SKyle Evans 		raise(sig);
41*f0865ec9SKyle Evans 	}
42*f0865ec9SKyle Evans 	/* Print the recorded backtrace */
43*f0865ec9SKyle Evans 	printf("**** BACKTRACE *****\n");
44*f0865ec9SKyle Evans 	printf("(from old to most recent calls)\n");
45*f0865ec9SKyle Evans 	printf("%s", backtrace_buffer);
46*f0865ec9SKyle Evans 	exit(-1);
47*f0865ec9SKyle Evans }
48*f0865ec9SKyle Evans 
49*f0865ec9SKyle Evans #define ADD_TO_BACKTRACE(...) do {\
50*f0865ec9SKyle Evans 	int written_size;\
51*f0865ec9SKyle Evans 	written_size = snprintf(backtrace_buffer + backtrace_buffer_ptr, BACKTRACE_SIZE - 1 - backtrace_buffer_ptr, __VA_ARGS__);\
52*f0865ec9SKyle Evans 	backtrace_buffer_ptr += written_size;\
53*f0865ec9SKyle Evans 	if(backtrace_buffer_ptr >= BACKTRACE_SIZE - 1){\
54*f0865ec9SKyle Evans 		memset(backtrace_buffer, 0, sizeof(backtrace_buffer)-1);\
55*f0865ec9SKyle Evans 		backtrace_buffer_ptr = 0;\
56*f0865ec9SKyle Evans 	}\
57*f0865ec9SKyle Evans } while(0)
58*f0865ec9SKyle Evans #else
59*f0865ec9SKyle Evans 
60*f0865ec9SKyle Evans #define ADD_TO_BACKTRACE(...) do {\
61*f0865ec9SKyle Evans } while(0)
62*f0865ec9SKyle Evans 
63*f0865ec9SKyle Evans #endif
64*f0865ec9SKyle Evans 
65*f0865ec9SKyle Evans /*
66*f0865ec9SKyle Evans  * Import integer number (found in hexadecimal form in hbuf buffer
67*f0865ec9SKyle Evans  * of length hbuflen) into already allocated out_nn. hbuflen is
68*f0865ec9SKyle Evans  * expected to be of even size. out_nn parameter is expected to
69*f0865ec9SKyle Evans  * have a large enough storage space (i.e. hbuflen / 2) to hold
70*f0865ec9SKyle Evans  * imported number.
71*f0865ec9SKyle Evans  */
72*f0865ec9SKyle Evans static int nn_import_from_hexbuf(nn_t out_nn, const char *hbuf, u32 hbuflen)
73*f0865ec9SKyle Evans {
74*f0865ec9SKyle Evans 	char buf[WORD_BYTES * 2 + 1];
75*f0865ec9SKyle Evans 	const char *start;
76*f0865ec9SKyle Evans 	u32 wlen;
77*f0865ec9SKyle Evans 	u32 k;
78*f0865ec9SKyle Evans 	int ret;
79*f0865ec9SKyle Evans 
80*f0865ec9SKyle Evans 	ret = nn_check_initialized(out_nn); EG(ret, err);
81*f0865ec9SKyle Evans 	MUST_HAVE((hbuf != NULL), ret, err);
82*f0865ec9SKyle Evans 	MUST_HAVE(((hbuflen / 2) / WORD_BYTES) == out_nn->wlen, ret, err);
83*f0865ec9SKyle Evans 
84*f0865ec9SKyle Evans 	wlen = (hbuflen + WORD_BYTES - 1) / (2 * WORD_BYTES);
85*f0865ec9SKyle Evans 	for (k = wlen; k > 0; k--) {
86*f0865ec9SKyle Evans 		/*
87*f0865ec9SKyle Evans 		 * Copy current hex encoded word into null terminated
88*f0865ec9SKyle Evans 		 * scratch buffer
89*f0865ec9SKyle Evans 		 */
90*f0865ec9SKyle Evans 		memset(buf, 0, WORD_BYTES * 2 + 1);
91*f0865ec9SKyle Evans 		start = hbuf + ((k - 1) * WORD_BYTES * 2);
92*f0865ec9SKyle Evans 		memcpy(buf, start, WORD_BYTES * 2);
93*f0865ec9SKyle Evans 
94*f0865ec9SKyle Evans 		/* Let strtoull() convert the value for us */
95*f0865ec9SKyle Evans 		out_nn->val[wlen - k] = strtoull(buf, NULL, 16);
96*f0865ec9SKyle Evans 	}
97*f0865ec9SKyle Evans 
98*f0865ec9SKyle Evans 	for (k = NN_MAX_WORD_LEN; k > wlen; k--) {
99*f0865ec9SKyle Evans 		out_nn->val[k - 1] = 0;
100*f0865ec9SKyle Evans 	}
101*f0865ec9SKyle Evans 
102*f0865ec9SKyle Evans err:
103*f0865ec9SKyle Evans 	return ret;
104*f0865ec9SKyle Evans }
105*f0865ec9SKyle Evans 
106*f0865ec9SKyle Evans #define DISPATCH_TABLE_MAGIC "FEEDBABE"
107*f0865ec9SKyle Evans struct dispatch_table {
108*f0865ec9SKyle Evans 	const char magic[sizeof(DISPATCH_TABLE_MAGIC)];
109*f0865ec9SKyle Evans 	const char *op_string;
110*f0865ec9SKyle Evans 	const char *op_string_helper;
111*f0865ec9SKyle Evans 	int (*fun) (const char *op, void **, int);
112*f0865ec9SKyle Evans };
113*f0865ec9SKyle Evans 
114*f0865ec9SKyle Evans #define ADD_TO_DISPATCH_TABLE(fun, op_string, op_string_helper) \
115*f0865ec9SKyle Evans 	static const struct dispatch_table entry_##fun \
116*f0865ec9SKyle Evans 		ATTRIBUTE_SECTION("tests_dispatch_table_section") ATTRIBUTE_USED = \
117*f0865ec9SKyle Evans 		{ DISPATCH_TABLE_MAGIC, op_string, op_string_helper, fun };
118*f0865ec9SKyle Evans 
119*f0865ec9SKyle Evans #define FIND_IN_DISPATCH_TABLE(op, to_find, type) do {\
120*f0865ec9SKyle Evans 	extern struct dispatch_table __start_tests_dispatch_table_section;\
121*f0865ec9SKyle Evans 	extern struct dispatch_table __stop_tests_dispatch_table_section;\
122*f0865ec9SKyle Evans 	struct dispatch_table *dt, *begin, *end;\
123*f0865ec9SKyle Evans 	char *ptr;\
124*f0865ec9SKyle Evans 	\
125*f0865ec9SKyle Evans 	begin = &__start_tests_dispatch_table_section;\
126*f0865ec9SKyle Evans 	end = &__stop_tests_dispatch_table_section;\
127*f0865ec9SKyle Evans 	ptr = (char*)begin;\
128*f0865ec9SKyle Evans 	\
129*f0865ec9SKyle Evans 	to_find = NULL;\
130*f0865ec9SKyle Evans 	\
131*f0865ec9SKyle Evans 	while(ptr < (char*)end){\
132*f0865ec9SKyle Evans 		dt = (struct dispatch_table*)ptr;\
133*f0865ec9SKyle Evans 		/* Find the magic */\
134*f0865ec9SKyle Evans 		while(memcmp(dt->magic, DISPATCH_TABLE_MAGIC, sizeof(DISPATCH_TABLE_MAGIC)) != 0){\
135*f0865ec9SKyle Evans 			ptr++;\
136*f0865ec9SKyle Evans 			dt = (struct dispatch_table*)ptr;\
137*f0865ec9SKyle Evans 		}\
138*f0865ec9SKyle Evans 		if(strcmp(dt->op_string, op) == 0){ \
139*f0865ec9SKyle Evans 			to_find = dt->type;\
140*f0865ec9SKyle Evans 			break;\
141*f0865ec9SKyle Evans 		}\
142*f0865ec9SKyle Evans 		ptr += sizeof(struct dispatch_table);\
143*f0865ec9SKyle Evans 	}\
144*f0865ec9SKyle Evans } while(0)
145*f0865ec9SKyle Evans 
146*f0865ec9SKyle Evans #define FIND_FUN_IN_DISPATCH_TABLE(op, function) FIND_IN_DISPATCH_TABLE(op, function, fun)
147*f0865ec9SKyle Evans 
148*f0865ec9SKyle Evans #define FIND_HELPER_IN_DISPATCH_TABLE(op, string_helper) FIND_IN_DISPATCH_TABLE(op, string_helper, op_string_helper)
149*f0865ec9SKyle Evans 
150*f0865ec9SKyle Evans /*****************/
151*f0865ec9SKyle Evans 
152*f0865ec9SKyle Evans #define GENERIC_TEST_FP_DECL_INIT0(name, ctx) \
153*f0865ec9SKyle Evans 	fp_t name##_ptr[] = {NULL};
154*f0865ec9SKyle Evans 
155*f0865ec9SKyle Evans #define GENERIC_TEST_FP_DECL_INIT1(name, ctx) \
156*f0865ec9SKyle Evans 	fp name##0; \
157*f0865ec9SKyle Evans 	fp_t name##_ptr[] = { &name##0 };\
158*f0865ec9SKyle Evans 	ret |= fp_init(&name##0, ctx);\
159*f0865ec9SKyle Evans 
160*f0865ec9SKyle Evans #define GENERIC_TEST_FP_DECL_INIT2(name, ctx) \
161*f0865ec9SKyle Evans 	fp name##0, name##1;\
162*f0865ec9SKyle Evans 	fp_t name##_ptr[] = { &name##0, &name##1 };\
163*f0865ec9SKyle Evans 	ret |= fp_init(&name##0, ctx);\
164*f0865ec9SKyle Evans 	ret |= fp_init(&name##1, ctx);\
165*f0865ec9SKyle Evans 
166*f0865ec9SKyle Evans #define GENERIC_TEST_FP_DECL_INIT3(name, ctx) \
167*f0865ec9SKyle Evans 	fp name##0, name##1, name##2;\
168*f0865ec9SKyle Evans 	fp_t name##_ptr[] = { &name##0, &name##1, &name##2 };\
169*f0865ec9SKyle Evans 	ret |= fp_init(&name##0, ctx);\
170*f0865ec9SKyle Evans 	ret |= fp_init(&name##1, ctx);\
171*f0865ec9SKyle Evans 	ret |= fp_init(&name##2, ctx);\
172*f0865ec9SKyle Evans 
173*f0865ec9SKyle Evans #define GENERIC_TEST_FP_DECL_INIT4(name, ctx) \
174*f0865ec9SKyle Evans 	fp name##0, name##1, name##2, name##3;\
175*f0865ec9SKyle Evans 	fp_t name##_ptr[] = { &name##0, &name##1, &name##2, &name##3 };\
176*f0865ec9SKyle Evans 	ret |= fp_init(&name##0, ctx);\
177*f0865ec9SKyle Evans 	ret |= fp_init(&name##1, ctx);\
178*f0865ec9SKyle Evans 	ret |= fp_init(&name##2, ctx);\
179*f0865ec9SKyle Evans 	ret |= fp_init(&name##3, ctx);\
180*f0865ec9SKyle Evans 
181*f0865ec9SKyle Evans #define GENERIC_TEST_FP_DECL_INIT5(name, ctx) \
182*f0865ec9SKyle Evans 	fp name##0, name##1, name##2, name##3, name##4;\
183*f0865ec9SKyle Evans 	fp_t name##_ptr[] = { &name##0, &name##1, &name##2, &name##3, &name##4 };\
184*f0865ec9SKyle Evans 	ret |= fp_init(&name##0, ctx);\
185*f0865ec9SKyle Evans 	ret |= fp_init(&name##1, ctx);\
186*f0865ec9SKyle Evans 	ret |= fp_init(&name##2, ctx);\
187*f0865ec9SKyle Evans 	ret |= fp_init(&name##3, ctx);\
188*f0865ec9SKyle Evans 	ret |= fp_init(&name##4, ctx);\
189*f0865ec9SKyle Evans 
190*f0865ec9SKyle Evans #define GENERIC_TEST_FP_DECL_INIT6(name, ctx) \
191*f0865ec9SKyle Evans 	fp name##0, name##1, name##2, name##3, name##4, name##5;\
192*f0865ec9SKyle Evans 	fp_t name##_ptr[] = { &name##0, &name##1, &name##2, &name##3, &name##4, &name##5 };\
193*f0865ec9SKyle Evans 	ret |= fp_init(&name##0, ctx);\
194*f0865ec9SKyle Evans 	ret |= fp_init(&name##1, ctx);\
195*f0865ec9SKyle Evans 	ret |= fp_init(&name##2, ctx);\
196*f0865ec9SKyle Evans 	ret |= fp_init(&name##3, ctx);\
197*f0865ec9SKyle Evans 	ret |= fp_init(&name##4, ctx);\
198*f0865ec9SKyle Evans 	ret |= fp_init(&name##5, ctx);\
199*f0865ec9SKyle Evans 
200*f0865ec9SKyle Evans #define GENERIC_TEST_NN_DECL_INIT0(name, size) \
201*f0865ec9SKyle Evans 	nn_t name##_ptr[] = {NULL};
202*f0865ec9SKyle Evans 
203*f0865ec9SKyle Evans #define GENERIC_TEST_NN_DECL_INIT1(name, size) \
204*f0865ec9SKyle Evans 	nn name##0;			       \
205*f0865ec9SKyle Evans 	nn_t name##_ptr[] = { &name##0 };      \
206*f0865ec9SKyle Evans 	ret |= nn_init(&name##0, size); \
207*f0865ec9SKyle Evans 
208*f0865ec9SKyle Evans #define GENERIC_TEST_NN_DECL_INIT2(name, size)       \
209*f0865ec9SKyle Evans 	nn name##0, name##1;			     \
210*f0865ec9SKyle Evans 	nn_t name##_ptr[] = { &name##0, &name##1 };  \
211*f0865ec9SKyle Evans 	ret |= nn_init(&name##0, size); \
212*f0865ec9SKyle Evans 	ret |= nn_init(&name##1, size); \
213*f0865ec9SKyle Evans 
214*f0865ec9SKyle Evans #define GENERIC_TEST_NN_DECL_INIT3(name, size)                  \
215*f0865ec9SKyle Evans 	nn name##0, name##1, name##2;				\
216*f0865ec9SKyle Evans 	nn_t name##_ptr[] = { &name##0, &name##1, &name##2 };	\
217*f0865ec9SKyle Evans 	ret |= nn_init(&name##0, size);		\
218*f0865ec9SKyle Evans 	ret |= nn_init(&name##1, size);		\
219*f0865ec9SKyle Evans 	ret |= nn_init(&name##2, size);   	\
220*f0865ec9SKyle Evans 
221*f0865ec9SKyle Evans #define GENERIC_TEST_NN_DECL_INIT4(name, size)				\
222*f0865ec9SKyle Evans 	nn name##0, name##1, name##2, name##3;				\
223*f0865ec9SKyle Evans 	nn_t name##_ptr[] = { &name##0, &name##1, &name##2, &name##3 }; \
224*f0865ec9SKyle Evans 	ret |= nn_init(&name##0, size);			\
225*f0865ec9SKyle Evans 	ret |= nn_init(&name##1, size);			\
226*f0865ec9SKyle Evans 	ret |= nn_init(&name##2, size);			\
227*f0865ec9SKyle Evans 	ret |= nn_init(&name##3, size);			\
228*f0865ec9SKyle Evans 
229*f0865ec9SKyle Evans #define GENERIC_TEST_NN_DECL_INIT5(name, size)		    \
230*f0865ec9SKyle Evans 	nn name##0, name##1, name##2, name##3, name##4;	    \
231*f0865ec9SKyle Evans 	nn_t name##_ptr[] = { &name##0, &name##1, &name##2, &name##3, &name##4 };\
232*f0865ec9SKyle Evans 	ret |= nn_init(&name##0, size);	    \
233*f0865ec9SKyle Evans 	ret |= nn_init(&name##1, size);	    \
234*f0865ec9SKyle Evans 	ret |= nn_init(&name##2, size);	    \
235*f0865ec9SKyle Evans 	ret |= nn_init(&name##3, size);	    \
236*f0865ec9SKyle Evans 	ret |= nn_init(&name##4, size);	    \
237*f0865ec9SKyle Evans 
238*f0865ec9SKyle Evans #define GENERIC_TEST_NN_DECL_INIT6(name, size)				\
239*f0865ec9SKyle Evans 	nn name##0, name##1, name##2, name##3, name##4, name##5;	\
240*f0865ec9SKyle Evans 	nn_t name##_ptr[] = { &name##0, &name##1, &name##2, &name##3, &name##4, &name##5 };\
241*f0865ec9SKyle Evans 	ret |= nn_init(&name##0, size);		\
242*f0865ec9SKyle Evans 	ret |= nn_init(&name##1, size);		\
243*f0865ec9SKyle Evans 	ret |= nn_init(&name##2, size);		\
244*f0865ec9SKyle Evans 	ret |= nn_init(&name##3, size);		\
245*f0865ec9SKyle Evans 	ret |= nn_init(&name##4, size);		\
246*f0865ec9SKyle Evans 	ret |= nn_init(&name##5, size);		\
247*f0865ec9SKyle Evans 
248*f0865ec9SKyle Evans #define GENERIC_TEST_FP_CLEAR0(name)
249*f0865ec9SKyle Evans 
250*f0865ec9SKyle Evans #define GENERIC_TEST_FP_CLEAR1(name) \
251*f0865ec9SKyle Evans 	fp_uninit(&name##0);\
252*f0865ec9SKyle Evans 
253*f0865ec9SKyle Evans #define GENERIC_TEST_FP_CLEAR2(name) \
254*f0865ec9SKyle Evans 	fp_uninit(&name##0);\
255*f0865ec9SKyle Evans 	fp_uninit(&name##1);\
256*f0865ec9SKyle Evans 
257*f0865ec9SKyle Evans #define GENERIC_TEST_FP_CLEAR3(name) \
258*f0865ec9SKyle Evans 	fp_uninit(&name##0);\
259*f0865ec9SKyle Evans 	fp_uninit(&name##1);\
260*f0865ec9SKyle Evans 	fp_uninit(&name##2);\
261*f0865ec9SKyle Evans 
262*f0865ec9SKyle Evans #define GENERIC_TEST_FP_CLEAR4(name) \
263*f0865ec9SKyle Evans 	fp_uninit(&name##0);\
264*f0865ec9SKyle Evans 	fp_uninit(&name##1);\
265*f0865ec9SKyle Evans 	fp_uninit(&name##2);\
266*f0865ec9SKyle Evans 	fp_uninit(&name##3);\
267*f0865ec9SKyle Evans 
268*f0865ec9SKyle Evans #define GENERIC_TEST_FP_CLEAR5(name) \
269*f0865ec9SKyle Evans 	fp_uninit(&name##0);\
270*f0865ec9SKyle Evans 	fp_uninit(&name##1);\
271*f0865ec9SKyle Evans 	fp_uninit(&name##2);\
272*f0865ec9SKyle Evans 	fp_uninit(&name##3);\
273*f0865ec9SKyle Evans 	fp_uninit(&name##4);\
274*f0865ec9SKyle Evans 
275*f0865ec9SKyle Evans #define GENERIC_TEST_FP_CLEAR6(name) \
276*f0865ec9SKyle Evans 	fp_uninit(&name##0);\
277*f0865ec9SKyle Evans 	fp_uninit(&name##1);\
278*f0865ec9SKyle Evans 	fp_uninit(&name##2);\
279*f0865ec9SKyle Evans 	fp_uninit(&name##3);\
280*f0865ec9SKyle Evans 	fp_uninit(&name##4);\
281*f0865ec9SKyle Evans 	fp_uninit(&name##5);\
282*f0865ec9SKyle Evans 
283*f0865ec9SKyle Evans #define GENERIC_TEST_nn_uninit0(name)
284*f0865ec9SKyle Evans 
285*f0865ec9SKyle Evans #define GENERIC_TEST_nn_uninit1(name) \
286*f0865ec9SKyle Evans 	nn_uninit(&name##0);\
287*f0865ec9SKyle Evans 
288*f0865ec9SKyle Evans #define GENERIC_TEST_nn_uninit2(name) \
289*f0865ec9SKyle Evans 	nn_uninit(&name##0);\
290*f0865ec9SKyle Evans 	nn_uninit(&name##1);\
291*f0865ec9SKyle Evans 
292*f0865ec9SKyle Evans #define GENERIC_TEST_nn_uninit3(name) \
293*f0865ec9SKyle Evans 	nn_uninit(&name##0);\
294*f0865ec9SKyle Evans 	nn_uninit(&name##1);\
295*f0865ec9SKyle Evans 	nn_uninit(&name##2);\
296*f0865ec9SKyle Evans 
297*f0865ec9SKyle Evans #define GENERIC_TEST_nn_uninit4(name) \
298*f0865ec9SKyle Evans 	nn_uninit(&name##0);\
299*f0865ec9SKyle Evans 	nn_uninit(&name##1);\
300*f0865ec9SKyle Evans 	nn_uninit(&name##2);\
301*f0865ec9SKyle Evans 	nn_uninit(&name##3);\
302*f0865ec9SKyle Evans 
303*f0865ec9SKyle Evans #define GENERIC_TEST_nn_uninit5(name) \
304*f0865ec9SKyle Evans 	nn_uninit(&name##0);\
305*f0865ec9SKyle Evans 	nn_uninit(&name##1);\
306*f0865ec9SKyle Evans 	nn_uninit(&name##2);\
307*f0865ec9SKyle Evans 	nn_uninit(&name##3);\
308*f0865ec9SKyle Evans 	nn_uninit(&name##4);\
309*f0865ec9SKyle Evans 
310*f0865ec9SKyle Evans #define GENERIC_TEST_nn_uninit6(name) \
311*f0865ec9SKyle Evans 	nn_uninit(&name##0);\
312*f0865ec9SKyle Evans 	nn_uninit(&name##1);\
313*f0865ec9SKyle Evans 	nn_uninit(&name##2);\
314*f0865ec9SKyle Evans 	nn_uninit(&name##3);\
315*f0865ec9SKyle Evans 	nn_uninit(&name##4);\
316*f0865ec9SKyle Evans 	nn_uninit(&name##5);\
317*f0865ec9SKyle Evans 
318*f0865ec9SKyle Evans #define FP_CTX_T_GENERIC_IN(num) ((fp_ctx_t)params[num])
319*f0865ec9SKyle Evans #define FP_T_GENERIC_IN(num) ((fp_t)params[num])
320*f0865ec9SKyle Evans #define NN_T_GENERIC_IN(num) ((nn_t)params[num])
321*f0865ec9SKyle Evans #define UINT_GENERIC_IN(num) ((u64)*((u64*)params[num]))
322*f0865ec9SKyle Evans #define WORD_T_GENERIC_IN(num) ((word_t)*((word_t*)params[num]))
323*f0865ec9SKyle Evans #define INT_GENERIC_IN(num) ((int)*((int*)params[num]))
324*f0865ec9SKyle Evans 
325*f0865ec9SKyle Evans #define FP_T_GENERIC_OUT(num) (&fp_out##num)
326*f0865ec9SKyle Evans #define NN_T_GENERIC_OUT(num) (&nn_out##num)
327*f0865ec9SKyle Evans #define WORD_T_GENERIC_OUT(num) (&(word_out[num]))
328*f0865ec9SKyle Evans #define INT_GENERIC_OUT(num) (&(int_out[num]))
329*f0865ec9SKyle Evans 
330*f0865ec9SKyle Evans #define CHECK_FUN_RET there_is_output = 1; fun_out_value = (int)
331*f0865ec9SKyle Evans 
332*f0865ec9SKyle Evans #define CHECK_FUN_NO_RET there_is_output = 0; fun_out_value = (int)
333*f0865ec9SKyle Evans 
334*f0865ec9SKyle Evans /* Number of pre-allocated */
335*f0865ec9SKyle Evans #define NUM_PRE_ALLOCATED_NN 6
336*f0865ec9SKyle Evans #define NUM_PRE_ALLOCATED_FP 6
337*f0865ec9SKyle Evans #define MAX_PARAMS 6
338*f0865ec9SKyle Evans 
339*f0865ec9SKyle Evans #define GENERIC_TEST_NN_DECL_INIT_MAX(name, n) GENERIC_TEST_NN_DECL_INIT6(name, n)
340*f0865ec9SKyle Evans #define GENERIC_TEST_FP_DECL_INIT_MAX(name, ctx) GENERIC_TEST_FP_DECL_INIT6(name, ctx)
341*f0865ec9SKyle Evans 
342*f0865ec9SKyle Evans /* Check that the string of parameters types only containes 'c', 'f', 'n' and 'u'
343*f0865ec9SKyle Evans  * Check that the string of parameters I/O only contains 'i', 'o' and 'O'
344*f0865ec9SKyle Evans  *
345*f0865ec9SKyle Evans  */
346*f0865ec9SKyle Evans #define PARAMETERS_SANITY_CHECK(test_num, param_types, param_io) do {\
347*f0865ec9SKyle Evans 	unsigned int i, real_output = 0;\
348*f0865ec9SKyle Evans 	assert(sizeof(param_types) == sizeof(param_io));\
349*f0865ec9SKyle Evans 	for(i = 0; i < sizeof(param_types)-1; i++){\
350*f0865ec9SKyle Evans 		if((param_types[i] != 'c') && (param_types[i] != 'f') && (param_types[i] != 'n') && (param_types[i] != 'u') && (param_types[i] != 's')){ \
351*f0865ec9SKyle Evans 			printf("Error: types parameters of test %d mismatch!\n", test_num);\
352*f0865ec9SKyle Evans 			return 0;\
353*f0865ec9SKyle Evans 		}\
354*f0865ec9SKyle Evans 		if((param_io[i] != 'i') && (param_io[i] != 'o') && (param_io[i] != 'O')){\
355*f0865ec9SKyle Evans 			printf("Error: I/O parameters of test %d mismatch!\n", test_num);\
356*f0865ec9SKyle Evans 			return 0;\
357*f0865ec9SKyle Evans 		}\
358*f0865ec9SKyle Evans 		if((param_io[i] == 'O') && (param_types[i] != 'u') && (param_types[i] != 's')){\
359*f0865ec9SKyle Evans 			printf("Error: types and I/O parameters of test %d mismatch!\n", test_num);\
360*f0865ec9SKyle Evans 			return 0;\
361*f0865ec9SKyle Evans 		}\
362*f0865ec9SKyle Evans 		if(param_io[i] == 'O'){\
363*f0865ec9SKyle Evans 			real_output++;\
364*f0865ec9SKyle Evans 		}\
365*f0865ec9SKyle Evans 	}\
366*f0865ec9SKyle Evans 	/* Check that we only have one function output */\
367*f0865ec9SKyle Evans 	if(real_output > 1){\
368*f0865ec9SKyle Evans 		printf("Error: multiple function output defined in I/O parameters of test %d!\n", test_num);\
369*f0865ec9SKyle Evans 		return 0;\
370*f0865ec9SKyle Evans 	}\
371*f0865ec9SKyle Evans } while(0);
372*f0865ec9SKyle Evans 
373*f0865ec9SKyle Evans #define SET_PARAMETER_PRETTY_NAME1(a) a
374*f0865ec9SKyle Evans #define SET_PARAMETER_PRETTY_NAME2(a, b) SET_PARAMETER_PRETTY_NAME1(a) "\0" b
375*f0865ec9SKyle Evans #define SET_PARAMETER_PRETTY_NAME3(a, b, c) SET_PARAMETER_PRETTY_NAME2(a, b) "\0" c
376*f0865ec9SKyle Evans #define SET_PARAMETER_PRETTY_NAME4(a, b, c, d) SET_PARAMETER_PRETTY_NAME3(a, b, c) "\0" d
377*f0865ec9SKyle Evans #define SET_PARAMETER_PRETTY_NAME5(a, b, c, d, e) SET_PARAMETER_PRETTY_NAME4(a, b, c, d) "\0" e
378*f0865ec9SKyle Evans #define SET_PARAMETER_PRETTY_NAME6(a, b, c, d, e, f) SET_PARAMETER_PRETTY_NAME5(a, b, c, d, e) "\0" f
379*f0865ec9SKyle Evans 
380*f0865ec9SKyle Evans #define SET_PARAMETER_PRETTY_NAME(num, ...) SET_PARAMETER_PRETTY_NAME##num(__VA_ARGS__)
381*f0865ec9SKyle Evans 
382*f0865ec9SKyle Evans /* Parse the helper string to get the pretty print names */
383*f0865ec9SKyle Evans #define GET_PARAMETER_PRETTY_NAME(parameters_string_names_, parameters_string_names, num, out) do {\
384*f0865ec9SKyle Evans 	unsigned int cnt = 0;\
385*f0865ec9SKyle Evans 	out = 0;\
386*f0865ec9SKyle Evans 	\
387*f0865ec9SKyle Evans 	/* Find the proper position */\
388*f0865ec9SKyle Evans 	while(out < sizeof(parameters_string_names_)-1){\
389*f0865ec9SKyle Evans 		if(cnt == num){\
390*f0865ec9SKyle Evans 			break;\
391*f0865ec9SKyle Evans 		}\
392*f0865ec9SKyle Evans 		if(parameters_string_names[out] == '\0'){\
393*f0865ec9SKyle Evans 			cnt++;\
394*f0865ec9SKyle Evans 		}\
395*f0865ec9SKyle Evans 		out++;\
396*f0865ec9SKyle Evans 	}\
397*f0865ec9SKyle Evans } while(0);
398*f0865ec9SKyle Evans 
399*f0865ec9SKyle Evans /* Print for a given test all the inputs, outpus and expected outputs */
400*f0865ec9SKyle Evans #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 { \
401*f0865ec9SKyle Evans 	unsigned int j;\
402*f0865ec9SKyle Evans 	unsigned int nn_out_local_cnt = 0, fp_out_local_cnt = 0;\
403*f0865ec9SKyle Evans 	unsigned int str_pos;\
404*f0865ec9SKyle Evans 	const char parameters_string_names[] = parameters_string_names_;\
405*f0865ec9SKyle Evans 	const char real[] = "Real ";\
406*f0865ec9SKyle Evans 	const char expected[] = "Expected ";\
407*f0865ec9SKyle Evans 	char expected_modified_string_names[sizeof(expected)+sizeof(parameters_string_names_)];\
408*f0865ec9SKyle Evans 	char real_modified_string_names[sizeof(real)+sizeof(parameters_string_names_)];\
409*f0865ec9SKyle Evans 	/* First print the inputs */\
410*f0865ec9SKyle Evans 	for(j=0; j<sizeof(parameters_types)-1; j++){\
411*f0865ec9SKyle Evans 		GET_PARAMETER_PRETTY_NAME(parameters_string_names_, parameters_string_names, j, str_pos);\
412*f0865ec9SKyle Evans 		if(parameters_io[j] == 'i'){\
413*f0865ec9SKyle Evans 			/* This is an input */\
414*f0865ec9SKyle Evans 			if(parameters_types[j] == 'c'){\
415*f0865ec9SKyle Evans 				nn_print(&(parameters_string_names[str_pos]), &(FP_CTX_T_GENERIC_IN(j)->p)); \
416*f0865ec9SKyle Evans 			}\
417*f0865ec9SKyle Evans 			if(parameters_types[j] == 'f'){\
418*f0865ec9SKyle Evans 				nn_print(&(parameters_string_names[str_pos]), &(FP_T_GENERIC_IN(j)->fp_val)); \
419*f0865ec9SKyle Evans 			}\
420*f0865ec9SKyle Evans 			if(parameters_types[j] == 'n'){\
421*f0865ec9SKyle Evans 				nn_print(&(parameters_string_names[str_pos]), NN_T_GENERIC_IN(j));\
422*f0865ec9SKyle Evans 			}\
423*f0865ec9SKyle Evans 			if(parameters_types[j] == 'u'){\
424*f0865ec9SKyle Evans 				printf("%16s: 0x", &(parameters_string_names[str_pos])); \
425*f0865ec9SKyle Evans 				printf(PRINTF_WORD_HEX_FMT, WORD_T_GENERIC_IN(j));	 \
426*f0865ec9SKyle Evans 				printf("\n");						 \
427*f0865ec9SKyle Evans 			}\
428*f0865ec9SKyle Evans 			if(parameters_types[j] == 's'){\
429*f0865ec9SKyle Evans 				printf("%16s:", &(parameters_string_names[str_pos])); 	 \
430*f0865ec9SKyle Evans 				printf("%d", INT_GENERIC_IN(j));			 \
431*f0865ec9SKyle Evans 				printf("\n");						 \
432*f0865ec9SKyle Evans 			}\
433*f0865ec9SKyle Evans 		}\
434*f0865ec9SKyle Evans 	}\
435*f0865ec9SKyle Evans 	/* Then print the outputs */\
436*f0865ec9SKyle Evans 	for(j=0; j<sizeof(parameters_types)-1; j++){\
437*f0865ec9SKyle Evans 		GET_PARAMETER_PRETTY_NAME(parameters_string_names_, parameters_string_names, j, str_pos);\
438*f0865ec9SKyle Evans 		memset(expected_modified_string_names, 0, sizeof(expected_modified_string_names));\
439*f0865ec9SKyle Evans 		strcat(expected_modified_string_names, expected);\
440*f0865ec9SKyle Evans 		strcat(expected_modified_string_names, &(parameters_string_names[str_pos]));\
441*f0865ec9SKyle Evans 		memset(real_modified_string_names, 0, sizeof(real_modified_string_names));\
442*f0865ec9SKyle Evans 		strcat(real_modified_string_names, real);\
443*f0865ec9SKyle Evans 		strcat(real_modified_string_names, &(parameters_string_names[str_pos]));\
444*f0865ec9SKyle Evans 		if(parameters_io[j] == 'o'){\
445*f0865ec9SKyle Evans 			/* This is an input that is an output */\
446*f0865ec9SKyle Evans 			if(parameters_types[j] == 'f'){\
447*f0865ec9SKyle Evans 				nn_print(real_modified_string_names, &(fp_out_ptr[j]->fp_val)); \
448*f0865ec9SKyle Evans 				nn_print(expected_modified_string_names, &(FP_T_GENERIC_IN(j)->fp_val)); \
449*f0865ec9SKyle Evans 				fp_out_local_cnt++;\
450*f0865ec9SKyle Evans 			}\
451*f0865ec9SKyle Evans 			if(parameters_types[j] == 'n'){\
452*f0865ec9SKyle Evans 				nn_print(real_modified_string_names, nn_out_ptr[j]);\
453*f0865ec9SKyle Evans 				nn_print(expected_modified_string_names, NN_T_GENERIC_IN(j));\
454*f0865ec9SKyle Evans 				nn_out_local_cnt++;\
455*f0865ec9SKyle Evans 			}\
456*f0865ec9SKyle Evans 			if(parameters_types[j] == 'u'){\
457*f0865ec9SKyle Evans 				printf("%16s: 0x", real_modified_string_names); 	\
458*f0865ec9SKyle Evans 				printf(PRINTF_WORD_HEX_FMT, *(WORD_T_GENERIC_OUT(j)));	\
459*f0865ec9SKyle Evans 				printf("\n");						\
460*f0865ec9SKyle Evans 				printf("%16s: 0x", expected_modified_string_names); 	\
461*f0865ec9SKyle Evans 				printf(PRINTF_WORD_HEX_FMT, WORD_T_GENERIC_IN(j));	\
462*f0865ec9SKyle Evans 				printf("\n");						\
463*f0865ec9SKyle Evans 			}\
464*f0865ec9SKyle Evans 			if(parameters_types[j] == 's'){\
465*f0865ec9SKyle Evans 				printf("%16s: ", real_modified_string_names); 		\
466*f0865ec9SKyle Evans 				printf("%d", *(INT_GENERIC_OUT(j)));			\
467*f0865ec9SKyle Evans 				printf("\n");						\
468*f0865ec9SKyle Evans 				printf("%16s: ", expected_modified_string_names); 	\
469*f0865ec9SKyle Evans 				printf("%d", INT_GENERIC_IN(j));			\
470*f0865ec9SKyle Evans 				printf("\n");						\
471*f0865ec9SKyle Evans 			}\
472*f0865ec9SKyle Evans 		}\
473*f0865ec9SKyle Evans 		if((parameters_io[j] == 'O') && (there_is_output == 1)){\
474*f0865ec9SKyle Evans 			/* This is a real function output */\
475*f0865ec9SKyle Evans 			if(parameters_types[j] == 'u'){\
476*f0865ec9SKyle Evans 				printf("%16s: 0x", real_modified_string_names); 	\
477*f0865ec9SKyle Evans 				printf(PRINTF_WORD_HEX_FMT, (word_t)fun_output);	\
478*f0865ec9SKyle Evans 				printf("\n");						\
479*f0865ec9SKyle Evans 				printf("%16s: 0x", expected_modified_string_names); 	\
480*f0865ec9SKyle Evans 				printf(PRINTF_WORD_HEX_FMT, WORD_T_GENERIC_IN(j));	\
481*f0865ec9SKyle Evans 				printf("\n");						\
482*f0865ec9SKyle Evans 			}\
483*f0865ec9SKyle Evans 			if(parameters_types[j] == 's'){\
484*f0865ec9SKyle Evans 				printf("%16s: ", real_modified_string_names); 		\
485*f0865ec9SKyle Evans 				printf("%d", (int)fun_output);				\
486*f0865ec9SKyle Evans 				printf("\n");						\
487*f0865ec9SKyle Evans 				printf("%16s: ", expected_modified_string_names); 	\
488*f0865ec9SKyle Evans 				printf("%d", INT_GENERIC_IN(j));			\
489*f0865ec9SKyle Evans 				printf("\n");						\
490*f0865ec9SKyle Evans 			}\
491*f0865ec9SKyle Evans 		}\
492*f0865ec9SKyle Evans 	}\
493*f0865ec9SKyle Evans } while(0)
494*f0865ec9SKyle Evans 
495*f0865ec9SKyle Evans /* Generic testing framework. Seems ugly but does the job! */
496*f0865ec9SKyle Evans #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, ...) \
497*f0865ec9SKyle Evans int test_##test_name(const char ATTRIBUTE_UNUSED *op, void **params, int test_num);\
498*f0865ec9SKyle Evans int test_##test_name(const char ATTRIBUTE_UNUSED *op, void **params, int test_num){\
499*f0865ec9SKyle Evans 	unsigned int i;\
500*f0865ec9SKyle Evans 	int ret = 0, cmp, mismatch = 0;		\
501*f0865ec9SKyle Evans 	const char *op_string = NULL;\
502*f0865ec9SKyle Evans 	unsigned int n_len ATTRIBUTE_UNUSED = 0;\
503*f0865ec9SKyle Evans 	int fun_out_value = 0;\
504*f0865ec9SKyle Evans 	u8 there_is_output = 0;\
505*f0865ec9SKyle Evans 	unsigned int nn_out_local_cnt = 0, fp_out_local_cnt = 0;\
506*f0865ec9SKyle Evans 	fp_ctx_t fp_ctx_param ATTRIBUTE_UNUSED = NULL;\
507*f0865ec9SKyle Evans 	int fp_ctx_initialized ATTRIBUTE_UNUSED = 0;\
508*f0865ec9SKyle Evans 	\
509*f0865ec9SKyle Evans 	const char parameters_types[] = parameters_types_;\
510*f0865ec9SKyle Evans 	const char parameters_io[] = parameters_io_;\
511*f0865ec9SKyle Evans 	\
512*f0865ec9SKyle Evans 	const char operation[] = #operation_;\
513*f0865ec9SKyle Evans 	\
514*f0865ec9SKyle Evans 	/* Our words used as output of functions */\
515*f0865ec9SKyle Evans 	word_t word_out[MAX_PARAMS] ATTRIBUTE_UNUSED = { 0 };\
516*f0865ec9SKyle Evans 	int int_out[MAX_PARAMS] ATTRIBUTE_UNUSED = { 0 };\
517*f0865ec9SKyle Evans 	\
518*f0865ec9SKyle Evans 	assert(memcmp(operation, op, sizeof(operation)) == 0);\
519*f0865ec9SKyle Evans 	\
520*f0865ec9SKyle Evans 	/* Sanity check: check that the parameters passed from the file are the same as the ones declared in the test */\
521*f0865ec9SKyle Evans 	if(memcmp(global_parameters, parameters_types, LOCAL_MIN(MAX_PARAMS, strlen(parameters_types))) != 0){\
522*f0865ec9SKyle Evans 		printf("Error: parameters %s given in the test file differ from the test expected parameters (%s)\n", parameters_types, global_parameters);\
523*f0865ec9SKyle Evans 		return -1;\
524*f0865ec9SKyle Evans 	}\
525*f0865ec9SKyle Evans 	\
526*f0865ec9SKyle Evans 	PARAMETERS_SANITY_CHECK(test_num, parameters_types, parameters_io);\
527*f0865ec9SKyle Evans 	\
528*f0865ec9SKyle Evans 	/* If we find an fp or nn, assume its length is the common length. */\
529*f0865ec9SKyle Evans 	for(i=0; i<sizeof(parameters_io)-1; i++){\
530*f0865ec9SKyle Evans 		if((parameters_io[i] == 'o') && (parameters_types[i] == 'f')){\
531*f0865ec9SKyle Evans 			n_len = (FP_T_GENERIC_IN(i))->fp_val.wlen;\
532*f0865ec9SKyle Evans 			break;\
533*f0865ec9SKyle Evans 		}\
534*f0865ec9SKyle Evans 		if((parameters_io[i] == 'o') && (parameters_types[i] == 'n')){\
535*f0865ec9SKyle Evans 			n_len = (NN_T_GENERIC_IN(i))->wlen;\
536*f0865ec9SKyle Evans 			break;\
537*f0865ec9SKyle Evans 		}\
538*f0865ec9SKyle Evans 	}\
539*f0865ec9SKyle Evans 	for(i=0; i<sizeof(parameters_io)-1; i++){\
540*f0865ec9SKyle Evans 		if(parameters_types[i] == 'c'){\
541*f0865ec9SKyle Evans 			fp_ctx_param = (FP_CTX_T_GENERIC_IN(i));\
542*f0865ec9SKyle Evans 			fp_ctx_initialized = 1;\
543*f0865ec9SKyle Evans 			break;\
544*f0865ec9SKyle Evans 		}\
545*f0865ec9SKyle Evans 	}\
546*f0865ec9SKyle Evans 	GENERIC_TEST_NN_DECL_INIT##nn_out_num(nn_out, n_len * WORD_BYTES);\
547*f0865ec9SKyle Evans 	assert(fp_out_num == 0 || fp_ctx_initialized != 0);\
548*f0865ec9SKyle Evans 	GENERIC_TEST_FP_DECL_INIT##fp_out_num(fp_out, fp_ctx_param);\
549*f0865ec9SKyle Evans 	if(ret){\
550*f0865ec9SKyle Evans 		goto err;\
551*f0865ec9SKyle Evans 	}\
552*f0865ec9SKyle Evans 	\
553*f0865ec9SKyle Evans 	CHECK_FUN_##fun_output fun_name(__VA_ARGS__);\
554*f0865ec9SKyle Evans 	/* Check generic value return is 0 */\
555*f0865ec9SKyle Evans 	if(there_is_output == 0){\
556*f0865ec9SKyle Evans 		assert(fun_out_value == 0);\
557*f0865ec9SKyle Evans 	}\
558*f0865ec9SKyle Evans 	\
559*f0865ec9SKyle Evans 	/* Check result is what we expect */\
560*f0865ec9SKyle Evans 	FIND_HELPER_IN_DISPATCH_TABLE(operation, op_string);\
561*f0865ec9SKyle Evans 	assert(op_string != NULL);\
562*f0865ec9SKyle Evans 	\
563*f0865ec9SKyle Evans 	for(i=0; i<sizeof(parameters_io)-1; i++){\
564*f0865ec9SKyle Evans 		if(parameters_io[i] == 'o'){\
565*f0865ec9SKyle Evans 			/* We have an input that is an output, check it */\
566*f0865ec9SKyle Evans 			if (parameters_types[i] == 'f') {\
567*f0865ec9SKyle Evans 				ret = fp_cmp(fp_out_ptr[i], FP_T_GENERIC_IN(i), &cmp); \
568*f0865ec9SKyle Evans 				if(ret || cmp){\
569*f0865ec9SKyle Evans 					printf("[-] Test %d (%s): result mismatch\n", test_num, op_string);\
570*f0865ec9SKyle Evans 					/* Print the expected outputs */\
571*f0865ec9SKyle Evans 					PRINT_ALL(parameters_types, parameters_io, params, nn_out_ptr, fp_out_ptr, fun_out_value, there_is_output, parameters_string_names, i);\
572*f0865ec9SKyle Evans 					mismatch = 1;\
573*f0865ec9SKyle Evans 					break;\
574*f0865ec9SKyle Evans 				}\
575*f0865ec9SKyle Evans 				fp_out_local_cnt++;\
576*f0865ec9SKyle Evans 			}\
577*f0865ec9SKyle Evans 			if (parameters_types[i] == 'n') {\
578*f0865ec9SKyle Evans 				ret = nn_cmp(nn_out_ptr[i], NN_T_GENERIC_IN(i), &cmp); \
579*f0865ec9SKyle Evans 				if(ret || cmp){\
580*f0865ec9SKyle Evans 					printf("[-] Test %d (%s): result mismatch\n", test_num, op_string);\
581*f0865ec9SKyle Evans 					/* Print the expected outputs */\
582*f0865ec9SKyle Evans 					PRINT_ALL(parameters_types, parameters_io, params, nn_out_ptr, fp_out_ptr, fun_out_value, there_is_output, parameters_string_names, i);\
583*f0865ec9SKyle Evans 					mismatch = 1;\
584*f0865ec9SKyle Evans 					break;\
585*f0865ec9SKyle Evans 				}\
586*f0865ec9SKyle Evans 				nn_out_local_cnt++;\
587*f0865ec9SKyle Evans 			}\
588*f0865ec9SKyle Evans 			if (parameters_types[i] == 'u') {\
589*f0865ec9SKyle Evans 				if((*(WORD_T_GENERIC_OUT(i))) != WORD_T_GENERIC_IN(i)){\
590*f0865ec9SKyle Evans 					printf("[-] Test %d (%s): result mismatch\n", test_num, op_string);\
591*f0865ec9SKyle Evans 					/* Print the expected outputs */\
592*f0865ec9SKyle Evans 					PRINT_ALL(parameters_types, parameters_io, params, nn_out_ptr, fp_out_ptr, fun_out_value, there_is_output, parameters_string_names, i);\
593*f0865ec9SKyle Evans 					mismatch = 1;\
594*f0865ec9SKyle Evans 					break;\
595*f0865ec9SKyle Evans 				}\
596*f0865ec9SKyle Evans 			}\
597*f0865ec9SKyle Evans 			if (parameters_types[i] == 's') {\
598*f0865ec9SKyle Evans 				if((*(INT_GENERIC_OUT(i))) != INT_GENERIC_IN(i)){\
599*f0865ec9SKyle Evans 					printf("[-] Test %d (%s): result mismatch\n", test_num, op_string);\
600*f0865ec9SKyle Evans 					/* Print the expected outputs */\
601*f0865ec9SKyle Evans 					PRINT_ALL(parameters_types, parameters_io, params, nn_out_ptr, fp_out_ptr, fun_out_value, there_is_output, parameters_string_names, i);\
602*f0865ec9SKyle Evans 					mismatch = 1;\
603*f0865ec9SKyle Evans 					break;\
604*f0865ec9SKyle Evans 				}\
605*f0865ec9SKyle Evans 			}\
606*f0865ec9SKyle Evans 		}\
607*f0865ec9SKyle Evans 		if(parameters_io[i] == 'O'){\
608*f0865ec9SKyle Evans 			/* We have a function output, check it */\
609*f0865ec9SKyle Evans 			if(fun_out_value != INT_GENERIC_IN(i)){\
610*f0865ec9SKyle Evans 				printf("[-] Test %d (%s): result mismatch\n", test_num, op_string);\
611*f0865ec9SKyle Evans 				/* Print the expected outputs */\
612*f0865ec9SKyle Evans 				PRINT_ALL(parameters_types, parameters_io, params, nn_out_ptr, fp_out_ptr, fun_out_value, there_is_output, parameters_string_names, i);\
613*f0865ec9SKyle Evans 				mismatch = 1;\
614*f0865ec9SKyle Evans 				break;\
615*f0865ec9SKyle Evans 			}\
616*f0865ec9SKyle Evans 		}\
617*f0865ec9SKyle Evans 	}\
618*f0865ec9SKyle Evans 	\
619*f0865ec9SKyle Evans 	GENERIC_TEST_nn_uninit##nn_out_num(nn_out);\
620*f0865ec9SKyle Evans 	GENERIC_TEST_FP_CLEAR##fp_out_num(fp_out);\
621*f0865ec9SKyle Evans 	\
622*f0865ec9SKyle Evans 	return !mismatch;\
623*f0865ec9SKyle Evans err:\
624*f0865ec9SKyle Evans 	printf("[-] Error: general error when initializing variables ...\n");\
625*f0865ec9SKyle Evans 	exit(-1);\
626*f0865ec9SKyle Evans }\
627*f0865ec9SKyle Evans ADD_TO_DISPATCH_TABLE(test_##test_name, #operation_, given_string_helper)
628*f0865ec9SKyle Evans 
629*f0865ec9SKyle Evans #define GENERIC_TEST_NN(test_name, operation_, given_string_helper, fun_name, parameters_types_, parameters_io_, parameters_string_names, fun_output, nn_out_num, ...) \
630*f0865ec9SKyle Evans GENERIC_TEST(test_name, operation_, given_string_helper, fun_name, parameters_types_, parameters_io_, parameters_string_names, fun_output, nn_out_num, 0, __VA_ARGS__)
631*f0865ec9SKyle Evans 
632*f0865ec9SKyle Evans #define GENERIC_TEST_FP(test_name, operation_, given_string_helper, fun_name, parameters_types_, parameters_io_, parameters_string_names, fun_output, nn_out_num, ...) \
633*f0865ec9SKyle Evans GENERIC_TEST(test_name, operation_, given_string_helper, fun_name, parameters_types_, parameters_io_, parameters_string_names, fun_output, nn_out_num, __VA_ARGS__)
634*f0865ec9SKyle Evans 
635*f0865ec9SKyle Evans 
636*f0865ec9SKyle Evans /* Global variable to keep track of parameters */
637*f0865ec9SKyle Evans static char global_parameters[MAX_PARAMS];
638*f0865ec9SKyle Evans 
639*f0865ec9SKyle Evans /*********** NN layer tests ************************************************/
640*f0865ec9SKyle Evans /* Testing shifts and rotates */
641*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_lshift_fixedlen, NN_SHIFT_LEFT_FIXEDLEN, "(fixed)<<", nn_lshift_fixedlen, "nnu", "oii",
642*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(3, "output", "input", "fixed lshift"), NO_RET, 1,
643*f0865ec9SKyle Evans 		NN_T_GENERIC_OUT(0), NN_T_GENERIC_IN(1), (bitcnt_t)UINT_GENERIC_IN(2))
644*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_rshift_fixedlen, NN_SHIFT_RIGHT_FIXEDLEN, "(fixed)>>", nn_rshift_fixedlen, "nnu", "oii",
645*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(3, "output", "input", "fixed rshift"), NO_RET, 1,
646*f0865ec9SKyle Evans 		NN_T_GENERIC_OUT(0), NN_T_GENERIC_IN(1), (bitcnt_t)UINT_GENERIC_IN(2))
647*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_lshift, NN_SHIFT_LEFT, "<<", nn_lshift, "nnu", "oii",
648*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(3, "output", "input", "lshift"), NO_RET, 1,
649*f0865ec9SKyle Evans 		NN_T_GENERIC_OUT(0), NN_T_GENERIC_IN(1), (bitcnt_t)UINT_GENERIC_IN(2))
650*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_rshift, NN_SHIFT_RIGHT, ">>", nn_rshift, "nnu", "oii",
651*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(3, "output", "input", "rshift"), NO_RET, 1,
652*f0865ec9SKyle Evans 		NN_T_GENERIC_OUT(0), NN_T_GENERIC_IN(1), (bitcnt_t)UINT_GENERIC_IN(2))
653*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_lrot, NN_ROTATE_LEFT, "lrot", nn_lrot, "nnuu", "oiii",
654*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(4, "output", "input", "lrot", "bitlen_base"), NO_RET, 1,
655*f0865ec9SKyle Evans 		NN_T_GENERIC_OUT(0), NN_T_GENERIC_IN(1), (bitcnt_t)UINT_GENERIC_IN(2), (bitcnt_t)UINT_GENERIC_IN(3))
656*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_rrot, NN_ROTATE_RIGHT, "rrot", nn_rrot, "nnuu", "oiii",
657*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(4, "output", "input", "rrot", "bitlen_base"), NO_RET, 1,
658*f0865ec9SKyle Evans 		NN_T_GENERIC_OUT(0), NN_T_GENERIC_IN(1), (bitcnt_t)UINT_GENERIC_IN(2), (bitcnt_t)UINT_GENERIC_IN(3))
659*f0865ec9SKyle Evans 
660*f0865ec9SKyle Evans 
661*f0865ec9SKyle Evans /* Testing xor, or, and, not */
662*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_xor, NN_XOR, "^", nn_xor, "nnn", "iio",
663*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(3, "input1", "input2", "output"), NO_RET, 3,
664*f0865ec9SKyle Evans 		NN_T_GENERIC_OUT(2), NN_T_GENERIC_IN(0), NN_T_GENERIC_IN(1))
665*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_or, NN_OR, "|", nn_or, "nnn", "iio",
666*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(3, "input1", "input2", "output"), NO_RET, 3,
667*f0865ec9SKyle Evans 		NN_T_GENERIC_OUT(2), NN_T_GENERIC_IN(0), NN_T_GENERIC_IN(1))
668*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_and, NN_AND, "&", nn_and, "nnn", "iio",
669*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(3, "input1", "input2", "output"), NO_RET, 3,
670*f0865ec9SKyle Evans 		NN_T_GENERIC_OUT(2), NN_T_GENERIC_IN(0), NN_T_GENERIC_IN(1))
671*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_not, NN_NOT, "~", nn_not, "nn", "io",
672*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(2, "input", "output"), NO_RET, 2,
673*f0865ec9SKyle Evans 		NN_T_GENERIC_OUT(1), NN_T_GENERIC_IN(0))
674*f0865ec9SKyle Evans 
675*f0865ec9SKyle Evans /* Testing add and sub */
676*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_add, NN_ADD, "+", nn_add, "nnn", "iio",
677*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(3, "input1", "input2", "output"),
678*f0865ec9SKyle Evans 		NO_RET, 3, NN_T_GENERIC_OUT(2), NN_T_GENERIC_IN(0),
679*f0865ec9SKyle Evans 		NN_T_GENERIC_IN(1))
680*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_sub, NN_SUB, "-", nn_sub, "nnn", "iio",
681*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(3, "input1", "input2", "output"),
682*f0865ec9SKyle Evans 		NO_RET, 3, NN_T_GENERIC_OUT(2), NN_T_GENERIC_IN(0),
683*f0865ec9SKyle Evans 		NN_T_GENERIC_IN(1))
684*f0865ec9SKyle Evans 
685*f0865ec9SKyle Evans /* Testing inc and dec */
686*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_inc, NN_INC, "++", nn_inc, "nn", "io",
687*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(2, "input", "output"), NO_RET, 2,
688*f0865ec9SKyle Evans 		NN_T_GENERIC_OUT(1), NN_T_GENERIC_IN(0))
689*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_dec, NN_DEC, "--", nn_dec, "nn", "io",
690*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(2, "input", "output"), NO_RET, 2,
691*f0865ec9SKyle Evans 		NN_T_GENERIC_OUT(1), NN_T_GENERIC_IN(0))
692*f0865ec9SKyle Evans 
693*f0865ec9SKyle Evans /* Testing modular add, sub, inc, dec, mul, exp (inputs are supposed < p except for exp) */
694*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_mod_add, NN_MOD_ADD, "+%", nn_mod_add, "nnnn", "iiio",
695*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(4, "input1", "input2", "modulo", "output"),
696*f0865ec9SKyle Evans 		NO_RET, 4, NN_T_GENERIC_OUT(3), NN_T_GENERIC_IN(0),
697*f0865ec9SKyle Evans 		NN_T_GENERIC_IN(1), NN_T_GENERIC_IN(2))
698*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_mod_sub, NN_MOD_SUB, "-%", nn_mod_sub, "nnnn", "iiio",
699*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(4, "input1", "input2", "modulo", "output"),
700*f0865ec9SKyle Evans 		NO_RET, 4, NN_T_GENERIC_OUT(3), NN_T_GENERIC_IN(0),
701*f0865ec9SKyle Evans 		NN_T_GENERIC_IN(1), NN_T_GENERIC_IN(2))
702*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_mod_inc, NN_MOD_INC, "++%", nn_mod_inc, "nnn", "iio",
703*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(3, "input1", "modulo", "output"),
704*f0865ec9SKyle Evans 		NO_RET, 3, NN_T_GENERIC_OUT(2), NN_T_GENERIC_IN(0),
705*f0865ec9SKyle Evans 		NN_T_GENERIC_IN(1))
706*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_mod_dec, NN_MOD_DEC, "--%", nn_mod_dec, "nnn", "iio",
707*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(3, "input1", "modulo", "output"),
708*f0865ec9SKyle Evans 		NO_RET, 3, NN_T_GENERIC_OUT(2), NN_T_GENERIC_IN(0),
709*f0865ec9SKyle Evans 		NN_T_GENERIC_IN(1))
710*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_mod_mul, NN_MOD_MUL, "*%", nn_mod_mul, "nnnn", "iiio",
711*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(4, "input1", "input2", "modulo", "output"),
712*f0865ec9SKyle Evans 		NO_RET, 4, NN_T_GENERIC_OUT(3), NN_T_GENERIC_IN(0),
713*f0865ec9SKyle Evans 		NN_T_GENERIC_IN(1), NN_T_GENERIC_IN(2))
714*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_mod_pow, NN_MOD_POW, "exp%", nn_mod_pow, "nnnn", "iiio",
715*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(4, "base", "exp", "modulo", "output"),
716*f0865ec9SKyle Evans 		NO_RET, 4, NN_T_GENERIC_OUT(3), NN_T_GENERIC_IN(0),
717*f0865ec9SKyle Evans 		NN_T_GENERIC_IN(1), NN_T_GENERIC_IN(2))
718*f0865ec9SKyle Evans 
719*f0865ec9SKyle Evans 
720*f0865ec9SKyle Evans /* Testing mul */
721*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_mul, NN_MUL, "*", nn_mul, "nnn", "oii",
722*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(3, "output1", "input1", "input2"),
723*f0865ec9SKyle Evans 		NO_RET, 1, NN_T_GENERIC_OUT(0), NN_T_GENERIC_IN(1),
724*f0865ec9SKyle Evans 		NN_T_GENERIC_IN(2))
725*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_sqr, NN_SQR, "(^2)", nn_sqr, "nn", "oi",
726*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(2, "output1", "input1"),
727*f0865ec9SKyle Evans 		NO_RET, 1, NN_T_GENERIC_OUT(0), NN_T_GENERIC_IN(1))
728*f0865ec9SKyle Evans 
729*f0865ec9SKyle Evans /* Testing division */
730*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_divrem, NN_DIVREM, "/", nn_divrem, "nnnn", "ooii",
731*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(4, "quotient", "remainder", "input1", "input2"),
732*f0865ec9SKyle Evans 		NO_RET, 2, NN_T_GENERIC_OUT(0), NN_T_GENERIC_OUT(1),
733*f0865ec9SKyle Evans 		NN_T_GENERIC_IN(2), NN_T_GENERIC_IN(3))
734*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_xgcd, NN_XGCD, "xgcd", nn_xgcd, "nnnnns", "oooiio",
735*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(6, "xgcd", "u", "v", "input1", "input2", "sign"),
736*f0865ec9SKyle Evans 		NO_RET, 3, NN_T_GENERIC_OUT(0), NN_T_GENERIC_OUT(1), NN_T_GENERIC_OUT(2),
737*f0865ec9SKyle Evans 		NN_T_GENERIC_IN(3), NN_T_GENERIC_IN(4), INT_GENERIC_OUT(5))
738*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_gcd, NN_GCD, "gcd", nn_gcd, "nnns", "oiio",
739*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(4, "gcd", "input1", "input2", "sign"),
740*f0865ec9SKyle Evans 		NO_RET, 1, NN_T_GENERIC_OUT(0),
741*f0865ec9SKyle Evans 		NN_T_GENERIC_IN(1), NN_T_GENERIC_IN(2), INT_GENERIC_OUT(3))
742*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_mod, NN_MOD, "%", nn_mod, "nnn", "oii",
743*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(3, "output", "input1", "input2"),
744*f0865ec9SKyle Evans 		NO_RET, 1, NN_T_GENERIC_OUT(0),
745*f0865ec9SKyle Evans 		NN_T_GENERIC_IN(1), NN_T_GENERIC_IN(2))
746*f0865ec9SKyle Evans 
747*f0865ec9SKyle Evans /* Testing modular inversion */
748*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_modinv, NN_MODINV, "(^-1%)", nn_modinv, "nnns", "oiiO",
749*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(4, "output", "input1", "input2", "ret"),
750*f0865ec9SKyle Evans 		RET, 1, NN_T_GENERIC_OUT(0),
751*f0865ec9SKyle Evans 		NN_T_GENERIC_IN(1), NN_T_GENERIC_IN(2))
752*f0865ec9SKyle Evans 
753*f0865ec9SKyle Evans /* Testing modular inversion modulo a 2**n */
754*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_modinv_2exp, NN_MODINV_2EXP, "(^-1%)(2exp)", nn_modinv_2exp, "nnus", "oiio",
755*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(4, "output", "input1", "input2", "isodd"),
756*f0865ec9SKyle Evans 		NO_RET, 1, NN_T_GENERIC_OUT(0), NN_T_GENERIC_IN(1),
757*f0865ec9SKyle Evans 			UINT_GENERIC_IN(2), INT_GENERIC_OUT(3))
758*f0865ec9SKyle Evans 
759*f0865ec9SKyle Evans /* Check Montgomery multiplication redcify primitives */
760*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_compute_redc1_coefs, NN_COEF_REDC1, "coef_redc1", nn_compute_redc1_coefs, "nnnu", "ooio",
761*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(4, "r", "r_square", "p", "mpinv"),
762*f0865ec9SKyle Evans 		NO_RET, 3, NN_T_GENERIC_OUT(0), NN_T_GENERIC_OUT(1), NN_T_GENERIC_IN(2), WORD_T_GENERIC_OUT(3))
763*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_compute_div_coefs, NN_COEF_DIV, "coef_div", nn_compute_div_coefs, "nuun", "oooi",
764*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(4, "p_normalized", "p_shift", "p_reciprocal", "p"),
765*f0865ec9SKyle Evans 		NO_RET, 3, NN_T_GENERIC_OUT(0), WORD_T_GENERIC_OUT(1), WORD_T_GENERIC_OUT(2), NN_T_GENERIC_IN(3))
766*f0865ec9SKyle Evans 	GENERIC_TEST_NN(nn_mul_redc1, NN_MUL_REDC1, "*_redc1", nn_mul_redc1, "nnnnu", "oiiii",
767*f0865ec9SKyle Evans 		SET_PARAMETER_PRETTY_NAME(5, "output", "input1", "input2", "p", "mpinv"),
768*f0865ec9SKyle Evans 		NO_RET, 1, NN_T_GENERIC_OUT(0), NN_T_GENERIC_IN(1), NN_T_GENERIC_IN(2),
769*f0865ec9SKyle Evans 		NN_T_GENERIC_IN(3), WORD_T_GENERIC_IN(4))
770*f0865ec9SKyle Evans 
771*f0865ec9SKyle Evans 
772*f0865ec9SKyle Evans 
773*f0865ec9SKyle Evans /*********** Fp layer tests ************************************************/
774*f0865ec9SKyle Evans /* Testing addition in F_p */
775*f0865ec9SKyle Evans 	GENERIC_TEST_FP(fp_add, FP_ADD, "+", fp_add, "cfff", "ioii",
776*f0865ec9SKyle Evans 	     SET_PARAMETER_PRETTY_NAME(4, "p", "sum", "input1", "input2"),
777*f0865ec9SKyle Evans 	     NO_RET, 0, 2,
778*f0865ec9SKyle Evans 	     FP_T_GENERIC_OUT(1), FP_T_GENERIC_IN(2), FP_T_GENERIC_IN(3))
779*f0865ec9SKyle Evans 
780*f0865ec9SKyle Evans /* Testing subtraction in F_p */
781*f0865ec9SKyle Evans 	GENERIC_TEST_FP(fp_sub, FP_SUB, "-", fp_sub, "cfff", "ioii",
782*f0865ec9SKyle Evans 	     SET_PARAMETER_PRETTY_NAME(4, "p", "diff", "input1", "input2"),
783*f0865ec9SKyle Evans 	     NO_RET, 0, 2,
784*f0865ec9SKyle Evans 	     FP_T_GENERIC_OUT(1), FP_T_GENERIC_IN(2), FP_T_GENERIC_IN(3))
785*f0865ec9SKyle Evans 
786*f0865ec9SKyle Evans /* Testing multiplication in F_p */
787*f0865ec9SKyle Evans 	GENERIC_TEST_FP(fp_mul, FP_MUL, "*", fp_mul, "cfff", "ioii",
788*f0865ec9SKyle Evans 	     SET_PARAMETER_PRETTY_NAME(4, "p", "prod", "input1", "input2"),
789*f0865ec9SKyle Evans 	     NO_RET, 0, 2,
790*f0865ec9SKyle Evans 	     FP_T_GENERIC_OUT(1), FP_T_GENERIC_IN(2), FP_T_GENERIC_IN(3))
791*f0865ec9SKyle Evans 	GENERIC_TEST_FP(fp_sqr, FP_SQR, "(^2)", fp_sqr, "cff", "ioi",
792*f0865ec9SKyle Evans 	     SET_PARAMETER_PRETTY_NAME(3, "p", "prod", "input1"),
793*f0865ec9SKyle Evans 	     NO_RET, 0, 2,
794*f0865ec9SKyle Evans 	     FP_T_GENERIC_OUT(1), FP_T_GENERIC_IN(2))
795*f0865ec9SKyle Evans 
796*f0865ec9SKyle Evans /* Testing division in F_p */
797*f0865ec9SKyle Evans 	GENERIC_TEST_FP(fp_div, FP_DIV, "/", fp_div, "cfff", "ioii",
798*f0865ec9SKyle Evans 	     SET_PARAMETER_PRETTY_NAME(4, "p", "quo", "input1", "input2"),
799*f0865ec9SKyle Evans 	     NO_RET, 0, 2,
800*f0865ec9SKyle Evans 	     FP_T_GENERIC_OUT(1), FP_T_GENERIC_IN(2), FP_T_GENERIC_IN(3))
801*f0865ec9SKyle Evans 
802*f0865ec9SKyle Evans /* Testing Montgomery multiplication in F_p */
803*f0865ec9SKyle Evans 	GENERIC_TEST_FP(fp_mul_monty, FP_MUL_MONTY, "*_monty", fp_mul_monty, "cfff", "ioii",
804*f0865ec9SKyle Evans 	     SET_PARAMETER_PRETTY_NAME(4, "p", "prod", "input1", "input2"),
805*f0865ec9SKyle Evans 	     NO_RET, 0, 2,
806*f0865ec9SKyle Evans 	     FP_T_GENERIC_OUT(1), FP_T_GENERIC_IN(2), FP_T_GENERIC_IN(3))
807*f0865ec9SKyle Evans 	GENERIC_TEST_FP(fp_sqr_monty, FP_SQR_MONTY, "(^2)_monty", fp_sqr_monty, "cff", "ioi",
808*f0865ec9SKyle Evans 	     SET_PARAMETER_PRETTY_NAME(3, "p", "prod", "input1"),
809*f0865ec9SKyle Evans 	     NO_RET, 0, 2,
810*f0865ec9SKyle Evans 	     FP_T_GENERIC_OUT(1), FP_T_GENERIC_IN(2))
811*f0865ec9SKyle Evans 
812*f0865ec9SKyle Evans /* Testing exponentiation in F_p */
813*f0865ec9SKyle Evans 	GENERIC_TEST_FP(fp_pow, FP_POW, "exp", fp_pow, "cffn", "ioii",
814*f0865ec9SKyle Evans 	     SET_PARAMETER_PRETTY_NAME(4, "p", "pow", "input", "exp"),
815*f0865ec9SKyle Evans 	     NO_RET, 0, 2,
816*f0865ec9SKyle Evans 	     FP_T_GENERIC_OUT(1), FP_T_GENERIC_IN(2), NN_T_GENERIC_IN(3))
817*f0865ec9SKyle Evans 
818*f0865ec9SKyle Evans /* Testing square residue in F_p */
819*f0865ec9SKyle Evans 	GENERIC_TEST_FP(fp_sqrt, FP_SQRT, "sqrt", fp_sqrt, "cfffs", "iooiO",
820*f0865ec9SKyle Evans 	     SET_PARAMETER_PRETTY_NAME(4, "sqrt1", "sqrt2", "p", "ret"),
821*f0865ec9SKyle Evans 	     RET, 0, 3,
822*f0865ec9SKyle Evans 	     FP_T_GENERIC_OUT(1), FP_T_GENERIC_OUT(2), FP_T_GENERIC_IN(3))
823*f0865ec9SKyle Evans 
824*f0865ec9SKyle Evans /*****************************************************************/
825*f0865ec9SKyle Evans 
826*f0865ec9SKyle Evans /*
827*f0865ec9SKyle Evans  * Read data on given fd until first newline character and put it in buf
828*f0865ec9SKyle Evans  * followed by a null character. buffer size is passed via buflen. The
829*f0865ec9SKyle Evans  * length of read line is returned to the caller in buflen on success
830*f0865ec9SKyle Evans  * (not including null character terminating read string).
831*f0865ec9SKyle Evans  *
832*f0865ec9SKyle Evans  *  0 is returned on success.
833*f0865ec9SKyle Evans  * -1 is returned on end of file.
834*f0865ec9SKyle Evans  * -2 is returned on error (buffer not sufficient, etc)
835*f0865ec9SKyle Evans  */
836*f0865ec9SKyle Evans int read_string(int fd, char *buf, unsigned int *buflen);
837*f0865ec9SKyle Evans int read_string(int fd, char *buf, unsigned int *buflen)
838*f0865ec9SKyle Evans {
839*f0865ec9SKyle Evans 	unsigned int pos = 0, len;
840*f0865ec9SKyle Evans 	int ret = -1;
841*f0865ec9SKyle Evans 	char c;
842*f0865ec9SKyle Evans 
843*f0865ec9SKyle Evans 	MUST_HAVE((buf != NULL) && (buflen != NULL), ret, err);
844*f0865ec9SKyle Evans 
845*f0865ec9SKyle Evans 	len = *buflen;
846*f0865ec9SKyle Evans 
847*f0865ec9SKyle Evans 	if (len < 2) {
848*f0865ec9SKyle Evans 		ret = -2;
849*f0865ec9SKyle Evans 		goto err;
850*f0865ec9SKyle Evans 	}
851*f0865ec9SKyle Evans 
852*f0865ec9SKyle Evans 	len -= 1;		/* keep some space to terminate the string */
853*f0865ec9SKyle Evans 
854*f0865ec9SKyle Evans 	while ((len > 0) && ((ret = read(fd, &c, 1)) != 0) && (c != '\n')) {
855*f0865ec9SKyle Evans 		buf[pos++] = c;
856*f0865ec9SKyle Evans 		len -= 1;
857*f0865ec9SKyle Evans 	}
858*f0865ec9SKyle Evans 
859*f0865ec9SKyle Evans 	if (len == 0) {
860*f0865ec9SKyle Evans 		ret = -2;
861*f0865ec9SKyle Evans 		goto err;
862*f0865ec9SKyle Evans 	}
863*f0865ec9SKyle Evans 
864*f0865ec9SKyle Evans 	if (!ret) {
865*f0865ec9SKyle Evans 		ret = -1;
866*f0865ec9SKyle Evans 		goto err;
867*f0865ec9SKyle Evans 	}
868*f0865ec9SKyle Evans 
869*f0865ec9SKyle Evans 	/* Terminate the string */
870*f0865ec9SKyle Evans 	buf[pos] = 0;
871*f0865ec9SKyle Evans 	*buflen = pos;
872*f0865ec9SKyle Evans 	ret = 0;
873*f0865ec9SKyle Evans 
874*f0865ec9SKyle Evans err:
875*f0865ec9SKyle Evans 	return ret;
876*f0865ec9SKyle Evans }
877*f0865ec9SKyle Evans 
878*f0865ec9SKyle Evans 
879*f0865ec9SKyle Evans /*
880*f0865ec9SKyle Evans  * Parse a test file and perform the tests it provides, one
881*f0865ec9SKyle Evans  * by one, in order.
882*f0865ec9SKyle Evans  */
883*f0865ec9SKyle Evans int main(int argc, char *argv[])
884*f0865ec9SKyle Evans {
885*f0865ec9SKyle Evans 	nn fp_ctx_modulus, fp_ctx_r, fp_ctx_r_square, fp_ctx_mpinv;
886*f0865ec9SKyle Evans 	nn fp_ctx_pshift, fp_ctx_pnorm, fp_ctx_prec;
887*f0865ec9SKyle Evans 	fp_ctx fp_ctx_param;
888*f0865ec9SKyle Evans 	int ret, cmp;
889*f0865ec9SKyle Evans 	u64 u_params[MAX_PARAMS];
890*f0865ec9SKyle Evans 	void *params[MAX_PARAMS];
891*f0865ec9SKyle Evans 	unsigned int ibuflen = BIT_LEN_WORDS(NN_MAX_BIT_LEN) * WORD_BYTES * 10;
892*f0865ec9SKyle Evans 	unsigned long int test_num, line = 0, oktests = 0;
893*f0865ec9SKyle Evans 	int test_ret;
894*f0865ec9SKyle Evans 	unsigned int len = ibuflen;
895*f0865ec9SKyle Evans 	int nrecs;
896*f0865ec9SKyle Evans 	int fd = 0, nn_local_cnt = 0, fp_local_cnt = 0, fp_ctx_local_cnt = 0;
897*f0865ec9SKyle Evans 	unsigned int nn_len;
898*f0865ec9SKyle Evans 	char op[1024];
899*f0865ec9SKyle Evans 	char *ibuf = NULL, *rec = NULL;
900*f0865ec9SKyle Evans 	nn *tmp;
901*f0865ec9SKyle Evans 	fp *fp_tmp;
902*f0865ec9SKyle Evans 	int (*curr_test_fun) (const char *, void **, int);
903*f0865ec9SKyle Evans 	unsigned long p_tmp;
904*f0865ec9SKyle Evans 
905*f0865ec9SKyle Evans 	ret = nn_init(&fp_ctx_modulus, 0);
906*f0865ec9SKyle Evans 	ret |= nn_init(&fp_ctx_r, 0);
907*f0865ec9SKyle Evans 	ret |= nn_init(&fp_ctx_r_square, 0);
908*f0865ec9SKyle Evans 	ret |= nn_init(&fp_ctx_mpinv, 0);
909*f0865ec9SKyle Evans 	ret |= nn_init(&fp_ctx_pshift, 0);
910*f0865ec9SKyle Evans 	ret |= nn_init(&fp_ctx_pnorm, 0);
911*f0865ec9SKyle Evans 	ret |= nn_init(&fp_ctx_prec, 0);
912*f0865ec9SKyle Evans 
913*f0865ec9SKyle Evans 	/* First "fake" context initialization with junk value
914*f0865ec9SKyle Evans 	 * one as prime number
915*f0865ec9SKyle Evans 	 */
916*f0865ec9SKyle Evans 	ret |= nn_one(&fp_ctx_modulus);
917*f0865ec9SKyle Evans 	ret |= fp_ctx_init_from_p(&fp_ctx_param, &fp_ctx_modulus);
918*f0865ec9SKyle Evans 	GENERIC_TEST_FP_DECL_INIT_MAX(fp_params, &fp_ctx_param)
919*f0865ec9SKyle Evans 	GENERIC_TEST_NN_DECL_INIT_MAX(nn_params, 0)
920*f0865ec9SKyle Evans 
921*f0865ec9SKyle Evans 	if(ret){
922*f0865ec9SKyle Evans 		goto err;
923*f0865ec9SKyle Evans 	}
924*f0865ec9SKyle Evans 
925*f0865ec9SKyle Evans #ifdef WITH_ASSERT_BACKTRACE
926*f0865ec9SKyle Evans 	memset(backtrace_buffer, 0, sizeof(backtrace_buffer) - 1);
927*f0865ec9SKyle Evans 	if (signal(SIGINT, assert_signal_handler) == SIG_ERR) {
928*f0865ec9SKyle Evans 		printf("Error: can't catch SIGINT signal ...\n");
929*f0865ec9SKyle Evans 		return -1;
930*f0865ec9SKyle Evans 	}
931*f0865ec9SKyle Evans #endif
932*f0865ec9SKyle Evans 
933*f0865ec9SKyle Evans 	if (argc > 2) {
934*f0865ec9SKyle Evans 		printf("Usage: %s [test_file]\n", argv[0]);
935*f0865ec9SKyle Evans 		printf("       If no test_file provided, stdin is taken\n");
936*f0865ec9SKyle Evans 		return -1;
937*f0865ec9SKyle Evans 	}
938*f0865ec9SKyle Evans 
939*f0865ec9SKyle Evans 	/* Special case where we want to dump information */
940*f0865ec9SKyle Evans 	if (argc == 2) {
941*f0865ec9SKyle Evans 		if (memcmp(argv[1], "-info", sizeof("-info")) == 0){
942*f0865ec9SKyle Evans 			printf("%d %d\n", WORDSIZE, NN_MAX_BASE);
943*f0865ec9SKyle Evans 			return 0;
944*f0865ec9SKyle Evans 		}
945*f0865ec9SKyle Evans 	}
946*f0865ec9SKyle Evans 
947*f0865ec9SKyle Evans 	ibuf = (char*)malloc(ibuflen);
948*f0865ec9SKyle Evans 	if (!ibuf) {
949*f0865ec9SKyle Evans 		return -1;
950*f0865ec9SKyle Evans 	}
951*f0865ec9SKyle Evans 	memset(ibuf, 0, ibuflen);
952*f0865ec9SKyle Evans 
953*f0865ec9SKyle Evans 	if(argc == 2){
954*f0865ec9SKyle Evans 		fd = open(argv[1], O_RDONLY);
955*f0865ec9SKyle Evans 	}
956*f0865ec9SKyle Evans 	else{
957*f0865ec9SKyle Evans 		fd = STDIN_FILENO;
958*f0865ec9SKyle Evans 	}
959*f0865ec9SKyle Evans 	while (read_string(fd, ibuf, &len) == 0) {
960*f0865ec9SKyle Evans 		char *t, *s = ibuf;
961*f0865ec9SKyle Evans 		int i;
962*f0865ec9SKyle Evans 
963*f0865ec9SKyle Evans 		/* Find end of first record (the test number) */
964*f0865ec9SKyle Evans 		t = strchr(s, ' ');
965*f0865ec9SKyle Evans 		if (t == NULL) {
966*f0865ec9SKyle Evans 			printf("\nLine %lu: unable to find record #1\n", line);
967*f0865ec9SKyle Evans 			return -1;
968*f0865ec9SKyle Evans 		}
969*f0865ec9SKyle Evans 		*t = 0;		/* mark end of record */
970*f0865ec9SKyle Evans 		test_num = strtoul(s, NULL, 10);
971*f0865ec9SKyle Evans 		assert(line == test_num);
972*f0865ec9SKyle Evans 		s = t + 1;	/* jump to beginning of next record */
973*f0865ec9SKyle Evans 
974*f0865ec9SKyle Evans 		/* Find end of second record (operation type) */
975*f0865ec9SKyle Evans 		t = strchr(s, ' ');
976*f0865ec9SKyle Evans 		if (t == NULL) {
977*f0865ec9SKyle Evans 			printf("\nLine %lu: unable to find record #2\n", line);
978*f0865ec9SKyle Evans 			return -1;
979*f0865ec9SKyle Evans 		}
980*f0865ec9SKyle Evans 		*t = 0;		/* mark end of record */
981*f0865ec9SKyle Evans 		strncpy(op, s, sizeof(op) - 1);	/* Copy opcode */
982*f0865ec9SKyle Evans 		s = t + 1;	/* jump to beginning of next record */
983*f0865ec9SKyle Evans 
984*f0865ec9SKyle Evans 		/* Pretty print the evolution of our tests */
985*f0865ec9SKyle Evans 		if((line % 1000 == 0) && (line != 0)){
986*f0865ec9SKyle Evans 			printf("\r%*s", 40, "");
987*f0865ec9SKyle Evans 			printf("\rTest %lu on the go [%s]", line, op);
988*f0865ec9SKyle Evans 			fflush(stdout);
989*f0865ec9SKyle Evans 		}
990*f0865ec9SKyle Evans 
991*f0865ec9SKyle Evans 		/* Find end of third record (str of types for next records) */
992*f0865ec9SKyle Evans 		t = strchr(s, ' ');
993*f0865ec9SKyle Evans 		if (t == NULL) {
994*f0865ec9SKyle Evans 			printf("\nLine %lu: unable to find record #3\n", line);
995*f0865ec9SKyle Evans 			return -1;
996*f0865ec9SKyle Evans 		}
997*f0865ec9SKyle Evans 		*t = 0;		/* mark end of record */
998*f0865ec9SKyle Evans 		nrecs = (int)(t - s);
999*f0865ec9SKyle Evans 
1000*f0865ec9SKyle Evans 		rec = t + 1;
1001*f0865ec9SKyle Evans 		ADD_TO_BACKTRACE("--------------\n");
1002*f0865ec9SKyle Evans 		for (i = 0; i < nrecs; i++) {
1003*f0865ec9SKyle Evans 			/* Find end of record */
1004*f0865ec9SKyle Evans 			t = strchr(rec, ' ');
1005*f0865ec9SKyle Evans 			if (t == NULL) {
1006*f0865ec9SKyle Evans 				t = ibuf + len;
1007*f0865ec9SKyle Evans 			}
1008*f0865ec9SKyle Evans 			*t = 0;
1009*f0865ec9SKyle Evans 			switch (s[i]) {
1010*f0865ec9SKyle Evans 			case 'c':	/* fp_ctx */
1011*f0865ec9SKyle Evans 				if (fp_ctx_local_cnt > 0) {
1012*f0865ec9SKyle Evans 					printf("\nLine %lu: Only one fp_ctx allowed\n", line);
1013*f0865ec9SKyle Evans 					ret = -1;
1014*f0865ec9SKyle Evans 					goto err;
1015*f0865ec9SKyle Evans 				}
1016*f0865ec9SKyle Evans 				/*
1017*f0865ec9SKyle Evans 				 * We expect a 3 nn of the same size (p, r, r^2)
1018*f0865ec9SKyle Evans 				 * followed by a single word providing mpinv
1019*f0865ec9SKyle Evans 				 * and an additional nn and two words.
1020*f0865ec9SKyle Evans 				 */
1021*f0865ec9SKyle Evans 				assert(((t - rec) % 2) == 0);
1022*f0865ec9SKyle Evans 				nn_len = (unsigned int)(t - rec -
1023*f0865ec9SKyle Evans 							3 * (WORD_BYTES * 2)) /
1024*f0865ec9SKyle Evans 					(2 * 4);
1025*f0865ec9SKyle Evans 				assert((nn_len % WORD_BYTES) == 0);
1026*f0865ec9SKyle Evans 				fp_ctx_local_cnt++;
1027*f0865ec9SKyle Evans 				tmp = &fp_ctx_modulus;
1028*f0865ec9SKyle Evans 				ret = nn_set_wlen(tmp, (u8)(nn_len / WORD_BYTES)); EG(ret, err);
1029*f0865ec9SKyle Evans 				ret = nn_import_from_hexbuf(tmp, rec, 2 * nn_len); EG(ret, err);
1030*f0865ec9SKyle Evans 
1031*f0865ec9SKyle Evans 				/* Initialize fp context from the prime modulus */
1032*f0865ec9SKyle Evans 				ret = fp_ctx_init_from_p(&fp_ctx_param, &fp_ctx_modulus); EG(ret, err);
1033*f0865ec9SKyle Evans 				/* Now get the other Fp context values and check that
1034*f0865ec9SKyle Evans 				 * everything is OK
1035*f0865ec9SKyle Evans 				 */
1036*f0865ec9SKyle Evans 				tmp = &fp_ctx_r;
1037*f0865ec9SKyle Evans 				ret = nn_set_wlen(tmp, (u8)(nn_len / WORD_BYTES)); EG(ret, err);
1038*f0865ec9SKyle Evans 				ret = nn_import_from_hexbuf(tmp, rec + (2 * nn_len),
1039*f0865ec9SKyle Evans 						      2 * nn_len); EG(ret, err);
1040*f0865ec9SKyle Evans 
1041*f0865ec9SKyle Evans 				/* Compare r */
1042*f0865ec9SKyle Evans 				ret = nn_cmp(&fp_ctx_r, &(fp_ctx_param.r), &cmp);
1043*f0865ec9SKyle Evans 				if(ret || cmp){
1044*f0865ec9SKyle Evans 					printf("\nLine %lu: Fp context import failed\n", line);
1045*f0865ec9SKyle Evans 					nn_print("Imported r from file   =", &fp_ctx_r);
1046*f0865ec9SKyle Evans 					nn_print("Computed r from modulus=", &(fp_ctx_param.r));
1047*f0865ec9SKyle Evans 					ret = -1;
1048*f0865ec9SKyle Evans 					goto err;
1049*f0865ec9SKyle Evans 				}
1050*f0865ec9SKyle Evans 				tmp = &fp_ctx_r_square;
1051*f0865ec9SKyle Evans 				ret = nn_set_wlen(tmp, (u8)(nn_len / WORD_BYTES)); EG(ret, err);
1052*f0865ec9SKyle Evans 				ret = nn_import_from_hexbuf(tmp, rec + (4 * nn_len),
1053*f0865ec9SKyle Evans 						      2 * nn_len); EG(ret, err);
1054*f0865ec9SKyle Evans 
1055*f0865ec9SKyle Evans 				/* Compare r_square */
1056*f0865ec9SKyle Evans 				ret = nn_cmp(&fp_ctx_r_square, &(fp_ctx_param.r_square), &cmp);
1057*f0865ec9SKyle Evans 				if(ret || cmp){
1058*f0865ec9SKyle Evans 					printf("\nLine %lu: Fp context import failed\n", line);
1059*f0865ec9SKyle Evans 					nn_print("Imported r_square from file   =", &fp_ctx_r_square);
1060*f0865ec9SKyle Evans 					nn_print("Computed r_square from modulus=", &(fp_ctx_param.r_square));
1061*f0865ec9SKyle Evans 					ret = -1;
1062*f0865ec9SKyle Evans 					goto err;
1063*f0865ec9SKyle Evans 				}
1064*f0865ec9SKyle Evans 				tmp = &fp_ctx_mpinv;
1065*f0865ec9SKyle Evans 				ret = nn_set_wlen(tmp, 1); EG(ret, err);
1066*f0865ec9SKyle Evans 				ret = nn_import_from_hexbuf(tmp, rec + (6 * nn_len),
1067*f0865ec9SKyle Evans 						      WORD_BYTES * 2); EG(ret, err);
1068*f0865ec9SKyle Evans 
1069*f0865ec9SKyle Evans 				/* Compare mpinv */
1070*f0865ec9SKyle Evans 				if(fp_ctx_mpinv.val[0] != fp_ctx_param.mpinv){
1071*f0865ec9SKyle Evans 					printf("\nLine %lu: Fp context import failed\n", line);
1072*f0865ec9SKyle Evans 					printf("Imported mpinv from modulus=" PRINTF_WORD_HEX_FMT, fp_ctx_mpinv.val[0]);
1073*f0865ec9SKyle Evans 					printf("Computed mpiv  from file   =" PRINTF_WORD_HEX_FMT, fp_ctx_param.mpinv);
1074*f0865ec9SKyle Evans 					ret = -1;
1075*f0865ec9SKyle Evans 					goto err;
1076*f0865ec9SKyle Evans 				}
1077*f0865ec9SKyle Evans 				tmp = &fp_ctx_pshift;
1078*f0865ec9SKyle Evans 				ret = nn_set_wlen(tmp, 1); EG(ret, err);
1079*f0865ec9SKyle Evans 				ret = nn_import_from_hexbuf(tmp, rec + (6 * nn_len + 2 * WORD_BYTES),
1080*f0865ec9SKyle Evans 						      WORD_BYTES * 2); EG(ret, err);
1081*f0865ec9SKyle Evans 
1082*f0865ec9SKyle Evans 				/* Compare p_shift */
1083*f0865ec9SKyle Evans 				if((bitcnt_t)fp_ctx_pshift.val[0] != fp_ctx_param.p_shift){
1084*f0865ec9SKyle Evans 					printf("\nLine %lu: Fp context import failed\n", line);
1085*f0865ec9SKyle Evans 					printf("Imported mpinv from modulus=%d", (bitcnt_t)fp_ctx_pshift.val[0]);
1086*f0865ec9SKyle Evans 					printf("Computed mpiv  from file   =%d", fp_ctx_param.p_shift);
1087*f0865ec9SKyle Evans 					ret = -1;
1088*f0865ec9SKyle Evans 					goto err;
1089*f0865ec9SKyle Evans 				}
1090*f0865ec9SKyle Evans 				tmp = &fp_ctx_pnorm;
1091*f0865ec9SKyle Evans 				ret = nn_set_wlen(tmp, (u8)(nn_len / WORD_BYTES)); EG(ret, err);
1092*f0865ec9SKyle Evans 				ret = nn_import_from_hexbuf(tmp, rec + (6 * nn_len + 4 * WORD_BYTES),
1093*f0865ec9SKyle Evans 						      nn_len * 2); EG(ret, err);
1094*f0865ec9SKyle Evans 
1095*f0865ec9SKyle Evans 				/* Compare p_normalized */
1096*f0865ec9SKyle Evans 				ret = nn_cmp(&fp_ctx_pnorm, &(fp_ctx_param.p_normalized), &cmp);
1097*f0865ec9SKyle Evans 				if(ret || (cmp != 0)){
1098*f0865ec9SKyle Evans 					printf("\nLine %lu: Fp context import failed\n", line);
1099*f0865ec9SKyle Evans 					nn_print("Imported r_square from file   =", &fp_ctx_pnorm);
1100*f0865ec9SKyle Evans 					nn_print("Computed r_square from modulus=", &(fp_ctx_param.p_normalized));
1101*f0865ec9SKyle Evans 					return -1;
1102*f0865ec9SKyle Evans 				}
1103*f0865ec9SKyle Evans 				tmp = &fp_ctx_prec;
1104*f0865ec9SKyle Evans 				ret = nn_set_wlen(tmp, 1); EG(ret, err);
1105*f0865ec9SKyle Evans 				ret = nn_import_from_hexbuf(tmp, rec + (8 * nn_len + 4 * WORD_BYTES),
1106*f0865ec9SKyle Evans 						      WORD_BYTES * 2); EG(ret, err);
1107*f0865ec9SKyle Evans 
1108*f0865ec9SKyle Evans 				/* Compare p_reciprocal */
1109*f0865ec9SKyle Evans 				if(fp_ctx_prec.val[0] != fp_ctx_param.p_reciprocal){
1110*f0865ec9SKyle Evans 					printf("\nLine %lu: Fp context import failed\n", line);
1111*f0865ec9SKyle Evans 					printf("Imported mpinv from modulus=" PRINTF_WORD_HEX_FMT, fp_ctx_prec.val[0]);
1112*f0865ec9SKyle Evans 					printf("Computed mpiv  from file   =" PRINTF_WORD_HEX_FMT, fp_ctx_param.p_reciprocal);
1113*f0865ec9SKyle Evans 					ret = -1;
1114*f0865ec9SKyle Evans 					goto err;
1115*f0865ec9SKyle Evans 				}
1116*f0865ec9SKyle Evans 				params[i] = &fp_ctx_param;
1117*f0865ec9SKyle Evans 				ADD_TO_BACKTRACE("'c' param: %s\n", rec);
1118*f0865ec9SKyle Evans 				break;
1119*f0865ec9SKyle Evans 			case 'f':	/* fp */
1120*f0865ec9SKyle Evans 				if (fp_ctx_local_cnt != 1) {
1121*f0865ec9SKyle Evans 					printf("\nLine %lu: No fp_ctx available\n", line);
1122*f0865ec9SKyle Evans 					ret = -1;
1123*f0865ec9SKyle Evans 					goto err;
1124*f0865ec9SKyle Evans 				}
1125*f0865ec9SKyle Evans 				if (fp_local_cnt >= NUM_PRE_ALLOCATED_FP) {
1126*f0865ec9SKyle Evans 					printf("\nLine %lu: Not enough fp\n",
1127*f0865ec9SKyle Evans 					       line);
1128*f0865ec9SKyle Evans 					ret = -1;
1129*f0865ec9SKyle Evans 					goto err;
1130*f0865ec9SKyle Evans 				}
1131*f0865ec9SKyle Evans 				assert(((t - rec) % 2) == 0);
1132*f0865ec9SKyle Evans 				nn_len = (unsigned int)(t - rec) / 2;
1133*f0865ec9SKyle Evans 				assert((nn_len / WORD_BYTES) <=
1134*f0865ec9SKyle Evans 				       fp_ctx_param.p.wlen);
1135*f0865ec9SKyle Evans 				fp_tmp = fp_params_ptr[fp_local_cnt++];
1136*f0865ec9SKyle Evans 				fp_tmp->ctx = &fp_ctx_param;
1137*f0865ec9SKyle Evans 				tmp = &(fp_tmp->fp_val);
1138*f0865ec9SKyle Evans 				ret = nn_set_wlen(tmp, (u8)(nn_len / WORD_BYTES)); EG(ret, err);
1139*f0865ec9SKyle Evans 				ret = nn_import_from_hexbuf(tmp, rec, 2 * nn_len); EG(ret, err);
1140*f0865ec9SKyle Evans 				ret = nn_set_wlen(tmp, fp_ctx_param.p.wlen); EG(ret, err);
1141*f0865ec9SKyle Evans 				params[i] = fp_tmp;
1142*f0865ec9SKyle Evans 				ADD_TO_BACKTRACE("'f' param: %s\n", rec);
1143*f0865ec9SKyle Evans 				break;
1144*f0865ec9SKyle Evans 			case 'p':	/* raw pointer value. Useful for NULL */
1145*f0865ec9SKyle Evans 				p_tmp = strtoull(rec, NULL, 10);
1146*f0865ec9SKyle Evans 				params[i] = (void *)p_tmp;
1147*f0865ec9SKyle Evans 				ADD_TO_BACKTRACE("'p' param: %s\n", rec);
1148*f0865ec9SKyle Evans 				/* If this is not a NULL pointer, this is weird!
1149*f0865ec9SKyle Evans 				 * Abort ...
1150*f0865ec9SKyle Evans 				 */
1151*f0865ec9SKyle Evans 				if(params[i] != NULL){
1152*f0865ec9SKyle Evans 					printf("\nLine %lu: imported a pointer (type 'p') non NULL\n",
1153*f0865ec9SKyle Evans 					       line);
1154*f0865ec9SKyle Evans 					ret = -1;
1155*f0865ec9SKyle Evans 					goto err;
1156*f0865ec9SKyle Evans 				}
1157*f0865ec9SKyle Evans 				break;
1158*f0865ec9SKyle Evans 			case 'n':	/* nn */
1159*f0865ec9SKyle Evans 				if (nn_local_cnt >= NUM_PRE_ALLOCATED_NN) {
1160*f0865ec9SKyle Evans 					printf("\nLine %lu: Not enough nn\n",
1161*f0865ec9SKyle Evans 					       line);
1162*f0865ec9SKyle Evans 					return -1;
1163*f0865ec9SKyle Evans 				}
1164*f0865ec9SKyle Evans 				assert(((t - rec) % 2) == 0);
1165*f0865ec9SKyle Evans 				nn_len = (unsigned int)(t - rec) / 2;
1166*f0865ec9SKyle Evans 				assert((nn_len % WORD_BYTES) == 0);
1167*f0865ec9SKyle Evans 				tmp = nn_params_ptr[nn_local_cnt++];
1168*f0865ec9SKyle Evans 				ret = nn_set_wlen(tmp, (u8)(nn_len / WORD_BYTES)); EG(ret, err);
1169*f0865ec9SKyle Evans 				ret = nn_import_from_hexbuf(tmp, rec, 2 * nn_len); EG(ret, err);
1170*f0865ec9SKyle Evans 				params[i] = tmp;
1171*f0865ec9SKyle Evans 				ADD_TO_BACKTRACE("'n' param: %s\n", rec);
1172*f0865ec9SKyle Evans 				break;
1173*f0865ec9SKyle Evans 			case 'u':	/* unsigned long int (in base 10) */
1174*f0865ec9SKyle Evans 				u_params[i] = (u64)strtoull(rec, NULL, 10);
1175*f0865ec9SKyle Evans 				params[i] = &u_params[i];
1176*f0865ec9SKyle Evans 				ADD_TO_BACKTRACE("'u' param: %s\n", rec);
1177*f0865ec9SKyle Evans 				break;
1178*f0865ec9SKyle Evans 			case 's':	/* signed long int (in base 10) */
1179*f0865ec9SKyle Evans 				u_params[i] = (u64)strtoll(rec, NULL, 10);
1180*f0865ec9SKyle Evans 				params[i] = &u_params[i];
1181*f0865ec9SKyle Evans 				ADD_TO_BACKTRACE("'s' param: %s\n", rec);
1182*f0865ec9SKyle Evans 				break;
1183*f0865ec9SKyle Evans 			default:
1184*f0865ec9SKyle Evans 				printf("\nUnknown record type '%c'\n", s[i]);
1185*f0865ec9SKyle Evans 				ret = -1;
1186*f0865ec9SKyle Evans 				goto err;
1187*f0865ec9SKyle Evans 			}
1188*f0865ec9SKyle Evans 			rec = t + 1;
1189*f0865ec9SKyle Evans 		}
1190*f0865ec9SKyle Evans 		/* Save current parameters format in the global variable */
1191*f0865ec9SKyle Evans 		memcpy(global_parameters, s, LOCAL_MIN(nrecs, MAX_PARAMS));
1192*f0865ec9SKyle Evans 		curr_test_fun = NULL;
1193*f0865ec9SKyle Evans 		FIND_FUN_IN_DISPATCH_TABLE(op, curr_test_fun);
1194*f0865ec9SKyle Evans 		if (curr_test_fun == NULL) {
1195*f0865ec9SKyle Evans 			printf("\nLine %lu: unknown opcode %s\n", line, op);
1196*f0865ec9SKyle Evans 		} else {
1197*f0865ec9SKyle Evans 			ADD_TO_BACKTRACE("\nLine %lu: testing opcode %s\n", line, op);
1198*f0865ec9SKyle Evans 			test_ret = curr_test_fun(op, params, (int)test_num);
1199*f0865ec9SKyle Evans 			if (test_ret == 1) {
1200*f0865ec9SKyle Evans 				ADD_TO_BACKTRACE("-- TEST OK ---\n");
1201*f0865ec9SKyle Evans 				oktests += (unsigned long)test_ret;
1202*f0865ec9SKyle Evans 			} else {
1203*f0865ec9SKyle Evans 				ADD_TO_BACKTRACE("-- TEST NOK --\n");
1204*f0865ec9SKyle Evans 			}
1205*f0865ec9SKyle Evans 		}
1206*f0865ec9SKyle Evans 		line += 1;
1207*f0865ec9SKyle Evans 		len = ibuflen;
1208*f0865ec9SKyle Evans 		nn_local_cnt = 0;
1209*f0865ec9SKyle Evans 		fp_local_cnt = 0;
1210*f0865ec9SKyle Evans 		fp_ctx_local_cnt = 0;
1211*f0865ec9SKyle Evans 	}
1212*f0865ec9SKyle Evans 
1213*f0865ec9SKyle Evans 	printf("\n%lu/%lu tests passed successfully (%lu on error)\n",
1214*f0865ec9SKyle Evans 	       oktests, line, line - oktests);
1215*f0865ec9SKyle Evans 
1216*f0865ec9SKyle Evans 	if(fd != 0){
1217*f0865ec9SKyle Evans 		close(fd);
1218*f0865ec9SKyle Evans 	}
1219*f0865ec9SKyle Evans 	if(ibuf != NULL){
1220*f0865ec9SKyle Evans 		free(ibuf);
1221*f0865ec9SKyle Evans 	}
1222*f0865ec9SKyle Evans 
1223*f0865ec9SKyle Evans 	return 0;
1224*f0865ec9SKyle Evans err:
1225*f0865ec9SKyle Evans 	printf("Error: critical error occured! Leaving ...\n");
1226*f0865ec9SKyle Evans 	if(fd != 0){
1227*f0865ec9SKyle Evans 		close(fd);
1228*f0865ec9SKyle Evans 	}
1229*f0865ec9SKyle Evans 	if(ibuf != NULL){
1230*f0865ec9SKyle Evans 		free(ibuf);
1231*f0865ec9SKyle Evans 	}
1232*f0865ec9SKyle Evans 	return -1;
1233*f0865ec9SKyle Evans }
1234