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

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:ebfcd7ee2cba
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 "ecl.h"
9 #include "ecl-curve.h"
10 #include "ecp.h"
11 #include <stdio.h>
12 #include <strings.h>
13 #include <assert.h>
14
15 #include <time.h>
16 #include <sys/time.h>
17 #include <sys/resource.h>
18
19 /* Time k repetitions of operation op. */
20 #define M_TimeOperation(op, k) { \
21 double dStart, dNow, dUserTime; \
22 struct rusage ru; \
23 int i; \
24 getrusage(RUSAGE_SELF, &ru); \
25 dStart = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \
26 for (i = 0; i < k; i++) { \
27 { op; } \
28 }; \
29 getrusage(RUSAGE_SELF, &ru); \
30 dNow = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \
31 dUserTime = dNow-dStart; \
32 if (dUserTime) printf(" %-45s k: %6i, t: %6.2f sec\n", #op, k, dUserTime); \
33 }
34
35 /* Test curve using generic field arithmetic. */
36 #define ECTEST_GENERIC_GFP(name_c, name) \
37 printf("Testing %s using generic implementation...\n", name_c); \
38 params = EC_GetNamedCurveParams(name); \
39 if (params == NULL) { \
40 printf(" Error: could not construct params.\n"); \
41 res = MP_NO; \
42 goto CLEANUP; \
43 } \
44 ECGroup_free(group); \
45 group = ECGroup_fromHex(params); \
46 if (group == NULL) { \
47 printf(" Error: could not construct group.\n"); \
48 res = MP_NO; \
49 goto CLEANUP; \
50 } \
51 MP_CHECKOK( ectest_curve_GFp(group, ectestPrint, ectestTime, 1) ); \
52 printf("... okay.\n");
53
54 /* Test curve using specific field arithmetic. */
55 #define ECTEST_NAMED_GFP(name_c, name) \
56 printf("Testing %s using specific implementation...\n", name_c); \
57 ECGroup_free(group); \
58 group = ECGroup_fromName(name); \
59 if (group == NULL) { \
60 printf(" Warning: could not construct group.\n"); \
61 printf("... failed; continuing with remaining tests.\n"); \
62 } else { \
63 MP_CHECKOK( ectest_curve_GFp(group, ectestPrint, ectestTime, 0) ); \
64 printf("... okay.\n"); \
65 }
66
67 /* Performs basic tests of elliptic curve cryptography over prime fields.
68 * If tests fail, then it prints an error message, aborts, and returns an
69 * error code. Otherwise, returns 0. */
70 int
71 ectest_curve_GFp(ECGroup *group, int ectestPrint, int ectestTime,
72 int generic)
73 {
74
75 mp_int one, order_1, gx, gy, rx, ry, n;
76 int size;
77 mp_err res;
78 char s[1000];
79
80 /* initialize values */
81 MP_CHECKOK(mp_init(&one));
82 MP_CHECKOK(mp_init(&order_1));
83 MP_CHECKOK(mp_init(&gx));
84 MP_CHECKOK(mp_init(&gy));
85 MP_CHECKOK(mp_init(&rx));
86 MP_CHECKOK(mp_init(&ry));
87 MP_CHECKOK(mp_init(&n));
88
89 MP_CHECKOK(mp_set_int(&one, 1));
90 MP_CHECKOK(mp_sub(&group->order, &one, &order_1));
91
92 /* encode base point */
93 if (group->meth->field_dec) {
94 MP_CHECKOK(group->meth->field_dec(&group->genx, &gx, group->meth));
95 MP_CHECKOK(group->meth->field_dec(&group->geny, &gy, group->meth));
96 } else {
97 MP_CHECKOK(mp_copy(&group->genx, &gx));
98 MP_CHECKOK(mp_copy(&group->geny, &gy));
99 }
100 if (ectestPrint) {
101 /* output base point */
102 printf(" base point P:\n");
103 MP_CHECKOK(mp_toradix(&gx, s, 16));
104 printf(" %s\n", s);
105 MP_CHECKOK(mp_toradix(&gy, s, 16));
106 printf(" %s\n", s);
107 if (group->meth->field_enc) {
108 printf(" base point P (encoded):\n");
109 MP_CHECKOK(mp_toradix(&group->genx, s, 16));
110 printf(" %s\n", s);
111 MP_CHECKOK(mp_toradix(&group->geny, s, 16));
112 printf(" %s\n", s);
113 }
114 }
115
116 #ifdef ECL_ENABLE_GFP_PT_MUL_AFF
117 /* multiply base point by order - 1 and check for negative of base
118 * point */
119 MP_CHECKOK(ec_GFp_pt_mul_aff
120 (&order_1, &group->genx, &group->geny, &rx, &ry, group));
121 if (ectestPrint) {
122 printf(" (order-1)*P (affine):\n");
123 MP_CHECKOK(mp_toradix(&rx, s, 16));
124 printf(" %s\n", s);
125 MP_CHECKOK(mp_toradix(&ry, s, 16));
126 printf(" %s\n", s);
127 }
128 MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth));
129 if ((mp_cmp(&rx, &group->genx) != 0)
130 || (mp_cmp(&ry, &group->geny) != 0)) {
131 printf(" Error: invalid result (expected (- base point)).\n");
132 res = MP_NO;
133 goto CLEANUP;
134 }
135 #endif
136
137 #ifdef ECL_ENABLE_GFP_PT_MUL_AFF
138 /* multiply base point by order - 1 and check for negative of base
139 * point */
140 MP_CHECKOK(ec_GFp_pt_mul_jac
141 (&order_1, &group->genx, &group->geny, &rx, &ry, group));
142 if (ectestPrint) {
143 printf(" (order-1)*P (jacobian):\n");
144 MP_CHECKOK(mp_toradix(&rx, s, 16));
145 printf(" %s\n", s);
146 MP_CHECKOK(mp_toradix(&ry, s, 16));
147 printf(" %s\n", s);
148 }
149 MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth));
150 if ((mp_cmp(&rx, &group->genx) != 0)
151 || (mp_cmp(&ry, &group->geny) != 0)) {
152 printf(" Error: invalid result (expected (- base point)).\n");
153 res = MP_NO;
154 goto CLEANUP;
155 }
156 #endif
157
158 /* multiply base point by order - 1 and check for negative of base
159 * point */
160 MP_CHECKOK(ECPoint_mul(group, &order_1, NULL, NULL, &rx, &ry));
161 if (ectestPrint) {
162 printf(" (order-1)*P (ECPoint_mul):\n");
163 MP_CHECKOK(mp_toradix(&rx, s, 16));
164 printf(" %s\n", s);
165 MP_CHECKOK(mp_toradix(&ry, s, 16));
166 printf(" %s\n", s);
167 }
168 MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
169 if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
170 printf(" Error: invalid result (expected (- base point)).\n");
171 res = MP_NO;
172 goto CLEANUP;
173 }
174
175 /* multiply base point by order - 1 and check for negative of base
176 * point */
177 MP_CHECKOK(ECPoint_mul(group, &order_1, &gx, &gy, &rx, &ry));
178 if (ectestPrint) {
179 printf(" (order-1)*P (ECPoint_mul):\n");
180 MP_CHECKOK(mp_toradix(&rx, s, 16));
181 printf(" %s\n", s);
182 MP_CHECKOK(mp_toradix(&ry, s, 16));
183 printf(" %s\n", s);
184 }
185 MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
186 if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
187 printf(" Error: invalid result (expected (- base point)).\n");
188 res = MP_NO;
189 goto CLEANUP;
190 }
191
192 #ifdef ECL_ENABLE_GFP_PT_MUL_AFF
193 /* multiply base point by order and check for point at infinity */
194 MP_CHECKOK(ec_GFp_pt_mul_aff
195 (&group->order, &group->genx, &group->geny, &rx, &ry,
196 group));
197 if (ectestPrint) {
198 printf(" (order)*P (affine):\n");
199 MP_CHECKOK(mp_toradix(&rx, s, 16));
200 printf(" %s\n", s);
201 MP_CHECKOK(mp_toradix(&ry, s, 16));
202 printf(" %s\n", s);
203 }
204 if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
205 printf(" Error: invalid result (expected point at infinity).\n");
206 res = MP_NO;
207 goto CLEANUP;
208 }
209 #endif
210
211 #ifdef ECL_ENABLE_GFP_PT_MUL_JAC
212 /* multiply base point by order and check for point at infinity */
213 MP_CHECKOK(ec_GFp_pt_mul_jac
214 (&group->order, &group->genx, &group->geny, &rx, &ry,
215 group));
216 if (ectestPrint) {
217 printf(" (order)*P (jacobian):\n");
218 MP_CHECKOK(mp_toradix(&rx, s, 16));
219 printf(" %s\n", s);
220 MP_CHECKOK(mp_toradix(&ry, s, 16));
221 printf(" %s\n", s);
222 }
223 if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
224 printf(" Error: invalid result (expected point at infinity).\n");
225 res = MP_NO;
226 goto CLEANUP;
227 }
228 #endif
229
230 /* multiply base point by order and check for point at infinity */
231 MP_CHECKOK(ECPoint_mul(group, &group->order, NULL, NULL, &rx, &ry));
232 if (ectestPrint) {
233 printf(" (order)*P (ECPoint_mul):\n");
234 MP_CHECKOK(mp_toradix(&rx, s, 16));
235 printf(" %s\n", s);
236 MP_CHECKOK(mp_toradix(&ry, s, 16));
237 printf(" %s\n", s);
238 }
239 if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
240 printf(" Error: invalid result (expected point at infinity).\n");
241 res = MP_NO;
242 goto CLEANUP;
243 }
244
245 /* multiply base point by order and check for point at infinity */
246 MP_CHECKOK(ECPoint_mul(group, &group->order, &gx, &gy, &rx, &ry));
247 if (ectestPrint) {
248 printf(" (order)*P (ECPoint_mul):\n");
249 MP_CHECKOK(mp_toradix(&rx, s, 16));
250 printf(" %s\n", s);
251 MP_CHECKOK(mp_toradix(&ry, s, 16));
252 printf(" %s\n", s);
253 }
254 if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
255 printf(" Error: invalid result (expected point at infinity).\n");
256 res = MP_NO;
257 goto CLEANUP;
258 }
259
260 /* check that (order-1)P + (order-1)P + P == (order-1)P */
261 MP_CHECKOK(ECPoints_mul
262 (group, &order_1, &order_1, &gx, &gy, &rx, &ry));
263 MP_CHECKOK(ECPoints_mul(group, &one, &one, &rx, &ry, &rx, &ry));
264 if (ectestPrint) {
265 printf
266 (" (order-1)*P + (order-1)*P + P == (order-1)*P (ECPoints_mul):\n");
267 MP_CHECKOK(mp_toradix(&rx, s, 16));
268 printf(" %s\n", s);
269 MP_CHECKOK(mp_toradix(&ry, s, 16));
270 printf(" %s\n", s);
271 }
272 MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
273 if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
274 printf(" Error: invalid result (expected (- base point)).\n");
275 res = MP_NO;
276 goto CLEANUP;
277 }
278
279 /* test validate_point function */
280 if (ECPoint_validate(group, &gx, &gy) != MP_YES) {
281 printf(" Error: validate point on base point failed.\n");
282 res = MP_NO;
283 goto CLEANUP;
284 }
285 MP_CHECKOK(mp_add_d(&gy, 1, &ry));
286 if (ECPoint_validate(group, &gx, &ry) != MP_NO) {
287 printf(" Error: validate point on invalid point passed.\n");
288 res = MP_NO;
289 goto CLEANUP;
290 }
291
292 if (ectestTime) {
293 /* compute random scalar */
294 size = mpl_significant_bits(&group->meth->irr);
295 if (size < MP_OKAY) {
296 goto CLEANUP;
297 }
298 MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS));
299 MP_CHECKOK(group->meth->field_mod(&n, &n, group->meth));
300 /* timed test */
301 if (generic) {
302 #ifdef ECL_ENABLE_GFP_PT_MUL_AFF
303 M_TimeOperation(MP_CHECKOK
304 (ec_GFp_pt_mul_aff
305 (&n, &group->genx, &group->geny, &rx, &ry,
306 group)), 100);
307 #endif
308 M_TimeOperation(MP_CHECKOK
309 (ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
310 100);
311 M_TimeOperation(MP_CHECKOK
312 (ECPoints_mul
313 (group, &n, &n, &gx, &gy, &rx, &ry)), 100);
314 } else {
315 M_TimeOperation(MP_CHECKOK
316 (ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
317 100);
318 M_TimeOperation(MP_CHECKOK
319 (ECPoint_mul(group, &n, &gx, &gy, &rx, &ry)),
320 100);
321 M_TimeOperation(MP_CHECKOK
322 (ECPoints_mul
323 (group, &n, &n, &gx, &gy, &rx, &ry)), 100);
324 }
325 }
326
327 CLEANUP:
328 mp_clear(&one);
329 mp_clear(&order_1);
330 mp_clear(&gx);
331 mp_clear(&gy);
332 mp_clear(&rx);
333 mp_clear(&ry);
334 mp_clear(&n);
335 if (res != MP_OKAY) {
336 printf(" Error: exiting with error value %i\n", res);
337 }
338 return res;
339 }
340
341 /* Prints help information. */
342 void
343 printUsage()
344 {
345 printf("Usage: ecp_test [--print] [--time]\n");
346 printf
347 (" --print Print out results of each point arithmetic test.\n");
348 printf
349 (" --time Benchmark point operations and print results.\n");
350 }
351
352 /* Performs tests of elliptic curve cryptography over prime fields If
353 * tests fail, then it prints an error message, aborts, and returns an
354 * error code. Otherwise, returns 0. */
355 int
356 main(int argv, char **argc)
357 {
358
359 int ectestTime = 0;
360 int ectestPrint = 0;
361 int i;
362 ECGroup *group = NULL;
363 ECCurveParams *params = NULL;
364 mp_err res;
365
366 /* read command-line arguments */
367 for (i = 1; i < argv; i++) {
368 if ((strcasecmp(argc[i], "time") == 0)
369 || (strcasecmp(argc[i], "-time") == 0)
370 || (strcasecmp(argc[i], "--time") == 0)) {
371 ectestTime = 1;
372 } else if ((strcasecmp(argc[i], "print") == 0)
373 || (strcasecmp(argc[i], "-print") == 0)
374 || (strcasecmp(argc[i], "--print") == 0)) {
375 ectestPrint = 1;
376 } else {
377 printUsage();
378 return 0;
379 }
380 }
381
382 /* generic arithmetic tests */
383 ECTEST_GENERIC_GFP("SECP-160R1", ECCurve_SECG_PRIME_160R1);
384
385 /* specific arithmetic tests */
386 ECTEST_NAMED_GFP("NIST-P192", ECCurve_NIST_P192);
387 ECTEST_NAMED_GFP("NIST-P224", ECCurve_NIST_P224);
388 ECTEST_NAMED_GFP("NIST-P256", ECCurve_NIST_P256);
389 ECTEST_NAMED_GFP("NIST-P384", ECCurve_NIST_P384);
390 ECTEST_NAMED_GFP("NIST-P521", ECCurve_NIST_P521);
391 ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v1", ECCurve_X9_62_PRIME_192V1);
392 ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v2", ECCurve_X9_62_PRIME_192V2);
393 ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v3", ECCurve_X9_62_PRIME_192V3);
394 ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v1", ECCurve_X9_62_PRIME_239V1);
395 ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v2", ECCurve_X9_62_PRIME_239V2);
396 ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v3", ECCurve_X9_62_PRIME_239V3);
397 ECTEST_NAMED_GFP("ANSI X9.62 PRIME256v1", ECCurve_X9_62_PRIME_256V1);
398 ECTEST_NAMED_GFP("SECP-112R1", ECCurve_SECG_PRIME_112R1);
399 ECTEST_NAMED_GFP("SECP-112R2", ECCurve_SECG_PRIME_112R2);
400 ECTEST_NAMED_GFP("SECP-128R1", ECCurve_SECG_PRIME_128R1);
401 ECTEST_NAMED_GFP("SECP-128R2", ECCurve_SECG_PRIME_128R2);
402 ECTEST_NAMED_GFP("SECP-160K1", ECCurve_SECG_PRIME_160K1);
403 ECTEST_NAMED_GFP("SECP-160R1", ECCurve_SECG_PRIME_160R1);
404 ECTEST_NAMED_GFP("SECP-160R2", ECCurve_SECG_PRIME_160R2);
405 ECTEST_NAMED_GFP("SECP-192K1", ECCurve_SECG_PRIME_192K1);
406 ECTEST_NAMED_GFP("SECP-192R1", ECCurve_SECG_PRIME_192R1);
407 ECTEST_NAMED_GFP("SECP-224K1", ECCurve_SECG_PRIME_224K1);
408 ECTEST_NAMED_GFP("SECP-224R1", ECCurve_SECG_PRIME_224R1);
409 ECTEST_NAMED_GFP("SECP-256K1", ECCurve_SECG_PRIME_256K1);
410 ECTEST_NAMED_GFP("SECP-256R1", ECCurve_SECG_PRIME_256R1);
411 ECTEST_NAMED_GFP("SECP-384R1", ECCurve_SECG_PRIME_384R1);
412 ECTEST_NAMED_GFP("SECP-521R1", ECCurve_SECG_PRIME_521R1);
413 ECTEST_NAMED_GFP("WTLS-6 (112)", ECCurve_WTLS_6);
414 ECTEST_NAMED_GFP("WTLS-7 (160)", ECCurve_WTLS_7);
415 ECTEST_NAMED_GFP("WTLS-8 (112)", ECCurve_WTLS_8);
416 ECTEST_NAMED_GFP("WTLS-9 (160)", ECCurve_WTLS_9);
417 ECTEST_NAMED_GFP("WTLS-12 (224)", ECCurve_WTLS_12);
418
419 CLEANUP:
420 EC_FreeCurveParams(params);
421 ECGroup_free(group);
422 if (res != MP_OKAY) {
423 printf("Error: exiting with error value %i\n", res);
424 }
425 return res;
426 }

mercurial