Back to index

lightning-sunbird  0.9+nobinonly
ecp_fpt.c
Go to the documentation of this file.
00001 /* 
00002  * ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the elliptic curve math library for prime field curves using floating point operations.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Sun Microsystems, Inc.
00019  * Portions created by the Initial Developer are Copyright (C) 2003
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Stephen Fung <fungstep@hotmail.com> and
00024  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "ecp_fp.h"
00041 #include "mpprime.h"
00042 
00043 #include <stdio.h>
00044 #include <time.h>
00045 #include <sys/time.h>
00046 #include <sys/resource.h>
00047 
00048 /* Time k repetitions of operation op. */
00049 #define M_TimeOperation(op, k) { \
00050   double dStart, dNow, dUserTime; \
00051   struct rusage ru; \
00052   int i; \
00053   getrusage(RUSAGE_SELF, &ru); \
00054   dStart = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \
00055   for (i = 0; i < k; i++) { \
00056     { op; } \
00057   }; \
00058   getrusage(RUSAGE_SELF, &ru); \
00059   dNow = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \
00060   dUserTime = dNow-dStart; \
00061   if (dUserTime) printf("    %-45s\n      k: %6i, t: %6.2f sec, k/t: %6.2f ops/sec\n", #op, k, dUserTime, k/dUserTime); \
00062 }
00063 
00064 /* Test curve using specific floating point field arithmetic. */
00065 #define M_TestCurve(name_c, name) { \
00066   printf("Testing %s using specific floating point implementation...\n", name_c); \
00067   ECGroup_free(ecgroup); \
00068   ecgroup = ECGroup_fromName(name); \
00069   if (ecgroup == NULL) { \
00070     printf("  Warning: could not construct group.\n"); \
00071     printf("%s failed.\n", name_c); \
00072     res = MP_NO; \
00073     goto CLEANUP; \
00074   } else { \
00075     MP_CHECKOK( testCurve(ecgroup)); \
00076     printf("%s passed.\n", name_c); \
00077   } \
00078 }
00079 
00080 /* Outputs a floating point double (currently not used) */
00081 void
00082 d_output(const double *u, int len, char *name, const EC_group_fp * group)
00083 {
00084        int i;
00085 
00086        printf("%s:  ", name);
00087        for (i = 0; i < len; i++) {
00088               printf("+ %.2f * 2^%i ", u[i] / ecfp_exp[i],
00089                         group->doubleBitSize * i);
00090        }
00091        printf("\n");
00092 }
00093 
00094 /* Tests a point p in Jacobian coordinates, comparing against the
00095  * expected affine result (x, y). */
00096 mp_err
00097 testJacPoint(ecfp_jac_pt * p, mp_int *x, mp_int *y, ECGroup *ecgroup)
00098 {
00099        char s[1000];
00100        mp_int rx, ry, rz;
00101        mp_err res = MP_OKAY;
00102 
00103        MP_DIGITS(&rx) = 0;
00104        MP_DIGITS(&ry) = 0;
00105        MP_DIGITS(&rz) = 0;
00106 
00107        MP_CHECKOK(mp_init(&rx));
00108        MP_CHECKOK(mp_init(&ry));
00109        MP_CHECKOK(mp_init(&rz));
00110 
00111        ecfp_fp2i(&rx, p->x, ecgroup);
00112        ecfp_fp2i(&ry, p->y, ecgroup);
00113        ecfp_fp2i(&rz, p->z, ecgroup);
00114 
00115        /* convert result R to affine coordinates */
00116        ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup);
00117 
00118        /* Compare to expected result */
00119        if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) {
00120               printf("  Error: Jacobian Floating Point Incorrect.\n");
00121               MP_CHECKOK(mp_toradix(&rx, s, 16));
00122               printf("floating point result\nrx    %s\n", s);
00123               MP_CHECKOK(mp_toradix(&ry, s, 16));
00124               printf("ry    %s\n", s);
00125               MP_CHECKOK(mp_toradix(x, s, 16));
00126               printf("integer result\nx   %s\n", s);
00127               MP_CHECKOK(mp_toradix(y, s, 16));
00128               printf("y   %s\n", s);
00129               res = MP_NO;
00130               goto CLEANUP;
00131        }
00132 
00133   CLEANUP:
00134        mp_clear(&rx);
00135        mp_clear(&ry);
00136        mp_clear(&rz);
00137 
00138        return res;
00139 }
00140 
00141 /* Tests a point p in Chudnovsky Jacobian coordinates, comparing against
00142  * the expected affine result (x, y). */
00143 mp_err
00144 testChudPoint(ecfp_chud_pt * p, mp_int *x, mp_int *y, ECGroup *ecgroup)
00145 {
00146 
00147        char s[1000];
00148        mp_int rx, ry, rz, rz2, rz3, test;
00149        mp_err res = MP_OKAY;
00150 
00151        /* Initialization */
00152        MP_DIGITS(&rx) = 0;
00153        MP_DIGITS(&ry) = 0;
00154        MP_DIGITS(&rz) = 0;
00155        MP_DIGITS(&rz2) = 0;
00156        MP_DIGITS(&rz3) = 0;
00157        MP_DIGITS(&test) = 0;
00158 
00159        MP_CHECKOK(mp_init(&rx));
00160        MP_CHECKOK(mp_init(&ry));
00161        MP_CHECKOK(mp_init(&rz));
00162        MP_CHECKOK(mp_init(&rz2));
00163        MP_CHECKOK(mp_init(&rz3));
00164        MP_CHECKOK(mp_init(&test));
00165 
00166        /* Convert to integers */
00167        ecfp_fp2i(&rx, p->x, ecgroup);
00168        ecfp_fp2i(&ry, p->y, ecgroup);
00169        ecfp_fp2i(&rz, p->z, ecgroup);
00170        ecfp_fp2i(&rz2, p->z2, ecgroup);
00171        ecfp_fp2i(&rz3, p->z3, ecgroup);
00172 
00173        /* Verify z2, z3 are valid */
00174        mp_sqrmod(&rz, &ecgroup->meth->irr, &test);
00175        if (mp_cmp(&test, &rz2) != 0) {
00176               printf("  Error: rzp2 not valid\n");
00177               res = MP_NO;
00178               goto CLEANUP;
00179        }
00180        mp_mulmod(&test, &rz, &ecgroup->meth->irr, &test);
00181        if (mp_cmp(&test, &rz3) != 0) {
00182               printf("  Error: rzp2 not valid\n");
00183               res = MP_NO;
00184               goto CLEANUP;
00185        }
00186 
00187        /* convert result R to affine coordinates */
00188        ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup);
00189 
00190        /* Compare against expected result */
00191        if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) {
00192               printf("  Error: Chudnovsky Floating Point Incorrect.\n");
00193               MP_CHECKOK(mp_toradix(&rx, s, 16));
00194               printf("floating point result\nrx    %s\n", s);
00195               MP_CHECKOK(mp_toradix(&ry, s, 16));
00196               printf("ry    %s\n", s);
00197               MP_CHECKOK(mp_toradix(x, s, 16));
00198               printf("integer result\nx   %s\n", s);
00199               MP_CHECKOK(mp_toradix(y, s, 16));
00200               printf("y   %s\n", s);
00201               res = MP_NO;
00202               goto CLEANUP;
00203        }
00204 
00205   CLEANUP:
00206        mp_clear(&rx);
00207        mp_clear(&ry);
00208        mp_clear(&rz);
00209        mp_clear(&rz2);
00210        mp_clear(&rz3);
00211        mp_clear(&test);
00212 
00213        return res;
00214 }
00215 
00216 /* Tests a point p in Modified Jacobian coordinates, comparing against the 
00217  * expected affine result (x, y). */
00218 mp_err
00219 testJmPoint(ecfp_jm_pt * r, mp_int *x, mp_int *y, ECGroup *ecgroup)
00220 {
00221 
00222        char s[1000];
00223        mp_int rx, ry, rz, raz4, test;
00224        mp_err res = MP_OKAY;
00225 
00226        /* Initialization */
00227        MP_DIGITS(&rx) = 0;
00228        MP_DIGITS(&ry) = 0;
00229        MP_DIGITS(&rz) = 0;
00230        MP_DIGITS(&raz4) = 0;
00231        MP_DIGITS(&test) = 0;
00232 
00233        MP_CHECKOK(mp_init(&rx));
00234        MP_CHECKOK(mp_init(&ry));
00235        MP_CHECKOK(mp_init(&rz));
00236        MP_CHECKOK(mp_init(&raz4));
00237        MP_CHECKOK(mp_init(&test));
00238 
00239        /* Convert to integer */
00240        ecfp_fp2i(&rx, r->x, ecgroup);
00241        ecfp_fp2i(&ry, r->y, ecgroup);
00242        ecfp_fp2i(&rz, r->z, ecgroup);
00243        ecfp_fp2i(&raz4, r->az4, ecgroup);
00244 
00245        /* Verify raz4 = rz^4 * a */
00246        mp_sqrmod(&rz, &ecgroup->meth->irr, &test);
00247        mp_sqrmod(&test, &ecgroup->meth->irr, &test);
00248        mp_mulmod(&test, &ecgroup->curvea, &ecgroup->meth->irr, &test);
00249        if (mp_cmp(&test, &raz4) != 0) {
00250               printf("  Error: a*z^4 not valid\n");
00251               MP_CHECKOK(mp_toradix(&ecgroup->curvea, s, 16));
00252               printf("a    %s\n", s);
00253               MP_CHECKOK(mp_toradix(&rz, s, 16));
00254               printf("rz   %s\n", s);
00255               MP_CHECKOK(mp_toradix(&raz4, s, 16));
00256               printf("raz4    %s\n", s);
00257               res = MP_NO;
00258               goto CLEANUP;
00259        }
00260 
00261        /* convert result R to affine coordinates */
00262        ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup);
00263 
00264        /* Compare against expected result */
00265        if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) {
00266               printf("  Error: Modified Jacobian Floating Point Incorrect.\n");
00267               MP_CHECKOK(mp_toradix(&rx, s, 16));
00268               printf("floating point result\nrx    %s\n", s);
00269               MP_CHECKOK(mp_toradix(&ry, s, 16));
00270               printf("ry    %s\n", s);
00271               MP_CHECKOK(mp_toradix(x, s, 16));
00272               printf("integer result\nx   %s\n", s);
00273               MP_CHECKOK(mp_toradix(y, s, 16));
00274               printf("y   %s\n", s);
00275               res = MP_NO;
00276               goto CLEANUP;
00277        }
00278   CLEANUP:
00279        mp_clear(&rx);
00280        mp_clear(&ry);
00281        mp_clear(&rz);
00282        mp_clear(&raz4);
00283        mp_clear(&test);
00284 
00285        return res;
00286 }
00287 
00288 /* Tests point addition of Jacobian + Affine -> Jacobian */
00289 mp_err
00290 testPointAddJacAff(ECGroup *ecgroup)
00291 {
00292        mp_err res;
00293        mp_int pz, rx2, ry2, rz2;
00294        ecfp_jac_pt p, r;
00295        ecfp_aff_pt q;
00296        EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
00297 
00298        /* Init */
00299        MP_DIGITS(&pz) = 0;
00300        MP_DIGITS(&rx2) = 0;
00301        MP_DIGITS(&ry2) = 0;
00302        MP_DIGITS(&rz2) = 0;
00303        MP_CHECKOK(mp_init(&pz));
00304        MP_CHECKOK(mp_init(&rx2));
00305        MP_CHECKOK(mp_init(&ry2));
00306        MP_CHECKOK(mp_init(&rz2));
00307 
00308        MP_CHECKOK(mp_set_int(&pz, 5));
00309 
00310        /* Set p */
00311        ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
00312        ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
00313        ecfp_i2fp(p.z, &pz, ecgroup);
00314        /* Set q */
00315        ecfp_i2fp(q.x, &ecgroup->geny, ecgroup);
00316        ecfp_i2fp(q.y, &ecgroup->genx, ecgroup);
00317 
00318        /* Do calculations */
00319        group->pt_add_jac_aff(&p, &q, &r, group);
00320 
00321        /* Do calculation in integer to compare against */
00322        MP_CHECKOK(ec_GFp_pt_add_jac_aff
00323                         (&ecgroup->genx, &ecgroup->geny, &pz, &ecgroup->geny,
00324                             &ecgroup->genx, &rx2, &ry2, &rz2, ecgroup));
00325        /* convert result R to affine coordinates */
00326        ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup);
00327 
00328        MP_CHECKOK(testJacPoint(&r, &rx2, &ry2, ecgroup));
00329 
00330   CLEANUP:
00331        if (res == MP_OKAY)
00332               printf("  Test Passed - Point Addition - Jacobian & Affine\n");
00333        else
00334               printf("TEST FAILED - Point Addition - Jacobian & Affine\n");
00335 
00336        mp_clear(&pz);
00337        mp_clear(&rx2);
00338        mp_clear(&ry2);
00339        mp_clear(&rz2);
00340 
00341        return res;
00342 }
00343 
00344 /* Tests point addition in Jacobian coordinates */
00345 mp_err
00346 testPointAddJac(ECGroup *ecgroup)
00347 {
00348        mp_err res;
00349        mp_int pz, qz, qx, qy, rx2, ry2, rz2;
00350        ecfp_jac_pt p, q, r;
00351        EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
00352 
00353        /* Init */
00354        MP_DIGITS(&pz) = 0;
00355        MP_DIGITS(&qx) = 0;
00356        MP_DIGITS(&qy) = 0;
00357        MP_DIGITS(&qz) = 0;
00358        MP_DIGITS(&rx2) = 0;
00359        MP_DIGITS(&ry2) = 0;
00360        MP_DIGITS(&rz2) = 0;
00361        MP_CHECKOK(mp_init(&pz));
00362        MP_CHECKOK(mp_init(&qx));
00363        MP_CHECKOK(mp_init(&qy));
00364        MP_CHECKOK(mp_init(&qz));
00365        MP_CHECKOK(mp_init(&rx2));
00366        MP_CHECKOK(mp_init(&ry2));
00367        MP_CHECKOK(mp_init(&rz2));
00368 
00369        MP_CHECKOK(mp_set_int(&pz, 5));
00370        MP_CHECKOK(mp_set_int(&qz, 105));
00371 
00372        /* Set p */
00373        ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
00374        ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
00375        ecfp_i2fp(p.z, &pz, ecgroup);
00376        /* Set q */
00377        ecfp_i2fp(q.x, &ecgroup->geny, ecgroup);
00378        ecfp_i2fp(q.y, &ecgroup->genx, ecgroup);
00379        ecfp_i2fp(q.z, &qz, ecgroup);
00380 
00381        /* Do calculations */
00382        group->pt_add_jac(&p, &q, &r, group);
00383 
00384        /* Do calculation in integer to compare against */
00385        ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy,
00386                                      ecgroup);
00387        MP_CHECKOK(ec_GFp_pt_add_jac_aff
00388                         (&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy, &rx2, &ry2,
00389                             &rz2, ecgroup));
00390        /* convert result R to affine coordinates */
00391        ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup);
00392 
00393        MP_CHECKOK(testJacPoint(&r, &rx2, &ry2, ecgroup));
00394 
00395   CLEANUP:
00396        if (res == MP_OKAY)
00397               printf("  Test Passed - Point Addition - Jacobian\n");
00398        else
00399               printf("TEST FAILED - Point Addition - Jacobian\n");
00400 
00401        mp_clear(&pz);
00402        mp_clear(&qx);
00403        mp_clear(&qy);
00404        mp_clear(&qz);
00405        mp_clear(&rx2);
00406        mp_clear(&ry2);
00407        mp_clear(&rz2);
00408 
00409        return res;
00410 }
00411 
00412 /* Tests point addition in Chudnovsky Jacobian Coordinates */
00413 mp_err
00414 testPointAddChud(ECGroup *ecgroup)
00415 {
00416        mp_err res;
00417        mp_int rx2, ry2, ix, iy, iz, test, pz, qx, qy, qz;
00418        ecfp_chud_pt p, q, r;
00419        EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
00420 
00421        MP_DIGITS(&qx) = 0;
00422        MP_DIGITS(&qy) = 0;
00423        MP_DIGITS(&qz) = 0;
00424        MP_DIGITS(&pz) = 0;
00425        MP_DIGITS(&rx2) = 0;
00426        MP_DIGITS(&ry2) = 0;
00427        MP_DIGITS(&ix) = 0;
00428        MP_DIGITS(&iy) = 0;
00429        MP_DIGITS(&iz) = 0;
00430        MP_DIGITS(&test) = 0;
00431 
00432        MP_CHECKOK(mp_init(&qx));
00433        MP_CHECKOK(mp_init(&qy));
00434        MP_CHECKOK(mp_init(&qz));
00435        MP_CHECKOK(mp_init(&pz));
00436        MP_CHECKOK(mp_init(&rx2));
00437        MP_CHECKOK(mp_init(&ry2));
00438        MP_CHECKOK(mp_init(&ix));
00439        MP_CHECKOK(mp_init(&iy));
00440        MP_CHECKOK(mp_init(&iz));
00441        MP_CHECKOK(mp_init(&test));
00442 
00443        /* Test Chudnovsky form addition */
00444        /* Set p */
00445        MP_CHECKOK(mp_set_int(&pz, 5));
00446        ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
00447        ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
00448        ecfp_i2fp(p.z, &pz, ecgroup);
00449        mp_sqrmod(&pz, &ecgroup->meth->irr, &test);
00450        ecfp_i2fp(p.z2, &test, ecgroup);
00451        mp_mulmod(&test, &pz, &ecgroup->meth->irr, &test);
00452        ecfp_i2fp(p.z3, &test, ecgroup);
00453 
00454        /* Set q */
00455        MP_CHECKOK(mp_set_int(&qz, 105));
00456        ecfp_i2fp(q.x, &ecgroup->geny, ecgroup);
00457        ecfp_i2fp(q.y, &ecgroup->genx, ecgroup);
00458        ecfp_i2fp(q.z, &qz, ecgroup);
00459        mp_sqrmod(&qz, &ecgroup->meth->irr, &test);
00460        ecfp_i2fp(q.z2, &test, ecgroup);
00461        mp_mulmod(&test, &qz, &ecgroup->meth->irr, &test);
00462        ecfp_i2fp(q.z3, &test, ecgroup);
00463 
00464        group->pt_add_chud(&p, &q, &r, group);
00465 
00466        /* Calculate addition to compare against */
00467        ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy,
00468                                      ecgroup);
00469        ec_GFp_pt_add_jac_aff(&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy,
00470                                             &ix, &iy, &iz, ecgroup);
00471        ec_GFp_pt_jac2aff(&ix, &iy, &iz, &rx2, &ry2, ecgroup);
00472 
00473        MP_CHECKOK(testChudPoint(&r, &rx2, &ry2, ecgroup));
00474 
00475   CLEANUP:
00476        if (res == MP_OKAY)
00477               printf("  Test Passed - Point Addition - Chudnovsky Jacobian\n");
00478        else
00479               printf("TEST FAILED - Point Addition - Chudnovsky Jacobian\n");
00480 
00481        mp_clear(&qx);
00482        mp_clear(&qy);
00483        mp_clear(&qz);
00484        mp_clear(&pz);
00485        mp_clear(&rx2);
00486        mp_clear(&ry2);
00487        mp_clear(&ix);
00488        mp_clear(&iy);
00489        mp_clear(&iz);
00490        mp_clear(&test);
00491 
00492        return res;
00493 }
00494 
00495 /* Tests point addition in Modified Jacobian + Chudnovsky Jacobian ->
00496  * Modified Jacobian coordinates. */
00497 mp_err
00498 testPointAddJmChud(ECGroup *ecgroup)
00499 {
00500        mp_err res;
00501        mp_int rx2, ry2, ix, iy, iz, test, pz, paz4, qx, qy, qz;
00502        ecfp_chud_pt q;
00503        ecfp_jm_pt p, r;
00504        EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
00505 
00506        MP_DIGITS(&qx) = 0;
00507        MP_DIGITS(&qy) = 0;
00508        MP_DIGITS(&qz) = 0;
00509        MP_DIGITS(&pz) = 0;
00510        MP_DIGITS(&paz4) = 0;
00511        MP_DIGITS(&iz) = 0;
00512        MP_DIGITS(&rx2) = 0;
00513        MP_DIGITS(&ry2) = 0;
00514        MP_DIGITS(&ix) = 0;
00515        MP_DIGITS(&iy) = 0;
00516        MP_DIGITS(&iz) = 0;
00517        MP_DIGITS(&test) = 0;
00518 
00519        MP_CHECKOK(mp_init(&qx));
00520        MP_CHECKOK(mp_init(&qy));
00521        MP_CHECKOK(mp_init(&qz));
00522        MP_CHECKOK(mp_init(&pz));
00523        MP_CHECKOK(mp_init(&paz4));
00524        MP_CHECKOK(mp_init(&rx2));
00525        MP_CHECKOK(mp_init(&ry2));
00526        MP_CHECKOK(mp_init(&ix));
00527        MP_CHECKOK(mp_init(&iy));
00528        MP_CHECKOK(mp_init(&iz));
00529        MP_CHECKOK(mp_init(&test));
00530 
00531        /* Test Modified Jacobian form addition */
00532        /* Set p */
00533        ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
00534        ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
00535        ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);
00536        /* paz4 = az^4 */
00537        MP_CHECKOK(mp_set_int(&pz, 5));
00538        mp_sqrmod(&pz, &ecgroup->meth->irr, &paz4);
00539        mp_sqrmod(&paz4, &ecgroup->meth->irr, &paz4);
00540        mp_mulmod(&paz4, &ecgroup->curvea, &ecgroup->meth->irr, &paz4);
00541        ecfp_i2fp(p.z, &pz, ecgroup);
00542        ecfp_i2fp(p.az4, &paz4, ecgroup);
00543 
00544        /* Set q */
00545        MP_CHECKOK(mp_set_int(&qz, 105));
00546        ecfp_i2fp(q.x, &ecgroup->geny, ecgroup);
00547        ecfp_i2fp(q.y, &ecgroup->genx, ecgroup);
00548        ecfp_i2fp(q.z, &qz, ecgroup);
00549        mp_sqrmod(&qz, &ecgroup->meth->irr, &test);
00550        ecfp_i2fp(q.z2, &test, ecgroup);
00551        mp_mulmod(&test, &qz, &ecgroup->meth->irr, &test);
00552        ecfp_i2fp(q.z3, &test, ecgroup);
00553 
00554        /* Do calculation */
00555        group->pt_add_jm_chud(&p, &q, &r, group);
00556 
00557        /* Calculate addition to compare against */
00558        ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy,
00559                                      ecgroup);
00560        ec_GFp_pt_add_jac_aff(&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy,
00561                                             &ix, &iy, &iz, ecgroup);
00562        ec_GFp_pt_jac2aff(&ix, &iy, &iz, &rx2, &ry2, ecgroup);
00563 
00564        MP_CHECKOK(testJmPoint(&r, &rx2, &ry2, ecgroup));
00565 
00566   CLEANUP:
00567        if (res == MP_OKAY)
00568               printf
00569                      ("  Test Passed - Point Addition - Modified & Chudnovsky Jacobian\n");
00570        else
00571               printf
00572                      ("TEST FAILED - Point Addition - Modified & Chudnovsky Jacobian\n");
00573 
00574        mp_clear(&qx);
00575        mp_clear(&qy);
00576        mp_clear(&qz);
00577        mp_clear(&pz);
00578        mp_clear(&paz4);
00579        mp_clear(&rx2);
00580        mp_clear(&ry2);
00581        mp_clear(&ix);
00582        mp_clear(&iy);
00583        mp_clear(&iz);
00584        mp_clear(&test);
00585 
00586        return res;
00587 }
00588 
00589 /* Tests point doubling in Modified Jacobian coordinates */
00590 mp_err
00591 testPointDoubleJm(ECGroup *ecgroup)
00592 {
00593        mp_err res;
00594        mp_int pz, paz4, rx2, ry2, rz2, raz4;
00595        ecfp_jm_pt p, r;
00596        EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
00597 
00598        MP_DIGITS(&pz) = 0;
00599        MP_DIGITS(&paz4) = 0;
00600        MP_DIGITS(&rx2) = 0;
00601        MP_DIGITS(&ry2) = 0;
00602        MP_DIGITS(&rz2) = 0;
00603        MP_DIGITS(&raz4) = 0;
00604 
00605        MP_CHECKOK(mp_init(&pz));
00606        MP_CHECKOK(mp_init(&paz4));
00607        MP_CHECKOK(mp_init(&rx2));
00608        MP_CHECKOK(mp_init(&ry2));
00609        MP_CHECKOK(mp_init(&rz2));
00610        MP_CHECKOK(mp_init(&raz4));
00611 
00612        /* Set p */
00613        ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
00614        ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
00615        ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);
00616 
00617        /* paz4 = az^4 */
00618        MP_CHECKOK(mp_set_int(&pz, 5));
00619        mp_sqrmod(&pz, &ecgroup->meth->irr, &paz4);
00620        mp_sqrmod(&paz4, &ecgroup->meth->irr, &paz4);
00621        mp_mulmod(&paz4, &ecgroup->curvea, &ecgroup->meth->irr, &paz4);
00622 
00623        ecfp_i2fp(p.z, &pz, ecgroup);
00624        ecfp_i2fp(p.az4, &paz4, ecgroup);
00625 
00626        group->pt_dbl_jm(&p, &r, group);
00627 
00628        M_TimeOperation(group->pt_dbl_jm(&p, &r, group), 100000);
00629 
00630        /* Calculate doubling to compare against */
00631        ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2,
00632                                      &rz2, ecgroup);
00633        ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup);
00634 
00635        /* Do comparison and check az^4 */
00636        MP_CHECKOK(testJmPoint(&r, &rx2, &ry2, ecgroup));
00637 
00638   CLEANUP:
00639        if (res == MP_OKAY)
00640               printf("  Test Passed - Point Doubling - Modified Jacobian\n");
00641        else
00642               printf("TEST FAILED - Point Doubling - Modified Jacobian\n");
00643        mp_clear(&pz);
00644        mp_clear(&paz4);
00645        mp_clear(&rx2);
00646        mp_clear(&ry2);
00647        mp_clear(&rz2);
00648        mp_clear(&raz4);
00649 
00650        return res;
00651 
00652 }
00653 
00654 /* Tests point doubling in Chudnovsky Jacobian coordinates */
00655 mp_err
00656 testPointDoubleChud(ECGroup *ecgroup)
00657 {
00658        mp_err res;
00659        mp_int px, py, pz, rx2, ry2, rz2;
00660        ecfp_aff_pt p;
00661        ecfp_chud_pt p2;
00662        EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
00663 
00664        MP_DIGITS(&rx2) = 0;
00665        MP_DIGITS(&ry2) = 0;
00666        MP_DIGITS(&rz2) = 0;
00667        MP_DIGITS(&px) = 0;
00668        MP_DIGITS(&py) = 0;
00669        MP_DIGITS(&pz) = 0;
00670 
00671        MP_CHECKOK(mp_init(&rx2));
00672        MP_CHECKOK(mp_init(&ry2));
00673        MP_CHECKOK(mp_init(&rz2));
00674        MP_CHECKOK(mp_init(&px));
00675        MP_CHECKOK(mp_init(&py));
00676        MP_CHECKOK(mp_init(&pz));
00677 
00678        /* Set p2 = 2P */
00679        ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
00680        ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
00681        ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);
00682 
00683        group->pt_dbl_aff2chud(&p, &p2, group);
00684 
00685        /* Calculate doubling to compare against */
00686        MP_CHECKOK(mp_set_int(&pz, 1));
00687        ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2,
00688                                      &rz2, ecgroup);
00689        ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup);
00690 
00691        /* Do comparison and check az^4 */
00692        MP_CHECKOK(testChudPoint(&p2, &rx2, &ry2, ecgroup));
00693 
00694   CLEANUP:
00695        if (res == MP_OKAY)
00696               printf("  Test Passed - Point Doubling - Chudnovsky Jacobian\n");
00697        else
00698               printf("TEST FAILED - Point Doubling - Chudnovsky Jacobian\n");
00699 
00700        mp_clear(&rx2);
00701        mp_clear(&ry2);
00702        mp_clear(&rz2);
00703        mp_clear(&px);
00704        mp_clear(&py);
00705        mp_clear(&pz);
00706 
00707        return res;
00708 }
00709 
00710 /* Test point doubling in Jacobian coordinates */
00711 mp_err
00712 testPointDoubleJac(ECGroup *ecgroup)
00713 {
00714        mp_err res;
00715        mp_int pz, rx, ry, rz, rx2, ry2, rz2;
00716        ecfp_jac_pt p, p2;
00717        EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
00718 
00719        MP_DIGITS(&pz) = 0;
00720        MP_DIGITS(&rx) = 0;
00721        MP_DIGITS(&ry) = 0;
00722        MP_DIGITS(&rz) = 0;
00723        MP_DIGITS(&rx2) = 0;
00724        MP_DIGITS(&ry2) = 0;
00725        MP_DIGITS(&rz2) = 0;
00726 
00727        MP_CHECKOK(mp_init(&pz));
00728        MP_CHECKOK(mp_init(&rx));
00729        MP_CHECKOK(mp_init(&ry));
00730        MP_CHECKOK(mp_init(&rz));
00731        MP_CHECKOK(mp_init(&rx2));
00732        MP_CHECKOK(mp_init(&ry2));
00733        MP_CHECKOK(mp_init(&rz2));
00734 
00735        MP_CHECKOK(mp_set_int(&pz, 5));
00736 
00737        /* Set p2 = 2P */
00738        ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
00739        ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
00740        ecfp_i2fp(p.z, &pz, ecgroup);
00741        ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);
00742 
00743        group->pt_dbl_jac(&p, &p2, group);
00744        M_TimeOperation(group->pt_dbl_jac(&p, &p2, group), 100000);
00745 
00746        /* Calculate doubling to compare against */
00747        ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2,
00748                                      &rz2, ecgroup);
00749        ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup);
00750 
00751        /* Do comparison */
00752        MP_CHECKOK(testJacPoint(&p2, &rx2, &ry2, ecgroup));
00753 
00754   CLEANUP:
00755        if (res == MP_OKAY)
00756               printf("  Test Passed - Point Doubling - Jacobian\n");
00757        else
00758               printf("TEST FAILED - Point Doubling - Jacobian\n");
00759 
00760        mp_clear(&pz);
00761        mp_clear(&rx);
00762        mp_clear(&ry);
00763        mp_clear(&rz);
00764        mp_clear(&rx2);
00765        mp_clear(&ry2);
00766        mp_clear(&rz2);
00767 
00768        return res;
00769 }
00770 
00771 /* Tests a point multiplication (various algorithms) */
00772 mp_err
00773 testPointMul(ECGroup *ecgroup)
00774 {
00775        mp_err res;
00776        char s[1000];
00777        mp_int rx, ry, order_1;
00778 
00779        /* Init */
00780        MP_DIGITS(&rx) = 0;
00781        MP_DIGITS(&ry) = 0;
00782        MP_DIGITS(&order_1) = 0;
00783 
00784        MP_CHECKOK(mp_init(&rx));
00785        MP_CHECKOK(mp_init(&ry));
00786        MP_CHECKOK(mp_init(&order_1));
00787 
00788        MP_CHECKOK(mp_set_int(&order_1, 1));
00789        MP_CHECKOK(mp_sub(&ecgroup->order, &order_1, &order_1));
00790 
00791        /* Test Algorithm 1: Jacobian-Affine Double & Add */
00792        ec_GFp_pt_mul_jac_fp(&order_1, &ecgroup->genx, &ecgroup->geny, &rx,
00793                                            &ry, ecgroup);
00794        MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth));
00795        if ((mp_cmp(&rx, &ecgroup->genx) != 0)
00796               || (mp_cmp(&ry, &ecgroup->geny) != 0)) {
00797               printf
00798                      ("  Error: ec_GFp_pt_mul_jac_fp invalid result (expected (- base point)).\n");
00799               MP_CHECKOK(mp_toradix(&rx, s, 16));
00800               printf("rx   %s\n", s);
00801               MP_CHECKOK(mp_toradix(&ry, s, 16));
00802               printf("ry   %s\n", s);
00803               res = MP_NO;
00804               goto CLEANUP;
00805        }
00806 
00807        ec_GFp_pt_mul_jac_fp(&ecgroup->order, &ecgroup->genx, &ecgroup->geny,
00808                                            &rx, &ry, ecgroup);
00809        if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
00810               printf
00811                      ("  Error: ec_GFp_pt_mul_jac_fp invalid result (expected point at infinity.\n");
00812               MP_CHECKOK(mp_toradix(&rx, s, 16));
00813               printf("rx   %s\n", s);
00814               MP_CHECKOK(mp_toradix(&ry, s, 16));
00815               printf("ry   %s\n", s);
00816               res = MP_NO;
00817               goto CLEANUP;
00818        }
00819 
00820        /* Test Algorithm 2: 4-bit Window in Jacobian */
00821        ec_GFp_point_mul_jac_4w_fp(&order_1, &ecgroup->genx, &ecgroup->geny,
00822                                                     &rx, &ry, ecgroup);
00823        MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth));
00824        if ((mp_cmp(&rx, &ecgroup->genx) != 0)
00825               || (mp_cmp(&ry, &ecgroup->geny) != 0)) {
00826               printf
00827                      ("  Error: ec_GFp_point_mul_jac_4w_fp invalid result (expected (- base point)).\n");
00828               MP_CHECKOK(mp_toradix(&rx, s, 16));
00829               printf("rx   %s\n", s);
00830               MP_CHECKOK(mp_toradix(&ry, s, 16));
00831               printf("ry   %s\n", s);
00832               res = MP_NO;
00833               goto CLEANUP;
00834        }
00835 
00836        ec_GFp_point_mul_jac_4w_fp(&ecgroup->order, &ecgroup->genx,
00837                                                     &ecgroup->geny, &rx, &ry, ecgroup);
00838        if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
00839               printf
00840                      ("  Error: ec_GFp_point_mul_jac_4w_fp invalid result (expected point at infinity.\n");
00841               MP_CHECKOK(mp_toradix(&rx, s, 16));
00842               printf("rx   %s\n", s);
00843               MP_CHECKOK(mp_toradix(&ry, s, 16));
00844               printf("ry   %s\n", s);
00845               res = MP_NO;
00846               goto CLEANUP;
00847        }
00848 
00849        /* Test Algorithm 3: wNAF with modified Jacobian coordinates */
00850        ec_GFp_point_mul_wNAF_fp(&order_1, &ecgroup->genx, &ecgroup->geny, &rx,
00851                                                   &ry, ecgroup);
00852        MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth));
00853        if ((mp_cmp(&rx, &ecgroup->genx) != 0)
00854               || (mp_cmp(&ry, &ecgroup->geny) != 0)) {
00855               printf
00856                      ("  Error: ec_GFp_pt_mul_wNAF_fp invalid result (expected (- base point)).\n");
00857               MP_CHECKOK(mp_toradix(&rx, s, 16));
00858               printf("rx   %s\n", s);
00859               MP_CHECKOK(mp_toradix(&ry, s, 16));
00860               printf("ry   %s\n", s);
00861               res = MP_NO;
00862               goto CLEANUP;
00863        }
00864 
00865        ec_GFp_point_mul_wNAF_fp(&ecgroup->order, &ecgroup->genx,
00866                                                   &ecgroup->geny, &rx, &ry, ecgroup);
00867        if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
00868               printf
00869                      ("  Error: ec_GFp_pt_mul_wNAF_fp invalid result (expected point at infinity.\n");
00870               MP_CHECKOK(mp_toradix(&rx, s, 16));
00871               printf("rx   %s\n", s);
00872               MP_CHECKOK(mp_toradix(&ry, s, 16));
00873               printf("ry   %s\n", s);
00874               res = MP_NO;
00875               goto CLEANUP;
00876        }
00877 
00878   CLEANUP:
00879        if (res == MP_OKAY)
00880               printf("  Test Passed - Point Multiplication\n");
00881        else
00882               printf("TEST FAILED - Point Multiplication\n");
00883        mp_clear(&rx);
00884        mp_clear(&ry);
00885        mp_clear(&order_1);
00886 
00887        return res;
00888 }
00889 
00890 /* Tests point multiplication with a random scalar repeatedly, comparing
00891  * for consistency within different algorithms. */
00892 mp_err
00893 testPointMulRandom(ECGroup *ecgroup)
00894 {
00895        mp_err res;
00896        mp_int rx, ry, rx2, ry2, n;
00897        int i, size;
00898        EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
00899 
00900        MP_DIGITS(&rx) = 0;
00901        MP_DIGITS(&ry) = 0;
00902        MP_DIGITS(&rx2) = 0;
00903        MP_DIGITS(&ry2) = 0;
00904        MP_DIGITS(&n) = 0;
00905 
00906        MP_CHECKOK(mp_init(&rx));
00907        MP_CHECKOK(mp_init(&ry));
00908        MP_CHECKOK(mp_init(&rx2));
00909        MP_CHECKOK(mp_init(&ry2));
00910        MP_CHECKOK(mp_init(&n));
00911 
00912        for (i = 0; i < 100; i++) {
00913               /* compute random scalar */
00914               size = mpl_significant_bits(&ecgroup->meth->irr);
00915               if (size < MP_OKAY) {
00916                      res = MP_NO;
00917                      goto CLEANUP;
00918               }
00919               MP_CHECKOK(mpp_random_size(&n, group->orderBitSize));
00920               MP_CHECKOK(mp_mod(&n, &ecgroup->order, &n));
00921 
00922               ec_GFp_pt_mul_jac(&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry,
00923                                             ecgroup);
00924               ec_GFp_pt_mul_jac_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx2,
00925                                                   &ry2, ecgroup);
00926 
00927               if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) {
00928                      printf
00929                             ("  Error: different results for Point Multiplication - Double & Add.\n");
00930                      res = MP_NO;
00931                      goto CLEANUP;
00932               }
00933 
00934               ec_GFp_point_mul_wNAF_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx,
00935                                                          &ry, ecgroup);
00936               if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) {
00937                      printf
00938                             ("  Error: different results for Point Multiplication - wNAF.\n");
00939                      res = MP_NO;
00940                      goto CLEANUP;
00941               }
00942 
00943               ec_GFp_point_mul_jac_4w_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx,
00944                                                            &ry, ecgroup);
00945               if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) {
00946                      printf
00947                             ("  Error: different results for Point Multiplication - 4 bit window.\n");
00948                      res = MP_NO;
00949                      goto CLEANUP;
00950               }
00951 
00952        }
00953 
00954   CLEANUP:
00955        if (res == MP_OKAY)
00956               printf("  Test Passed - Point Random Multiplication\n");
00957        else
00958               printf("TEST FAILED - Point Random Multiplication\n");
00959        mp_clear(&rx);
00960        mp_clear(&ry);
00961        mp_clear(&rx2);
00962        mp_clear(&ry2);
00963        mp_clear(&n);
00964 
00965        return res;
00966 }
00967 
00968 /* Tests the time required for a point multiplication */
00969 mp_err
00970 testPointMulTime(ECGroup *ecgroup)
00971 {
00972        mp_err res = MP_OKAY;
00973        mp_int rx, ry, n;
00974        int size;
00975 
00976        MP_DIGITS(&rx) = 0;
00977        MP_DIGITS(&ry) = 0;
00978        MP_DIGITS(&n) = 0;
00979 
00980        MP_CHECKOK(mp_init(&rx));
00981        MP_CHECKOK(mp_init(&ry));
00982        MP_CHECKOK(mp_init(&n));
00983 
00984        /* compute random scalar */
00985        size = mpl_significant_bits(&ecgroup->meth->irr);
00986        if (size < MP_OKAY) {
00987               res = MP_NO;
00988               goto CLEANUP;
00989        }
00990 
00991        MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS));
00992        MP_CHECKOK(ecgroup->meth->field_mod(&n, &n, ecgroup->meth));
00993 
00994        M_TimeOperation(ec_GFp_pt_mul_jac_fp
00995                                    (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry,
00996                                     ecgroup), 1000);
00997 
00998        M_TimeOperation(ec_GFp_point_mul_jac_4w_fp
00999                                    (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry,
01000                                     ecgroup), 1000);
01001 
01002        M_TimeOperation(ec_GFp_point_mul_wNAF_fp
01003                                    (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry,
01004                                     ecgroup), 1000);
01005 
01006        M_TimeOperation(ec_GFp_pt_mul_jac
01007                                    (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry,
01008                                     ecgroup), 100);
01009 
01010   CLEANUP:
01011        if (res == MP_OKAY)
01012               printf("  Test Passed - Point Multiplication Timing\n");
01013        else
01014               printf("TEST FAILED - Point Multiplication Timing\n");
01015        mp_clear(&rx);
01016        mp_clear(&ry);
01017        mp_clear(&n);
01018 
01019        return res;
01020 }
01021 
01022 /* Tests pre computation of Chudnovsky Jacobian points used in wNAF form */
01023 mp_err
01024 testPreCompute(ECGroup *ecgroup)
01025 {
01026        ecfp_chud_pt precomp[16];
01027        ecfp_aff_pt p;
01028        EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
01029        int i;
01030        mp_err res;
01031 
01032        mp_int x, y, ny, x2, y2;
01033 
01034        MP_DIGITS(&x) = 0;
01035        MP_DIGITS(&y) = 0;
01036        MP_DIGITS(&ny) = 0;
01037        MP_DIGITS(&x2) = 0;
01038        MP_DIGITS(&y2) = 0;
01039 
01040        MP_CHECKOK(mp_init(&x));
01041        MP_CHECKOK(mp_init(&y));
01042        MP_CHECKOK(mp_init(&ny));
01043        MP_CHECKOK(mp_init(&x2));
01044        MP_CHECKOK(mp_init(&y2));
01045 
01046        ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
01047        ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
01048        ecfp_i2fp(group->curvea, &(ecgroup->curvea), ecgroup);
01049 
01050        /* Perform precomputation */
01051        group->precompute_chud(precomp, &p, group);
01052 
01053        M_TimeOperation(group->precompute_chud(precomp, &p, group), 10000);
01054 
01055        /* Calculate addition to compare against */
01056        MP_CHECKOK(mp_copy(&ecgroup->genx, &x));
01057        MP_CHECKOK(mp_copy(&ecgroup->geny, &y));
01058        MP_CHECKOK(ecgroup->meth->field_neg(&y, &ny, ecgroup->meth));
01059 
01060        ec_GFp_pt_dbl_aff(&x, &y, &x2, &y2, ecgroup);
01061 
01062        for (i = 0; i < 8; i++) {
01063               MP_CHECKOK(testChudPoint(&precomp[8 + i], &x, &y, ecgroup));
01064               MP_CHECKOK(testChudPoint(&precomp[7 - i], &x, &ny, ecgroup));
01065               ec_GFp_pt_add_aff(&x, &y, &x2, &y2, &x, &y, ecgroup);
01066               MP_CHECKOK(ecgroup->meth->field_neg(&y, &ny, ecgroup->meth));
01067        }
01068 
01069   CLEANUP:
01070        if (res == MP_OKAY)
01071               printf("  Test Passed - Precomputation\n");
01072        else
01073               printf("TEST FAILED - Precomputation\n");
01074 
01075        mp_clear(&x);
01076        mp_clear(&y);
01077        mp_clear(&ny);
01078        mp_clear(&x2);
01079        mp_clear(&y2);
01080        return res;
01081 }
01082 
01083 /* Given a curve using floating point arithmetic, test it. This method
01084  * specifies which of the above tests to run. */
01085 mp_err
01086 testCurve(ECGroup *ecgroup)
01087 {
01088        int res = MP_OKAY;
01089 
01090        MP_CHECKOK(testPointAddJacAff(ecgroup));
01091        MP_CHECKOK(testPointAddJac(ecgroup));
01092        MP_CHECKOK(testPointAddChud(ecgroup));
01093        MP_CHECKOK(testPointAddJmChud(ecgroup));
01094        MP_CHECKOK(testPointDoubleJac(ecgroup));
01095        MP_CHECKOK(testPointDoubleChud(ecgroup));
01096        MP_CHECKOK(testPointDoubleJm(ecgroup));
01097        MP_CHECKOK(testPreCompute(ecgroup));
01098        MP_CHECKOK(testPointMul(ecgroup));
01099        MP_CHECKOK(testPointMulRandom(ecgroup));
01100        MP_CHECKOK(testPointMulTime(ecgroup));
01101   CLEANUP:
01102        return res;
01103 }
01104 
01105 /* Tests a number of curves optimized using floating point arithmetic */
01106 int
01107 main(void)
01108 {
01109        mp_err res = MP_OKAY;
01110        ECGroup *ecgroup = NULL;
01111 
01112        /* specific arithmetic tests */
01113        M_TestCurve("SECG-160R1", ECCurve_SECG_PRIME_160R1);
01114        M_TestCurve("SECG-192R1", ECCurve_SECG_PRIME_192R1);
01115        M_TestCurve("SEGC-224R1", ECCurve_SECG_PRIME_224R1);
01116 
01117   CLEANUP:
01118        ECGroup_free(ecgroup);
01119        if (res != MP_OKAY) {
01120               printf("Error: exiting with error value %i\n", res);
01121        }
01122        return res;
01123 }