security/nss/lib/freebl/ecl/tests/ec2_test.c

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:93b543a4eaa6
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 #include "mpi.h"
6 #include "mplogic.h"
7 #include "mpprime.h"
8 #include "mp_gf2m.h"
9 #include "ecl.h"
10 #include "ecl-curve.h"
11 #include "ec2.h"
12 #include <stdio.h>
13 #include <strings.h>
14 #include <assert.h>
15
16 #include <time.h>
17 #include <sys/time.h>
18 #include <sys/resource.h>
19
20 /* Time k repetitions of operation op. */
21 #define M_TimeOperation(op, k) { \
22 double dStart, dNow, dUserTime; \
23 struct rusage ru; \
24 int i; \
25 getrusage(RUSAGE_SELF, &ru); \
26 dStart = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \
27 for (i = 0; i < k; i++) { \
28 { op; } \
29 }; \
30 getrusage(RUSAGE_SELF, &ru); \
31 dNow = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \
32 dUserTime = dNow-dStart; \
33 if (dUserTime) printf(" %-45s k: %6i, t: %6.2f sec\n", #op, k, dUserTime); \
34 }
35
36 /* Test curve using generic field arithmetic. */
37 #define ECTEST_GENERIC_GF2M(name_c, name) \
38 printf("Testing %s using generic implementation...\n", name_c); \
39 params = EC_GetNamedCurveParams(name); \
40 if (params == NULL) { \
41 printf(" Error: could not construct params.\n"); \
42 res = MP_NO; \
43 goto CLEANUP; \
44 } \
45 ECGroup_free(group); \
46 group = ECGroup_fromHex(params); \
47 if (group == NULL) { \
48 printf(" Error: could not construct group.\n"); \
49 res = MP_NO; \
50 goto CLEANUP; \
51 } \
52 MP_CHECKOK( ectest_curve_GF2m(group, ectestPrint, ectestTime, 1) ); \
53 printf("... okay.\n");
54
55 /* Test curve using specific field arithmetic. */
56 #define ECTEST_NAMED_GF2M(name_c, name) \
57 printf("Testing %s using specific implementation...\n", name_c); \
58 ECGroup_free(group); \
59 group = ECGroup_fromName(name); \
60 if (group == NULL) { \
61 printf(" Warning: could not construct group.\n"); \
62 printf("... failed; continuing with remaining tests.\n"); \
63 } else { \
64 MP_CHECKOK( ectest_curve_GF2m(group, ectestPrint, ectestTime, 0) ); \
65 printf("... okay.\n"); \
66 }
67
68 /* Performs basic tests of elliptic curve cryptography over binary
69 * polynomial fields. If tests fail, then it prints an error message,
70 * aborts, and returns an error code. Otherwise, returns 0. */
71 int
72 ectest_curve_GF2m(ECGroup *group, int ectestPrint, int ectestTime,
73 int generic)
74 {
75
76 mp_int one, order_1, gx, gy, rx, ry, n;
77 int size;
78 mp_err res;
79 char s[1000];
80
81 /* initialize values */
82 MP_CHECKOK(mp_init(&one));
83 MP_CHECKOK(mp_init(&order_1));
84 MP_CHECKOK(mp_init(&gx));
85 MP_CHECKOK(mp_init(&gy));
86 MP_CHECKOK(mp_init(&rx));
87 MP_CHECKOK(mp_init(&ry));
88 MP_CHECKOK(mp_init(&n));
89
90 MP_CHECKOK(mp_set_int(&one, 1));
91 MP_CHECKOK(mp_sub(&group->order, &one, &order_1));
92
93 /* encode base point */
94 if (group->meth->field_dec) {
95 MP_CHECKOK(group->meth->field_dec(&group->genx, &gx, group->meth));
96 MP_CHECKOK(group->meth->field_dec(&group->geny, &gy, group->meth));
97 } else {
98 MP_CHECKOK(mp_copy(&group->genx, &gx));
99 MP_CHECKOK(mp_copy(&group->geny, &gy));
100 }
101
102 if (ectestPrint) {
103 /* output base point */
104 printf(" base point P:\n");
105 MP_CHECKOK(mp_toradix(&gx, s, 16));
106 printf(" %s\n", s);
107 MP_CHECKOK(mp_toradix(&gy, s, 16));
108 printf(" %s\n", s);
109 if (group->meth->field_enc) {
110 printf(" base point P (encoded):\n");
111 MP_CHECKOK(mp_toradix(&group->genx, s, 16));
112 printf(" %s\n", s);
113 MP_CHECKOK(mp_toradix(&group->geny, s, 16));
114 printf(" %s\n", s);
115 }
116 }
117
118 #ifdef ECL_ENABLE_GF2M_PT_MUL_AFF
119 /* multiply base point by order - 1 and check for negative of base
120 * point */
121 MP_CHECKOK(ec_GF2m_pt_mul_aff
122 (&order_1, &group->genx, &group->geny, &rx, &ry, group));
123 if (ectestPrint) {
124 printf(" (order-1)*P (affine):\n");
125 MP_CHECKOK(mp_toradix(&rx, s, 16));
126 printf(" %s\n", s);
127 MP_CHECKOK(mp_toradix(&ry, s, 16));
128 printf(" %s\n", s);
129 }
130 MP_CHECKOK(group->meth->field_add(&ry, &rx, &ry, group->meth));
131 if ((mp_cmp(&rx, &group->genx) != 0)
132 || (mp_cmp(&ry, &group->geny) != 0)) {
133 printf(" Error: invalid result (expected (- base point)).\n");
134 res = MP_NO;
135 goto CLEANUP;
136 }
137 #endif
138
139 /* multiply base point by order - 1 and check for negative of base
140 * point */
141 MP_CHECKOK(ec_GF2m_pt_mul_mont
142 (&order_1, &group->genx, &group->geny, &rx, &ry, group));
143 if (ectestPrint) {
144 printf(" (order-1)*P (montgomery):\n");
145 MP_CHECKOK(mp_toradix(&rx, s, 16));
146 printf(" %s\n", s);
147 MP_CHECKOK(mp_toradix(&ry, s, 16));
148 printf(" %s\n", s);
149 }
150 MP_CHECKOK(group->meth->field_add(&ry, &rx, &ry, group->meth));
151 if ((mp_cmp(&rx, &group->genx) != 0)
152 || (mp_cmp(&ry, &group->geny) != 0)) {
153 printf(" Error: invalid result (expected (- base point)).\n");
154 res = MP_NO;
155 goto CLEANUP;
156 }
157
158 #ifdef ECL_ENABLE_GF2M_PROJ
159 /* multiply base point by order - 1 and check for negative of base
160 * point */
161 MP_CHECKOK(ec_GF2m_pt_mul_proj
162 (&order_1, &group->genx, &group->geny, &rx, &ry, group));
163 if (ectestPrint) {
164 printf(" (order-1)*P (projective):\n");
165 MP_CHECKOK(mp_toradix(&rx, s, 16));
166 printf(" %s\n", s);
167 MP_CHECKOK(mp_toradix(&ry, s, 16));
168 printf(" %s\n", s);
169 }
170 MP_CHECKOK(group->meth->field_add(&ry, &rx, &ry, group->meth));
171 if ((mp_cmp(&rx, &group->genx) != 0)
172 || (mp_cmp(&ry, &group->geny) != 0)) {
173 printf(" Error: invalid result (expected (- base point)).\n");
174 res = MP_NO;
175 goto CLEANUP;
176 }
177 #endif
178
179 /* multiply base point by order - 1 and check for negative of base
180 * point */
181 MP_CHECKOK(ECPoint_mul(group, &order_1, NULL, NULL, &rx, &ry));
182 if (ectestPrint) {
183 printf(" (order-1)*P (ECPoint_mul):\n");
184 MP_CHECKOK(mp_toradix(&rx, s, 16));
185 printf(" %s\n", s);
186 MP_CHECKOK(mp_toradix(&ry, s, 16));
187 printf(" %s\n", s);
188 }
189 MP_CHECKOK(ec_GF2m_add(&ry, &rx, &ry, group->meth));
190 if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
191 printf(" Error: invalid result (expected (- base point)).\n");
192 res = MP_NO;
193 goto CLEANUP;
194 }
195
196 /* multiply base point by order - 1 and check for negative of base
197 * point */
198 MP_CHECKOK(ECPoint_mul(group, &order_1, &gx, &gy, &rx, &ry));
199 if (ectestPrint) {
200 printf(" (order-1)*P (ECPoint_mul):\n");
201 MP_CHECKOK(mp_toradix(&rx, s, 16));
202 printf(" %s\n", s);
203 MP_CHECKOK(mp_toradix(&ry, s, 16));
204 printf(" %s\n", s);
205 }
206 MP_CHECKOK(ec_GF2m_add(&ry, &rx, &ry, group->meth));
207 if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
208 printf(" Error: invalid result (expected (- base point)).\n");
209 res = MP_NO;
210 goto CLEANUP;
211 }
212
213 #ifdef ECL_ENABLE_GF2M_PT_MUL_AFF
214 /* multiply base point by order and check for point at infinity */
215 MP_CHECKOK(ec_GF2m_pt_mul_aff
216 (&group->order, &group->genx, &group->geny, &rx, &ry,
217 group));
218 if (ectestPrint) {
219 printf(" (order)*P (affine):\n");
220 MP_CHECKOK(mp_toradix(&rx, s, 16));
221 printf(" %s\n", s);
222 MP_CHECKOK(mp_toradix(&ry, s, 16));
223 printf(" %s\n", s);
224 }
225 if (ec_GF2m_pt_is_inf_aff(&rx, &ry) != MP_YES) {
226 printf(" Error: invalid result (expected point at infinity).\n");
227 res = MP_NO;
228 goto CLEANUP;
229 }
230 #endif
231
232 /* multiply base point by order and check for point at infinity */
233 MP_CHECKOK(ec_GF2m_pt_mul_mont
234 (&group->order, &group->genx, &group->geny, &rx, &ry,
235 group));
236 if (ectestPrint) {
237 printf(" (order)*P (montgomery):\n");
238 MP_CHECKOK(mp_toradix(&rx, s, 16));
239 printf(" %s\n", s);
240 MP_CHECKOK(mp_toradix(&ry, s, 16));
241 printf(" %s\n", s);
242 }
243 if (ec_GF2m_pt_is_inf_aff(&rx, &ry) != MP_YES) {
244 printf(" Error: invalid result (expected point at infinity).\n");
245 res = MP_NO;
246 goto CLEANUP;
247 }
248
249 #ifdef ECL_ENABLE_GF2M_PROJ
250 /* multiply base point by order and check for point at infinity */
251 MP_CHECKOK(ec_GF2m_pt_mul_proj
252 (&group->order, &group->genx, &group->geny, &rx, &ry,
253 group));
254 if (ectestPrint) {
255 printf(" (order)*P (projective):\n");
256 MP_CHECKOK(mp_toradix(&rx, s, 16));
257 printf(" %s\n", s);
258 MP_CHECKOK(mp_toradix(&ry, s, 16));
259 printf(" %s\n", s);
260 }
261 if (ec_GF2m_pt_is_inf_aff(&rx, &ry) != MP_YES) {
262 printf(" Error: invalid result (expected point at infinity).\n");
263 res = MP_NO;
264 goto CLEANUP;
265 }
266 #endif
267
268 /* multiply base point by order and check for point at infinity */
269 MP_CHECKOK(ECPoint_mul(group, &group->order, NULL, NULL, &rx, &ry));
270 if (ectestPrint) {
271 printf(" (order)*P (ECPoint_mul):\n");
272 MP_CHECKOK(mp_toradix(&rx, s, 16));
273 printf(" %s\n", s);
274 MP_CHECKOK(mp_toradix(&ry, s, 16));
275 printf(" %s\n", s);
276 }
277 if (ec_GF2m_pt_is_inf_aff(&rx, &ry) != MP_YES) {
278 printf(" Error: invalid result (expected point at infinity).\n");
279 res = MP_NO;
280 goto CLEANUP;
281 }
282
283 /* multiply base point by order and check for point at infinity */
284 MP_CHECKOK(ECPoint_mul(group, &group->order, &gx, &gy, &rx, &ry));
285 if (ectestPrint) {
286 printf(" (order)*P (ECPoint_mul):\n");
287 MP_CHECKOK(mp_toradix(&rx, s, 16));
288 printf(" %s\n", s);
289 MP_CHECKOK(mp_toradix(&ry, s, 16));
290 printf(" %s\n", s);
291 }
292 if (ec_GF2m_pt_is_inf_aff(&rx, &ry) != MP_YES) {
293 printf(" Error: invalid result (expected point at infinity).\n");
294 res = MP_NO;
295 goto CLEANUP;
296 }
297
298 /* check that (order-1)P + (order-1)P + P == (order-1)P */
299 MP_CHECKOK(ECPoints_mul
300 (group, &order_1, &order_1, &gx, &gy, &rx, &ry));
301 MP_CHECKOK(ECPoints_mul(group, &one, &one, &rx, &ry, &rx, &ry));
302 if (ectestPrint) {
303 printf
304 (" (order-1)*P + (order-1)*P + P == (order-1)*P (ECPoints_mul):\n");
305 MP_CHECKOK(mp_toradix(&rx, s, 16));
306 printf(" %s\n", s);
307 MP_CHECKOK(mp_toradix(&ry, s, 16));
308 printf(" %s\n", s);
309 }
310 MP_CHECKOK(ec_GF2m_add(&ry, &rx, &ry, group->meth));
311 if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
312 printf(" Error: invalid result (expected (- base point)).\n");
313 res = MP_NO;
314 goto CLEANUP;
315 }
316
317 /* test validate_point function */
318 if (ECPoint_validate(group, &gx, &gy) != MP_YES) {
319 printf(" Error: validate point on base point failed.\n");
320 res = MP_NO;
321 goto CLEANUP;
322 }
323 MP_CHECKOK(mp_add_d(&gy, 1, &ry));
324 if (ECPoint_validate(group, &gx, &ry) != MP_NO) {
325 printf(" Error: validate point on invalid point passed.\n");
326 res = MP_NO;
327 goto CLEANUP;
328 }
329
330 if (ectestTime) {
331 /* compute random scalar */
332 size = mpl_significant_bits(&group->meth->irr);
333 if (size < MP_OKAY) {
334 goto CLEANUP;
335 }
336 MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS));
337 MP_CHECKOK(group->meth->field_mod(&n, &n, group->meth));
338 /* timed test */
339 if (generic) {
340 #ifdef ECL_ENABLE_GF2M_PT_MUL_AFF
341 M_TimeOperation(MP_CHECKOK
342 (ec_GF2m_pt_mul_aff
343 (&n, &group->genx, &group->geny, &rx, &ry,
344 group)), 100);
345 #endif
346 M_TimeOperation(MP_CHECKOK
347 (ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
348 100);
349 M_TimeOperation(MP_CHECKOK
350 (ECPoints_mul
351 (group, &n, &n, &gx, &gy, &rx, &ry)), 100);
352 } else {
353 M_TimeOperation(MP_CHECKOK
354 (ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
355 100);
356 M_TimeOperation(MP_CHECKOK
357 (ECPoint_mul(group, &n, &gx, &gy, &rx, &ry)),
358 100);
359 M_TimeOperation(MP_CHECKOK
360 (ECPoints_mul
361 (group, &n, &n, &gx, &gy, &rx, &ry)), 100);
362 }
363 }
364
365 CLEANUP:
366 mp_clear(&one);
367 mp_clear(&order_1);
368 mp_clear(&gx);
369 mp_clear(&gy);
370 mp_clear(&rx);
371 mp_clear(&ry);
372 mp_clear(&n);
373 if (res != MP_OKAY) {
374 printf(" Error: exiting with error value %i\n", res);
375 }
376 return res;
377 }
378
379 /* Prints help information. */
380 void
381 printUsage()
382 {
383 printf("Usage: ecp_test [--print] [--time]\n");
384 printf
385 (" --print Print out results of each point arithmetic test.\n");
386 printf
387 (" --time Benchmark point operations and print results.\n");
388 }
389
390 /* Performs tests of elliptic curve cryptography over binary polynomial
391 * fields. If tests fail, then it prints an error message, aborts, and
392 * returns an error code. Otherwise, returns 0. */
393 int
394 main(int argv, char **argc)
395 {
396
397 int ectestTime = 0;
398 int ectestPrint = 0;
399 int i;
400 ECGroup *group = NULL;
401 ECCurveParams *params = NULL;
402 mp_err res;
403
404 /* read command-line arguments */
405 for (i = 1; i < argv; i++) {
406 if ((strcasecmp(argc[i], "time") == 0)
407 || (strcasecmp(argc[i], "-time") == 0)
408 || (strcasecmp(argc[i], "--time") == 0)) {
409 ectestTime = 1;
410 } else if ((strcasecmp(argc[i], "print") == 0)
411 || (strcasecmp(argc[i], "-print") == 0)
412 || (strcasecmp(argc[i], "--print") == 0)) {
413 ectestPrint = 1;
414 } else {
415 printUsage();
416 return 0;
417 }
418 }
419
420 /* generic arithmetic tests */
421 ECTEST_GENERIC_GF2M("SECT-131R1", ECCurve_SECG_CHAR2_131R1);
422
423 /* specific arithmetic tests */
424 ECTEST_NAMED_GF2M("NIST-K163", ECCurve_NIST_K163);
425 ECTEST_NAMED_GF2M("NIST-B163", ECCurve_NIST_B163);
426 ECTEST_NAMED_GF2M("NIST-K233", ECCurve_NIST_K233);
427 ECTEST_NAMED_GF2M("NIST-B233", ECCurve_NIST_B233);
428 ECTEST_NAMED_GF2M("NIST-K283", ECCurve_NIST_K283);
429 ECTEST_NAMED_GF2M("NIST-B283", ECCurve_NIST_B283);
430 ECTEST_NAMED_GF2M("NIST-K409", ECCurve_NIST_K409);
431 ECTEST_NAMED_GF2M("NIST-B409", ECCurve_NIST_B409);
432 ECTEST_NAMED_GF2M("NIST-K571", ECCurve_NIST_K571);
433 ECTEST_NAMED_GF2M("NIST-B571", ECCurve_NIST_B571);
434 ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB163V1", ECCurve_X9_62_CHAR2_PNB163V1);
435 ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB163V2", ECCurve_X9_62_CHAR2_PNB163V2);
436 ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB163V3", ECCurve_X9_62_CHAR2_PNB163V3);
437 ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB176V1", ECCurve_X9_62_CHAR2_PNB176V1);
438 ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB191V1", ECCurve_X9_62_CHAR2_TNB191V1);
439 ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB191V2", ECCurve_X9_62_CHAR2_TNB191V2);
440 ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB191V3", ECCurve_X9_62_CHAR2_TNB191V3);
441 ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB208W1", ECCurve_X9_62_CHAR2_PNB208W1);
442 ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB239V1", ECCurve_X9_62_CHAR2_TNB239V1);
443 ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB239V2", ECCurve_X9_62_CHAR2_TNB239V2);
444 ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB239V3", ECCurve_X9_62_CHAR2_TNB239V3);
445 ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB272W1", ECCurve_X9_62_CHAR2_PNB272W1);
446 ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB304W1", ECCurve_X9_62_CHAR2_PNB304W1);
447 ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB359V1", ECCurve_X9_62_CHAR2_TNB359V1);
448 ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB368W1", ECCurve_X9_62_CHAR2_PNB368W1);
449 ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB431R1", ECCurve_X9_62_CHAR2_TNB431R1);
450 ECTEST_NAMED_GF2M("SECT-113R1", ECCurve_SECG_CHAR2_113R1);
451 ECTEST_NAMED_GF2M("SECT-113R2", ECCurve_SECG_CHAR2_113R2);
452 ECTEST_NAMED_GF2M("SECT-131R1", ECCurve_SECG_CHAR2_131R1);
453 ECTEST_NAMED_GF2M("SECT-131R2", ECCurve_SECG_CHAR2_131R2);
454 ECTEST_NAMED_GF2M("SECT-163K1", ECCurve_SECG_CHAR2_163K1);
455 ECTEST_NAMED_GF2M("SECT-163R1", ECCurve_SECG_CHAR2_163R1);
456 ECTEST_NAMED_GF2M("SECT-163R2", ECCurve_SECG_CHAR2_163R2);
457 ECTEST_NAMED_GF2M("SECT-193R1", ECCurve_SECG_CHAR2_193R1);
458 ECTEST_NAMED_GF2M("SECT-193R2", ECCurve_SECG_CHAR2_193R2);
459 ECTEST_NAMED_GF2M("SECT-233K1", ECCurve_SECG_CHAR2_233K1);
460 ECTEST_NAMED_GF2M("SECT-233R1", ECCurve_SECG_CHAR2_233R1);
461 ECTEST_NAMED_GF2M("SECT-239K1", ECCurve_SECG_CHAR2_239K1);
462 ECTEST_NAMED_GF2M("SECT-283K1", ECCurve_SECG_CHAR2_283K1);
463 ECTEST_NAMED_GF2M("SECT-283R1", ECCurve_SECG_CHAR2_283R1);
464 ECTEST_NAMED_GF2M("SECT-409K1", ECCurve_SECG_CHAR2_409K1);
465 ECTEST_NAMED_GF2M("SECT-409R1", ECCurve_SECG_CHAR2_409R1);
466 ECTEST_NAMED_GF2M("SECT-571K1", ECCurve_SECG_CHAR2_571K1);
467 ECTEST_NAMED_GF2M("SECT-571R1", ECCurve_SECG_CHAR2_571R1);
468 ECTEST_NAMED_GF2M("WTLS-1 (113)", ECCurve_WTLS_1);
469 ECTEST_NAMED_GF2M("WTLS-3 (163)", ECCurve_WTLS_3);
470 ECTEST_NAMED_GF2M("WTLS-4 (113)", ECCurve_WTLS_4);
471 ECTEST_NAMED_GF2M("WTLS-5 (163)", ECCurve_WTLS_5);
472 ECTEST_NAMED_GF2M("WTLS-10 (233)", ECCurve_WTLS_10);
473 ECTEST_NAMED_GF2M("WTLS-11 (233)", ECCurve_WTLS_11);
474
475 CLEANUP:
476 EC_FreeCurveParams(params);
477 ECGroup_free(group);
478 if (res != MP_OKAY) {
479 printf("Error: exiting with error value %i\n", res);
480 }
481 return res;
482 }

mercurial