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

changeset 0
6474c204b198
     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 +}

mercurial