1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/freebl/ecl/tests/ecp_fpt.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1088 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "ecp_fp.h" 1.9 +#include "mpprime.h" 1.10 + 1.11 +#include <stdio.h> 1.12 +#include <time.h> 1.13 +#include <sys/time.h> 1.14 +#include <sys/resource.h> 1.15 + 1.16 +/* Time k repetitions of operation op. */ 1.17 +#define M_TimeOperation(op, k) { \ 1.18 + double dStart, dNow, dUserTime; \ 1.19 + struct rusage ru; \ 1.20 + int i; \ 1.21 + getrusage(RUSAGE_SELF, &ru); \ 1.22 + dStart = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \ 1.23 + for (i = 0; i < k; i++) { \ 1.24 + { op; } \ 1.25 + }; \ 1.26 + getrusage(RUSAGE_SELF, &ru); \ 1.27 + dNow = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \ 1.28 + dUserTime = dNow-dStart; \ 1.29 + if (dUserTime) printf(" %-45s\n k: %6i, t: %6.2f sec, k/t: %6.2f ops/sec\n", #op, k, dUserTime, k/dUserTime); \ 1.30 +} 1.31 + 1.32 +/* Test curve using specific floating point field arithmetic. */ 1.33 +#define M_TestCurve(name_c, name) { \ 1.34 + printf("Testing %s using specific floating point implementation...\n", name_c); \ 1.35 + ECGroup_free(ecgroup); \ 1.36 + ecgroup = ECGroup_fromName(name); \ 1.37 + if (ecgroup == NULL) { \ 1.38 + printf(" Warning: could not construct group.\n"); \ 1.39 + printf("%s failed.\n", name_c); \ 1.40 + res = MP_NO; \ 1.41 + goto CLEANUP; \ 1.42 + } else { \ 1.43 + MP_CHECKOK( testCurve(ecgroup)); \ 1.44 + printf("%s passed.\n", name_c); \ 1.45 + } \ 1.46 +} 1.47 + 1.48 +/* Outputs a floating point double (currently not used) */ 1.49 +void 1.50 +d_output(const double *u, int len, char *name, const EC_group_fp * group) 1.51 +{ 1.52 + int i; 1.53 + 1.54 + printf("%s: ", name); 1.55 + for (i = 0; i < len; i++) { 1.56 + printf("+ %.2f * 2^%i ", u[i] / ecfp_exp[i], 1.57 + group->doubleBitSize * i); 1.58 + } 1.59 + printf("\n"); 1.60 +} 1.61 + 1.62 +/* Tests a point p in Jacobian coordinates, comparing against the 1.63 + * expected affine result (x, y). */ 1.64 +mp_err 1.65 +testJacPoint(ecfp_jac_pt * p, mp_int *x, mp_int *y, ECGroup *ecgroup) 1.66 +{ 1.67 + char s[1000]; 1.68 + mp_int rx, ry, rz; 1.69 + mp_err res = MP_OKAY; 1.70 + 1.71 + MP_DIGITS(&rx) = 0; 1.72 + MP_DIGITS(&ry) = 0; 1.73 + MP_DIGITS(&rz) = 0; 1.74 + 1.75 + MP_CHECKOK(mp_init(&rx)); 1.76 + MP_CHECKOK(mp_init(&ry)); 1.77 + MP_CHECKOK(mp_init(&rz)); 1.78 + 1.79 + ecfp_fp2i(&rx, p->x, ecgroup); 1.80 + ecfp_fp2i(&ry, p->y, ecgroup); 1.81 + ecfp_fp2i(&rz, p->z, ecgroup); 1.82 + 1.83 + /* convert result R to affine coordinates */ 1.84 + ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup); 1.85 + 1.86 + /* Compare to expected result */ 1.87 + if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) { 1.88 + printf(" Error: Jacobian Floating Point Incorrect.\n"); 1.89 + MP_CHECKOK(mp_toradix(&rx, s, 16)); 1.90 + printf("floating point result\nrx %s\n", s); 1.91 + MP_CHECKOK(mp_toradix(&ry, s, 16)); 1.92 + printf("ry %s\n", s); 1.93 + MP_CHECKOK(mp_toradix(x, s, 16)); 1.94 + printf("integer result\nx %s\n", s); 1.95 + MP_CHECKOK(mp_toradix(y, s, 16)); 1.96 + printf("y %s\n", s); 1.97 + res = MP_NO; 1.98 + goto CLEANUP; 1.99 + } 1.100 + 1.101 + CLEANUP: 1.102 + mp_clear(&rx); 1.103 + mp_clear(&ry); 1.104 + mp_clear(&rz); 1.105 + 1.106 + return res; 1.107 +} 1.108 + 1.109 +/* Tests a point p in Chudnovsky Jacobian coordinates, comparing against 1.110 + * the expected affine result (x, y). */ 1.111 +mp_err 1.112 +testChudPoint(ecfp_chud_pt * p, mp_int *x, mp_int *y, ECGroup *ecgroup) 1.113 +{ 1.114 + 1.115 + char s[1000]; 1.116 + mp_int rx, ry, rz, rz2, rz3, test; 1.117 + mp_err res = MP_OKAY; 1.118 + 1.119 + /* Initialization */ 1.120 + MP_DIGITS(&rx) = 0; 1.121 + MP_DIGITS(&ry) = 0; 1.122 + MP_DIGITS(&rz) = 0; 1.123 + MP_DIGITS(&rz2) = 0; 1.124 + MP_DIGITS(&rz3) = 0; 1.125 + MP_DIGITS(&test) = 0; 1.126 + 1.127 + MP_CHECKOK(mp_init(&rx)); 1.128 + MP_CHECKOK(mp_init(&ry)); 1.129 + MP_CHECKOK(mp_init(&rz)); 1.130 + MP_CHECKOK(mp_init(&rz2)); 1.131 + MP_CHECKOK(mp_init(&rz3)); 1.132 + MP_CHECKOK(mp_init(&test)); 1.133 + 1.134 + /* Convert to integers */ 1.135 + ecfp_fp2i(&rx, p->x, ecgroup); 1.136 + ecfp_fp2i(&ry, p->y, ecgroup); 1.137 + ecfp_fp2i(&rz, p->z, ecgroup); 1.138 + ecfp_fp2i(&rz2, p->z2, ecgroup); 1.139 + ecfp_fp2i(&rz3, p->z3, ecgroup); 1.140 + 1.141 + /* Verify z2, z3 are valid */ 1.142 + mp_sqrmod(&rz, &ecgroup->meth->irr, &test); 1.143 + if (mp_cmp(&test, &rz2) != 0) { 1.144 + printf(" Error: rzp2 not valid\n"); 1.145 + res = MP_NO; 1.146 + goto CLEANUP; 1.147 + } 1.148 + mp_mulmod(&test, &rz, &ecgroup->meth->irr, &test); 1.149 + if (mp_cmp(&test, &rz3) != 0) { 1.150 + printf(" Error: rzp2 not valid\n"); 1.151 + res = MP_NO; 1.152 + goto CLEANUP; 1.153 + } 1.154 + 1.155 + /* convert result R to affine coordinates */ 1.156 + ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup); 1.157 + 1.158 + /* Compare against expected result */ 1.159 + if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) { 1.160 + printf(" Error: Chudnovsky Floating Point Incorrect.\n"); 1.161 + MP_CHECKOK(mp_toradix(&rx, s, 16)); 1.162 + printf("floating point result\nrx %s\n", s); 1.163 + MP_CHECKOK(mp_toradix(&ry, s, 16)); 1.164 + printf("ry %s\n", s); 1.165 + MP_CHECKOK(mp_toradix(x, s, 16)); 1.166 + printf("integer result\nx %s\n", s); 1.167 + MP_CHECKOK(mp_toradix(y, s, 16)); 1.168 + printf("y %s\n", s); 1.169 + res = MP_NO; 1.170 + goto CLEANUP; 1.171 + } 1.172 + 1.173 + CLEANUP: 1.174 + mp_clear(&rx); 1.175 + mp_clear(&ry); 1.176 + mp_clear(&rz); 1.177 + mp_clear(&rz2); 1.178 + mp_clear(&rz3); 1.179 + mp_clear(&test); 1.180 + 1.181 + return res; 1.182 +} 1.183 + 1.184 +/* Tests a point p in Modified Jacobian coordinates, comparing against the 1.185 + * expected affine result (x, y). */ 1.186 +mp_err 1.187 +testJmPoint(ecfp_jm_pt * r, mp_int *x, mp_int *y, ECGroup *ecgroup) 1.188 +{ 1.189 + 1.190 + char s[1000]; 1.191 + mp_int rx, ry, rz, raz4, test; 1.192 + mp_err res = MP_OKAY; 1.193 + 1.194 + /* Initialization */ 1.195 + MP_DIGITS(&rx) = 0; 1.196 + MP_DIGITS(&ry) = 0; 1.197 + MP_DIGITS(&rz) = 0; 1.198 + MP_DIGITS(&raz4) = 0; 1.199 + MP_DIGITS(&test) = 0; 1.200 + 1.201 + MP_CHECKOK(mp_init(&rx)); 1.202 + MP_CHECKOK(mp_init(&ry)); 1.203 + MP_CHECKOK(mp_init(&rz)); 1.204 + MP_CHECKOK(mp_init(&raz4)); 1.205 + MP_CHECKOK(mp_init(&test)); 1.206 + 1.207 + /* Convert to integer */ 1.208 + ecfp_fp2i(&rx, r->x, ecgroup); 1.209 + ecfp_fp2i(&ry, r->y, ecgroup); 1.210 + ecfp_fp2i(&rz, r->z, ecgroup); 1.211 + ecfp_fp2i(&raz4, r->az4, ecgroup); 1.212 + 1.213 + /* Verify raz4 = rz^4 * a */ 1.214 + mp_sqrmod(&rz, &ecgroup->meth->irr, &test); 1.215 + mp_sqrmod(&test, &ecgroup->meth->irr, &test); 1.216 + mp_mulmod(&test, &ecgroup->curvea, &ecgroup->meth->irr, &test); 1.217 + if (mp_cmp(&test, &raz4) != 0) { 1.218 + printf(" Error: a*z^4 not valid\n"); 1.219 + MP_CHECKOK(mp_toradix(&ecgroup->curvea, s, 16)); 1.220 + printf("a %s\n", s); 1.221 + MP_CHECKOK(mp_toradix(&rz, s, 16)); 1.222 + printf("rz %s\n", s); 1.223 + MP_CHECKOK(mp_toradix(&raz4, s, 16)); 1.224 + printf("raz4 %s\n", s); 1.225 + res = MP_NO; 1.226 + goto CLEANUP; 1.227 + } 1.228 + 1.229 + /* convert result R to affine coordinates */ 1.230 + ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup); 1.231 + 1.232 + /* Compare against expected result */ 1.233 + if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) { 1.234 + printf(" Error: Modified Jacobian Floating Point Incorrect.\n"); 1.235 + MP_CHECKOK(mp_toradix(&rx, s, 16)); 1.236 + printf("floating point result\nrx %s\n", s); 1.237 + MP_CHECKOK(mp_toradix(&ry, s, 16)); 1.238 + printf("ry %s\n", s); 1.239 + MP_CHECKOK(mp_toradix(x, s, 16)); 1.240 + printf("integer result\nx %s\n", s); 1.241 + MP_CHECKOK(mp_toradix(y, s, 16)); 1.242 + printf("y %s\n", s); 1.243 + res = MP_NO; 1.244 + goto CLEANUP; 1.245 + } 1.246 + CLEANUP: 1.247 + mp_clear(&rx); 1.248 + mp_clear(&ry); 1.249 + mp_clear(&rz); 1.250 + mp_clear(&raz4); 1.251 + mp_clear(&test); 1.252 + 1.253 + return res; 1.254 +} 1.255 + 1.256 +/* Tests point addition of Jacobian + Affine -> Jacobian */ 1.257 +mp_err 1.258 +testPointAddJacAff(ECGroup *ecgroup) 1.259 +{ 1.260 + mp_err res; 1.261 + mp_int pz, rx2, ry2, rz2; 1.262 + ecfp_jac_pt p, r; 1.263 + ecfp_aff_pt q; 1.264 + EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; 1.265 + 1.266 + /* Init */ 1.267 + MP_DIGITS(&pz) = 0; 1.268 + MP_DIGITS(&rx2) = 0; 1.269 + MP_DIGITS(&ry2) = 0; 1.270 + MP_DIGITS(&rz2) = 0; 1.271 + MP_CHECKOK(mp_init(&pz)); 1.272 + MP_CHECKOK(mp_init(&rx2)); 1.273 + MP_CHECKOK(mp_init(&ry2)); 1.274 + MP_CHECKOK(mp_init(&rz2)); 1.275 + 1.276 + MP_CHECKOK(mp_set_int(&pz, 5)); 1.277 + 1.278 + /* Set p */ 1.279 + ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); 1.280 + ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); 1.281 + ecfp_i2fp(p.z, &pz, ecgroup); 1.282 + /* Set q */ 1.283 + ecfp_i2fp(q.x, &ecgroup->geny, ecgroup); 1.284 + ecfp_i2fp(q.y, &ecgroup->genx, ecgroup); 1.285 + 1.286 + /* Do calculations */ 1.287 + group->pt_add_jac_aff(&p, &q, &r, group); 1.288 + 1.289 + /* Do calculation in integer to compare against */ 1.290 + MP_CHECKOK(ec_GFp_pt_add_jac_aff 1.291 + (&ecgroup->genx, &ecgroup->geny, &pz, &ecgroup->geny, 1.292 + &ecgroup->genx, &rx2, &ry2, &rz2, ecgroup)); 1.293 + /* convert result R to affine coordinates */ 1.294 + ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup); 1.295 + 1.296 + MP_CHECKOK(testJacPoint(&r, &rx2, &ry2, ecgroup)); 1.297 + 1.298 + CLEANUP: 1.299 + if (res == MP_OKAY) 1.300 + printf(" Test Passed - Point Addition - Jacobian & Affine\n"); 1.301 + else 1.302 + printf("TEST FAILED - Point Addition - Jacobian & Affine\n"); 1.303 + 1.304 + mp_clear(&pz); 1.305 + mp_clear(&rx2); 1.306 + mp_clear(&ry2); 1.307 + mp_clear(&rz2); 1.308 + 1.309 + return res; 1.310 +} 1.311 + 1.312 +/* Tests point addition in Jacobian coordinates */ 1.313 +mp_err 1.314 +testPointAddJac(ECGroup *ecgroup) 1.315 +{ 1.316 + mp_err res; 1.317 + mp_int pz, qz, qx, qy, rx2, ry2, rz2; 1.318 + ecfp_jac_pt p, q, r; 1.319 + EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; 1.320 + 1.321 + /* Init */ 1.322 + MP_DIGITS(&pz) = 0; 1.323 + MP_DIGITS(&qx) = 0; 1.324 + MP_DIGITS(&qy) = 0; 1.325 + MP_DIGITS(&qz) = 0; 1.326 + MP_DIGITS(&rx2) = 0; 1.327 + MP_DIGITS(&ry2) = 0; 1.328 + MP_DIGITS(&rz2) = 0; 1.329 + MP_CHECKOK(mp_init(&pz)); 1.330 + MP_CHECKOK(mp_init(&qx)); 1.331 + MP_CHECKOK(mp_init(&qy)); 1.332 + MP_CHECKOK(mp_init(&qz)); 1.333 + MP_CHECKOK(mp_init(&rx2)); 1.334 + MP_CHECKOK(mp_init(&ry2)); 1.335 + MP_CHECKOK(mp_init(&rz2)); 1.336 + 1.337 + MP_CHECKOK(mp_set_int(&pz, 5)); 1.338 + MP_CHECKOK(mp_set_int(&qz, 105)); 1.339 + 1.340 + /* Set p */ 1.341 + ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); 1.342 + ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); 1.343 + ecfp_i2fp(p.z, &pz, ecgroup); 1.344 + /* Set q */ 1.345 + ecfp_i2fp(q.x, &ecgroup->geny, ecgroup); 1.346 + ecfp_i2fp(q.y, &ecgroup->genx, ecgroup); 1.347 + ecfp_i2fp(q.z, &qz, ecgroup); 1.348 + 1.349 + /* Do calculations */ 1.350 + group->pt_add_jac(&p, &q, &r, group); 1.351 + 1.352 + /* Do calculation in integer to compare against */ 1.353 + ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy, 1.354 + ecgroup); 1.355 + MP_CHECKOK(ec_GFp_pt_add_jac_aff 1.356 + (&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy, &rx2, &ry2, 1.357 + &rz2, ecgroup)); 1.358 + /* convert result R to affine coordinates */ 1.359 + ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup); 1.360 + 1.361 + MP_CHECKOK(testJacPoint(&r, &rx2, &ry2, ecgroup)); 1.362 + 1.363 + CLEANUP: 1.364 + if (res == MP_OKAY) 1.365 + printf(" Test Passed - Point Addition - Jacobian\n"); 1.366 + else 1.367 + printf("TEST FAILED - Point Addition - Jacobian\n"); 1.368 + 1.369 + mp_clear(&pz); 1.370 + mp_clear(&qx); 1.371 + mp_clear(&qy); 1.372 + mp_clear(&qz); 1.373 + mp_clear(&rx2); 1.374 + mp_clear(&ry2); 1.375 + mp_clear(&rz2); 1.376 + 1.377 + return res; 1.378 +} 1.379 + 1.380 +/* Tests point addition in Chudnovsky Jacobian Coordinates */ 1.381 +mp_err 1.382 +testPointAddChud(ECGroup *ecgroup) 1.383 +{ 1.384 + mp_err res; 1.385 + mp_int rx2, ry2, ix, iy, iz, test, pz, qx, qy, qz; 1.386 + ecfp_chud_pt p, q, r; 1.387 + EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; 1.388 + 1.389 + MP_DIGITS(&qx) = 0; 1.390 + MP_DIGITS(&qy) = 0; 1.391 + MP_DIGITS(&qz) = 0; 1.392 + MP_DIGITS(&pz) = 0; 1.393 + MP_DIGITS(&rx2) = 0; 1.394 + MP_DIGITS(&ry2) = 0; 1.395 + MP_DIGITS(&ix) = 0; 1.396 + MP_DIGITS(&iy) = 0; 1.397 + MP_DIGITS(&iz) = 0; 1.398 + MP_DIGITS(&test) = 0; 1.399 + 1.400 + MP_CHECKOK(mp_init(&qx)); 1.401 + MP_CHECKOK(mp_init(&qy)); 1.402 + MP_CHECKOK(mp_init(&qz)); 1.403 + MP_CHECKOK(mp_init(&pz)); 1.404 + MP_CHECKOK(mp_init(&rx2)); 1.405 + MP_CHECKOK(mp_init(&ry2)); 1.406 + MP_CHECKOK(mp_init(&ix)); 1.407 + MP_CHECKOK(mp_init(&iy)); 1.408 + MP_CHECKOK(mp_init(&iz)); 1.409 + MP_CHECKOK(mp_init(&test)); 1.410 + 1.411 + /* Test Chudnovsky form addition */ 1.412 + /* Set p */ 1.413 + MP_CHECKOK(mp_set_int(&pz, 5)); 1.414 + ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); 1.415 + ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); 1.416 + ecfp_i2fp(p.z, &pz, ecgroup); 1.417 + mp_sqrmod(&pz, &ecgroup->meth->irr, &test); 1.418 + ecfp_i2fp(p.z2, &test, ecgroup); 1.419 + mp_mulmod(&test, &pz, &ecgroup->meth->irr, &test); 1.420 + ecfp_i2fp(p.z3, &test, ecgroup); 1.421 + 1.422 + /* Set q */ 1.423 + MP_CHECKOK(mp_set_int(&qz, 105)); 1.424 + ecfp_i2fp(q.x, &ecgroup->geny, ecgroup); 1.425 + ecfp_i2fp(q.y, &ecgroup->genx, ecgroup); 1.426 + ecfp_i2fp(q.z, &qz, ecgroup); 1.427 + mp_sqrmod(&qz, &ecgroup->meth->irr, &test); 1.428 + ecfp_i2fp(q.z2, &test, ecgroup); 1.429 + mp_mulmod(&test, &qz, &ecgroup->meth->irr, &test); 1.430 + ecfp_i2fp(q.z3, &test, ecgroup); 1.431 + 1.432 + group->pt_add_chud(&p, &q, &r, group); 1.433 + 1.434 + /* Calculate addition to compare against */ 1.435 + ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy, 1.436 + ecgroup); 1.437 + ec_GFp_pt_add_jac_aff(&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy, 1.438 + &ix, &iy, &iz, ecgroup); 1.439 + ec_GFp_pt_jac2aff(&ix, &iy, &iz, &rx2, &ry2, ecgroup); 1.440 + 1.441 + MP_CHECKOK(testChudPoint(&r, &rx2, &ry2, ecgroup)); 1.442 + 1.443 + CLEANUP: 1.444 + if (res == MP_OKAY) 1.445 + printf(" Test Passed - Point Addition - Chudnovsky Jacobian\n"); 1.446 + else 1.447 + printf("TEST FAILED - Point Addition - Chudnovsky Jacobian\n"); 1.448 + 1.449 + mp_clear(&qx); 1.450 + mp_clear(&qy); 1.451 + mp_clear(&qz); 1.452 + mp_clear(&pz); 1.453 + mp_clear(&rx2); 1.454 + mp_clear(&ry2); 1.455 + mp_clear(&ix); 1.456 + mp_clear(&iy); 1.457 + mp_clear(&iz); 1.458 + mp_clear(&test); 1.459 + 1.460 + return res; 1.461 +} 1.462 + 1.463 +/* Tests point addition in Modified Jacobian + Chudnovsky Jacobian -> 1.464 + * Modified Jacobian coordinates. */ 1.465 +mp_err 1.466 +testPointAddJmChud(ECGroup *ecgroup) 1.467 +{ 1.468 + mp_err res; 1.469 + mp_int rx2, ry2, ix, iy, iz, test, pz, paz4, qx, qy, qz; 1.470 + ecfp_chud_pt q; 1.471 + ecfp_jm_pt p, r; 1.472 + EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; 1.473 + 1.474 + MP_DIGITS(&qx) = 0; 1.475 + MP_DIGITS(&qy) = 0; 1.476 + MP_DIGITS(&qz) = 0; 1.477 + MP_DIGITS(&pz) = 0; 1.478 + MP_DIGITS(&paz4) = 0; 1.479 + MP_DIGITS(&iz) = 0; 1.480 + MP_DIGITS(&rx2) = 0; 1.481 + MP_DIGITS(&ry2) = 0; 1.482 + MP_DIGITS(&ix) = 0; 1.483 + MP_DIGITS(&iy) = 0; 1.484 + MP_DIGITS(&iz) = 0; 1.485 + MP_DIGITS(&test) = 0; 1.486 + 1.487 + MP_CHECKOK(mp_init(&qx)); 1.488 + MP_CHECKOK(mp_init(&qy)); 1.489 + MP_CHECKOK(mp_init(&qz)); 1.490 + MP_CHECKOK(mp_init(&pz)); 1.491 + MP_CHECKOK(mp_init(&paz4)); 1.492 + MP_CHECKOK(mp_init(&rx2)); 1.493 + MP_CHECKOK(mp_init(&ry2)); 1.494 + MP_CHECKOK(mp_init(&ix)); 1.495 + MP_CHECKOK(mp_init(&iy)); 1.496 + MP_CHECKOK(mp_init(&iz)); 1.497 + MP_CHECKOK(mp_init(&test)); 1.498 + 1.499 + /* Test Modified Jacobian form addition */ 1.500 + /* Set p */ 1.501 + ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); 1.502 + ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); 1.503 + ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup); 1.504 + /* paz4 = az^4 */ 1.505 + MP_CHECKOK(mp_set_int(&pz, 5)); 1.506 + mp_sqrmod(&pz, &ecgroup->meth->irr, &paz4); 1.507 + mp_sqrmod(&paz4, &ecgroup->meth->irr, &paz4); 1.508 + mp_mulmod(&paz4, &ecgroup->curvea, &ecgroup->meth->irr, &paz4); 1.509 + ecfp_i2fp(p.z, &pz, ecgroup); 1.510 + ecfp_i2fp(p.az4, &paz4, ecgroup); 1.511 + 1.512 + /* Set q */ 1.513 + MP_CHECKOK(mp_set_int(&qz, 105)); 1.514 + ecfp_i2fp(q.x, &ecgroup->geny, ecgroup); 1.515 + ecfp_i2fp(q.y, &ecgroup->genx, ecgroup); 1.516 + ecfp_i2fp(q.z, &qz, ecgroup); 1.517 + mp_sqrmod(&qz, &ecgroup->meth->irr, &test); 1.518 + ecfp_i2fp(q.z2, &test, ecgroup); 1.519 + mp_mulmod(&test, &qz, &ecgroup->meth->irr, &test); 1.520 + ecfp_i2fp(q.z3, &test, ecgroup); 1.521 + 1.522 + /* Do calculation */ 1.523 + group->pt_add_jm_chud(&p, &q, &r, group); 1.524 + 1.525 + /* Calculate addition to compare against */ 1.526 + ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy, 1.527 + ecgroup); 1.528 + ec_GFp_pt_add_jac_aff(&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy, 1.529 + &ix, &iy, &iz, ecgroup); 1.530 + ec_GFp_pt_jac2aff(&ix, &iy, &iz, &rx2, &ry2, ecgroup); 1.531 + 1.532 + MP_CHECKOK(testJmPoint(&r, &rx2, &ry2, ecgroup)); 1.533 + 1.534 + CLEANUP: 1.535 + if (res == MP_OKAY) 1.536 + printf 1.537 + (" Test Passed - Point Addition - Modified & Chudnovsky Jacobian\n"); 1.538 + else 1.539 + printf 1.540 + ("TEST FAILED - Point Addition - Modified & Chudnovsky Jacobian\n"); 1.541 + 1.542 + mp_clear(&qx); 1.543 + mp_clear(&qy); 1.544 + mp_clear(&qz); 1.545 + mp_clear(&pz); 1.546 + mp_clear(&paz4); 1.547 + mp_clear(&rx2); 1.548 + mp_clear(&ry2); 1.549 + mp_clear(&ix); 1.550 + mp_clear(&iy); 1.551 + mp_clear(&iz); 1.552 + mp_clear(&test); 1.553 + 1.554 + return res; 1.555 +} 1.556 + 1.557 +/* Tests point doubling in Modified Jacobian coordinates */ 1.558 +mp_err 1.559 +testPointDoubleJm(ECGroup *ecgroup) 1.560 +{ 1.561 + mp_err res; 1.562 + mp_int pz, paz4, rx2, ry2, rz2, raz4; 1.563 + ecfp_jm_pt p, r; 1.564 + EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; 1.565 + 1.566 + MP_DIGITS(&pz) = 0; 1.567 + MP_DIGITS(&paz4) = 0; 1.568 + MP_DIGITS(&rx2) = 0; 1.569 + MP_DIGITS(&ry2) = 0; 1.570 + MP_DIGITS(&rz2) = 0; 1.571 + MP_DIGITS(&raz4) = 0; 1.572 + 1.573 + MP_CHECKOK(mp_init(&pz)); 1.574 + MP_CHECKOK(mp_init(&paz4)); 1.575 + MP_CHECKOK(mp_init(&rx2)); 1.576 + MP_CHECKOK(mp_init(&ry2)); 1.577 + MP_CHECKOK(mp_init(&rz2)); 1.578 + MP_CHECKOK(mp_init(&raz4)); 1.579 + 1.580 + /* Set p */ 1.581 + ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); 1.582 + ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); 1.583 + ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup); 1.584 + 1.585 + /* paz4 = az^4 */ 1.586 + MP_CHECKOK(mp_set_int(&pz, 5)); 1.587 + mp_sqrmod(&pz, &ecgroup->meth->irr, &paz4); 1.588 + mp_sqrmod(&paz4, &ecgroup->meth->irr, &paz4); 1.589 + mp_mulmod(&paz4, &ecgroup->curvea, &ecgroup->meth->irr, &paz4); 1.590 + 1.591 + ecfp_i2fp(p.z, &pz, ecgroup); 1.592 + ecfp_i2fp(p.az4, &paz4, ecgroup); 1.593 + 1.594 + group->pt_dbl_jm(&p, &r, group); 1.595 + 1.596 + M_TimeOperation(group->pt_dbl_jm(&p, &r, group), 100000); 1.597 + 1.598 + /* Calculate doubling to compare against */ 1.599 + ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2, 1.600 + &rz2, ecgroup); 1.601 + ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup); 1.602 + 1.603 + /* Do comparison and check az^4 */ 1.604 + MP_CHECKOK(testJmPoint(&r, &rx2, &ry2, ecgroup)); 1.605 + 1.606 + CLEANUP: 1.607 + if (res == MP_OKAY) 1.608 + printf(" Test Passed - Point Doubling - Modified Jacobian\n"); 1.609 + else 1.610 + printf("TEST FAILED - Point Doubling - Modified Jacobian\n"); 1.611 + mp_clear(&pz); 1.612 + mp_clear(&paz4); 1.613 + mp_clear(&rx2); 1.614 + mp_clear(&ry2); 1.615 + mp_clear(&rz2); 1.616 + mp_clear(&raz4); 1.617 + 1.618 + return res; 1.619 + 1.620 +} 1.621 + 1.622 +/* Tests point doubling in Chudnovsky Jacobian coordinates */ 1.623 +mp_err 1.624 +testPointDoubleChud(ECGroup *ecgroup) 1.625 +{ 1.626 + mp_err res; 1.627 + mp_int px, py, pz, rx2, ry2, rz2; 1.628 + ecfp_aff_pt p; 1.629 + ecfp_chud_pt p2; 1.630 + EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; 1.631 + 1.632 + MP_DIGITS(&rx2) = 0; 1.633 + MP_DIGITS(&ry2) = 0; 1.634 + MP_DIGITS(&rz2) = 0; 1.635 + MP_DIGITS(&px) = 0; 1.636 + MP_DIGITS(&py) = 0; 1.637 + MP_DIGITS(&pz) = 0; 1.638 + 1.639 + MP_CHECKOK(mp_init(&rx2)); 1.640 + MP_CHECKOK(mp_init(&ry2)); 1.641 + MP_CHECKOK(mp_init(&rz2)); 1.642 + MP_CHECKOK(mp_init(&px)); 1.643 + MP_CHECKOK(mp_init(&py)); 1.644 + MP_CHECKOK(mp_init(&pz)); 1.645 + 1.646 + /* Set p2 = 2P */ 1.647 + ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); 1.648 + ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); 1.649 + ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup); 1.650 + 1.651 + group->pt_dbl_aff2chud(&p, &p2, group); 1.652 + 1.653 + /* Calculate doubling to compare against */ 1.654 + MP_CHECKOK(mp_set_int(&pz, 1)); 1.655 + ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2, 1.656 + &rz2, ecgroup); 1.657 + ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup); 1.658 + 1.659 + /* Do comparison and check az^4 */ 1.660 + MP_CHECKOK(testChudPoint(&p2, &rx2, &ry2, ecgroup)); 1.661 + 1.662 + CLEANUP: 1.663 + if (res == MP_OKAY) 1.664 + printf(" Test Passed - Point Doubling - Chudnovsky Jacobian\n"); 1.665 + else 1.666 + printf("TEST FAILED - Point Doubling - Chudnovsky Jacobian\n"); 1.667 + 1.668 + mp_clear(&rx2); 1.669 + mp_clear(&ry2); 1.670 + mp_clear(&rz2); 1.671 + mp_clear(&px); 1.672 + mp_clear(&py); 1.673 + mp_clear(&pz); 1.674 + 1.675 + return res; 1.676 +} 1.677 + 1.678 +/* Test point doubling in Jacobian coordinates */ 1.679 +mp_err 1.680 +testPointDoubleJac(ECGroup *ecgroup) 1.681 +{ 1.682 + mp_err res; 1.683 + mp_int pz, rx, ry, rz, rx2, ry2, rz2; 1.684 + ecfp_jac_pt p, p2; 1.685 + EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; 1.686 + 1.687 + MP_DIGITS(&pz) = 0; 1.688 + MP_DIGITS(&rx) = 0; 1.689 + MP_DIGITS(&ry) = 0; 1.690 + MP_DIGITS(&rz) = 0; 1.691 + MP_DIGITS(&rx2) = 0; 1.692 + MP_DIGITS(&ry2) = 0; 1.693 + MP_DIGITS(&rz2) = 0; 1.694 + 1.695 + MP_CHECKOK(mp_init(&pz)); 1.696 + MP_CHECKOK(mp_init(&rx)); 1.697 + MP_CHECKOK(mp_init(&ry)); 1.698 + MP_CHECKOK(mp_init(&rz)); 1.699 + MP_CHECKOK(mp_init(&rx2)); 1.700 + MP_CHECKOK(mp_init(&ry2)); 1.701 + MP_CHECKOK(mp_init(&rz2)); 1.702 + 1.703 + MP_CHECKOK(mp_set_int(&pz, 5)); 1.704 + 1.705 + /* Set p2 = 2P */ 1.706 + ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); 1.707 + ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); 1.708 + ecfp_i2fp(p.z, &pz, ecgroup); 1.709 + ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup); 1.710 + 1.711 + group->pt_dbl_jac(&p, &p2, group); 1.712 + M_TimeOperation(group->pt_dbl_jac(&p, &p2, group), 100000); 1.713 + 1.714 + /* Calculate doubling to compare against */ 1.715 + ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2, 1.716 + &rz2, ecgroup); 1.717 + ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup); 1.718 + 1.719 + /* Do comparison */ 1.720 + MP_CHECKOK(testJacPoint(&p2, &rx2, &ry2, ecgroup)); 1.721 + 1.722 + CLEANUP: 1.723 + if (res == MP_OKAY) 1.724 + printf(" Test Passed - Point Doubling - Jacobian\n"); 1.725 + else 1.726 + printf("TEST FAILED - Point Doubling - Jacobian\n"); 1.727 + 1.728 + mp_clear(&pz); 1.729 + mp_clear(&rx); 1.730 + mp_clear(&ry); 1.731 + mp_clear(&rz); 1.732 + mp_clear(&rx2); 1.733 + mp_clear(&ry2); 1.734 + mp_clear(&rz2); 1.735 + 1.736 + return res; 1.737 +} 1.738 + 1.739 +/* Tests a point multiplication (various algorithms) */ 1.740 +mp_err 1.741 +testPointMul(ECGroup *ecgroup) 1.742 +{ 1.743 + mp_err res; 1.744 + char s[1000]; 1.745 + mp_int rx, ry, order_1; 1.746 + 1.747 + /* Init */ 1.748 + MP_DIGITS(&rx) = 0; 1.749 + MP_DIGITS(&ry) = 0; 1.750 + MP_DIGITS(&order_1) = 0; 1.751 + 1.752 + MP_CHECKOK(mp_init(&rx)); 1.753 + MP_CHECKOK(mp_init(&ry)); 1.754 + MP_CHECKOK(mp_init(&order_1)); 1.755 + 1.756 + MP_CHECKOK(mp_set_int(&order_1, 1)); 1.757 + MP_CHECKOK(mp_sub(&ecgroup->order, &order_1, &order_1)); 1.758 + 1.759 + /* Test Algorithm 1: Jacobian-Affine Double & Add */ 1.760 + ec_GFp_pt_mul_jac_fp(&order_1, &ecgroup->genx, &ecgroup->geny, &rx, 1.761 + &ry, ecgroup); 1.762 + MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth)); 1.763 + if ((mp_cmp(&rx, &ecgroup->genx) != 0) 1.764 + || (mp_cmp(&ry, &ecgroup->geny) != 0)) { 1.765 + printf 1.766 + (" Error: ec_GFp_pt_mul_jac_fp invalid result (expected (- base point)).\n"); 1.767 + MP_CHECKOK(mp_toradix(&rx, s, 16)); 1.768 + printf("rx %s\n", s); 1.769 + MP_CHECKOK(mp_toradix(&ry, s, 16)); 1.770 + printf("ry %s\n", s); 1.771 + res = MP_NO; 1.772 + goto CLEANUP; 1.773 + } 1.774 + 1.775 + ec_GFp_pt_mul_jac_fp(&ecgroup->order, &ecgroup->genx, &ecgroup->geny, 1.776 + &rx, &ry, ecgroup); 1.777 + if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { 1.778 + printf 1.779 + (" Error: ec_GFp_pt_mul_jac_fp invalid result (expected point at infinity.\n"); 1.780 + MP_CHECKOK(mp_toradix(&rx, s, 16)); 1.781 + printf("rx %s\n", s); 1.782 + MP_CHECKOK(mp_toradix(&ry, s, 16)); 1.783 + printf("ry %s\n", s); 1.784 + res = MP_NO; 1.785 + goto CLEANUP; 1.786 + } 1.787 + 1.788 + /* Test Algorithm 2: 4-bit Window in Jacobian */ 1.789 + ec_GFp_point_mul_jac_4w_fp(&order_1, &ecgroup->genx, &ecgroup->geny, 1.790 + &rx, &ry, ecgroup); 1.791 + MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth)); 1.792 + if ((mp_cmp(&rx, &ecgroup->genx) != 0) 1.793 + || (mp_cmp(&ry, &ecgroup->geny) != 0)) { 1.794 + printf 1.795 + (" Error: ec_GFp_point_mul_jac_4w_fp invalid result (expected (- base point)).\n"); 1.796 + MP_CHECKOK(mp_toradix(&rx, s, 16)); 1.797 + printf("rx %s\n", s); 1.798 + MP_CHECKOK(mp_toradix(&ry, s, 16)); 1.799 + printf("ry %s\n", s); 1.800 + res = MP_NO; 1.801 + goto CLEANUP; 1.802 + } 1.803 + 1.804 + ec_GFp_point_mul_jac_4w_fp(&ecgroup->order, &ecgroup->genx, 1.805 + &ecgroup->geny, &rx, &ry, ecgroup); 1.806 + if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { 1.807 + printf 1.808 + (" Error: ec_GFp_point_mul_jac_4w_fp invalid result (expected point at infinity.\n"); 1.809 + MP_CHECKOK(mp_toradix(&rx, s, 16)); 1.810 + printf("rx %s\n", s); 1.811 + MP_CHECKOK(mp_toradix(&ry, s, 16)); 1.812 + printf("ry %s\n", s); 1.813 + res = MP_NO; 1.814 + goto CLEANUP; 1.815 + } 1.816 + 1.817 + /* Test Algorithm 3: wNAF with modified Jacobian coordinates */ 1.818 + ec_GFp_point_mul_wNAF_fp(&order_1, &ecgroup->genx, &ecgroup->geny, &rx, 1.819 + &ry, ecgroup); 1.820 + MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth)); 1.821 + if ((mp_cmp(&rx, &ecgroup->genx) != 0) 1.822 + || (mp_cmp(&ry, &ecgroup->geny) != 0)) { 1.823 + printf 1.824 + (" Error: ec_GFp_pt_mul_wNAF_fp invalid result (expected (- base point)).\n"); 1.825 + MP_CHECKOK(mp_toradix(&rx, s, 16)); 1.826 + printf("rx %s\n", s); 1.827 + MP_CHECKOK(mp_toradix(&ry, s, 16)); 1.828 + printf("ry %s\n", s); 1.829 + res = MP_NO; 1.830 + goto CLEANUP; 1.831 + } 1.832 + 1.833 + ec_GFp_point_mul_wNAF_fp(&ecgroup->order, &ecgroup->genx, 1.834 + &ecgroup->geny, &rx, &ry, ecgroup); 1.835 + if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { 1.836 + printf 1.837 + (" Error: ec_GFp_pt_mul_wNAF_fp invalid result (expected point at infinity.\n"); 1.838 + MP_CHECKOK(mp_toradix(&rx, s, 16)); 1.839 + printf("rx %s\n", s); 1.840 + MP_CHECKOK(mp_toradix(&ry, s, 16)); 1.841 + printf("ry %s\n", s); 1.842 + res = MP_NO; 1.843 + goto CLEANUP; 1.844 + } 1.845 + 1.846 + CLEANUP: 1.847 + if (res == MP_OKAY) 1.848 + printf(" Test Passed - Point Multiplication\n"); 1.849 + else 1.850 + printf("TEST FAILED - Point Multiplication\n"); 1.851 + mp_clear(&rx); 1.852 + mp_clear(&ry); 1.853 + mp_clear(&order_1); 1.854 + 1.855 + return res; 1.856 +} 1.857 + 1.858 +/* Tests point multiplication with a random scalar repeatedly, comparing 1.859 + * for consistency within different algorithms. */ 1.860 +mp_err 1.861 +testPointMulRandom(ECGroup *ecgroup) 1.862 +{ 1.863 + mp_err res; 1.864 + mp_int rx, ry, rx2, ry2, n; 1.865 + int i, size; 1.866 + EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; 1.867 + 1.868 + MP_DIGITS(&rx) = 0; 1.869 + MP_DIGITS(&ry) = 0; 1.870 + MP_DIGITS(&rx2) = 0; 1.871 + MP_DIGITS(&ry2) = 0; 1.872 + MP_DIGITS(&n) = 0; 1.873 + 1.874 + MP_CHECKOK(mp_init(&rx)); 1.875 + MP_CHECKOK(mp_init(&ry)); 1.876 + MP_CHECKOK(mp_init(&rx2)); 1.877 + MP_CHECKOK(mp_init(&ry2)); 1.878 + MP_CHECKOK(mp_init(&n)); 1.879 + 1.880 + for (i = 0; i < 100; i++) { 1.881 + /* compute random scalar */ 1.882 + size = mpl_significant_bits(&ecgroup->meth->irr); 1.883 + if (size < MP_OKAY) { 1.884 + res = MP_NO; 1.885 + goto CLEANUP; 1.886 + } 1.887 + MP_CHECKOK(mpp_random_size(&n, group->orderBitSize)); 1.888 + MP_CHECKOK(mp_mod(&n, &ecgroup->order, &n)); 1.889 + 1.890 + ec_GFp_pt_mul_jac(&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry, 1.891 + ecgroup); 1.892 + ec_GFp_pt_mul_jac_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx2, 1.893 + &ry2, ecgroup); 1.894 + 1.895 + if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) { 1.896 + printf 1.897 + (" Error: different results for Point Multiplication - Double & Add.\n"); 1.898 + res = MP_NO; 1.899 + goto CLEANUP; 1.900 + } 1.901 + 1.902 + ec_GFp_point_mul_wNAF_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx, 1.903 + &ry, ecgroup); 1.904 + if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) { 1.905 + printf 1.906 + (" Error: different results for Point Multiplication - wNAF.\n"); 1.907 + res = MP_NO; 1.908 + goto CLEANUP; 1.909 + } 1.910 + 1.911 + ec_GFp_point_mul_jac_4w_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx, 1.912 + &ry, ecgroup); 1.913 + if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) { 1.914 + printf 1.915 + (" Error: different results for Point Multiplication - 4 bit window.\n"); 1.916 + res = MP_NO; 1.917 + goto CLEANUP; 1.918 + } 1.919 + 1.920 + } 1.921 + 1.922 + CLEANUP: 1.923 + if (res == MP_OKAY) 1.924 + printf(" Test Passed - Point Random Multiplication\n"); 1.925 + else 1.926 + printf("TEST FAILED - Point Random Multiplication\n"); 1.927 + mp_clear(&rx); 1.928 + mp_clear(&ry); 1.929 + mp_clear(&rx2); 1.930 + mp_clear(&ry2); 1.931 + mp_clear(&n); 1.932 + 1.933 + return res; 1.934 +} 1.935 + 1.936 +/* Tests the time required for a point multiplication */ 1.937 +mp_err 1.938 +testPointMulTime(ECGroup *ecgroup) 1.939 +{ 1.940 + mp_err res = MP_OKAY; 1.941 + mp_int rx, ry, n; 1.942 + int size; 1.943 + 1.944 + MP_DIGITS(&rx) = 0; 1.945 + MP_DIGITS(&ry) = 0; 1.946 + MP_DIGITS(&n) = 0; 1.947 + 1.948 + MP_CHECKOK(mp_init(&rx)); 1.949 + MP_CHECKOK(mp_init(&ry)); 1.950 + MP_CHECKOK(mp_init(&n)); 1.951 + 1.952 + /* compute random scalar */ 1.953 + size = mpl_significant_bits(&ecgroup->meth->irr); 1.954 + if (size < MP_OKAY) { 1.955 + res = MP_NO; 1.956 + goto CLEANUP; 1.957 + } 1.958 + 1.959 + MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS)); 1.960 + MP_CHECKOK(ecgroup->meth->field_mod(&n, &n, ecgroup->meth)); 1.961 + 1.962 + M_TimeOperation(ec_GFp_pt_mul_jac_fp 1.963 + (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry, 1.964 + ecgroup), 1000); 1.965 + 1.966 + M_TimeOperation(ec_GFp_point_mul_jac_4w_fp 1.967 + (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry, 1.968 + ecgroup), 1000); 1.969 + 1.970 + M_TimeOperation(ec_GFp_point_mul_wNAF_fp 1.971 + (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry, 1.972 + ecgroup), 1000); 1.973 + 1.974 + M_TimeOperation(ec_GFp_pt_mul_jac 1.975 + (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry, 1.976 + ecgroup), 100); 1.977 + 1.978 + CLEANUP: 1.979 + if (res == MP_OKAY) 1.980 + printf(" Test Passed - Point Multiplication Timing\n"); 1.981 + else 1.982 + printf("TEST FAILED - Point Multiplication Timing\n"); 1.983 + mp_clear(&rx); 1.984 + mp_clear(&ry); 1.985 + mp_clear(&n); 1.986 + 1.987 + return res; 1.988 +} 1.989 + 1.990 +/* Tests pre computation of Chudnovsky Jacobian points used in wNAF form */ 1.991 +mp_err 1.992 +testPreCompute(ECGroup *ecgroup) 1.993 +{ 1.994 + ecfp_chud_pt precomp[16]; 1.995 + ecfp_aff_pt p; 1.996 + EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; 1.997 + int i; 1.998 + mp_err res; 1.999 + 1.1000 + mp_int x, y, ny, x2, y2; 1.1001 + 1.1002 + MP_DIGITS(&x) = 0; 1.1003 + MP_DIGITS(&y) = 0; 1.1004 + MP_DIGITS(&ny) = 0; 1.1005 + MP_DIGITS(&x2) = 0; 1.1006 + MP_DIGITS(&y2) = 0; 1.1007 + 1.1008 + MP_CHECKOK(mp_init(&x)); 1.1009 + MP_CHECKOK(mp_init(&y)); 1.1010 + MP_CHECKOK(mp_init(&ny)); 1.1011 + MP_CHECKOK(mp_init(&x2)); 1.1012 + MP_CHECKOK(mp_init(&y2)); 1.1013 + 1.1014 + ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); 1.1015 + ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); 1.1016 + ecfp_i2fp(group->curvea, &(ecgroup->curvea), ecgroup); 1.1017 + 1.1018 + /* Perform precomputation */ 1.1019 + group->precompute_chud(precomp, &p, group); 1.1020 + 1.1021 + M_TimeOperation(group->precompute_chud(precomp, &p, group), 10000); 1.1022 + 1.1023 + /* Calculate addition to compare against */ 1.1024 + MP_CHECKOK(mp_copy(&ecgroup->genx, &x)); 1.1025 + MP_CHECKOK(mp_copy(&ecgroup->geny, &y)); 1.1026 + MP_CHECKOK(ecgroup->meth->field_neg(&y, &ny, ecgroup->meth)); 1.1027 + 1.1028 + ec_GFp_pt_dbl_aff(&x, &y, &x2, &y2, ecgroup); 1.1029 + 1.1030 + for (i = 0; i < 8; i++) { 1.1031 + MP_CHECKOK(testChudPoint(&precomp[8 + i], &x, &y, ecgroup)); 1.1032 + MP_CHECKOK(testChudPoint(&precomp[7 - i], &x, &ny, ecgroup)); 1.1033 + ec_GFp_pt_add_aff(&x, &y, &x2, &y2, &x, &y, ecgroup); 1.1034 + MP_CHECKOK(ecgroup->meth->field_neg(&y, &ny, ecgroup->meth)); 1.1035 + } 1.1036 + 1.1037 + CLEANUP: 1.1038 + if (res == MP_OKAY) 1.1039 + printf(" Test Passed - Precomputation\n"); 1.1040 + else 1.1041 + printf("TEST FAILED - Precomputation\n"); 1.1042 + 1.1043 + mp_clear(&x); 1.1044 + mp_clear(&y); 1.1045 + mp_clear(&ny); 1.1046 + mp_clear(&x2); 1.1047 + mp_clear(&y2); 1.1048 + return res; 1.1049 +} 1.1050 + 1.1051 +/* Given a curve using floating point arithmetic, test it. This method 1.1052 + * specifies which of the above tests to run. */ 1.1053 +mp_err 1.1054 +testCurve(ECGroup *ecgroup) 1.1055 +{ 1.1056 + int res = MP_OKAY; 1.1057 + 1.1058 + MP_CHECKOK(testPointAddJacAff(ecgroup)); 1.1059 + MP_CHECKOK(testPointAddJac(ecgroup)); 1.1060 + MP_CHECKOK(testPointAddChud(ecgroup)); 1.1061 + MP_CHECKOK(testPointAddJmChud(ecgroup)); 1.1062 + MP_CHECKOK(testPointDoubleJac(ecgroup)); 1.1063 + MP_CHECKOK(testPointDoubleChud(ecgroup)); 1.1064 + MP_CHECKOK(testPointDoubleJm(ecgroup)); 1.1065 + MP_CHECKOK(testPreCompute(ecgroup)); 1.1066 + MP_CHECKOK(testPointMul(ecgroup)); 1.1067 + MP_CHECKOK(testPointMulRandom(ecgroup)); 1.1068 + MP_CHECKOK(testPointMulTime(ecgroup)); 1.1069 + CLEANUP: 1.1070 + return res; 1.1071 +} 1.1072 + 1.1073 +/* Tests a number of curves optimized using floating point arithmetic */ 1.1074 +int 1.1075 +main(void) 1.1076 +{ 1.1077 + mp_err res = MP_OKAY; 1.1078 + ECGroup *ecgroup = NULL; 1.1079 + 1.1080 + /* specific arithmetic tests */ 1.1081 + M_TestCurve("SECG-160R1", ECCurve_SECG_PRIME_160R1); 1.1082 + M_TestCurve("SECG-192R1", ECCurve_SECG_PRIME_192R1); 1.1083 + M_TestCurve("SEGC-224R1", ECCurve_SECG_PRIME_224R1); 1.1084 + 1.1085 + CLEANUP: 1.1086 + ECGroup_free(ecgroup); 1.1087 + if (res != MP_OKAY) { 1.1088 + printf("Error: exiting with error value %i\n", res); 1.1089 + } 1.1090 + return res; 1.1091 +}