michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "ecp_fp.h" michael@0: #include "mpprime.h" michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: /* Time k repetitions of operation op. */ michael@0: #define M_TimeOperation(op, k) { \ michael@0: double dStart, dNow, dUserTime; \ michael@0: struct rusage ru; \ michael@0: int i; \ michael@0: getrusage(RUSAGE_SELF, &ru); \ michael@0: dStart = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \ michael@0: for (i = 0; i < k; i++) { \ michael@0: { op; } \ michael@0: }; \ michael@0: getrusage(RUSAGE_SELF, &ru); \ michael@0: dNow = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \ michael@0: dUserTime = dNow-dStart; \ michael@0: if (dUserTime) printf(" %-45s\n k: %6i, t: %6.2f sec, k/t: %6.2f ops/sec\n", #op, k, dUserTime, k/dUserTime); \ michael@0: } michael@0: michael@0: /* Test curve using specific floating point field arithmetic. */ michael@0: #define M_TestCurve(name_c, name) { \ michael@0: printf("Testing %s using specific floating point implementation...\n", name_c); \ michael@0: ECGroup_free(ecgroup); \ michael@0: ecgroup = ECGroup_fromName(name); \ michael@0: if (ecgroup == NULL) { \ michael@0: printf(" Warning: could not construct group.\n"); \ michael@0: printf("%s failed.\n", name_c); \ michael@0: res = MP_NO; \ michael@0: goto CLEANUP; \ michael@0: } else { \ michael@0: MP_CHECKOK( testCurve(ecgroup)); \ michael@0: printf("%s passed.\n", name_c); \ michael@0: } \ michael@0: } michael@0: michael@0: /* Outputs a floating point double (currently not used) */ michael@0: void michael@0: d_output(const double *u, int len, char *name, const EC_group_fp * group) michael@0: { michael@0: int i; michael@0: michael@0: printf("%s: ", name); michael@0: for (i = 0; i < len; i++) { michael@0: printf("+ %.2f * 2^%i ", u[i] / ecfp_exp[i], michael@0: group->doubleBitSize * i); michael@0: } michael@0: printf("\n"); michael@0: } michael@0: michael@0: /* Tests a point p in Jacobian coordinates, comparing against the michael@0: * expected affine result (x, y). */ michael@0: mp_err michael@0: testJacPoint(ecfp_jac_pt * p, mp_int *x, mp_int *y, ECGroup *ecgroup) michael@0: { michael@0: char s[1000]; michael@0: mp_int rx, ry, rz; michael@0: mp_err res = MP_OKAY; michael@0: michael@0: MP_DIGITS(&rx) = 0; michael@0: MP_DIGITS(&ry) = 0; michael@0: MP_DIGITS(&rz) = 0; michael@0: michael@0: MP_CHECKOK(mp_init(&rx)); michael@0: MP_CHECKOK(mp_init(&ry)); michael@0: MP_CHECKOK(mp_init(&rz)); michael@0: michael@0: ecfp_fp2i(&rx, p->x, ecgroup); michael@0: ecfp_fp2i(&ry, p->y, ecgroup); michael@0: ecfp_fp2i(&rz, p->z, ecgroup); michael@0: michael@0: /* convert result R to affine coordinates */ michael@0: ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup); michael@0: michael@0: /* Compare to expected result */ michael@0: if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) { michael@0: printf(" Error: Jacobian Floating Point Incorrect.\n"); michael@0: MP_CHECKOK(mp_toradix(&rx, s, 16)); michael@0: printf("floating point result\nrx %s\n", s); michael@0: MP_CHECKOK(mp_toradix(&ry, s, 16)); michael@0: printf("ry %s\n", s); michael@0: MP_CHECKOK(mp_toradix(x, s, 16)); michael@0: printf("integer result\nx %s\n", s); michael@0: MP_CHECKOK(mp_toradix(y, s, 16)); michael@0: printf("y %s\n", s); michael@0: res = MP_NO; michael@0: goto CLEANUP; michael@0: } michael@0: michael@0: CLEANUP: michael@0: mp_clear(&rx); michael@0: mp_clear(&ry); michael@0: mp_clear(&rz); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: /* Tests a point p in Chudnovsky Jacobian coordinates, comparing against michael@0: * the expected affine result (x, y). */ michael@0: mp_err michael@0: testChudPoint(ecfp_chud_pt * p, mp_int *x, mp_int *y, ECGroup *ecgroup) michael@0: { michael@0: michael@0: char s[1000]; michael@0: mp_int rx, ry, rz, rz2, rz3, test; michael@0: mp_err res = MP_OKAY; michael@0: michael@0: /* Initialization */ michael@0: MP_DIGITS(&rx) = 0; michael@0: MP_DIGITS(&ry) = 0; michael@0: MP_DIGITS(&rz) = 0; michael@0: MP_DIGITS(&rz2) = 0; michael@0: MP_DIGITS(&rz3) = 0; michael@0: MP_DIGITS(&test) = 0; michael@0: michael@0: MP_CHECKOK(mp_init(&rx)); michael@0: MP_CHECKOK(mp_init(&ry)); michael@0: MP_CHECKOK(mp_init(&rz)); michael@0: MP_CHECKOK(mp_init(&rz2)); michael@0: MP_CHECKOK(mp_init(&rz3)); michael@0: MP_CHECKOK(mp_init(&test)); michael@0: michael@0: /* Convert to integers */ michael@0: ecfp_fp2i(&rx, p->x, ecgroup); michael@0: ecfp_fp2i(&ry, p->y, ecgroup); michael@0: ecfp_fp2i(&rz, p->z, ecgroup); michael@0: ecfp_fp2i(&rz2, p->z2, ecgroup); michael@0: ecfp_fp2i(&rz3, p->z3, ecgroup); michael@0: michael@0: /* Verify z2, z3 are valid */ michael@0: mp_sqrmod(&rz, &ecgroup->meth->irr, &test); michael@0: if (mp_cmp(&test, &rz2) != 0) { michael@0: printf(" Error: rzp2 not valid\n"); michael@0: res = MP_NO; michael@0: goto CLEANUP; michael@0: } michael@0: mp_mulmod(&test, &rz, &ecgroup->meth->irr, &test); michael@0: if (mp_cmp(&test, &rz3) != 0) { michael@0: printf(" Error: rzp2 not valid\n"); michael@0: res = MP_NO; michael@0: goto CLEANUP; michael@0: } michael@0: michael@0: /* convert result R to affine coordinates */ michael@0: ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup); michael@0: michael@0: /* Compare against expected result */ michael@0: if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) { michael@0: printf(" Error: Chudnovsky Floating Point Incorrect.\n"); michael@0: MP_CHECKOK(mp_toradix(&rx, s, 16)); michael@0: printf("floating point result\nrx %s\n", s); michael@0: MP_CHECKOK(mp_toradix(&ry, s, 16)); michael@0: printf("ry %s\n", s); michael@0: MP_CHECKOK(mp_toradix(x, s, 16)); michael@0: printf("integer result\nx %s\n", s); michael@0: MP_CHECKOK(mp_toradix(y, s, 16)); michael@0: printf("y %s\n", s); michael@0: res = MP_NO; michael@0: goto CLEANUP; michael@0: } michael@0: michael@0: CLEANUP: michael@0: mp_clear(&rx); michael@0: mp_clear(&ry); michael@0: mp_clear(&rz); michael@0: mp_clear(&rz2); michael@0: mp_clear(&rz3); michael@0: mp_clear(&test); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: /* Tests a point p in Modified Jacobian coordinates, comparing against the michael@0: * expected affine result (x, y). */ michael@0: mp_err michael@0: testJmPoint(ecfp_jm_pt * r, mp_int *x, mp_int *y, ECGroup *ecgroup) michael@0: { michael@0: michael@0: char s[1000]; michael@0: mp_int rx, ry, rz, raz4, test; michael@0: mp_err res = MP_OKAY; michael@0: michael@0: /* Initialization */ michael@0: MP_DIGITS(&rx) = 0; michael@0: MP_DIGITS(&ry) = 0; michael@0: MP_DIGITS(&rz) = 0; michael@0: MP_DIGITS(&raz4) = 0; michael@0: MP_DIGITS(&test) = 0; michael@0: michael@0: MP_CHECKOK(mp_init(&rx)); michael@0: MP_CHECKOK(mp_init(&ry)); michael@0: MP_CHECKOK(mp_init(&rz)); michael@0: MP_CHECKOK(mp_init(&raz4)); michael@0: MP_CHECKOK(mp_init(&test)); michael@0: michael@0: /* Convert to integer */ michael@0: ecfp_fp2i(&rx, r->x, ecgroup); michael@0: ecfp_fp2i(&ry, r->y, ecgroup); michael@0: ecfp_fp2i(&rz, r->z, ecgroup); michael@0: ecfp_fp2i(&raz4, r->az4, ecgroup); michael@0: michael@0: /* Verify raz4 = rz^4 * a */ michael@0: mp_sqrmod(&rz, &ecgroup->meth->irr, &test); michael@0: mp_sqrmod(&test, &ecgroup->meth->irr, &test); michael@0: mp_mulmod(&test, &ecgroup->curvea, &ecgroup->meth->irr, &test); michael@0: if (mp_cmp(&test, &raz4) != 0) { michael@0: printf(" Error: a*z^4 not valid\n"); michael@0: MP_CHECKOK(mp_toradix(&ecgroup->curvea, s, 16)); michael@0: printf("a %s\n", s); michael@0: MP_CHECKOK(mp_toradix(&rz, s, 16)); michael@0: printf("rz %s\n", s); michael@0: MP_CHECKOK(mp_toradix(&raz4, s, 16)); michael@0: printf("raz4 %s\n", s); michael@0: res = MP_NO; michael@0: goto CLEANUP; michael@0: } michael@0: michael@0: /* convert result R to affine coordinates */ michael@0: ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup); michael@0: michael@0: /* Compare against expected result */ michael@0: if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) { michael@0: printf(" Error: Modified Jacobian Floating Point Incorrect.\n"); michael@0: MP_CHECKOK(mp_toradix(&rx, s, 16)); michael@0: printf("floating point result\nrx %s\n", s); michael@0: MP_CHECKOK(mp_toradix(&ry, s, 16)); michael@0: printf("ry %s\n", s); michael@0: MP_CHECKOK(mp_toradix(x, s, 16)); michael@0: printf("integer result\nx %s\n", s); michael@0: MP_CHECKOK(mp_toradix(y, s, 16)); michael@0: printf("y %s\n", s); michael@0: res = MP_NO; michael@0: goto CLEANUP; michael@0: } michael@0: CLEANUP: michael@0: mp_clear(&rx); michael@0: mp_clear(&ry); michael@0: mp_clear(&rz); michael@0: mp_clear(&raz4); michael@0: mp_clear(&test); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: /* Tests point addition of Jacobian + Affine -> Jacobian */ michael@0: mp_err michael@0: testPointAddJacAff(ECGroup *ecgroup) michael@0: { michael@0: mp_err res; michael@0: mp_int pz, rx2, ry2, rz2; michael@0: ecfp_jac_pt p, r; michael@0: ecfp_aff_pt q; michael@0: EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; michael@0: michael@0: /* Init */ michael@0: MP_DIGITS(&pz) = 0; michael@0: MP_DIGITS(&rx2) = 0; michael@0: MP_DIGITS(&ry2) = 0; michael@0: MP_DIGITS(&rz2) = 0; michael@0: MP_CHECKOK(mp_init(&pz)); michael@0: MP_CHECKOK(mp_init(&rx2)); michael@0: MP_CHECKOK(mp_init(&ry2)); michael@0: MP_CHECKOK(mp_init(&rz2)); michael@0: michael@0: MP_CHECKOK(mp_set_int(&pz, 5)); michael@0: michael@0: /* Set p */ michael@0: ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); michael@0: ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); michael@0: ecfp_i2fp(p.z, &pz, ecgroup); michael@0: /* Set q */ michael@0: ecfp_i2fp(q.x, &ecgroup->geny, ecgroup); michael@0: ecfp_i2fp(q.y, &ecgroup->genx, ecgroup); michael@0: michael@0: /* Do calculations */ michael@0: group->pt_add_jac_aff(&p, &q, &r, group); michael@0: michael@0: /* Do calculation in integer to compare against */ michael@0: MP_CHECKOK(ec_GFp_pt_add_jac_aff michael@0: (&ecgroup->genx, &ecgroup->geny, &pz, &ecgroup->geny, michael@0: &ecgroup->genx, &rx2, &ry2, &rz2, ecgroup)); michael@0: /* convert result R to affine coordinates */ michael@0: ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup); michael@0: michael@0: MP_CHECKOK(testJacPoint(&r, &rx2, &ry2, ecgroup)); michael@0: michael@0: CLEANUP: michael@0: if (res == MP_OKAY) michael@0: printf(" Test Passed - Point Addition - Jacobian & Affine\n"); michael@0: else michael@0: printf("TEST FAILED - Point Addition - Jacobian & Affine\n"); michael@0: michael@0: mp_clear(&pz); michael@0: mp_clear(&rx2); michael@0: mp_clear(&ry2); michael@0: mp_clear(&rz2); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: /* Tests point addition in Jacobian coordinates */ michael@0: mp_err michael@0: testPointAddJac(ECGroup *ecgroup) michael@0: { michael@0: mp_err res; michael@0: mp_int pz, qz, qx, qy, rx2, ry2, rz2; michael@0: ecfp_jac_pt p, q, r; michael@0: EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; michael@0: michael@0: /* Init */ michael@0: MP_DIGITS(&pz) = 0; michael@0: MP_DIGITS(&qx) = 0; michael@0: MP_DIGITS(&qy) = 0; michael@0: MP_DIGITS(&qz) = 0; michael@0: MP_DIGITS(&rx2) = 0; michael@0: MP_DIGITS(&ry2) = 0; michael@0: MP_DIGITS(&rz2) = 0; michael@0: MP_CHECKOK(mp_init(&pz)); michael@0: MP_CHECKOK(mp_init(&qx)); michael@0: MP_CHECKOK(mp_init(&qy)); michael@0: MP_CHECKOK(mp_init(&qz)); michael@0: MP_CHECKOK(mp_init(&rx2)); michael@0: MP_CHECKOK(mp_init(&ry2)); michael@0: MP_CHECKOK(mp_init(&rz2)); michael@0: michael@0: MP_CHECKOK(mp_set_int(&pz, 5)); michael@0: MP_CHECKOK(mp_set_int(&qz, 105)); michael@0: michael@0: /* Set p */ michael@0: ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); michael@0: ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); michael@0: ecfp_i2fp(p.z, &pz, ecgroup); michael@0: /* Set q */ michael@0: ecfp_i2fp(q.x, &ecgroup->geny, ecgroup); michael@0: ecfp_i2fp(q.y, &ecgroup->genx, ecgroup); michael@0: ecfp_i2fp(q.z, &qz, ecgroup); michael@0: michael@0: /* Do calculations */ michael@0: group->pt_add_jac(&p, &q, &r, group); michael@0: michael@0: /* Do calculation in integer to compare against */ michael@0: ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy, michael@0: ecgroup); michael@0: MP_CHECKOK(ec_GFp_pt_add_jac_aff michael@0: (&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy, &rx2, &ry2, michael@0: &rz2, ecgroup)); michael@0: /* convert result R to affine coordinates */ michael@0: ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup); michael@0: michael@0: MP_CHECKOK(testJacPoint(&r, &rx2, &ry2, ecgroup)); michael@0: michael@0: CLEANUP: michael@0: if (res == MP_OKAY) michael@0: printf(" Test Passed - Point Addition - Jacobian\n"); michael@0: else michael@0: printf("TEST FAILED - Point Addition - Jacobian\n"); michael@0: michael@0: mp_clear(&pz); michael@0: mp_clear(&qx); michael@0: mp_clear(&qy); michael@0: mp_clear(&qz); michael@0: mp_clear(&rx2); michael@0: mp_clear(&ry2); michael@0: mp_clear(&rz2); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: /* Tests point addition in Chudnovsky Jacobian Coordinates */ michael@0: mp_err michael@0: testPointAddChud(ECGroup *ecgroup) michael@0: { michael@0: mp_err res; michael@0: mp_int rx2, ry2, ix, iy, iz, test, pz, qx, qy, qz; michael@0: ecfp_chud_pt p, q, r; michael@0: EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; michael@0: michael@0: MP_DIGITS(&qx) = 0; michael@0: MP_DIGITS(&qy) = 0; michael@0: MP_DIGITS(&qz) = 0; michael@0: MP_DIGITS(&pz) = 0; michael@0: MP_DIGITS(&rx2) = 0; michael@0: MP_DIGITS(&ry2) = 0; michael@0: MP_DIGITS(&ix) = 0; michael@0: MP_DIGITS(&iy) = 0; michael@0: MP_DIGITS(&iz) = 0; michael@0: MP_DIGITS(&test) = 0; michael@0: michael@0: MP_CHECKOK(mp_init(&qx)); michael@0: MP_CHECKOK(mp_init(&qy)); michael@0: MP_CHECKOK(mp_init(&qz)); michael@0: MP_CHECKOK(mp_init(&pz)); michael@0: MP_CHECKOK(mp_init(&rx2)); michael@0: MP_CHECKOK(mp_init(&ry2)); michael@0: MP_CHECKOK(mp_init(&ix)); michael@0: MP_CHECKOK(mp_init(&iy)); michael@0: MP_CHECKOK(mp_init(&iz)); michael@0: MP_CHECKOK(mp_init(&test)); michael@0: michael@0: /* Test Chudnovsky form addition */ michael@0: /* Set p */ michael@0: MP_CHECKOK(mp_set_int(&pz, 5)); michael@0: ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); michael@0: ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); michael@0: ecfp_i2fp(p.z, &pz, ecgroup); michael@0: mp_sqrmod(&pz, &ecgroup->meth->irr, &test); michael@0: ecfp_i2fp(p.z2, &test, ecgroup); michael@0: mp_mulmod(&test, &pz, &ecgroup->meth->irr, &test); michael@0: ecfp_i2fp(p.z3, &test, ecgroup); michael@0: michael@0: /* Set q */ michael@0: MP_CHECKOK(mp_set_int(&qz, 105)); michael@0: ecfp_i2fp(q.x, &ecgroup->geny, ecgroup); michael@0: ecfp_i2fp(q.y, &ecgroup->genx, ecgroup); michael@0: ecfp_i2fp(q.z, &qz, ecgroup); michael@0: mp_sqrmod(&qz, &ecgroup->meth->irr, &test); michael@0: ecfp_i2fp(q.z2, &test, ecgroup); michael@0: mp_mulmod(&test, &qz, &ecgroup->meth->irr, &test); michael@0: ecfp_i2fp(q.z3, &test, ecgroup); michael@0: michael@0: group->pt_add_chud(&p, &q, &r, group); michael@0: michael@0: /* Calculate addition to compare against */ michael@0: ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy, michael@0: ecgroup); michael@0: ec_GFp_pt_add_jac_aff(&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy, michael@0: &ix, &iy, &iz, ecgroup); michael@0: ec_GFp_pt_jac2aff(&ix, &iy, &iz, &rx2, &ry2, ecgroup); michael@0: michael@0: MP_CHECKOK(testChudPoint(&r, &rx2, &ry2, ecgroup)); michael@0: michael@0: CLEANUP: michael@0: if (res == MP_OKAY) michael@0: printf(" Test Passed - Point Addition - Chudnovsky Jacobian\n"); michael@0: else michael@0: printf("TEST FAILED - Point Addition - Chudnovsky Jacobian\n"); michael@0: michael@0: mp_clear(&qx); michael@0: mp_clear(&qy); michael@0: mp_clear(&qz); michael@0: mp_clear(&pz); michael@0: mp_clear(&rx2); michael@0: mp_clear(&ry2); michael@0: mp_clear(&ix); michael@0: mp_clear(&iy); michael@0: mp_clear(&iz); michael@0: mp_clear(&test); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: /* Tests point addition in Modified Jacobian + Chudnovsky Jacobian -> michael@0: * Modified Jacobian coordinates. */ michael@0: mp_err michael@0: testPointAddJmChud(ECGroup *ecgroup) michael@0: { michael@0: mp_err res; michael@0: mp_int rx2, ry2, ix, iy, iz, test, pz, paz4, qx, qy, qz; michael@0: ecfp_chud_pt q; michael@0: ecfp_jm_pt p, r; michael@0: EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; michael@0: michael@0: MP_DIGITS(&qx) = 0; michael@0: MP_DIGITS(&qy) = 0; michael@0: MP_DIGITS(&qz) = 0; michael@0: MP_DIGITS(&pz) = 0; michael@0: MP_DIGITS(&paz4) = 0; michael@0: MP_DIGITS(&iz) = 0; michael@0: MP_DIGITS(&rx2) = 0; michael@0: MP_DIGITS(&ry2) = 0; michael@0: MP_DIGITS(&ix) = 0; michael@0: MP_DIGITS(&iy) = 0; michael@0: MP_DIGITS(&iz) = 0; michael@0: MP_DIGITS(&test) = 0; michael@0: michael@0: MP_CHECKOK(mp_init(&qx)); michael@0: MP_CHECKOK(mp_init(&qy)); michael@0: MP_CHECKOK(mp_init(&qz)); michael@0: MP_CHECKOK(mp_init(&pz)); michael@0: MP_CHECKOK(mp_init(&paz4)); michael@0: MP_CHECKOK(mp_init(&rx2)); michael@0: MP_CHECKOK(mp_init(&ry2)); michael@0: MP_CHECKOK(mp_init(&ix)); michael@0: MP_CHECKOK(mp_init(&iy)); michael@0: MP_CHECKOK(mp_init(&iz)); michael@0: MP_CHECKOK(mp_init(&test)); michael@0: michael@0: /* Test Modified Jacobian form addition */ michael@0: /* Set p */ michael@0: ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); michael@0: ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); michael@0: ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup); michael@0: /* paz4 = az^4 */ michael@0: MP_CHECKOK(mp_set_int(&pz, 5)); michael@0: mp_sqrmod(&pz, &ecgroup->meth->irr, &paz4); michael@0: mp_sqrmod(&paz4, &ecgroup->meth->irr, &paz4); michael@0: mp_mulmod(&paz4, &ecgroup->curvea, &ecgroup->meth->irr, &paz4); michael@0: ecfp_i2fp(p.z, &pz, ecgroup); michael@0: ecfp_i2fp(p.az4, &paz4, ecgroup); michael@0: michael@0: /* Set q */ michael@0: MP_CHECKOK(mp_set_int(&qz, 105)); michael@0: ecfp_i2fp(q.x, &ecgroup->geny, ecgroup); michael@0: ecfp_i2fp(q.y, &ecgroup->genx, ecgroup); michael@0: ecfp_i2fp(q.z, &qz, ecgroup); michael@0: mp_sqrmod(&qz, &ecgroup->meth->irr, &test); michael@0: ecfp_i2fp(q.z2, &test, ecgroup); michael@0: mp_mulmod(&test, &qz, &ecgroup->meth->irr, &test); michael@0: ecfp_i2fp(q.z3, &test, ecgroup); michael@0: michael@0: /* Do calculation */ michael@0: group->pt_add_jm_chud(&p, &q, &r, group); michael@0: michael@0: /* Calculate addition to compare against */ michael@0: ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy, michael@0: ecgroup); michael@0: ec_GFp_pt_add_jac_aff(&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy, michael@0: &ix, &iy, &iz, ecgroup); michael@0: ec_GFp_pt_jac2aff(&ix, &iy, &iz, &rx2, &ry2, ecgroup); michael@0: michael@0: MP_CHECKOK(testJmPoint(&r, &rx2, &ry2, ecgroup)); michael@0: michael@0: CLEANUP: michael@0: if (res == MP_OKAY) michael@0: printf michael@0: (" Test Passed - Point Addition - Modified & Chudnovsky Jacobian\n"); michael@0: else michael@0: printf michael@0: ("TEST FAILED - Point Addition - Modified & Chudnovsky Jacobian\n"); michael@0: michael@0: mp_clear(&qx); michael@0: mp_clear(&qy); michael@0: mp_clear(&qz); michael@0: mp_clear(&pz); michael@0: mp_clear(&paz4); michael@0: mp_clear(&rx2); michael@0: mp_clear(&ry2); michael@0: mp_clear(&ix); michael@0: mp_clear(&iy); michael@0: mp_clear(&iz); michael@0: mp_clear(&test); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: /* Tests point doubling in Modified Jacobian coordinates */ michael@0: mp_err michael@0: testPointDoubleJm(ECGroup *ecgroup) michael@0: { michael@0: mp_err res; michael@0: mp_int pz, paz4, rx2, ry2, rz2, raz4; michael@0: ecfp_jm_pt p, r; michael@0: EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; michael@0: michael@0: MP_DIGITS(&pz) = 0; michael@0: MP_DIGITS(&paz4) = 0; michael@0: MP_DIGITS(&rx2) = 0; michael@0: MP_DIGITS(&ry2) = 0; michael@0: MP_DIGITS(&rz2) = 0; michael@0: MP_DIGITS(&raz4) = 0; michael@0: michael@0: MP_CHECKOK(mp_init(&pz)); michael@0: MP_CHECKOK(mp_init(&paz4)); michael@0: MP_CHECKOK(mp_init(&rx2)); michael@0: MP_CHECKOK(mp_init(&ry2)); michael@0: MP_CHECKOK(mp_init(&rz2)); michael@0: MP_CHECKOK(mp_init(&raz4)); michael@0: michael@0: /* Set p */ michael@0: ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); michael@0: ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); michael@0: ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup); michael@0: michael@0: /* paz4 = az^4 */ michael@0: MP_CHECKOK(mp_set_int(&pz, 5)); michael@0: mp_sqrmod(&pz, &ecgroup->meth->irr, &paz4); michael@0: mp_sqrmod(&paz4, &ecgroup->meth->irr, &paz4); michael@0: mp_mulmod(&paz4, &ecgroup->curvea, &ecgroup->meth->irr, &paz4); michael@0: michael@0: ecfp_i2fp(p.z, &pz, ecgroup); michael@0: ecfp_i2fp(p.az4, &paz4, ecgroup); michael@0: michael@0: group->pt_dbl_jm(&p, &r, group); michael@0: michael@0: M_TimeOperation(group->pt_dbl_jm(&p, &r, group), 100000); michael@0: michael@0: /* Calculate doubling to compare against */ michael@0: ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2, michael@0: &rz2, ecgroup); michael@0: ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup); michael@0: michael@0: /* Do comparison and check az^4 */ michael@0: MP_CHECKOK(testJmPoint(&r, &rx2, &ry2, ecgroup)); michael@0: michael@0: CLEANUP: michael@0: if (res == MP_OKAY) michael@0: printf(" Test Passed - Point Doubling - Modified Jacobian\n"); michael@0: else michael@0: printf("TEST FAILED - Point Doubling - Modified Jacobian\n"); michael@0: mp_clear(&pz); michael@0: mp_clear(&paz4); michael@0: mp_clear(&rx2); michael@0: mp_clear(&ry2); michael@0: mp_clear(&rz2); michael@0: mp_clear(&raz4); michael@0: michael@0: return res; michael@0: michael@0: } michael@0: michael@0: /* Tests point doubling in Chudnovsky Jacobian coordinates */ michael@0: mp_err michael@0: testPointDoubleChud(ECGroup *ecgroup) michael@0: { michael@0: mp_err res; michael@0: mp_int px, py, pz, rx2, ry2, rz2; michael@0: ecfp_aff_pt p; michael@0: ecfp_chud_pt p2; michael@0: EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; michael@0: michael@0: MP_DIGITS(&rx2) = 0; michael@0: MP_DIGITS(&ry2) = 0; michael@0: MP_DIGITS(&rz2) = 0; michael@0: MP_DIGITS(&px) = 0; michael@0: MP_DIGITS(&py) = 0; michael@0: MP_DIGITS(&pz) = 0; michael@0: michael@0: MP_CHECKOK(mp_init(&rx2)); michael@0: MP_CHECKOK(mp_init(&ry2)); michael@0: MP_CHECKOK(mp_init(&rz2)); michael@0: MP_CHECKOK(mp_init(&px)); michael@0: MP_CHECKOK(mp_init(&py)); michael@0: MP_CHECKOK(mp_init(&pz)); michael@0: michael@0: /* Set p2 = 2P */ michael@0: ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); michael@0: ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); michael@0: ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup); michael@0: michael@0: group->pt_dbl_aff2chud(&p, &p2, group); michael@0: michael@0: /* Calculate doubling to compare against */ michael@0: MP_CHECKOK(mp_set_int(&pz, 1)); michael@0: ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2, michael@0: &rz2, ecgroup); michael@0: ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup); michael@0: michael@0: /* Do comparison and check az^4 */ michael@0: MP_CHECKOK(testChudPoint(&p2, &rx2, &ry2, ecgroup)); michael@0: michael@0: CLEANUP: michael@0: if (res == MP_OKAY) michael@0: printf(" Test Passed - Point Doubling - Chudnovsky Jacobian\n"); michael@0: else michael@0: printf("TEST FAILED - Point Doubling - Chudnovsky Jacobian\n"); michael@0: michael@0: mp_clear(&rx2); michael@0: mp_clear(&ry2); michael@0: mp_clear(&rz2); michael@0: mp_clear(&px); michael@0: mp_clear(&py); michael@0: mp_clear(&pz); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: /* Test point doubling in Jacobian coordinates */ michael@0: mp_err michael@0: testPointDoubleJac(ECGroup *ecgroup) michael@0: { michael@0: mp_err res; michael@0: mp_int pz, rx, ry, rz, rx2, ry2, rz2; michael@0: ecfp_jac_pt p, p2; michael@0: EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; michael@0: michael@0: MP_DIGITS(&pz) = 0; michael@0: MP_DIGITS(&rx) = 0; michael@0: MP_DIGITS(&ry) = 0; michael@0: MP_DIGITS(&rz) = 0; michael@0: MP_DIGITS(&rx2) = 0; michael@0: MP_DIGITS(&ry2) = 0; michael@0: MP_DIGITS(&rz2) = 0; michael@0: michael@0: MP_CHECKOK(mp_init(&pz)); michael@0: MP_CHECKOK(mp_init(&rx)); michael@0: MP_CHECKOK(mp_init(&ry)); michael@0: MP_CHECKOK(mp_init(&rz)); michael@0: MP_CHECKOK(mp_init(&rx2)); michael@0: MP_CHECKOK(mp_init(&ry2)); michael@0: MP_CHECKOK(mp_init(&rz2)); michael@0: michael@0: MP_CHECKOK(mp_set_int(&pz, 5)); michael@0: michael@0: /* Set p2 = 2P */ michael@0: ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); michael@0: ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); michael@0: ecfp_i2fp(p.z, &pz, ecgroup); michael@0: ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup); michael@0: michael@0: group->pt_dbl_jac(&p, &p2, group); michael@0: M_TimeOperation(group->pt_dbl_jac(&p, &p2, group), 100000); michael@0: michael@0: /* Calculate doubling to compare against */ michael@0: ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2, michael@0: &rz2, ecgroup); michael@0: ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup); michael@0: michael@0: /* Do comparison */ michael@0: MP_CHECKOK(testJacPoint(&p2, &rx2, &ry2, ecgroup)); michael@0: michael@0: CLEANUP: michael@0: if (res == MP_OKAY) michael@0: printf(" Test Passed - Point Doubling - Jacobian\n"); michael@0: else michael@0: printf("TEST FAILED - Point Doubling - Jacobian\n"); michael@0: michael@0: mp_clear(&pz); michael@0: mp_clear(&rx); michael@0: mp_clear(&ry); michael@0: mp_clear(&rz); michael@0: mp_clear(&rx2); michael@0: mp_clear(&ry2); michael@0: mp_clear(&rz2); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: /* Tests a point multiplication (various algorithms) */ michael@0: mp_err michael@0: testPointMul(ECGroup *ecgroup) michael@0: { michael@0: mp_err res; michael@0: char s[1000]; michael@0: mp_int rx, ry, order_1; michael@0: michael@0: /* Init */ michael@0: MP_DIGITS(&rx) = 0; michael@0: MP_DIGITS(&ry) = 0; michael@0: MP_DIGITS(&order_1) = 0; michael@0: michael@0: MP_CHECKOK(mp_init(&rx)); michael@0: MP_CHECKOK(mp_init(&ry)); michael@0: MP_CHECKOK(mp_init(&order_1)); michael@0: michael@0: MP_CHECKOK(mp_set_int(&order_1, 1)); michael@0: MP_CHECKOK(mp_sub(&ecgroup->order, &order_1, &order_1)); michael@0: michael@0: /* Test Algorithm 1: Jacobian-Affine Double & Add */ michael@0: ec_GFp_pt_mul_jac_fp(&order_1, &ecgroup->genx, &ecgroup->geny, &rx, michael@0: &ry, ecgroup); michael@0: MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth)); michael@0: if ((mp_cmp(&rx, &ecgroup->genx) != 0) michael@0: || (mp_cmp(&ry, &ecgroup->geny) != 0)) { michael@0: printf michael@0: (" Error: ec_GFp_pt_mul_jac_fp invalid result (expected (- base point)).\n"); michael@0: MP_CHECKOK(mp_toradix(&rx, s, 16)); michael@0: printf("rx %s\n", s); michael@0: MP_CHECKOK(mp_toradix(&ry, s, 16)); michael@0: printf("ry %s\n", s); michael@0: res = MP_NO; michael@0: goto CLEANUP; michael@0: } michael@0: michael@0: ec_GFp_pt_mul_jac_fp(&ecgroup->order, &ecgroup->genx, &ecgroup->geny, michael@0: &rx, &ry, ecgroup); michael@0: if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { michael@0: printf michael@0: (" Error: ec_GFp_pt_mul_jac_fp invalid result (expected point at infinity.\n"); michael@0: MP_CHECKOK(mp_toradix(&rx, s, 16)); michael@0: printf("rx %s\n", s); michael@0: MP_CHECKOK(mp_toradix(&ry, s, 16)); michael@0: printf("ry %s\n", s); michael@0: res = MP_NO; michael@0: goto CLEANUP; michael@0: } michael@0: michael@0: /* Test Algorithm 2: 4-bit Window in Jacobian */ michael@0: ec_GFp_point_mul_jac_4w_fp(&order_1, &ecgroup->genx, &ecgroup->geny, michael@0: &rx, &ry, ecgroup); michael@0: MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth)); michael@0: if ((mp_cmp(&rx, &ecgroup->genx) != 0) michael@0: || (mp_cmp(&ry, &ecgroup->geny) != 0)) { michael@0: printf michael@0: (" Error: ec_GFp_point_mul_jac_4w_fp invalid result (expected (- base point)).\n"); michael@0: MP_CHECKOK(mp_toradix(&rx, s, 16)); michael@0: printf("rx %s\n", s); michael@0: MP_CHECKOK(mp_toradix(&ry, s, 16)); michael@0: printf("ry %s\n", s); michael@0: res = MP_NO; michael@0: goto CLEANUP; michael@0: } michael@0: michael@0: ec_GFp_point_mul_jac_4w_fp(&ecgroup->order, &ecgroup->genx, michael@0: &ecgroup->geny, &rx, &ry, ecgroup); michael@0: if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { michael@0: printf michael@0: (" Error: ec_GFp_point_mul_jac_4w_fp invalid result (expected point at infinity.\n"); michael@0: MP_CHECKOK(mp_toradix(&rx, s, 16)); michael@0: printf("rx %s\n", s); michael@0: MP_CHECKOK(mp_toradix(&ry, s, 16)); michael@0: printf("ry %s\n", s); michael@0: res = MP_NO; michael@0: goto CLEANUP; michael@0: } michael@0: michael@0: /* Test Algorithm 3: wNAF with modified Jacobian coordinates */ michael@0: ec_GFp_point_mul_wNAF_fp(&order_1, &ecgroup->genx, &ecgroup->geny, &rx, michael@0: &ry, ecgroup); michael@0: MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth)); michael@0: if ((mp_cmp(&rx, &ecgroup->genx) != 0) michael@0: || (mp_cmp(&ry, &ecgroup->geny) != 0)) { michael@0: printf michael@0: (" Error: ec_GFp_pt_mul_wNAF_fp invalid result (expected (- base point)).\n"); michael@0: MP_CHECKOK(mp_toradix(&rx, s, 16)); michael@0: printf("rx %s\n", s); michael@0: MP_CHECKOK(mp_toradix(&ry, s, 16)); michael@0: printf("ry %s\n", s); michael@0: res = MP_NO; michael@0: goto CLEANUP; michael@0: } michael@0: michael@0: ec_GFp_point_mul_wNAF_fp(&ecgroup->order, &ecgroup->genx, michael@0: &ecgroup->geny, &rx, &ry, ecgroup); michael@0: if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { michael@0: printf michael@0: (" Error: ec_GFp_pt_mul_wNAF_fp invalid result (expected point at infinity.\n"); michael@0: MP_CHECKOK(mp_toradix(&rx, s, 16)); michael@0: printf("rx %s\n", s); michael@0: MP_CHECKOK(mp_toradix(&ry, s, 16)); michael@0: printf("ry %s\n", s); michael@0: res = MP_NO; michael@0: goto CLEANUP; michael@0: } michael@0: michael@0: CLEANUP: michael@0: if (res == MP_OKAY) michael@0: printf(" Test Passed - Point Multiplication\n"); michael@0: else michael@0: printf("TEST FAILED - Point Multiplication\n"); michael@0: mp_clear(&rx); michael@0: mp_clear(&ry); michael@0: mp_clear(&order_1); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: /* Tests point multiplication with a random scalar repeatedly, comparing michael@0: * for consistency within different algorithms. */ michael@0: mp_err michael@0: testPointMulRandom(ECGroup *ecgroup) michael@0: { michael@0: mp_err res; michael@0: mp_int rx, ry, rx2, ry2, n; michael@0: int i, size; michael@0: EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; michael@0: michael@0: MP_DIGITS(&rx) = 0; michael@0: MP_DIGITS(&ry) = 0; michael@0: MP_DIGITS(&rx2) = 0; michael@0: MP_DIGITS(&ry2) = 0; michael@0: MP_DIGITS(&n) = 0; michael@0: michael@0: MP_CHECKOK(mp_init(&rx)); michael@0: MP_CHECKOK(mp_init(&ry)); michael@0: MP_CHECKOK(mp_init(&rx2)); michael@0: MP_CHECKOK(mp_init(&ry2)); michael@0: MP_CHECKOK(mp_init(&n)); michael@0: michael@0: for (i = 0; i < 100; i++) { michael@0: /* compute random scalar */ michael@0: size = mpl_significant_bits(&ecgroup->meth->irr); michael@0: if (size < MP_OKAY) { michael@0: res = MP_NO; michael@0: goto CLEANUP; michael@0: } michael@0: MP_CHECKOK(mpp_random_size(&n, group->orderBitSize)); michael@0: MP_CHECKOK(mp_mod(&n, &ecgroup->order, &n)); michael@0: michael@0: ec_GFp_pt_mul_jac(&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry, michael@0: ecgroup); michael@0: ec_GFp_pt_mul_jac_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx2, michael@0: &ry2, ecgroup); michael@0: michael@0: if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) { michael@0: printf michael@0: (" Error: different results for Point Multiplication - Double & Add.\n"); michael@0: res = MP_NO; michael@0: goto CLEANUP; michael@0: } michael@0: michael@0: ec_GFp_point_mul_wNAF_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx, michael@0: &ry, ecgroup); michael@0: if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) { michael@0: printf michael@0: (" Error: different results for Point Multiplication - wNAF.\n"); michael@0: res = MP_NO; michael@0: goto CLEANUP; michael@0: } michael@0: michael@0: ec_GFp_point_mul_jac_4w_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx, michael@0: &ry, ecgroup); michael@0: if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) { michael@0: printf michael@0: (" Error: different results for Point Multiplication - 4 bit window.\n"); michael@0: res = MP_NO; michael@0: goto CLEANUP; michael@0: } michael@0: michael@0: } michael@0: michael@0: CLEANUP: michael@0: if (res == MP_OKAY) michael@0: printf(" Test Passed - Point Random Multiplication\n"); michael@0: else michael@0: printf("TEST FAILED - Point Random Multiplication\n"); michael@0: mp_clear(&rx); michael@0: mp_clear(&ry); michael@0: mp_clear(&rx2); michael@0: mp_clear(&ry2); michael@0: mp_clear(&n); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: /* Tests the time required for a point multiplication */ michael@0: mp_err michael@0: testPointMulTime(ECGroup *ecgroup) michael@0: { michael@0: mp_err res = MP_OKAY; michael@0: mp_int rx, ry, n; michael@0: int size; michael@0: michael@0: MP_DIGITS(&rx) = 0; michael@0: MP_DIGITS(&ry) = 0; michael@0: MP_DIGITS(&n) = 0; michael@0: michael@0: MP_CHECKOK(mp_init(&rx)); michael@0: MP_CHECKOK(mp_init(&ry)); michael@0: MP_CHECKOK(mp_init(&n)); michael@0: michael@0: /* compute random scalar */ michael@0: size = mpl_significant_bits(&ecgroup->meth->irr); michael@0: if (size < MP_OKAY) { michael@0: res = MP_NO; michael@0: goto CLEANUP; michael@0: } michael@0: michael@0: MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS)); michael@0: MP_CHECKOK(ecgroup->meth->field_mod(&n, &n, ecgroup->meth)); michael@0: michael@0: M_TimeOperation(ec_GFp_pt_mul_jac_fp michael@0: (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry, michael@0: ecgroup), 1000); michael@0: michael@0: M_TimeOperation(ec_GFp_point_mul_jac_4w_fp michael@0: (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry, michael@0: ecgroup), 1000); michael@0: michael@0: M_TimeOperation(ec_GFp_point_mul_wNAF_fp michael@0: (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry, michael@0: ecgroup), 1000); michael@0: michael@0: M_TimeOperation(ec_GFp_pt_mul_jac michael@0: (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry, michael@0: ecgroup), 100); michael@0: michael@0: CLEANUP: michael@0: if (res == MP_OKAY) michael@0: printf(" Test Passed - Point Multiplication Timing\n"); michael@0: else michael@0: printf("TEST FAILED - Point Multiplication Timing\n"); michael@0: mp_clear(&rx); michael@0: mp_clear(&ry); michael@0: mp_clear(&n); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: /* Tests pre computation of Chudnovsky Jacobian points used in wNAF form */ michael@0: mp_err michael@0: testPreCompute(ECGroup *ecgroup) michael@0: { michael@0: ecfp_chud_pt precomp[16]; michael@0: ecfp_aff_pt p; michael@0: EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; michael@0: int i; michael@0: mp_err res; michael@0: michael@0: mp_int x, y, ny, x2, y2; michael@0: michael@0: MP_DIGITS(&x) = 0; michael@0: MP_DIGITS(&y) = 0; michael@0: MP_DIGITS(&ny) = 0; michael@0: MP_DIGITS(&x2) = 0; michael@0: MP_DIGITS(&y2) = 0; michael@0: michael@0: MP_CHECKOK(mp_init(&x)); michael@0: MP_CHECKOK(mp_init(&y)); michael@0: MP_CHECKOK(mp_init(&ny)); michael@0: MP_CHECKOK(mp_init(&x2)); michael@0: MP_CHECKOK(mp_init(&y2)); michael@0: michael@0: ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); michael@0: ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); michael@0: ecfp_i2fp(group->curvea, &(ecgroup->curvea), ecgroup); michael@0: michael@0: /* Perform precomputation */ michael@0: group->precompute_chud(precomp, &p, group); michael@0: michael@0: M_TimeOperation(group->precompute_chud(precomp, &p, group), 10000); michael@0: michael@0: /* Calculate addition to compare against */ michael@0: MP_CHECKOK(mp_copy(&ecgroup->genx, &x)); michael@0: MP_CHECKOK(mp_copy(&ecgroup->geny, &y)); michael@0: MP_CHECKOK(ecgroup->meth->field_neg(&y, &ny, ecgroup->meth)); michael@0: michael@0: ec_GFp_pt_dbl_aff(&x, &y, &x2, &y2, ecgroup); michael@0: michael@0: for (i = 0; i < 8; i++) { michael@0: MP_CHECKOK(testChudPoint(&precomp[8 + i], &x, &y, ecgroup)); michael@0: MP_CHECKOK(testChudPoint(&precomp[7 - i], &x, &ny, ecgroup)); michael@0: ec_GFp_pt_add_aff(&x, &y, &x2, &y2, &x, &y, ecgroup); michael@0: MP_CHECKOK(ecgroup->meth->field_neg(&y, &ny, ecgroup->meth)); michael@0: } michael@0: michael@0: CLEANUP: michael@0: if (res == MP_OKAY) michael@0: printf(" Test Passed - Precomputation\n"); michael@0: else michael@0: printf("TEST FAILED - Precomputation\n"); michael@0: michael@0: mp_clear(&x); michael@0: mp_clear(&y); michael@0: mp_clear(&ny); michael@0: mp_clear(&x2); michael@0: mp_clear(&y2); michael@0: return res; michael@0: } michael@0: michael@0: /* Given a curve using floating point arithmetic, test it. This method michael@0: * specifies which of the above tests to run. */ michael@0: mp_err michael@0: testCurve(ECGroup *ecgroup) michael@0: { michael@0: int res = MP_OKAY; michael@0: michael@0: MP_CHECKOK(testPointAddJacAff(ecgroup)); michael@0: MP_CHECKOK(testPointAddJac(ecgroup)); michael@0: MP_CHECKOK(testPointAddChud(ecgroup)); michael@0: MP_CHECKOK(testPointAddJmChud(ecgroup)); michael@0: MP_CHECKOK(testPointDoubleJac(ecgroup)); michael@0: MP_CHECKOK(testPointDoubleChud(ecgroup)); michael@0: MP_CHECKOK(testPointDoubleJm(ecgroup)); michael@0: MP_CHECKOK(testPreCompute(ecgroup)); michael@0: MP_CHECKOK(testPointMul(ecgroup)); michael@0: MP_CHECKOK(testPointMulRandom(ecgroup)); michael@0: MP_CHECKOK(testPointMulTime(ecgroup)); michael@0: CLEANUP: michael@0: return res; michael@0: } michael@0: michael@0: /* Tests a number of curves optimized using floating point arithmetic */ michael@0: int michael@0: main(void) michael@0: { michael@0: mp_err res = MP_OKAY; michael@0: ECGroup *ecgroup = NULL; michael@0: michael@0: /* specific arithmetic tests */ michael@0: M_TestCurve("SECG-160R1", ECCurve_SECG_PRIME_160R1); michael@0: M_TestCurve("SECG-192R1", ECCurve_SECG_PRIME_192R1); michael@0: M_TestCurve("SEGC-224R1", ECCurve_SECG_PRIME_224R1); michael@0: michael@0: CLEANUP: michael@0: ECGroup_free(ecgroup); michael@0: if (res != MP_OKAY) { michael@0: printf("Error: exiting with error value %i\n", res); michael@0: } michael@0: return res; michael@0: }