mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-14 03:30:17 +01:00
1124 lines
29 KiB
C
1124 lines
29 KiB
C
|
/*
|
||
|
* ***** BEGIN LICENSE BLOCK *****
|
||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||
|
*
|
||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||
|
* the License. You may obtain a copy of the License at
|
||
|
* http://www.mozilla.org/MPL/
|
||
|
*
|
||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||
|
* for the specific language governing rights and limitations under the
|
||
|
* License.
|
||
|
*
|
||
|
* The Original Code is the elliptic curve math library for prime field curves using floating point operations.
|
||
|
*
|
||
|
* The Initial Developer of the Original Code is
|
||
|
* Sun Microsystems, Inc.
|
||
|
* Portions created by the Initial Developer are Copyright (C) 2003
|
||
|
* the Initial Developer. All Rights Reserved.
|
||
|
*
|
||
|
* Contributor(s):
|
||
|
* Stephen Fung <fungstep@hotmail.com> and
|
||
|
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||
|
*
|
||
|
* Alternatively, the contents of this file may be used under the terms of
|
||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||
|
* of those above. If you wish to allow use of your version of this file only
|
||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||
|
* use your version of this file under the terms of the MPL, indicate your
|
||
|
* decision by deleting the provisions above and replace them with the notice
|
||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||
|
* the provisions above, a recipient may use your version of this file under
|
||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||
|
*
|
||
|
* ***** END LICENSE BLOCK ***** */
|
||
|
|
||
|
#include "ecp_fp.h"
|
||
|
#include "mpprime.h"
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <time.h>
|
||
|
#include <sys/time.h>
|
||
|
#include <sys/resource.h>
|
||
|
|
||
|
/* Time k repetitions of operation op. */
|
||
|
#define M_TimeOperation(op, k) { \
|
||
|
double dStart, dNow, dUserTime; \
|
||
|
struct rusage ru; \
|
||
|
int i; \
|
||
|
getrusage(RUSAGE_SELF, &ru); \
|
||
|
dStart = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \
|
||
|
for (i = 0; i < k; i++) { \
|
||
|
{ op; } \
|
||
|
}; \
|
||
|
getrusage(RUSAGE_SELF, &ru); \
|
||
|
dNow = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \
|
||
|
dUserTime = dNow-dStart; \
|
||
|
if (dUserTime) printf(" %-45s\n k: %6i, t: %6.2f sec, k/t: %6.2f ops/sec\n", #op, k, dUserTime, k/dUserTime); \
|
||
|
}
|
||
|
|
||
|
/* Test curve using specific floating point field arithmetic. */
|
||
|
#define M_TestCurve(name_c, name) { \
|
||
|
printf("Testing %s using specific floating point implementation...\n", name_c); \
|
||
|
ECGroup_free(ecgroup); \
|
||
|
ecgroup = ECGroup_fromName(name); \
|
||
|
if (ecgroup == NULL) { \
|
||
|
printf(" Warning: could not construct group.\n"); \
|
||
|
printf("%s failed.\n", name_c); \
|
||
|
res = MP_NO; \
|
||
|
goto CLEANUP; \
|
||
|
} else { \
|
||
|
MP_CHECKOK( testCurve(ecgroup)); \
|
||
|
printf("%s passed.\n", name_c); \
|
||
|
} \
|
||
|
}
|
||
|
|
||
|
/* Outputs a floating point double (currently not used) */
|
||
|
void
|
||
|
d_output(const double *u, int len, char *name, const EC_group_fp * group)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
printf("%s: ", name);
|
||
|
for (i = 0; i < len; i++) {
|
||
|
printf("+ %.2f * 2^%i ", u[i] / ecfp_exp[i],
|
||
|
group->doubleBitSize * i);
|
||
|
}
|
||
|
printf("\n");
|
||
|
}
|
||
|
|
||
|
/* Tests a point p in Jacobian coordinates, comparing against the
|
||
|
* expected affine result (x, y). */
|
||
|
mp_err
|
||
|
testJacPoint(ecfp_jac_pt * p, mp_int *x, mp_int *y, ECGroup *ecgroup)
|
||
|
{
|
||
|
char s[1000];
|
||
|
mp_int rx, ry, rz;
|
||
|
mp_err res = MP_OKAY;
|
||
|
|
||
|
MP_DIGITS(&rx) = 0;
|
||
|
MP_DIGITS(&ry) = 0;
|
||
|
MP_DIGITS(&rz) = 0;
|
||
|
|
||
|
MP_CHECKOK(mp_init(&rx));
|
||
|
MP_CHECKOK(mp_init(&ry));
|
||
|
MP_CHECKOK(mp_init(&rz));
|
||
|
|
||
|
ecfp_fp2i(&rx, p->x, ecgroup);
|
||
|
ecfp_fp2i(&ry, p->y, ecgroup);
|
||
|
ecfp_fp2i(&rz, p->z, ecgroup);
|
||
|
|
||
|
/* convert result R to affine coordinates */
|
||
|
ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup);
|
||
|
|
||
|
/* Compare to expected result */
|
||
|
if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) {
|
||
|
printf(" Error: Jacobian Floating Point Incorrect.\n");
|
||
|
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||
|
printf("floating point result\nrx %s\n", s);
|
||
|
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||
|
printf("ry %s\n", s);
|
||
|
MP_CHECKOK(mp_toradix(x, s, 16));
|
||
|
printf("integer result\nx %s\n", s);
|
||
|
MP_CHECKOK(mp_toradix(y, s, 16));
|
||
|
printf("y %s\n", s);
|
||
|
res = MP_NO;
|
||
|
goto CLEANUP;
|
||
|
}
|
||
|
|
||
|
CLEANUP:
|
||
|
mp_clear(&rx);
|
||
|
mp_clear(&ry);
|
||
|
mp_clear(&rz);
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
/* Tests a point p in Chudnovsky Jacobian coordinates, comparing against
|
||
|
* the expected affine result (x, y). */
|
||
|
mp_err
|
||
|
testChudPoint(ecfp_chud_pt * p, mp_int *x, mp_int *y, ECGroup *ecgroup)
|
||
|
{
|
||
|
|
||
|
char s[1000];
|
||
|
mp_int rx, ry, rz, rz2, rz3, test;
|
||
|
mp_err res = MP_OKAY;
|
||
|
|
||
|
/* Initialization */
|
||
|
MP_DIGITS(&rx) = 0;
|
||
|
MP_DIGITS(&ry) = 0;
|
||
|
MP_DIGITS(&rz) = 0;
|
||
|
MP_DIGITS(&rz2) = 0;
|
||
|
MP_DIGITS(&rz3) = 0;
|
||
|
MP_DIGITS(&test) = 0;
|
||
|
|
||
|
MP_CHECKOK(mp_init(&rx));
|
||
|
MP_CHECKOK(mp_init(&ry));
|
||
|
MP_CHECKOK(mp_init(&rz));
|
||
|
MP_CHECKOK(mp_init(&rz2));
|
||
|
MP_CHECKOK(mp_init(&rz3));
|
||
|
MP_CHECKOK(mp_init(&test));
|
||
|
|
||
|
/* Convert to integers */
|
||
|
ecfp_fp2i(&rx, p->x, ecgroup);
|
||
|
ecfp_fp2i(&ry, p->y, ecgroup);
|
||
|
ecfp_fp2i(&rz, p->z, ecgroup);
|
||
|
ecfp_fp2i(&rz2, p->z2, ecgroup);
|
||
|
ecfp_fp2i(&rz3, p->z3, ecgroup);
|
||
|
|
||
|
/* Verify z2, z3 are valid */
|
||
|
mp_sqrmod(&rz, &ecgroup->meth->irr, &test);
|
||
|
if (mp_cmp(&test, &rz2) != 0) {
|
||
|
printf(" Error: rzp2 not valid\n");
|
||
|
res = MP_NO;
|
||
|
goto CLEANUP;
|
||
|
}
|
||
|
mp_mulmod(&test, &rz, &ecgroup->meth->irr, &test);
|
||
|
if (mp_cmp(&test, &rz3) != 0) {
|
||
|
printf(" Error: rzp2 not valid\n");
|
||
|
res = MP_NO;
|
||
|
goto CLEANUP;
|
||
|
}
|
||
|
|
||
|
/* convert result R to affine coordinates */
|
||
|
ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup);
|
||
|
|
||
|
/* Compare against expected result */
|
||
|
if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) {
|
||
|
printf(" Error: Chudnovsky Floating Point Incorrect.\n");
|
||
|
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||
|
printf("floating point result\nrx %s\n", s);
|
||
|
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||
|
printf("ry %s\n", s);
|
||
|
MP_CHECKOK(mp_toradix(x, s, 16));
|
||
|
printf("integer result\nx %s\n", s);
|
||
|
MP_CHECKOK(mp_toradix(y, s, 16));
|
||
|
printf("y %s\n", s);
|
||
|
res = MP_NO;
|
||
|
goto CLEANUP;
|
||
|
}
|
||
|
|
||
|
CLEANUP:
|
||
|
mp_clear(&rx);
|
||
|
mp_clear(&ry);
|
||
|
mp_clear(&rz);
|
||
|
mp_clear(&rz2);
|
||
|
mp_clear(&rz3);
|
||
|
mp_clear(&test);
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
/* Tests a point p in Modified Jacobian coordinates, comparing against the
|
||
|
* expected affine result (x, y). */
|
||
|
mp_err
|
||
|
testJmPoint(ecfp_jm_pt * r, mp_int *x, mp_int *y, ECGroup *ecgroup)
|
||
|
{
|
||
|
|
||
|
char s[1000];
|
||
|
mp_int rx, ry, rz, raz4, test;
|
||
|
mp_err res = MP_OKAY;
|
||
|
|
||
|
/* Initialization */
|
||
|
MP_DIGITS(&rx) = 0;
|
||
|
MP_DIGITS(&ry) = 0;
|
||
|
MP_DIGITS(&rz) = 0;
|
||
|
MP_DIGITS(&raz4) = 0;
|
||
|
MP_DIGITS(&test) = 0;
|
||
|
|
||
|
MP_CHECKOK(mp_init(&rx));
|
||
|
MP_CHECKOK(mp_init(&ry));
|
||
|
MP_CHECKOK(mp_init(&rz));
|
||
|
MP_CHECKOK(mp_init(&raz4));
|
||
|
MP_CHECKOK(mp_init(&test));
|
||
|
|
||
|
/* Convert to integer */
|
||
|
ecfp_fp2i(&rx, r->x, ecgroup);
|
||
|
ecfp_fp2i(&ry, r->y, ecgroup);
|
||
|
ecfp_fp2i(&rz, r->z, ecgroup);
|
||
|
ecfp_fp2i(&raz4, r->az4, ecgroup);
|
||
|
|
||
|
/* Verify raz4 = rz^4 * a */
|
||
|
mp_sqrmod(&rz, &ecgroup->meth->irr, &test);
|
||
|
mp_sqrmod(&test, &ecgroup->meth->irr, &test);
|
||
|
mp_mulmod(&test, &ecgroup->curvea, &ecgroup->meth->irr, &test);
|
||
|
if (mp_cmp(&test, &raz4) != 0) {
|
||
|
printf(" Error: a*z^4 not valid\n");
|
||
|
MP_CHECKOK(mp_toradix(&ecgroup->curvea, s, 16));
|
||
|
printf("a %s\n", s);
|
||
|
MP_CHECKOK(mp_toradix(&rz, s, 16));
|
||
|
printf("rz %s\n", s);
|
||
|
MP_CHECKOK(mp_toradix(&raz4, s, 16));
|
||
|
printf("raz4 %s\n", s);
|
||
|
res = MP_NO;
|
||
|
goto CLEANUP;
|
||
|
}
|
||
|
|
||
|
/* convert result R to affine coordinates */
|
||
|
ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup);
|
||
|
|
||
|
/* Compare against expected result */
|
||
|
if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) {
|
||
|
printf(" Error: Modified Jacobian Floating Point Incorrect.\n");
|
||
|
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||
|
printf("floating point result\nrx %s\n", s);
|
||
|
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||
|
printf("ry %s\n", s);
|
||
|
MP_CHECKOK(mp_toradix(x, s, 16));
|
||
|
printf("integer result\nx %s\n", s);
|
||
|
MP_CHECKOK(mp_toradix(y, s, 16));
|
||
|
printf("y %s\n", s);
|
||
|
res = MP_NO;
|
||
|
goto CLEANUP;
|
||
|
}
|
||
|
CLEANUP:
|
||
|
mp_clear(&rx);
|
||
|
mp_clear(&ry);
|
||
|
mp_clear(&rz);
|
||
|
mp_clear(&raz4);
|
||
|
mp_clear(&test);
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
/* Tests point addition of Jacobian + Affine -> Jacobian */
|
||
|
mp_err
|
||
|
testPointAddJacAff(ECGroup *ecgroup)
|
||
|
{
|
||
|
mp_err res;
|
||
|
mp_int pz, rx2, ry2, rz2;
|
||
|
ecfp_jac_pt p, r;
|
||
|
ecfp_aff_pt q;
|
||
|
EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
|
||
|
|
||
|
/* Init */
|
||
|
MP_DIGITS(&pz) = 0;
|
||
|
MP_DIGITS(&rx2) = 0;
|
||
|
MP_DIGITS(&ry2) = 0;
|
||
|
MP_DIGITS(&rz2) = 0;
|
||
|
MP_CHECKOK(mp_init(&pz));
|
||
|
MP_CHECKOK(mp_init(&rx2));
|
||
|
MP_CHECKOK(mp_init(&ry2));
|
||
|
MP_CHECKOK(mp_init(&rz2));
|
||
|
|
||
|
MP_CHECKOK(mp_set_int(&pz, 5));
|
||
|
|
||
|
/* Set p */
|
||
|
ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
|
||
|
ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
|
||
|
ecfp_i2fp(p.z, &pz, ecgroup);
|
||
|
/* Set q */
|
||
|
ecfp_i2fp(q.x, &ecgroup->geny, ecgroup);
|
||
|
ecfp_i2fp(q.y, &ecgroup->genx, ecgroup);
|
||
|
|
||
|
/* Do calculations */
|
||
|
group->pt_add_jac_aff(&p, &q, &r, group);
|
||
|
|
||
|
/* Do calculation in integer to compare against */
|
||
|
MP_CHECKOK(ec_GFp_pt_add_jac_aff
|
||
|
(&ecgroup->genx, &ecgroup->geny, &pz, &ecgroup->geny,
|
||
|
&ecgroup->genx, &rx2, &ry2, &rz2, ecgroup));
|
||
|
/* convert result R to affine coordinates */
|
||
|
ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup);
|
||
|
|
||
|
MP_CHECKOK(testJacPoint(&r, &rx2, &ry2, ecgroup));
|
||
|
|
||
|
CLEANUP:
|
||
|
if (res == MP_OKAY)
|
||
|
printf(" Test Passed - Point Addition - Jacobian & Affine\n");
|
||
|
else
|
||
|
printf("TEST FAILED - Point Addition - Jacobian & Affine\n");
|
||
|
|
||
|
mp_clear(&pz);
|
||
|
mp_clear(&rx2);
|
||
|
mp_clear(&ry2);
|
||
|
mp_clear(&rz2);
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
/* Tests point addition in Jacobian coordinates */
|
||
|
mp_err
|
||
|
testPointAddJac(ECGroup *ecgroup)
|
||
|
{
|
||
|
mp_err res;
|
||
|
mp_int pz, qz, qx, qy, rx2, ry2, rz2;
|
||
|
ecfp_jac_pt p, q, r;
|
||
|
EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
|
||
|
|
||
|
/* Init */
|
||
|
MP_DIGITS(&pz) = 0;
|
||
|
MP_DIGITS(&qx) = 0;
|
||
|
MP_DIGITS(&qy) = 0;
|
||
|
MP_DIGITS(&qz) = 0;
|
||
|
MP_DIGITS(&rx2) = 0;
|
||
|
MP_DIGITS(&ry2) = 0;
|
||
|
MP_DIGITS(&rz2) = 0;
|
||
|
MP_CHECKOK(mp_init(&pz));
|
||
|
MP_CHECKOK(mp_init(&qx));
|
||
|
MP_CHECKOK(mp_init(&qy));
|
||
|
MP_CHECKOK(mp_init(&qz));
|
||
|
MP_CHECKOK(mp_init(&rx2));
|
||
|
MP_CHECKOK(mp_init(&ry2));
|
||
|
MP_CHECKOK(mp_init(&rz2));
|
||
|
|
||
|
MP_CHECKOK(mp_set_int(&pz, 5));
|
||
|
MP_CHECKOK(mp_set_int(&qz, 105));
|
||
|
|
||
|
/* Set p */
|
||
|
ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
|
||
|
ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
|
||
|
ecfp_i2fp(p.z, &pz, ecgroup);
|
||
|
/* Set q */
|
||
|
ecfp_i2fp(q.x, &ecgroup->geny, ecgroup);
|
||
|
ecfp_i2fp(q.y, &ecgroup->genx, ecgroup);
|
||
|
ecfp_i2fp(q.z, &qz, ecgroup);
|
||
|
|
||
|
/* Do calculations */
|
||
|
group->pt_add_jac(&p, &q, &r, group);
|
||
|
|
||
|
/* Do calculation in integer to compare against */
|
||
|
ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy,
|
||
|
ecgroup);
|
||
|
MP_CHECKOK(ec_GFp_pt_add_jac_aff
|
||
|
(&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy, &rx2, &ry2,
|
||
|
&rz2, ecgroup));
|
||
|
/* convert result R to affine coordinates */
|
||
|
ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup);
|
||
|
|
||
|
MP_CHECKOK(testJacPoint(&r, &rx2, &ry2, ecgroup));
|
||
|
|
||
|
CLEANUP:
|
||
|
if (res == MP_OKAY)
|
||
|
printf(" Test Passed - Point Addition - Jacobian\n");
|
||
|
else
|
||
|
printf("TEST FAILED - Point Addition - Jacobian\n");
|
||
|
|
||
|
mp_clear(&pz);
|
||
|
mp_clear(&qx);
|
||
|
mp_clear(&qy);
|
||
|
mp_clear(&qz);
|
||
|
mp_clear(&rx2);
|
||
|
mp_clear(&ry2);
|
||
|
mp_clear(&rz2);
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
/* Tests point addition in Chudnovsky Jacobian Coordinates */
|
||
|
mp_err
|
||
|
testPointAddChud(ECGroup *ecgroup)
|
||
|
{
|
||
|
mp_err res;
|
||
|
mp_int rx2, ry2, ix, iy, iz, test, pz, qx, qy, qz;
|
||
|
ecfp_chud_pt p, q, r;
|
||
|
EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
|
||
|
|
||
|
MP_DIGITS(&qx) = 0;
|
||
|
MP_DIGITS(&qy) = 0;
|
||
|
MP_DIGITS(&qz) = 0;
|
||
|
MP_DIGITS(&pz) = 0;
|
||
|
MP_DIGITS(&rx2) = 0;
|
||
|
MP_DIGITS(&ry2) = 0;
|
||
|
MP_DIGITS(&ix) = 0;
|
||
|
MP_DIGITS(&iy) = 0;
|
||
|
MP_DIGITS(&iz) = 0;
|
||
|
MP_DIGITS(&test) = 0;
|
||
|
|
||
|
MP_CHECKOK(mp_init(&qx));
|
||
|
MP_CHECKOK(mp_init(&qy));
|
||
|
MP_CHECKOK(mp_init(&qz));
|
||
|
MP_CHECKOK(mp_init(&pz));
|
||
|
MP_CHECKOK(mp_init(&rx2));
|
||
|
MP_CHECKOK(mp_init(&ry2));
|
||
|
MP_CHECKOK(mp_init(&ix));
|
||
|
MP_CHECKOK(mp_init(&iy));
|
||
|
MP_CHECKOK(mp_init(&iz));
|
||
|
MP_CHECKOK(mp_init(&test));
|
||
|
|
||
|
/* Test Chudnovsky form addition */
|
||
|
/* Set p */
|
||
|
MP_CHECKOK(mp_set_int(&pz, 5));
|
||
|
ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
|
||
|
ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
|
||
|
ecfp_i2fp(p.z, &pz, ecgroup);
|
||
|
mp_sqrmod(&pz, &ecgroup->meth->irr, &test);
|
||
|
ecfp_i2fp(p.z2, &test, ecgroup);
|
||
|
mp_mulmod(&test, &pz, &ecgroup->meth->irr, &test);
|
||
|
ecfp_i2fp(p.z3, &test, ecgroup);
|
||
|
|
||
|
/* Set q */
|
||
|
MP_CHECKOK(mp_set_int(&qz, 105));
|
||
|
ecfp_i2fp(q.x, &ecgroup->geny, ecgroup);
|
||
|
ecfp_i2fp(q.y, &ecgroup->genx, ecgroup);
|
||
|
ecfp_i2fp(q.z, &qz, ecgroup);
|
||
|
mp_sqrmod(&qz, &ecgroup->meth->irr, &test);
|
||
|
ecfp_i2fp(q.z2, &test, ecgroup);
|
||
|
mp_mulmod(&test, &qz, &ecgroup->meth->irr, &test);
|
||
|
ecfp_i2fp(q.z3, &test, ecgroup);
|
||
|
|
||
|
group->pt_add_chud(&p, &q, &r, group);
|
||
|
|
||
|
/* Calculate addition to compare against */
|
||
|
ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy,
|
||
|
ecgroup);
|
||
|
ec_GFp_pt_add_jac_aff(&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy,
|
||
|
&ix, &iy, &iz, ecgroup);
|
||
|
ec_GFp_pt_jac2aff(&ix, &iy, &iz, &rx2, &ry2, ecgroup);
|
||
|
|
||
|
MP_CHECKOK(testChudPoint(&r, &rx2, &ry2, ecgroup));
|
||
|
|
||
|
CLEANUP:
|
||
|
if (res == MP_OKAY)
|
||
|
printf(" Test Passed - Point Addition - Chudnovsky Jacobian\n");
|
||
|
else
|
||
|
printf("TEST FAILED - Point Addition - Chudnovsky Jacobian\n");
|
||
|
|
||
|
mp_clear(&qx);
|
||
|
mp_clear(&qy);
|
||
|
mp_clear(&qz);
|
||
|
mp_clear(&pz);
|
||
|
mp_clear(&rx2);
|
||
|
mp_clear(&ry2);
|
||
|
mp_clear(&ix);
|
||
|
mp_clear(&iy);
|
||
|
mp_clear(&iz);
|
||
|
mp_clear(&test);
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
/* Tests point addition in Modified Jacobian + Chudnovsky Jacobian ->
|
||
|
* Modified Jacobian coordinates. */
|
||
|
mp_err
|
||
|
testPointAddJmChud(ECGroup *ecgroup)
|
||
|
{
|
||
|
mp_err res;
|
||
|
mp_int rx2, ry2, ix, iy, iz, test, pz, paz4, qx, qy, qz;
|
||
|
ecfp_chud_pt q;
|
||
|
ecfp_jm_pt p, r;
|
||
|
EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
|
||
|
|
||
|
MP_DIGITS(&qx) = 0;
|
||
|
MP_DIGITS(&qy) = 0;
|
||
|
MP_DIGITS(&qz) = 0;
|
||
|
MP_DIGITS(&pz) = 0;
|
||
|
MP_DIGITS(&paz4) = 0;
|
||
|
MP_DIGITS(&iz) = 0;
|
||
|
MP_DIGITS(&rx2) = 0;
|
||
|
MP_DIGITS(&ry2) = 0;
|
||
|
MP_DIGITS(&ix) = 0;
|
||
|
MP_DIGITS(&iy) = 0;
|
||
|
MP_DIGITS(&iz) = 0;
|
||
|
MP_DIGITS(&test) = 0;
|
||
|
|
||
|
MP_CHECKOK(mp_init(&qx));
|
||
|
MP_CHECKOK(mp_init(&qy));
|
||
|
MP_CHECKOK(mp_init(&qz));
|
||
|
MP_CHECKOK(mp_init(&pz));
|
||
|
MP_CHECKOK(mp_init(&paz4));
|
||
|
MP_CHECKOK(mp_init(&rx2));
|
||
|
MP_CHECKOK(mp_init(&ry2));
|
||
|
MP_CHECKOK(mp_init(&ix));
|
||
|
MP_CHECKOK(mp_init(&iy));
|
||
|
MP_CHECKOK(mp_init(&iz));
|
||
|
MP_CHECKOK(mp_init(&test));
|
||
|
|
||
|
/* Test Modified Jacobian form addition */
|
||
|
/* Set p */
|
||
|
ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
|
||
|
ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
|
||
|
ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);
|
||
|
/* paz4 = az^4 */
|
||
|
MP_CHECKOK(mp_set_int(&pz, 5));
|
||
|
mp_sqrmod(&pz, &ecgroup->meth->irr, &paz4);
|
||
|
mp_sqrmod(&paz4, &ecgroup->meth->irr, &paz4);
|
||
|
mp_mulmod(&paz4, &ecgroup->curvea, &ecgroup->meth->irr, &paz4);
|
||
|
ecfp_i2fp(p.z, &pz, ecgroup);
|
||
|
ecfp_i2fp(p.az4, &paz4, ecgroup);
|
||
|
|
||
|
/* Set q */
|
||
|
MP_CHECKOK(mp_set_int(&qz, 105));
|
||
|
ecfp_i2fp(q.x, &ecgroup->geny, ecgroup);
|
||
|
ecfp_i2fp(q.y, &ecgroup->genx, ecgroup);
|
||
|
ecfp_i2fp(q.z, &qz, ecgroup);
|
||
|
mp_sqrmod(&qz, &ecgroup->meth->irr, &test);
|
||
|
ecfp_i2fp(q.z2, &test, ecgroup);
|
||
|
mp_mulmod(&test, &qz, &ecgroup->meth->irr, &test);
|
||
|
ecfp_i2fp(q.z3, &test, ecgroup);
|
||
|
|
||
|
/* Do calculation */
|
||
|
group->pt_add_jm_chud(&p, &q, &r, group);
|
||
|
|
||
|
/* Calculate addition to compare against */
|
||
|
ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy,
|
||
|
ecgroup);
|
||
|
ec_GFp_pt_add_jac_aff(&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy,
|
||
|
&ix, &iy, &iz, ecgroup);
|
||
|
ec_GFp_pt_jac2aff(&ix, &iy, &iz, &rx2, &ry2, ecgroup);
|
||
|
|
||
|
MP_CHECKOK(testJmPoint(&r, &rx2, &ry2, ecgroup));
|
||
|
|
||
|
CLEANUP:
|
||
|
if (res == MP_OKAY)
|
||
|
printf
|
||
|
(" Test Passed - Point Addition - Modified & Chudnovsky Jacobian\n");
|
||
|
else
|
||
|
printf
|
||
|
("TEST FAILED - Point Addition - Modified & Chudnovsky Jacobian\n");
|
||
|
|
||
|
mp_clear(&qx);
|
||
|
mp_clear(&qy);
|
||
|
mp_clear(&qz);
|
||
|
mp_clear(&pz);
|
||
|
mp_clear(&paz4);
|
||
|
mp_clear(&rx2);
|
||
|
mp_clear(&ry2);
|
||
|
mp_clear(&ix);
|
||
|
mp_clear(&iy);
|
||
|
mp_clear(&iz);
|
||
|
mp_clear(&test);
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
/* Tests point doubling in Modified Jacobian coordinates */
|
||
|
mp_err
|
||
|
testPointDoubleJm(ECGroup *ecgroup)
|
||
|
{
|
||
|
mp_err res;
|
||
|
mp_int pz, paz4, rx2, ry2, rz2, raz4;
|
||
|
ecfp_jm_pt p, r;
|
||
|
EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
|
||
|
|
||
|
MP_DIGITS(&pz) = 0;
|
||
|
MP_DIGITS(&paz4) = 0;
|
||
|
MP_DIGITS(&rx2) = 0;
|
||
|
MP_DIGITS(&ry2) = 0;
|
||
|
MP_DIGITS(&rz2) = 0;
|
||
|
MP_DIGITS(&raz4) = 0;
|
||
|
|
||
|
MP_CHECKOK(mp_init(&pz));
|
||
|
MP_CHECKOK(mp_init(&paz4));
|
||
|
MP_CHECKOK(mp_init(&rx2));
|
||
|
MP_CHECKOK(mp_init(&ry2));
|
||
|
MP_CHECKOK(mp_init(&rz2));
|
||
|
MP_CHECKOK(mp_init(&raz4));
|
||
|
|
||
|
/* Set p */
|
||
|
ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
|
||
|
ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
|
||
|
ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);
|
||
|
|
||
|
/* paz4 = az^4 */
|
||
|
MP_CHECKOK(mp_set_int(&pz, 5));
|
||
|
mp_sqrmod(&pz, &ecgroup->meth->irr, &paz4);
|
||
|
mp_sqrmod(&paz4, &ecgroup->meth->irr, &paz4);
|
||
|
mp_mulmod(&paz4, &ecgroup->curvea, &ecgroup->meth->irr, &paz4);
|
||
|
|
||
|
ecfp_i2fp(p.z, &pz, ecgroup);
|
||
|
ecfp_i2fp(p.az4, &paz4, ecgroup);
|
||
|
|
||
|
group->pt_dbl_jm(&p, &r, group);
|
||
|
|
||
|
M_TimeOperation(group->pt_dbl_jm(&p, &r, group), 100000);
|
||
|
|
||
|
/* Calculate doubling to compare against */
|
||
|
ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2,
|
||
|
&rz2, ecgroup);
|
||
|
ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup);
|
||
|
|
||
|
/* Do comparison and check az^4 */
|
||
|
MP_CHECKOK(testJmPoint(&r, &rx2, &ry2, ecgroup));
|
||
|
|
||
|
CLEANUP:
|
||
|
if (res == MP_OKAY)
|
||
|
printf(" Test Passed - Point Doubling - Modified Jacobian\n");
|
||
|
else
|
||
|
printf("TEST FAILED - Point Doubling - Modified Jacobian\n");
|
||
|
mp_clear(&pz);
|
||
|
mp_clear(&paz4);
|
||
|
mp_clear(&rx2);
|
||
|
mp_clear(&ry2);
|
||
|
mp_clear(&rz2);
|
||
|
mp_clear(&raz4);
|
||
|
|
||
|
return res;
|
||
|
|
||
|
}
|
||
|
|
||
|
/* Tests point doubling in Chudnovsky Jacobian coordinates */
|
||
|
mp_err
|
||
|
testPointDoubleChud(ECGroup *ecgroup)
|
||
|
{
|
||
|
mp_err res;
|
||
|
mp_int px, py, pz, rx2, ry2, rz2;
|
||
|
ecfp_aff_pt p;
|
||
|
ecfp_chud_pt p2;
|
||
|
EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
|
||
|
|
||
|
MP_DIGITS(&rx2) = 0;
|
||
|
MP_DIGITS(&ry2) = 0;
|
||
|
MP_DIGITS(&rz2) = 0;
|
||
|
MP_DIGITS(&px) = 0;
|
||
|
MP_DIGITS(&py) = 0;
|
||
|
MP_DIGITS(&pz) = 0;
|
||
|
|
||
|
MP_CHECKOK(mp_init(&rx2));
|
||
|
MP_CHECKOK(mp_init(&ry2));
|
||
|
MP_CHECKOK(mp_init(&rz2));
|
||
|
MP_CHECKOK(mp_init(&px));
|
||
|
MP_CHECKOK(mp_init(&py));
|
||
|
MP_CHECKOK(mp_init(&pz));
|
||
|
|
||
|
/* Set p2 = 2P */
|
||
|
ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
|
||
|
ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
|
||
|
ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);
|
||
|
|
||
|
group->pt_dbl_aff2chud(&p, &p2, group);
|
||
|
|
||
|
/* Calculate doubling to compare against */
|
||
|
MP_CHECKOK(mp_set_int(&pz, 1));
|
||
|
ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2,
|
||
|
&rz2, ecgroup);
|
||
|
ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup);
|
||
|
|
||
|
/* Do comparison and check az^4 */
|
||
|
MP_CHECKOK(testChudPoint(&p2, &rx2, &ry2, ecgroup));
|
||
|
|
||
|
CLEANUP:
|
||
|
if (res == MP_OKAY)
|
||
|
printf(" Test Passed - Point Doubling - Chudnovsky Jacobian\n");
|
||
|
else
|
||
|
printf("TEST FAILED - Point Doubling - Chudnovsky Jacobian\n");
|
||
|
|
||
|
mp_clear(&rx2);
|
||
|
mp_clear(&ry2);
|
||
|
mp_clear(&rz2);
|
||
|
mp_clear(&px);
|
||
|
mp_clear(&py);
|
||
|
mp_clear(&pz);
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
/* Test point doubling in Jacobian coordinates */
|
||
|
mp_err
|
||
|
testPointDoubleJac(ECGroup *ecgroup)
|
||
|
{
|
||
|
mp_err res;
|
||
|
mp_int pz, rx, ry, rz, rx2, ry2, rz2;
|
||
|
ecfp_jac_pt p, p2;
|
||
|
EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
|
||
|
|
||
|
MP_DIGITS(&pz) = 0;
|
||
|
MP_DIGITS(&rx) = 0;
|
||
|
MP_DIGITS(&ry) = 0;
|
||
|
MP_DIGITS(&rz) = 0;
|
||
|
MP_DIGITS(&rx2) = 0;
|
||
|
MP_DIGITS(&ry2) = 0;
|
||
|
MP_DIGITS(&rz2) = 0;
|
||
|
|
||
|
MP_CHECKOK(mp_init(&pz));
|
||
|
MP_CHECKOK(mp_init(&rx));
|
||
|
MP_CHECKOK(mp_init(&ry));
|
||
|
MP_CHECKOK(mp_init(&rz));
|
||
|
MP_CHECKOK(mp_init(&rx2));
|
||
|
MP_CHECKOK(mp_init(&ry2));
|
||
|
MP_CHECKOK(mp_init(&rz2));
|
||
|
|
||
|
MP_CHECKOK(mp_set_int(&pz, 5));
|
||
|
|
||
|
/* Set p2 = 2P */
|
||
|
ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
|
||
|
ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
|
||
|
ecfp_i2fp(p.z, &pz, ecgroup);
|
||
|
ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);
|
||
|
|
||
|
group->pt_dbl_jac(&p, &p2, group);
|
||
|
M_TimeOperation(group->pt_dbl_jac(&p, &p2, group), 100000);
|
||
|
|
||
|
/* Calculate doubling to compare against */
|
||
|
ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2,
|
||
|
&rz2, ecgroup);
|
||
|
ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup);
|
||
|
|
||
|
/* Do comparison */
|
||
|
MP_CHECKOK(testJacPoint(&p2, &rx2, &ry2, ecgroup));
|
||
|
|
||
|
CLEANUP:
|
||
|
if (res == MP_OKAY)
|
||
|
printf(" Test Passed - Point Doubling - Jacobian\n");
|
||
|
else
|
||
|
printf("TEST FAILED - Point Doubling - Jacobian\n");
|
||
|
|
||
|
mp_clear(&pz);
|
||
|
mp_clear(&rx);
|
||
|
mp_clear(&ry);
|
||
|
mp_clear(&rz);
|
||
|
mp_clear(&rx2);
|
||
|
mp_clear(&ry2);
|
||
|
mp_clear(&rz2);
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
/* Tests a point multiplication (various algorithms) */
|
||
|
mp_err
|
||
|
testPointMul(ECGroup *ecgroup)
|
||
|
{
|
||
|
mp_err res;
|
||
|
char s[1000];
|
||
|
mp_int rx, ry, order_1;
|
||
|
|
||
|
/* Init */
|
||
|
MP_DIGITS(&rx) = 0;
|
||
|
MP_DIGITS(&ry) = 0;
|
||
|
MP_DIGITS(&order_1) = 0;
|
||
|
|
||
|
MP_CHECKOK(mp_init(&rx));
|
||
|
MP_CHECKOK(mp_init(&ry));
|
||
|
MP_CHECKOK(mp_init(&order_1));
|
||
|
|
||
|
MP_CHECKOK(mp_set_int(&order_1, 1));
|
||
|
MP_CHECKOK(mp_sub(&ecgroup->order, &order_1, &order_1));
|
||
|
|
||
|
/* Test Algorithm 1: Jacobian-Affine Double & Add */
|
||
|
ec_GFp_pt_mul_jac_fp(&order_1, &ecgroup->genx, &ecgroup->geny, &rx,
|
||
|
&ry, ecgroup);
|
||
|
MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth));
|
||
|
if ((mp_cmp(&rx, &ecgroup->genx) != 0)
|
||
|
|| (mp_cmp(&ry, &ecgroup->geny) != 0)) {
|
||
|
printf
|
||
|
(" Error: ec_GFp_pt_mul_jac_fp invalid result (expected (- base point)).\n");
|
||
|
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||
|
printf("rx %s\n", s);
|
||
|
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||
|
printf("ry %s\n", s);
|
||
|
res = MP_NO;
|
||
|
goto CLEANUP;
|
||
|
}
|
||
|
|
||
|
ec_GFp_pt_mul_jac_fp(&ecgroup->order, &ecgroup->genx, &ecgroup->geny,
|
||
|
&rx, &ry, ecgroup);
|
||
|
if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
|
||
|
printf
|
||
|
(" Error: ec_GFp_pt_mul_jac_fp invalid result (expected point at infinity.\n");
|
||
|
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||
|
printf("rx %s\n", s);
|
||
|
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||
|
printf("ry %s\n", s);
|
||
|
res = MP_NO;
|
||
|
goto CLEANUP;
|
||
|
}
|
||
|
|
||
|
/* Test Algorithm 2: 4-bit Window in Jacobian */
|
||
|
ec_GFp_point_mul_jac_4w_fp(&order_1, &ecgroup->genx, &ecgroup->geny,
|
||
|
&rx, &ry, ecgroup);
|
||
|
MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth));
|
||
|
if ((mp_cmp(&rx, &ecgroup->genx) != 0)
|
||
|
|| (mp_cmp(&ry, &ecgroup->geny) != 0)) {
|
||
|
printf
|
||
|
(" Error: ec_GFp_point_mul_jac_4w_fp invalid result (expected (- base point)).\n");
|
||
|
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||
|
printf("rx %s\n", s);
|
||
|
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||
|
printf("ry %s\n", s);
|
||
|
res = MP_NO;
|
||
|
goto CLEANUP;
|
||
|
}
|
||
|
|
||
|
ec_GFp_point_mul_jac_4w_fp(&ecgroup->order, &ecgroup->genx,
|
||
|
&ecgroup->geny, &rx, &ry, ecgroup);
|
||
|
if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
|
||
|
printf
|
||
|
(" Error: ec_GFp_point_mul_jac_4w_fp invalid result (expected point at infinity.\n");
|
||
|
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||
|
printf("rx %s\n", s);
|
||
|
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||
|
printf("ry %s\n", s);
|
||
|
res = MP_NO;
|
||
|
goto CLEANUP;
|
||
|
}
|
||
|
|
||
|
/* Test Algorithm 3: wNAF with modified Jacobian coordinates */
|
||
|
ec_GFp_point_mul_wNAF_fp(&order_1, &ecgroup->genx, &ecgroup->geny, &rx,
|
||
|
&ry, ecgroup);
|
||
|
MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth));
|
||
|
if ((mp_cmp(&rx, &ecgroup->genx) != 0)
|
||
|
|| (mp_cmp(&ry, &ecgroup->geny) != 0)) {
|
||
|
printf
|
||
|
(" Error: ec_GFp_pt_mul_wNAF_fp invalid result (expected (- base point)).\n");
|
||
|
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||
|
printf("rx %s\n", s);
|
||
|
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||
|
printf("ry %s\n", s);
|
||
|
res = MP_NO;
|
||
|
goto CLEANUP;
|
||
|
}
|
||
|
|
||
|
ec_GFp_point_mul_wNAF_fp(&ecgroup->order, &ecgroup->genx,
|
||
|
&ecgroup->geny, &rx, &ry, ecgroup);
|
||
|
if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
|
||
|
printf
|
||
|
(" Error: ec_GFp_pt_mul_wNAF_fp invalid result (expected point at infinity.\n");
|
||
|
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||
|
printf("rx %s\n", s);
|
||
|
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||
|
printf("ry %s\n", s);
|
||
|
res = MP_NO;
|
||
|
goto CLEANUP;
|
||
|
}
|
||
|
|
||
|
CLEANUP:
|
||
|
if (res == MP_OKAY)
|
||
|
printf(" Test Passed - Point Multiplication\n");
|
||
|
else
|
||
|
printf("TEST FAILED - Point Multiplication\n");
|
||
|
mp_clear(&rx);
|
||
|
mp_clear(&ry);
|
||
|
mp_clear(&order_1);
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
/* Tests point multiplication with a random scalar repeatedly, comparing
|
||
|
* for consistency within different algorithms. */
|
||
|
mp_err
|
||
|
testPointMulRandom(ECGroup *ecgroup)
|
||
|
{
|
||
|
mp_err res;
|
||
|
mp_int rx, ry, rx2, ry2, n;
|
||
|
int i, size;
|
||
|
EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
|
||
|
|
||
|
MP_DIGITS(&rx) = 0;
|
||
|
MP_DIGITS(&ry) = 0;
|
||
|
MP_DIGITS(&rx2) = 0;
|
||
|
MP_DIGITS(&ry2) = 0;
|
||
|
MP_DIGITS(&n) = 0;
|
||
|
|
||
|
MP_CHECKOK(mp_init(&rx));
|
||
|
MP_CHECKOK(mp_init(&ry));
|
||
|
MP_CHECKOK(mp_init(&rx2));
|
||
|
MP_CHECKOK(mp_init(&ry2));
|
||
|
MP_CHECKOK(mp_init(&n));
|
||
|
|
||
|
for (i = 0; i < 100; i++) {
|
||
|
/* compute random scalar */
|
||
|
size = mpl_significant_bits(&ecgroup->meth->irr);
|
||
|
if (size < MP_OKAY) {
|
||
|
res = MP_NO;
|
||
|
goto CLEANUP;
|
||
|
}
|
||
|
MP_CHECKOK(mpp_random_size(&n, group->orderBitSize));
|
||
|
MP_CHECKOK(mp_mod(&n, &ecgroup->order, &n));
|
||
|
|
||
|
ec_GFp_pt_mul_jac(&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry,
|
||
|
ecgroup);
|
||
|
ec_GFp_pt_mul_jac_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx2,
|
||
|
&ry2, ecgroup);
|
||
|
|
||
|
if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) {
|
||
|
printf
|
||
|
(" Error: different results for Point Multiplication - Double & Add.\n");
|
||
|
res = MP_NO;
|
||
|
goto CLEANUP;
|
||
|
}
|
||
|
|
||
|
ec_GFp_point_mul_wNAF_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx,
|
||
|
&ry, ecgroup);
|
||
|
if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) {
|
||
|
printf
|
||
|
(" Error: different results for Point Multiplication - wNAF.\n");
|
||
|
res = MP_NO;
|
||
|
goto CLEANUP;
|
||
|
}
|
||
|
|
||
|
ec_GFp_point_mul_jac_4w_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx,
|
||
|
&ry, ecgroup);
|
||
|
if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) {
|
||
|
printf
|
||
|
(" Error: different results for Point Multiplication - 4 bit window.\n");
|
||
|
res = MP_NO;
|
||
|
goto CLEANUP;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
CLEANUP:
|
||
|
if (res == MP_OKAY)
|
||
|
printf(" Test Passed - Point Random Multiplication\n");
|
||
|
else
|
||
|
printf("TEST FAILED - Point Random Multiplication\n");
|
||
|
mp_clear(&rx);
|
||
|
mp_clear(&ry);
|
||
|
mp_clear(&rx2);
|
||
|
mp_clear(&ry2);
|
||
|
mp_clear(&n);
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
/* Tests the time required for a point multiplication */
|
||
|
mp_err
|
||
|
testPointMulTime(ECGroup *ecgroup)
|
||
|
{
|
||
|
mp_err res = MP_OKAY;
|
||
|
mp_int rx, ry, n;
|
||
|
int size;
|
||
|
|
||
|
MP_DIGITS(&rx) = 0;
|
||
|
MP_DIGITS(&ry) = 0;
|
||
|
MP_DIGITS(&n) = 0;
|
||
|
|
||
|
MP_CHECKOK(mp_init(&rx));
|
||
|
MP_CHECKOK(mp_init(&ry));
|
||
|
MP_CHECKOK(mp_init(&n));
|
||
|
|
||
|
/* compute random scalar */
|
||
|
size = mpl_significant_bits(&ecgroup->meth->irr);
|
||
|
if (size < MP_OKAY) {
|
||
|
res = MP_NO;
|
||
|
goto CLEANUP;
|
||
|
}
|
||
|
|
||
|
MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS));
|
||
|
MP_CHECKOK(ecgroup->meth->field_mod(&n, &n, ecgroup->meth));
|
||
|
|
||
|
M_TimeOperation(ec_GFp_pt_mul_jac_fp
|
||
|
(&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry,
|
||
|
ecgroup), 1000);
|
||
|
|
||
|
M_TimeOperation(ec_GFp_point_mul_jac_4w_fp
|
||
|
(&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry,
|
||
|
ecgroup), 1000);
|
||
|
|
||
|
M_TimeOperation(ec_GFp_point_mul_wNAF_fp
|
||
|
(&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry,
|
||
|
ecgroup), 1000);
|
||
|
|
||
|
M_TimeOperation(ec_GFp_pt_mul_jac
|
||
|
(&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry,
|
||
|
ecgroup), 100);
|
||
|
|
||
|
CLEANUP:
|
||
|
if (res == MP_OKAY)
|
||
|
printf(" Test Passed - Point Multiplication Timing\n");
|
||
|
else
|
||
|
printf("TEST FAILED - Point Multiplication Timing\n");
|
||
|
mp_clear(&rx);
|
||
|
mp_clear(&ry);
|
||
|
mp_clear(&n);
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
/* Tests pre computation of Chudnovsky Jacobian points used in wNAF form */
|
||
|
mp_err
|
||
|
testPreCompute(ECGroup *ecgroup)
|
||
|
{
|
||
|
ecfp_chud_pt precomp[16];
|
||
|
ecfp_aff_pt p;
|
||
|
EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
|
||
|
int i;
|
||
|
mp_err res;
|
||
|
|
||
|
mp_int x, y, ny, x2, y2;
|
||
|
|
||
|
MP_DIGITS(&x) = 0;
|
||
|
MP_DIGITS(&y) = 0;
|
||
|
MP_DIGITS(&ny) = 0;
|
||
|
MP_DIGITS(&x2) = 0;
|
||
|
MP_DIGITS(&y2) = 0;
|
||
|
|
||
|
MP_CHECKOK(mp_init(&x));
|
||
|
MP_CHECKOK(mp_init(&y));
|
||
|
MP_CHECKOK(mp_init(&ny));
|
||
|
MP_CHECKOK(mp_init(&x2));
|
||
|
MP_CHECKOK(mp_init(&y2));
|
||
|
|
||
|
ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
|
||
|
ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
|
||
|
ecfp_i2fp(group->curvea, &(ecgroup->curvea), ecgroup);
|
||
|
|
||
|
/* Perform precomputation */
|
||
|
group->precompute_chud(precomp, &p, group);
|
||
|
|
||
|
M_TimeOperation(group->precompute_chud(precomp, &p, group), 10000);
|
||
|
|
||
|
/* Calculate addition to compare against */
|
||
|
MP_CHECKOK(mp_copy(&ecgroup->genx, &x));
|
||
|
MP_CHECKOK(mp_copy(&ecgroup->geny, &y));
|
||
|
MP_CHECKOK(ecgroup->meth->field_neg(&y, &ny, ecgroup->meth));
|
||
|
|
||
|
ec_GFp_pt_dbl_aff(&x, &y, &x2, &y2, ecgroup);
|
||
|
|
||
|
for (i = 0; i < 8; i++) {
|
||
|
MP_CHECKOK(testChudPoint(&precomp[8 + i], &x, &y, ecgroup));
|
||
|
MP_CHECKOK(testChudPoint(&precomp[7 - i], &x, &ny, ecgroup));
|
||
|
ec_GFp_pt_add_aff(&x, &y, &x2, &y2, &x, &y, ecgroup);
|
||
|
MP_CHECKOK(ecgroup->meth->field_neg(&y, &ny, ecgroup->meth));
|
||
|
}
|
||
|
|
||
|
CLEANUP:
|
||
|
if (res == MP_OKAY)
|
||
|
printf(" Test Passed - Precomputation\n");
|
||
|
else
|
||
|
printf("TEST FAILED - Precomputation\n");
|
||
|
|
||
|
mp_clear(&x);
|
||
|
mp_clear(&y);
|
||
|
mp_clear(&ny);
|
||
|
mp_clear(&x2);
|
||
|
mp_clear(&y2);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
/* Given a curve using floating point arithmetic, test it. This method
|
||
|
* specifies which of the above tests to run. */
|
||
|
mp_err
|
||
|
testCurve(ECGroup *ecgroup)
|
||
|
{
|
||
|
int res = MP_OKAY;
|
||
|
|
||
|
MP_CHECKOK(testPointAddJacAff(ecgroup));
|
||
|
MP_CHECKOK(testPointAddJac(ecgroup));
|
||
|
MP_CHECKOK(testPointAddChud(ecgroup));
|
||
|
MP_CHECKOK(testPointAddJmChud(ecgroup));
|
||
|
MP_CHECKOK(testPointDoubleJac(ecgroup));
|
||
|
MP_CHECKOK(testPointDoubleChud(ecgroup));
|
||
|
MP_CHECKOK(testPointDoubleJm(ecgroup));
|
||
|
MP_CHECKOK(testPreCompute(ecgroup));
|
||
|
MP_CHECKOK(testPointMul(ecgroup));
|
||
|
MP_CHECKOK(testPointMulRandom(ecgroup));
|
||
|
MP_CHECKOK(testPointMulTime(ecgroup));
|
||
|
CLEANUP:
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
/* Tests a number of curves optimized using floating point arithmetic */
|
||
|
int
|
||
|
main(void)
|
||
|
{
|
||
|
mp_err res = MP_OKAY;
|
||
|
ECGroup *ecgroup = NULL;
|
||
|
|
||
|
/* specific arithmetic tests */
|
||
|
M_TestCurve("SECG-160R1", ECCurve_SECG_PRIME_160R1);
|
||
|
M_TestCurve("SECG-192R1", ECCurve_SECG_PRIME_192R1);
|
||
|
M_TestCurve("SEGC-224R1", ECCurve_SECG_PRIME_224R1);
|
||
|
|
||
|
CLEANUP:
|
||
|
ECGroup_free(ecgroup);
|
||
|
if (res != MP_OKAY) {
|
||
|
printf("Error: exiting with error value %i\n", res);
|
||
|
}
|
||
|
return res;
|
||
|
}
|