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