|
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 "ecp_fp.h" |
|
6 #include "mpprime.h" |
|
7 |
|
8 #include <stdio.h> |
|
9 #include <time.h> |
|
10 #include <sys/time.h> |
|
11 #include <sys/resource.h> |
|
12 |
|
13 /* Time k repetitions of operation op. */ |
|
14 #define M_TimeOperation(op, k) { \ |
|
15 double dStart, dNow, dUserTime; \ |
|
16 struct rusage ru; \ |
|
17 int i; \ |
|
18 getrusage(RUSAGE_SELF, &ru); \ |
|
19 dStart = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \ |
|
20 for (i = 0; i < k; i++) { \ |
|
21 { op; } \ |
|
22 }; \ |
|
23 getrusage(RUSAGE_SELF, &ru); \ |
|
24 dNow = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \ |
|
25 dUserTime = dNow-dStart; \ |
|
26 if (dUserTime) printf(" %-45s\n k: %6i, t: %6.2f sec, k/t: %6.2f ops/sec\n", #op, k, dUserTime, k/dUserTime); \ |
|
27 } |
|
28 |
|
29 /* Test curve using specific floating point field arithmetic. */ |
|
30 #define M_TestCurve(name_c, name) { \ |
|
31 printf("Testing %s using specific floating point implementation...\n", name_c); \ |
|
32 ECGroup_free(ecgroup); \ |
|
33 ecgroup = ECGroup_fromName(name); \ |
|
34 if (ecgroup == NULL) { \ |
|
35 printf(" Warning: could not construct group.\n"); \ |
|
36 printf("%s failed.\n", name_c); \ |
|
37 res = MP_NO; \ |
|
38 goto CLEANUP; \ |
|
39 } else { \ |
|
40 MP_CHECKOK( testCurve(ecgroup)); \ |
|
41 printf("%s passed.\n", name_c); \ |
|
42 } \ |
|
43 } |
|
44 |
|
45 /* Outputs a floating point double (currently not used) */ |
|
46 void |
|
47 d_output(const double *u, int len, char *name, const EC_group_fp * group) |
|
48 { |
|
49 int i; |
|
50 |
|
51 printf("%s: ", name); |
|
52 for (i = 0; i < len; i++) { |
|
53 printf("+ %.2f * 2^%i ", u[i] / ecfp_exp[i], |
|
54 group->doubleBitSize * i); |
|
55 } |
|
56 printf("\n"); |
|
57 } |
|
58 |
|
59 /* Tests a point p in Jacobian coordinates, comparing against the |
|
60 * expected affine result (x, y). */ |
|
61 mp_err |
|
62 testJacPoint(ecfp_jac_pt * p, mp_int *x, mp_int *y, ECGroup *ecgroup) |
|
63 { |
|
64 char s[1000]; |
|
65 mp_int rx, ry, rz; |
|
66 mp_err res = MP_OKAY; |
|
67 |
|
68 MP_DIGITS(&rx) = 0; |
|
69 MP_DIGITS(&ry) = 0; |
|
70 MP_DIGITS(&rz) = 0; |
|
71 |
|
72 MP_CHECKOK(mp_init(&rx)); |
|
73 MP_CHECKOK(mp_init(&ry)); |
|
74 MP_CHECKOK(mp_init(&rz)); |
|
75 |
|
76 ecfp_fp2i(&rx, p->x, ecgroup); |
|
77 ecfp_fp2i(&ry, p->y, ecgroup); |
|
78 ecfp_fp2i(&rz, p->z, ecgroup); |
|
79 |
|
80 /* convert result R to affine coordinates */ |
|
81 ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup); |
|
82 |
|
83 /* Compare to expected result */ |
|
84 if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) { |
|
85 printf(" Error: Jacobian Floating Point Incorrect.\n"); |
|
86 MP_CHECKOK(mp_toradix(&rx, s, 16)); |
|
87 printf("floating point result\nrx %s\n", s); |
|
88 MP_CHECKOK(mp_toradix(&ry, s, 16)); |
|
89 printf("ry %s\n", s); |
|
90 MP_CHECKOK(mp_toradix(x, s, 16)); |
|
91 printf("integer result\nx %s\n", s); |
|
92 MP_CHECKOK(mp_toradix(y, s, 16)); |
|
93 printf("y %s\n", s); |
|
94 res = MP_NO; |
|
95 goto CLEANUP; |
|
96 } |
|
97 |
|
98 CLEANUP: |
|
99 mp_clear(&rx); |
|
100 mp_clear(&ry); |
|
101 mp_clear(&rz); |
|
102 |
|
103 return res; |
|
104 } |
|
105 |
|
106 /* Tests a point p in Chudnovsky Jacobian coordinates, comparing against |
|
107 * the expected affine result (x, y). */ |
|
108 mp_err |
|
109 testChudPoint(ecfp_chud_pt * p, mp_int *x, mp_int *y, ECGroup *ecgroup) |
|
110 { |
|
111 |
|
112 char s[1000]; |
|
113 mp_int rx, ry, rz, rz2, rz3, test; |
|
114 mp_err res = MP_OKAY; |
|
115 |
|
116 /* Initialization */ |
|
117 MP_DIGITS(&rx) = 0; |
|
118 MP_DIGITS(&ry) = 0; |
|
119 MP_DIGITS(&rz) = 0; |
|
120 MP_DIGITS(&rz2) = 0; |
|
121 MP_DIGITS(&rz3) = 0; |
|
122 MP_DIGITS(&test) = 0; |
|
123 |
|
124 MP_CHECKOK(mp_init(&rx)); |
|
125 MP_CHECKOK(mp_init(&ry)); |
|
126 MP_CHECKOK(mp_init(&rz)); |
|
127 MP_CHECKOK(mp_init(&rz2)); |
|
128 MP_CHECKOK(mp_init(&rz3)); |
|
129 MP_CHECKOK(mp_init(&test)); |
|
130 |
|
131 /* Convert to integers */ |
|
132 ecfp_fp2i(&rx, p->x, ecgroup); |
|
133 ecfp_fp2i(&ry, p->y, ecgroup); |
|
134 ecfp_fp2i(&rz, p->z, ecgroup); |
|
135 ecfp_fp2i(&rz2, p->z2, ecgroup); |
|
136 ecfp_fp2i(&rz3, p->z3, ecgroup); |
|
137 |
|
138 /* Verify z2, z3 are valid */ |
|
139 mp_sqrmod(&rz, &ecgroup->meth->irr, &test); |
|
140 if (mp_cmp(&test, &rz2) != 0) { |
|
141 printf(" Error: rzp2 not valid\n"); |
|
142 res = MP_NO; |
|
143 goto CLEANUP; |
|
144 } |
|
145 mp_mulmod(&test, &rz, &ecgroup->meth->irr, &test); |
|
146 if (mp_cmp(&test, &rz3) != 0) { |
|
147 printf(" Error: rzp2 not valid\n"); |
|
148 res = MP_NO; |
|
149 goto CLEANUP; |
|
150 } |
|
151 |
|
152 /* convert result R to affine coordinates */ |
|
153 ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup); |
|
154 |
|
155 /* Compare against expected result */ |
|
156 if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) { |
|
157 printf(" Error: Chudnovsky Floating Point Incorrect.\n"); |
|
158 MP_CHECKOK(mp_toradix(&rx, s, 16)); |
|
159 printf("floating point result\nrx %s\n", s); |
|
160 MP_CHECKOK(mp_toradix(&ry, s, 16)); |
|
161 printf("ry %s\n", s); |
|
162 MP_CHECKOK(mp_toradix(x, s, 16)); |
|
163 printf("integer result\nx %s\n", s); |
|
164 MP_CHECKOK(mp_toradix(y, s, 16)); |
|
165 printf("y %s\n", s); |
|
166 res = MP_NO; |
|
167 goto CLEANUP; |
|
168 } |
|
169 |
|
170 CLEANUP: |
|
171 mp_clear(&rx); |
|
172 mp_clear(&ry); |
|
173 mp_clear(&rz); |
|
174 mp_clear(&rz2); |
|
175 mp_clear(&rz3); |
|
176 mp_clear(&test); |
|
177 |
|
178 return res; |
|
179 } |
|
180 |
|
181 /* Tests a point p in Modified Jacobian coordinates, comparing against the |
|
182 * expected affine result (x, y). */ |
|
183 mp_err |
|
184 testJmPoint(ecfp_jm_pt * r, mp_int *x, mp_int *y, ECGroup *ecgroup) |
|
185 { |
|
186 |
|
187 char s[1000]; |
|
188 mp_int rx, ry, rz, raz4, test; |
|
189 mp_err res = MP_OKAY; |
|
190 |
|
191 /* Initialization */ |
|
192 MP_DIGITS(&rx) = 0; |
|
193 MP_DIGITS(&ry) = 0; |
|
194 MP_DIGITS(&rz) = 0; |
|
195 MP_DIGITS(&raz4) = 0; |
|
196 MP_DIGITS(&test) = 0; |
|
197 |
|
198 MP_CHECKOK(mp_init(&rx)); |
|
199 MP_CHECKOK(mp_init(&ry)); |
|
200 MP_CHECKOK(mp_init(&rz)); |
|
201 MP_CHECKOK(mp_init(&raz4)); |
|
202 MP_CHECKOK(mp_init(&test)); |
|
203 |
|
204 /* Convert to integer */ |
|
205 ecfp_fp2i(&rx, r->x, ecgroup); |
|
206 ecfp_fp2i(&ry, r->y, ecgroup); |
|
207 ecfp_fp2i(&rz, r->z, ecgroup); |
|
208 ecfp_fp2i(&raz4, r->az4, ecgroup); |
|
209 |
|
210 /* Verify raz4 = rz^4 * a */ |
|
211 mp_sqrmod(&rz, &ecgroup->meth->irr, &test); |
|
212 mp_sqrmod(&test, &ecgroup->meth->irr, &test); |
|
213 mp_mulmod(&test, &ecgroup->curvea, &ecgroup->meth->irr, &test); |
|
214 if (mp_cmp(&test, &raz4) != 0) { |
|
215 printf(" Error: a*z^4 not valid\n"); |
|
216 MP_CHECKOK(mp_toradix(&ecgroup->curvea, s, 16)); |
|
217 printf("a %s\n", s); |
|
218 MP_CHECKOK(mp_toradix(&rz, s, 16)); |
|
219 printf("rz %s\n", s); |
|
220 MP_CHECKOK(mp_toradix(&raz4, s, 16)); |
|
221 printf("raz4 %s\n", s); |
|
222 res = MP_NO; |
|
223 goto CLEANUP; |
|
224 } |
|
225 |
|
226 /* convert result R to affine coordinates */ |
|
227 ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup); |
|
228 |
|
229 /* Compare against expected result */ |
|
230 if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) { |
|
231 printf(" Error: Modified Jacobian Floating Point Incorrect.\n"); |
|
232 MP_CHECKOK(mp_toradix(&rx, s, 16)); |
|
233 printf("floating point result\nrx %s\n", s); |
|
234 MP_CHECKOK(mp_toradix(&ry, s, 16)); |
|
235 printf("ry %s\n", s); |
|
236 MP_CHECKOK(mp_toradix(x, s, 16)); |
|
237 printf("integer result\nx %s\n", s); |
|
238 MP_CHECKOK(mp_toradix(y, s, 16)); |
|
239 printf("y %s\n", s); |
|
240 res = MP_NO; |
|
241 goto CLEANUP; |
|
242 } |
|
243 CLEANUP: |
|
244 mp_clear(&rx); |
|
245 mp_clear(&ry); |
|
246 mp_clear(&rz); |
|
247 mp_clear(&raz4); |
|
248 mp_clear(&test); |
|
249 |
|
250 return res; |
|
251 } |
|
252 |
|
253 /* Tests point addition of Jacobian + Affine -> Jacobian */ |
|
254 mp_err |
|
255 testPointAddJacAff(ECGroup *ecgroup) |
|
256 { |
|
257 mp_err res; |
|
258 mp_int pz, rx2, ry2, rz2; |
|
259 ecfp_jac_pt p, r; |
|
260 ecfp_aff_pt q; |
|
261 EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; |
|
262 |
|
263 /* Init */ |
|
264 MP_DIGITS(&pz) = 0; |
|
265 MP_DIGITS(&rx2) = 0; |
|
266 MP_DIGITS(&ry2) = 0; |
|
267 MP_DIGITS(&rz2) = 0; |
|
268 MP_CHECKOK(mp_init(&pz)); |
|
269 MP_CHECKOK(mp_init(&rx2)); |
|
270 MP_CHECKOK(mp_init(&ry2)); |
|
271 MP_CHECKOK(mp_init(&rz2)); |
|
272 |
|
273 MP_CHECKOK(mp_set_int(&pz, 5)); |
|
274 |
|
275 /* Set p */ |
|
276 ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); |
|
277 ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); |
|
278 ecfp_i2fp(p.z, &pz, ecgroup); |
|
279 /* Set q */ |
|
280 ecfp_i2fp(q.x, &ecgroup->geny, ecgroup); |
|
281 ecfp_i2fp(q.y, &ecgroup->genx, ecgroup); |
|
282 |
|
283 /* Do calculations */ |
|
284 group->pt_add_jac_aff(&p, &q, &r, group); |
|
285 |
|
286 /* Do calculation in integer to compare against */ |
|
287 MP_CHECKOK(ec_GFp_pt_add_jac_aff |
|
288 (&ecgroup->genx, &ecgroup->geny, &pz, &ecgroup->geny, |
|
289 &ecgroup->genx, &rx2, &ry2, &rz2, ecgroup)); |
|
290 /* convert result R to affine coordinates */ |
|
291 ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup); |
|
292 |
|
293 MP_CHECKOK(testJacPoint(&r, &rx2, &ry2, ecgroup)); |
|
294 |
|
295 CLEANUP: |
|
296 if (res == MP_OKAY) |
|
297 printf(" Test Passed - Point Addition - Jacobian & Affine\n"); |
|
298 else |
|
299 printf("TEST FAILED - Point Addition - Jacobian & Affine\n"); |
|
300 |
|
301 mp_clear(&pz); |
|
302 mp_clear(&rx2); |
|
303 mp_clear(&ry2); |
|
304 mp_clear(&rz2); |
|
305 |
|
306 return res; |
|
307 } |
|
308 |
|
309 /* Tests point addition in Jacobian coordinates */ |
|
310 mp_err |
|
311 testPointAddJac(ECGroup *ecgroup) |
|
312 { |
|
313 mp_err res; |
|
314 mp_int pz, qz, qx, qy, rx2, ry2, rz2; |
|
315 ecfp_jac_pt p, q, r; |
|
316 EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; |
|
317 |
|
318 /* Init */ |
|
319 MP_DIGITS(&pz) = 0; |
|
320 MP_DIGITS(&qx) = 0; |
|
321 MP_DIGITS(&qy) = 0; |
|
322 MP_DIGITS(&qz) = 0; |
|
323 MP_DIGITS(&rx2) = 0; |
|
324 MP_DIGITS(&ry2) = 0; |
|
325 MP_DIGITS(&rz2) = 0; |
|
326 MP_CHECKOK(mp_init(&pz)); |
|
327 MP_CHECKOK(mp_init(&qx)); |
|
328 MP_CHECKOK(mp_init(&qy)); |
|
329 MP_CHECKOK(mp_init(&qz)); |
|
330 MP_CHECKOK(mp_init(&rx2)); |
|
331 MP_CHECKOK(mp_init(&ry2)); |
|
332 MP_CHECKOK(mp_init(&rz2)); |
|
333 |
|
334 MP_CHECKOK(mp_set_int(&pz, 5)); |
|
335 MP_CHECKOK(mp_set_int(&qz, 105)); |
|
336 |
|
337 /* Set p */ |
|
338 ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); |
|
339 ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); |
|
340 ecfp_i2fp(p.z, &pz, ecgroup); |
|
341 /* Set q */ |
|
342 ecfp_i2fp(q.x, &ecgroup->geny, ecgroup); |
|
343 ecfp_i2fp(q.y, &ecgroup->genx, ecgroup); |
|
344 ecfp_i2fp(q.z, &qz, ecgroup); |
|
345 |
|
346 /* Do calculations */ |
|
347 group->pt_add_jac(&p, &q, &r, group); |
|
348 |
|
349 /* Do calculation in integer to compare against */ |
|
350 ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy, |
|
351 ecgroup); |
|
352 MP_CHECKOK(ec_GFp_pt_add_jac_aff |
|
353 (&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy, &rx2, &ry2, |
|
354 &rz2, ecgroup)); |
|
355 /* convert result R to affine coordinates */ |
|
356 ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup); |
|
357 |
|
358 MP_CHECKOK(testJacPoint(&r, &rx2, &ry2, ecgroup)); |
|
359 |
|
360 CLEANUP: |
|
361 if (res == MP_OKAY) |
|
362 printf(" Test Passed - Point Addition - Jacobian\n"); |
|
363 else |
|
364 printf("TEST FAILED - Point Addition - Jacobian\n"); |
|
365 |
|
366 mp_clear(&pz); |
|
367 mp_clear(&qx); |
|
368 mp_clear(&qy); |
|
369 mp_clear(&qz); |
|
370 mp_clear(&rx2); |
|
371 mp_clear(&ry2); |
|
372 mp_clear(&rz2); |
|
373 |
|
374 return res; |
|
375 } |
|
376 |
|
377 /* Tests point addition in Chudnovsky Jacobian Coordinates */ |
|
378 mp_err |
|
379 testPointAddChud(ECGroup *ecgroup) |
|
380 { |
|
381 mp_err res; |
|
382 mp_int rx2, ry2, ix, iy, iz, test, pz, qx, qy, qz; |
|
383 ecfp_chud_pt p, q, r; |
|
384 EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; |
|
385 |
|
386 MP_DIGITS(&qx) = 0; |
|
387 MP_DIGITS(&qy) = 0; |
|
388 MP_DIGITS(&qz) = 0; |
|
389 MP_DIGITS(&pz) = 0; |
|
390 MP_DIGITS(&rx2) = 0; |
|
391 MP_DIGITS(&ry2) = 0; |
|
392 MP_DIGITS(&ix) = 0; |
|
393 MP_DIGITS(&iy) = 0; |
|
394 MP_DIGITS(&iz) = 0; |
|
395 MP_DIGITS(&test) = 0; |
|
396 |
|
397 MP_CHECKOK(mp_init(&qx)); |
|
398 MP_CHECKOK(mp_init(&qy)); |
|
399 MP_CHECKOK(mp_init(&qz)); |
|
400 MP_CHECKOK(mp_init(&pz)); |
|
401 MP_CHECKOK(mp_init(&rx2)); |
|
402 MP_CHECKOK(mp_init(&ry2)); |
|
403 MP_CHECKOK(mp_init(&ix)); |
|
404 MP_CHECKOK(mp_init(&iy)); |
|
405 MP_CHECKOK(mp_init(&iz)); |
|
406 MP_CHECKOK(mp_init(&test)); |
|
407 |
|
408 /* Test Chudnovsky form addition */ |
|
409 /* Set p */ |
|
410 MP_CHECKOK(mp_set_int(&pz, 5)); |
|
411 ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); |
|
412 ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); |
|
413 ecfp_i2fp(p.z, &pz, ecgroup); |
|
414 mp_sqrmod(&pz, &ecgroup->meth->irr, &test); |
|
415 ecfp_i2fp(p.z2, &test, ecgroup); |
|
416 mp_mulmod(&test, &pz, &ecgroup->meth->irr, &test); |
|
417 ecfp_i2fp(p.z3, &test, ecgroup); |
|
418 |
|
419 /* Set q */ |
|
420 MP_CHECKOK(mp_set_int(&qz, 105)); |
|
421 ecfp_i2fp(q.x, &ecgroup->geny, ecgroup); |
|
422 ecfp_i2fp(q.y, &ecgroup->genx, ecgroup); |
|
423 ecfp_i2fp(q.z, &qz, ecgroup); |
|
424 mp_sqrmod(&qz, &ecgroup->meth->irr, &test); |
|
425 ecfp_i2fp(q.z2, &test, ecgroup); |
|
426 mp_mulmod(&test, &qz, &ecgroup->meth->irr, &test); |
|
427 ecfp_i2fp(q.z3, &test, ecgroup); |
|
428 |
|
429 group->pt_add_chud(&p, &q, &r, group); |
|
430 |
|
431 /* Calculate addition to compare against */ |
|
432 ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy, |
|
433 ecgroup); |
|
434 ec_GFp_pt_add_jac_aff(&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy, |
|
435 &ix, &iy, &iz, ecgroup); |
|
436 ec_GFp_pt_jac2aff(&ix, &iy, &iz, &rx2, &ry2, ecgroup); |
|
437 |
|
438 MP_CHECKOK(testChudPoint(&r, &rx2, &ry2, ecgroup)); |
|
439 |
|
440 CLEANUP: |
|
441 if (res == MP_OKAY) |
|
442 printf(" Test Passed - Point Addition - Chudnovsky Jacobian\n"); |
|
443 else |
|
444 printf("TEST FAILED - Point Addition - Chudnovsky Jacobian\n"); |
|
445 |
|
446 mp_clear(&qx); |
|
447 mp_clear(&qy); |
|
448 mp_clear(&qz); |
|
449 mp_clear(&pz); |
|
450 mp_clear(&rx2); |
|
451 mp_clear(&ry2); |
|
452 mp_clear(&ix); |
|
453 mp_clear(&iy); |
|
454 mp_clear(&iz); |
|
455 mp_clear(&test); |
|
456 |
|
457 return res; |
|
458 } |
|
459 |
|
460 /* Tests point addition in Modified Jacobian + Chudnovsky Jacobian -> |
|
461 * Modified Jacobian coordinates. */ |
|
462 mp_err |
|
463 testPointAddJmChud(ECGroup *ecgroup) |
|
464 { |
|
465 mp_err res; |
|
466 mp_int rx2, ry2, ix, iy, iz, test, pz, paz4, qx, qy, qz; |
|
467 ecfp_chud_pt q; |
|
468 ecfp_jm_pt p, r; |
|
469 EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; |
|
470 |
|
471 MP_DIGITS(&qx) = 0; |
|
472 MP_DIGITS(&qy) = 0; |
|
473 MP_DIGITS(&qz) = 0; |
|
474 MP_DIGITS(&pz) = 0; |
|
475 MP_DIGITS(&paz4) = 0; |
|
476 MP_DIGITS(&iz) = 0; |
|
477 MP_DIGITS(&rx2) = 0; |
|
478 MP_DIGITS(&ry2) = 0; |
|
479 MP_DIGITS(&ix) = 0; |
|
480 MP_DIGITS(&iy) = 0; |
|
481 MP_DIGITS(&iz) = 0; |
|
482 MP_DIGITS(&test) = 0; |
|
483 |
|
484 MP_CHECKOK(mp_init(&qx)); |
|
485 MP_CHECKOK(mp_init(&qy)); |
|
486 MP_CHECKOK(mp_init(&qz)); |
|
487 MP_CHECKOK(mp_init(&pz)); |
|
488 MP_CHECKOK(mp_init(&paz4)); |
|
489 MP_CHECKOK(mp_init(&rx2)); |
|
490 MP_CHECKOK(mp_init(&ry2)); |
|
491 MP_CHECKOK(mp_init(&ix)); |
|
492 MP_CHECKOK(mp_init(&iy)); |
|
493 MP_CHECKOK(mp_init(&iz)); |
|
494 MP_CHECKOK(mp_init(&test)); |
|
495 |
|
496 /* Test Modified Jacobian form addition */ |
|
497 /* Set p */ |
|
498 ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); |
|
499 ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); |
|
500 ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup); |
|
501 /* paz4 = az^4 */ |
|
502 MP_CHECKOK(mp_set_int(&pz, 5)); |
|
503 mp_sqrmod(&pz, &ecgroup->meth->irr, &paz4); |
|
504 mp_sqrmod(&paz4, &ecgroup->meth->irr, &paz4); |
|
505 mp_mulmod(&paz4, &ecgroup->curvea, &ecgroup->meth->irr, &paz4); |
|
506 ecfp_i2fp(p.z, &pz, ecgroup); |
|
507 ecfp_i2fp(p.az4, &paz4, ecgroup); |
|
508 |
|
509 /* Set q */ |
|
510 MP_CHECKOK(mp_set_int(&qz, 105)); |
|
511 ecfp_i2fp(q.x, &ecgroup->geny, ecgroup); |
|
512 ecfp_i2fp(q.y, &ecgroup->genx, ecgroup); |
|
513 ecfp_i2fp(q.z, &qz, ecgroup); |
|
514 mp_sqrmod(&qz, &ecgroup->meth->irr, &test); |
|
515 ecfp_i2fp(q.z2, &test, ecgroup); |
|
516 mp_mulmod(&test, &qz, &ecgroup->meth->irr, &test); |
|
517 ecfp_i2fp(q.z3, &test, ecgroup); |
|
518 |
|
519 /* Do calculation */ |
|
520 group->pt_add_jm_chud(&p, &q, &r, group); |
|
521 |
|
522 /* Calculate addition to compare against */ |
|
523 ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy, |
|
524 ecgroup); |
|
525 ec_GFp_pt_add_jac_aff(&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy, |
|
526 &ix, &iy, &iz, ecgroup); |
|
527 ec_GFp_pt_jac2aff(&ix, &iy, &iz, &rx2, &ry2, ecgroup); |
|
528 |
|
529 MP_CHECKOK(testJmPoint(&r, &rx2, &ry2, ecgroup)); |
|
530 |
|
531 CLEANUP: |
|
532 if (res == MP_OKAY) |
|
533 printf |
|
534 (" Test Passed - Point Addition - Modified & Chudnovsky Jacobian\n"); |
|
535 else |
|
536 printf |
|
537 ("TEST FAILED - Point Addition - Modified & Chudnovsky Jacobian\n"); |
|
538 |
|
539 mp_clear(&qx); |
|
540 mp_clear(&qy); |
|
541 mp_clear(&qz); |
|
542 mp_clear(&pz); |
|
543 mp_clear(&paz4); |
|
544 mp_clear(&rx2); |
|
545 mp_clear(&ry2); |
|
546 mp_clear(&ix); |
|
547 mp_clear(&iy); |
|
548 mp_clear(&iz); |
|
549 mp_clear(&test); |
|
550 |
|
551 return res; |
|
552 } |
|
553 |
|
554 /* Tests point doubling in Modified Jacobian coordinates */ |
|
555 mp_err |
|
556 testPointDoubleJm(ECGroup *ecgroup) |
|
557 { |
|
558 mp_err res; |
|
559 mp_int pz, paz4, rx2, ry2, rz2, raz4; |
|
560 ecfp_jm_pt p, r; |
|
561 EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; |
|
562 |
|
563 MP_DIGITS(&pz) = 0; |
|
564 MP_DIGITS(&paz4) = 0; |
|
565 MP_DIGITS(&rx2) = 0; |
|
566 MP_DIGITS(&ry2) = 0; |
|
567 MP_DIGITS(&rz2) = 0; |
|
568 MP_DIGITS(&raz4) = 0; |
|
569 |
|
570 MP_CHECKOK(mp_init(&pz)); |
|
571 MP_CHECKOK(mp_init(&paz4)); |
|
572 MP_CHECKOK(mp_init(&rx2)); |
|
573 MP_CHECKOK(mp_init(&ry2)); |
|
574 MP_CHECKOK(mp_init(&rz2)); |
|
575 MP_CHECKOK(mp_init(&raz4)); |
|
576 |
|
577 /* Set p */ |
|
578 ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); |
|
579 ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); |
|
580 ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup); |
|
581 |
|
582 /* paz4 = az^4 */ |
|
583 MP_CHECKOK(mp_set_int(&pz, 5)); |
|
584 mp_sqrmod(&pz, &ecgroup->meth->irr, &paz4); |
|
585 mp_sqrmod(&paz4, &ecgroup->meth->irr, &paz4); |
|
586 mp_mulmod(&paz4, &ecgroup->curvea, &ecgroup->meth->irr, &paz4); |
|
587 |
|
588 ecfp_i2fp(p.z, &pz, ecgroup); |
|
589 ecfp_i2fp(p.az4, &paz4, ecgroup); |
|
590 |
|
591 group->pt_dbl_jm(&p, &r, group); |
|
592 |
|
593 M_TimeOperation(group->pt_dbl_jm(&p, &r, group), 100000); |
|
594 |
|
595 /* Calculate doubling to compare against */ |
|
596 ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2, |
|
597 &rz2, ecgroup); |
|
598 ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup); |
|
599 |
|
600 /* Do comparison and check az^4 */ |
|
601 MP_CHECKOK(testJmPoint(&r, &rx2, &ry2, ecgroup)); |
|
602 |
|
603 CLEANUP: |
|
604 if (res == MP_OKAY) |
|
605 printf(" Test Passed - Point Doubling - Modified Jacobian\n"); |
|
606 else |
|
607 printf("TEST FAILED - Point Doubling - Modified Jacobian\n"); |
|
608 mp_clear(&pz); |
|
609 mp_clear(&paz4); |
|
610 mp_clear(&rx2); |
|
611 mp_clear(&ry2); |
|
612 mp_clear(&rz2); |
|
613 mp_clear(&raz4); |
|
614 |
|
615 return res; |
|
616 |
|
617 } |
|
618 |
|
619 /* Tests point doubling in Chudnovsky Jacobian coordinates */ |
|
620 mp_err |
|
621 testPointDoubleChud(ECGroup *ecgroup) |
|
622 { |
|
623 mp_err res; |
|
624 mp_int px, py, pz, rx2, ry2, rz2; |
|
625 ecfp_aff_pt p; |
|
626 ecfp_chud_pt p2; |
|
627 EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; |
|
628 |
|
629 MP_DIGITS(&rx2) = 0; |
|
630 MP_DIGITS(&ry2) = 0; |
|
631 MP_DIGITS(&rz2) = 0; |
|
632 MP_DIGITS(&px) = 0; |
|
633 MP_DIGITS(&py) = 0; |
|
634 MP_DIGITS(&pz) = 0; |
|
635 |
|
636 MP_CHECKOK(mp_init(&rx2)); |
|
637 MP_CHECKOK(mp_init(&ry2)); |
|
638 MP_CHECKOK(mp_init(&rz2)); |
|
639 MP_CHECKOK(mp_init(&px)); |
|
640 MP_CHECKOK(mp_init(&py)); |
|
641 MP_CHECKOK(mp_init(&pz)); |
|
642 |
|
643 /* Set p2 = 2P */ |
|
644 ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); |
|
645 ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); |
|
646 ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup); |
|
647 |
|
648 group->pt_dbl_aff2chud(&p, &p2, group); |
|
649 |
|
650 /* Calculate doubling to compare against */ |
|
651 MP_CHECKOK(mp_set_int(&pz, 1)); |
|
652 ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2, |
|
653 &rz2, ecgroup); |
|
654 ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup); |
|
655 |
|
656 /* Do comparison and check az^4 */ |
|
657 MP_CHECKOK(testChudPoint(&p2, &rx2, &ry2, ecgroup)); |
|
658 |
|
659 CLEANUP: |
|
660 if (res == MP_OKAY) |
|
661 printf(" Test Passed - Point Doubling - Chudnovsky Jacobian\n"); |
|
662 else |
|
663 printf("TEST FAILED - Point Doubling - Chudnovsky Jacobian\n"); |
|
664 |
|
665 mp_clear(&rx2); |
|
666 mp_clear(&ry2); |
|
667 mp_clear(&rz2); |
|
668 mp_clear(&px); |
|
669 mp_clear(&py); |
|
670 mp_clear(&pz); |
|
671 |
|
672 return res; |
|
673 } |
|
674 |
|
675 /* Test point doubling in Jacobian coordinates */ |
|
676 mp_err |
|
677 testPointDoubleJac(ECGroup *ecgroup) |
|
678 { |
|
679 mp_err res; |
|
680 mp_int pz, rx, ry, rz, rx2, ry2, rz2; |
|
681 ecfp_jac_pt p, p2; |
|
682 EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; |
|
683 |
|
684 MP_DIGITS(&pz) = 0; |
|
685 MP_DIGITS(&rx) = 0; |
|
686 MP_DIGITS(&ry) = 0; |
|
687 MP_DIGITS(&rz) = 0; |
|
688 MP_DIGITS(&rx2) = 0; |
|
689 MP_DIGITS(&ry2) = 0; |
|
690 MP_DIGITS(&rz2) = 0; |
|
691 |
|
692 MP_CHECKOK(mp_init(&pz)); |
|
693 MP_CHECKOK(mp_init(&rx)); |
|
694 MP_CHECKOK(mp_init(&ry)); |
|
695 MP_CHECKOK(mp_init(&rz)); |
|
696 MP_CHECKOK(mp_init(&rx2)); |
|
697 MP_CHECKOK(mp_init(&ry2)); |
|
698 MP_CHECKOK(mp_init(&rz2)); |
|
699 |
|
700 MP_CHECKOK(mp_set_int(&pz, 5)); |
|
701 |
|
702 /* Set p2 = 2P */ |
|
703 ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); |
|
704 ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); |
|
705 ecfp_i2fp(p.z, &pz, ecgroup); |
|
706 ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup); |
|
707 |
|
708 group->pt_dbl_jac(&p, &p2, group); |
|
709 M_TimeOperation(group->pt_dbl_jac(&p, &p2, group), 100000); |
|
710 |
|
711 /* Calculate doubling to compare against */ |
|
712 ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2, |
|
713 &rz2, ecgroup); |
|
714 ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup); |
|
715 |
|
716 /* Do comparison */ |
|
717 MP_CHECKOK(testJacPoint(&p2, &rx2, &ry2, ecgroup)); |
|
718 |
|
719 CLEANUP: |
|
720 if (res == MP_OKAY) |
|
721 printf(" Test Passed - Point Doubling - Jacobian\n"); |
|
722 else |
|
723 printf("TEST FAILED - Point Doubling - Jacobian\n"); |
|
724 |
|
725 mp_clear(&pz); |
|
726 mp_clear(&rx); |
|
727 mp_clear(&ry); |
|
728 mp_clear(&rz); |
|
729 mp_clear(&rx2); |
|
730 mp_clear(&ry2); |
|
731 mp_clear(&rz2); |
|
732 |
|
733 return res; |
|
734 } |
|
735 |
|
736 /* Tests a point multiplication (various algorithms) */ |
|
737 mp_err |
|
738 testPointMul(ECGroup *ecgroup) |
|
739 { |
|
740 mp_err res; |
|
741 char s[1000]; |
|
742 mp_int rx, ry, order_1; |
|
743 |
|
744 /* Init */ |
|
745 MP_DIGITS(&rx) = 0; |
|
746 MP_DIGITS(&ry) = 0; |
|
747 MP_DIGITS(&order_1) = 0; |
|
748 |
|
749 MP_CHECKOK(mp_init(&rx)); |
|
750 MP_CHECKOK(mp_init(&ry)); |
|
751 MP_CHECKOK(mp_init(&order_1)); |
|
752 |
|
753 MP_CHECKOK(mp_set_int(&order_1, 1)); |
|
754 MP_CHECKOK(mp_sub(&ecgroup->order, &order_1, &order_1)); |
|
755 |
|
756 /* Test Algorithm 1: Jacobian-Affine Double & Add */ |
|
757 ec_GFp_pt_mul_jac_fp(&order_1, &ecgroup->genx, &ecgroup->geny, &rx, |
|
758 &ry, ecgroup); |
|
759 MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth)); |
|
760 if ((mp_cmp(&rx, &ecgroup->genx) != 0) |
|
761 || (mp_cmp(&ry, &ecgroup->geny) != 0)) { |
|
762 printf |
|
763 (" Error: ec_GFp_pt_mul_jac_fp invalid result (expected (- base point)).\n"); |
|
764 MP_CHECKOK(mp_toradix(&rx, s, 16)); |
|
765 printf("rx %s\n", s); |
|
766 MP_CHECKOK(mp_toradix(&ry, s, 16)); |
|
767 printf("ry %s\n", s); |
|
768 res = MP_NO; |
|
769 goto CLEANUP; |
|
770 } |
|
771 |
|
772 ec_GFp_pt_mul_jac_fp(&ecgroup->order, &ecgroup->genx, &ecgroup->geny, |
|
773 &rx, &ry, ecgroup); |
|
774 if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { |
|
775 printf |
|
776 (" Error: ec_GFp_pt_mul_jac_fp invalid result (expected point at infinity.\n"); |
|
777 MP_CHECKOK(mp_toradix(&rx, s, 16)); |
|
778 printf("rx %s\n", s); |
|
779 MP_CHECKOK(mp_toradix(&ry, s, 16)); |
|
780 printf("ry %s\n", s); |
|
781 res = MP_NO; |
|
782 goto CLEANUP; |
|
783 } |
|
784 |
|
785 /* Test Algorithm 2: 4-bit Window in Jacobian */ |
|
786 ec_GFp_point_mul_jac_4w_fp(&order_1, &ecgroup->genx, &ecgroup->geny, |
|
787 &rx, &ry, ecgroup); |
|
788 MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth)); |
|
789 if ((mp_cmp(&rx, &ecgroup->genx) != 0) |
|
790 || (mp_cmp(&ry, &ecgroup->geny) != 0)) { |
|
791 printf |
|
792 (" Error: ec_GFp_point_mul_jac_4w_fp invalid result (expected (- base point)).\n"); |
|
793 MP_CHECKOK(mp_toradix(&rx, s, 16)); |
|
794 printf("rx %s\n", s); |
|
795 MP_CHECKOK(mp_toradix(&ry, s, 16)); |
|
796 printf("ry %s\n", s); |
|
797 res = MP_NO; |
|
798 goto CLEANUP; |
|
799 } |
|
800 |
|
801 ec_GFp_point_mul_jac_4w_fp(&ecgroup->order, &ecgroup->genx, |
|
802 &ecgroup->geny, &rx, &ry, ecgroup); |
|
803 if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { |
|
804 printf |
|
805 (" Error: ec_GFp_point_mul_jac_4w_fp invalid result (expected point at infinity.\n"); |
|
806 MP_CHECKOK(mp_toradix(&rx, s, 16)); |
|
807 printf("rx %s\n", s); |
|
808 MP_CHECKOK(mp_toradix(&ry, s, 16)); |
|
809 printf("ry %s\n", s); |
|
810 res = MP_NO; |
|
811 goto CLEANUP; |
|
812 } |
|
813 |
|
814 /* Test Algorithm 3: wNAF with modified Jacobian coordinates */ |
|
815 ec_GFp_point_mul_wNAF_fp(&order_1, &ecgroup->genx, &ecgroup->geny, &rx, |
|
816 &ry, ecgroup); |
|
817 MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth)); |
|
818 if ((mp_cmp(&rx, &ecgroup->genx) != 0) |
|
819 || (mp_cmp(&ry, &ecgroup->geny) != 0)) { |
|
820 printf |
|
821 (" Error: ec_GFp_pt_mul_wNAF_fp invalid result (expected (- base point)).\n"); |
|
822 MP_CHECKOK(mp_toradix(&rx, s, 16)); |
|
823 printf("rx %s\n", s); |
|
824 MP_CHECKOK(mp_toradix(&ry, s, 16)); |
|
825 printf("ry %s\n", s); |
|
826 res = MP_NO; |
|
827 goto CLEANUP; |
|
828 } |
|
829 |
|
830 ec_GFp_point_mul_wNAF_fp(&ecgroup->order, &ecgroup->genx, |
|
831 &ecgroup->geny, &rx, &ry, ecgroup); |
|
832 if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { |
|
833 printf |
|
834 (" Error: ec_GFp_pt_mul_wNAF_fp invalid result (expected point at infinity.\n"); |
|
835 MP_CHECKOK(mp_toradix(&rx, s, 16)); |
|
836 printf("rx %s\n", s); |
|
837 MP_CHECKOK(mp_toradix(&ry, s, 16)); |
|
838 printf("ry %s\n", s); |
|
839 res = MP_NO; |
|
840 goto CLEANUP; |
|
841 } |
|
842 |
|
843 CLEANUP: |
|
844 if (res == MP_OKAY) |
|
845 printf(" Test Passed - Point Multiplication\n"); |
|
846 else |
|
847 printf("TEST FAILED - Point Multiplication\n"); |
|
848 mp_clear(&rx); |
|
849 mp_clear(&ry); |
|
850 mp_clear(&order_1); |
|
851 |
|
852 return res; |
|
853 } |
|
854 |
|
855 /* Tests point multiplication with a random scalar repeatedly, comparing |
|
856 * for consistency within different algorithms. */ |
|
857 mp_err |
|
858 testPointMulRandom(ECGroup *ecgroup) |
|
859 { |
|
860 mp_err res; |
|
861 mp_int rx, ry, rx2, ry2, n; |
|
862 int i, size; |
|
863 EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; |
|
864 |
|
865 MP_DIGITS(&rx) = 0; |
|
866 MP_DIGITS(&ry) = 0; |
|
867 MP_DIGITS(&rx2) = 0; |
|
868 MP_DIGITS(&ry2) = 0; |
|
869 MP_DIGITS(&n) = 0; |
|
870 |
|
871 MP_CHECKOK(mp_init(&rx)); |
|
872 MP_CHECKOK(mp_init(&ry)); |
|
873 MP_CHECKOK(mp_init(&rx2)); |
|
874 MP_CHECKOK(mp_init(&ry2)); |
|
875 MP_CHECKOK(mp_init(&n)); |
|
876 |
|
877 for (i = 0; i < 100; i++) { |
|
878 /* compute random scalar */ |
|
879 size = mpl_significant_bits(&ecgroup->meth->irr); |
|
880 if (size < MP_OKAY) { |
|
881 res = MP_NO; |
|
882 goto CLEANUP; |
|
883 } |
|
884 MP_CHECKOK(mpp_random_size(&n, group->orderBitSize)); |
|
885 MP_CHECKOK(mp_mod(&n, &ecgroup->order, &n)); |
|
886 |
|
887 ec_GFp_pt_mul_jac(&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry, |
|
888 ecgroup); |
|
889 ec_GFp_pt_mul_jac_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx2, |
|
890 &ry2, ecgroup); |
|
891 |
|
892 if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) { |
|
893 printf |
|
894 (" Error: different results for Point Multiplication - Double & Add.\n"); |
|
895 res = MP_NO; |
|
896 goto CLEANUP; |
|
897 } |
|
898 |
|
899 ec_GFp_point_mul_wNAF_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx, |
|
900 &ry, ecgroup); |
|
901 if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) { |
|
902 printf |
|
903 (" Error: different results for Point Multiplication - wNAF.\n"); |
|
904 res = MP_NO; |
|
905 goto CLEANUP; |
|
906 } |
|
907 |
|
908 ec_GFp_point_mul_jac_4w_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx, |
|
909 &ry, ecgroup); |
|
910 if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) { |
|
911 printf |
|
912 (" Error: different results for Point Multiplication - 4 bit window.\n"); |
|
913 res = MP_NO; |
|
914 goto CLEANUP; |
|
915 } |
|
916 |
|
917 } |
|
918 |
|
919 CLEANUP: |
|
920 if (res == MP_OKAY) |
|
921 printf(" Test Passed - Point Random Multiplication\n"); |
|
922 else |
|
923 printf("TEST FAILED - Point Random Multiplication\n"); |
|
924 mp_clear(&rx); |
|
925 mp_clear(&ry); |
|
926 mp_clear(&rx2); |
|
927 mp_clear(&ry2); |
|
928 mp_clear(&n); |
|
929 |
|
930 return res; |
|
931 } |
|
932 |
|
933 /* Tests the time required for a point multiplication */ |
|
934 mp_err |
|
935 testPointMulTime(ECGroup *ecgroup) |
|
936 { |
|
937 mp_err res = MP_OKAY; |
|
938 mp_int rx, ry, n; |
|
939 int size; |
|
940 |
|
941 MP_DIGITS(&rx) = 0; |
|
942 MP_DIGITS(&ry) = 0; |
|
943 MP_DIGITS(&n) = 0; |
|
944 |
|
945 MP_CHECKOK(mp_init(&rx)); |
|
946 MP_CHECKOK(mp_init(&ry)); |
|
947 MP_CHECKOK(mp_init(&n)); |
|
948 |
|
949 /* compute random scalar */ |
|
950 size = mpl_significant_bits(&ecgroup->meth->irr); |
|
951 if (size < MP_OKAY) { |
|
952 res = MP_NO; |
|
953 goto CLEANUP; |
|
954 } |
|
955 |
|
956 MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS)); |
|
957 MP_CHECKOK(ecgroup->meth->field_mod(&n, &n, ecgroup->meth)); |
|
958 |
|
959 M_TimeOperation(ec_GFp_pt_mul_jac_fp |
|
960 (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry, |
|
961 ecgroup), 1000); |
|
962 |
|
963 M_TimeOperation(ec_GFp_point_mul_jac_4w_fp |
|
964 (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry, |
|
965 ecgroup), 1000); |
|
966 |
|
967 M_TimeOperation(ec_GFp_point_mul_wNAF_fp |
|
968 (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry, |
|
969 ecgroup), 1000); |
|
970 |
|
971 M_TimeOperation(ec_GFp_pt_mul_jac |
|
972 (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry, |
|
973 ecgroup), 100); |
|
974 |
|
975 CLEANUP: |
|
976 if (res == MP_OKAY) |
|
977 printf(" Test Passed - Point Multiplication Timing\n"); |
|
978 else |
|
979 printf("TEST FAILED - Point Multiplication Timing\n"); |
|
980 mp_clear(&rx); |
|
981 mp_clear(&ry); |
|
982 mp_clear(&n); |
|
983 |
|
984 return res; |
|
985 } |
|
986 |
|
987 /* Tests pre computation of Chudnovsky Jacobian points used in wNAF form */ |
|
988 mp_err |
|
989 testPreCompute(ECGroup *ecgroup) |
|
990 { |
|
991 ecfp_chud_pt precomp[16]; |
|
992 ecfp_aff_pt p; |
|
993 EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; |
|
994 int i; |
|
995 mp_err res; |
|
996 |
|
997 mp_int x, y, ny, x2, y2; |
|
998 |
|
999 MP_DIGITS(&x) = 0; |
|
1000 MP_DIGITS(&y) = 0; |
|
1001 MP_DIGITS(&ny) = 0; |
|
1002 MP_DIGITS(&x2) = 0; |
|
1003 MP_DIGITS(&y2) = 0; |
|
1004 |
|
1005 MP_CHECKOK(mp_init(&x)); |
|
1006 MP_CHECKOK(mp_init(&y)); |
|
1007 MP_CHECKOK(mp_init(&ny)); |
|
1008 MP_CHECKOK(mp_init(&x2)); |
|
1009 MP_CHECKOK(mp_init(&y2)); |
|
1010 |
|
1011 ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); |
|
1012 ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); |
|
1013 ecfp_i2fp(group->curvea, &(ecgroup->curvea), ecgroup); |
|
1014 |
|
1015 /* Perform precomputation */ |
|
1016 group->precompute_chud(precomp, &p, group); |
|
1017 |
|
1018 M_TimeOperation(group->precompute_chud(precomp, &p, group), 10000); |
|
1019 |
|
1020 /* Calculate addition to compare against */ |
|
1021 MP_CHECKOK(mp_copy(&ecgroup->genx, &x)); |
|
1022 MP_CHECKOK(mp_copy(&ecgroup->geny, &y)); |
|
1023 MP_CHECKOK(ecgroup->meth->field_neg(&y, &ny, ecgroup->meth)); |
|
1024 |
|
1025 ec_GFp_pt_dbl_aff(&x, &y, &x2, &y2, ecgroup); |
|
1026 |
|
1027 for (i = 0; i < 8; i++) { |
|
1028 MP_CHECKOK(testChudPoint(&precomp[8 + i], &x, &y, ecgroup)); |
|
1029 MP_CHECKOK(testChudPoint(&precomp[7 - i], &x, &ny, ecgroup)); |
|
1030 ec_GFp_pt_add_aff(&x, &y, &x2, &y2, &x, &y, ecgroup); |
|
1031 MP_CHECKOK(ecgroup->meth->field_neg(&y, &ny, ecgroup->meth)); |
|
1032 } |
|
1033 |
|
1034 CLEANUP: |
|
1035 if (res == MP_OKAY) |
|
1036 printf(" Test Passed - Precomputation\n"); |
|
1037 else |
|
1038 printf("TEST FAILED - Precomputation\n"); |
|
1039 |
|
1040 mp_clear(&x); |
|
1041 mp_clear(&y); |
|
1042 mp_clear(&ny); |
|
1043 mp_clear(&x2); |
|
1044 mp_clear(&y2); |
|
1045 return res; |
|
1046 } |
|
1047 |
|
1048 /* Given a curve using floating point arithmetic, test it. This method |
|
1049 * specifies which of the above tests to run. */ |
|
1050 mp_err |
|
1051 testCurve(ECGroup *ecgroup) |
|
1052 { |
|
1053 int res = MP_OKAY; |
|
1054 |
|
1055 MP_CHECKOK(testPointAddJacAff(ecgroup)); |
|
1056 MP_CHECKOK(testPointAddJac(ecgroup)); |
|
1057 MP_CHECKOK(testPointAddChud(ecgroup)); |
|
1058 MP_CHECKOK(testPointAddJmChud(ecgroup)); |
|
1059 MP_CHECKOK(testPointDoubleJac(ecgroup)); |
|
1060 MP_CHECKOK(testPointDoubleChud(ecgroup)); |
|
1061 MP_CHECKOK(testPointDoubleJm(ecgroup)); |
|
1062 MP_CHECKOK(testPreCompute(ecgroup)); |
|
1063 MP_CHECKOK(testPointMul(ecgroup)); |
|
1064 MP_CHECKOK(testPointMulRandom(ecgroup)); |
|
1065 MP_CHECKOK(testPointMulTime(ecgroup)); |
|
1066 CLEANUP: |
|
1067 return res; |
|
1068 } |
|
1069 |
|
1070 /* Tests a number of curves optimized using floating point arithmetic */ |
|
1071 int |
|
1072 main(void) |
|
1073 { |
|
1074 mp_err res = MP_OKAY; |
|
1075 ECGroup *ecgroup = NULL; |
|
1076 |
|
1077 /* specific arithmetic tests */ |
|
1078 M_TestCurve("SECG-160R1", ECCurve_SECG_PRIME_160R1); |
|
1079 M_TestCurve("SECG-192R1", ECCurve_SECG_PRIME_192R1); |
|
1080 M_TestCurve("SEGC-224R1", ECCurve_SECG_PRIME_224R1); |
|
1081 |
|
1082 CLEANUP: |
|
1083 ECGroup_free(ecgroup); |
|
1084 if (res != MP_OKAY) { |
|
1085 printf("Error: exiting with error value %i\n", res); |
|
1086 } |
|
1087 return res; |
|
1088 } |