~ubuntu-branches/ubuntu/lucid/seamonkey/lucid-security

« back to all changes in this revision

Viewing changes to security/nss-fips/lib/freebl/ecl/tests/ecp_fpt.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabien Tassin
  • Date: 2008-07-29 21:29:02 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20080729212902-spm9kpvchp9udwbw
Tags: 1.1.11+nobinonly-0ubuntu1
* New security upstream release: 1.1.11 (LP: #218534)
  Fixes USN-602-1, USN-619-1, USN-623-1 and USN-629-1
* Refresh diverged patch:
  - update debian/patches/80_security_build.patch
* Fix FTBFS with missing -lfontconfig
  - add debian/patches/11_fix_ftbfs_with_fontconfig.patch
  - update debian/patches/series
* Build with default gcc (hardy: 4.2, intrepid: 4.3)
  - update debian/rules
  - update debian/control

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 * ***** BEGIN LICENSE BLOCK *****
 
3
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
4
 *
 
5
 * The contents of this file are subject to the Mozilla Public License Version
 
6
 * 1.1 (the "License"); you may not use this file except in compliance with
 
7
 * the License. You may obtain a copy of the License at
 
8
 * http://www.mozilla.org/MPL/
 
9
 *
 
10
 * Software distributed under the License is distributed on an "AS IS" basis,
 
11
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
12
 * for the specific language governing rights and limitations under the
 
13
 * License.
 
14
 *
 
15
 * The Original Code is the elliptic curve math library for prime field curves using floating point operations.
 
16
 *
 
17
 * The Initial Developer of the Original Code is
 
18
 * Sun Microsystems, Inc.
 
19
 * Portions created by the Initial Developer are Copyright (C) 2003
 
20
 * the Initial Developer. All Rights Reserved.
 
21
 *
 
22
 * Contributor(s):
 
23
 *   Stephen Fung <fungstep@hotmail.com> and
 
24
 *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
 
25
 *
 
26
 * Alternatively, the contents of this file may be used under the terms of
 
27
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 
28
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
29
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
30
 * of those above. If you wish to allow use of your version of this file only
 
31
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
32
 * use your version of this file under the terms of the MPL, indicate your
 
33
 * decision by deleting the provisions above and replace them with the notice
 
34
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
35
 * the provisions above, a recipient may use your version of this file under
 
36
 * the terms of any one of the MPL, the GPL or the LGPL.
 
37
 *
 
38
 * ***** END LICENSE BLOCK ***** */
 
39
 
 
40
#include "ecp_fp.h"
 
41
#include "mpprime.h"
 
42
 
 
43
#include <stdio.h>
 
44
#include <time.h>
 
45
#include <sys/time.h>
 
46
#include <sys/resource.h>
 
47
 
 
48
/* Time k repetitions of operation op. */
 
49
#define M_TimeOperation(op, k) { \
 
50
  double dStart, dNow, dUserTime; \
 
51
  struct rusage ru; \
 
52
  int i; \
 
53
  getrusage(RUSAGE_SELF, &ru); \
 
54
  dStart = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \
 
55
  for (i = 0; i < k; i++) { \
 
56
    { op; } \
 
57
  }; \
 
58
  getrusage(RUSAGE_SELF, &ru); \
 
59
  dNow = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \
 
60
  dUserTime = dNow-dStart; \
 
61
  if (dUserTime) printf("    %-45s\n      k: %6i, t: %6.2f sec, k/t: %6.2f ops/sec\n", #op, k, dUserTime, k/dUserTime); \
 
62
}
 
63
 
 
64
/* Test curve using specific floating point field arithmetic. */
 
65
#define M_TestCurve(name_c, name) { \
 
66
  printf("Testing %s using specific floating point implementation...\n", name_c); \
 
67
  ECGroup_free(ecgroup); \
 
68
  ecgroup = ECGroup_fromName(name); \
 
69
  if (ecgroup == NULL) { \
 
70
    printf("  Warning: could not construct group.\n"); \
 
71
    printf("%s failed.\n", name_c); \
 
72
    res = MP_NO; \
 
73
    goto CLEANUP; \
 
74
  } else { \
 
75
    MP_CHECKOK( testCurve(ecgroup)); \
 
76
    printf("%s passed.\n", name_c); \
 
77
  } \
 
78
}
 
79
 
 
80
/* Outputs a floating point double (currently not used) */
 
81
void
 
82
d_output(const double *u, int len, char *name, const EC_group_fp * group)
 
83
{
 
84
        int i;
 
85
 
 
86
        printf("%s:  ", name);
 
87
        for (i = 0; i < len; i++) {
 
88
                printf("+ %.2f * 2^%i ", u[i] / ecfp_exp[i],
 
89
                           group->doubleBitSize * i);
 
90
        }
 
91
        printf("\n");
 
92
}
 
93
 
 
94
/* Tests a point p in Jacobian coordinates, comparing against the
 
95
 * expected affine result (x, y). */
 
96
mp_err
 
97
testJacPoint(ecfp_jac_pt * p, mp_int *x, mp_int *y, ECGroup *ecgroup)
 
98
{
 
99
        char s[1000];
 
100
        mp_int rx, ry, rz;
 
101
        mp_err res = MP_OKAY;
 
102
 
 
103
        MP_DIGITS(&rx) = 0;
 
104
        MP_DIGITS(&ry) = 0;
 
105
        MP_DIGITS(&rz) = 0;
 
106
 
 
107
        MP_CHECKOK(mp_init(&rx));
 
108
        MP_CHECKOK(mp_init(&ry));
 
109
        MP_CHECKOK(mp_init(&rz));
 
110
 
 
111
        ecfp_fp2i(&rx, p->x, ecgroup);
 
112
        ecfp_fp2i(&ry, p->y, ecgroup);
 
113
        ecfp_fp2i(&rz, p->z, ecgroup);
 
114
 
 
115
        /* convert result R to affine coordinates */
 
116
        ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup);
 
117
 
 
118
        /* Compare to expected result */
 
119
        if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) {
 
120
                printf("  Error: Jacobian Floating Point Incorrect.\n");
 
121
                MP_CHECKOK(mp_toradix(&rx, s, 16));
 
122
                printf("floating point result\nrx    %s\n", s);
 
123
                MP_CHECKOK(mp_toradix(&ry, s, 16));
 
124
                printf("ry    %s\n", s);
 
125
                MP_CHECKOK(mp_toradix(x, s, 16));
 
126
                printf("integer result\nx   %s\n", s);
 
127
                MP_CHECKOK(mp_toradix(y, s, 16));
 
128
                printf("y   %s\n", s);
 
129
                res = MP_NO;
 
130
                goto CLEANUP;
 
131
        }
 
132
 
 
133
  CLEANUP:
 
134
        mp_clear(&rx);
 
135
        mp_clear(&ry);
 
136
        mp_clear(&rz);
 
137
 
 
138
        return res;
 
139
}
 
140
 
 
141
/* Tests a point p in Chudnovsky Jacobian coordinates, comparing against
 
142
 * the expected affine result (x, y). */
 
143
mp_err
 
144
testChudPoint(ecfp_chud_pt * p, mp_int *x, mp_int *y, ECGroup *ecgroup)
 
145
{
 
146
 
 
147
        char s[1000];
 
148
        mp_int rx, ry, rz, rz2, rz3, test;
 
149
        mp_err res = MP_OKAY;
 
150
 
 
151
        /* Initialization */
 
152
        MP_DIGITS(&rx) = 0;
 
153
        MP_DIGITS(&ry) = 0;
 
154
        MP_DIGITS(&rz) = 0;
 
155
        MP_DIGITS(&rz2) = 0;
 
156
        MP_DIGITS(&rz3) = 0;
 
157
        MP_DIGITS(&test) = 0;
 
158
 
 
159
        MP_CHECKOK(mp_init(&rx));
 
160
        MP_CHECKOK(mp_init(&ry));
 
161
        MP_CHECKOK(mp_init(&rz));
 
162
        MP_CHECKOK(mp_init(&rz2));
 
163
        MP_CHECKOK(mp_init(&rz3));
 
164
        MP_CHECKOK(mp_init(&test));
 
165
 
 
166
        /* Convert to integers */
 
167
        ecfp_fp2i(&rx, p->x, ecgroup);
 
168
        ecfp_fp2i(&ry, p->y, ecgroup);
 
169
        ecfp_fp2i(&rz, p->z, ecgroup);
 
170
        ecfp_fp2i(&rz2, p->z2, ecgroup);
 
171
        ecfp_fp2i(&rz3, p->z3, ecgroup);
 
172
 
 
173
        /* Verify z2, z3 are valid */
 
174
        mp_sqrmod(&rz, &ecgroup->meth->irr, &test);
 
175
        if (mp_cmp(&test, &rz2) != 0) {
 
176
                printf("  Error: rzp2 not valid\n");
 
177
                res = MP_NO;
 
178
                goto CLEANUP;
 
179
        }
 
180
        mp_mulmod(&test, &rz, &ecgroup->meth->irr, &test);
 
181
        if (mp_cmp(&test, &rz3) != 0) {
 
182
                printf("  Error: rzp2 not valid\n");
 
183
                res = MP_NO;
 
184
                goto CLEANUP;
 
185
        }
 
186
 
 
187
        /* convert result R to affine coordinates */
 
188
        ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup);
 
189
 
 
190
        /* Compare against expected result */
 
191
        if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) {
 
192
                printf("  Error: Chudnovsky Floating Point Incorrect.\n");
 
193
                MP_CHECKOK(mp_toradix(&rx, s, 16));
 
194
                printf("floating point result\nrx    %s\n", s);
 
195
                MP_CHECKOK(mp_toradix(&ry, s, 16));
 
196
                printf("ry    %s\n", s);
 
197
                MP_CHECKOK(mp_toradix(x, s, 16));
 
198
                printf("integer result\nx   %s\n", s);
 
199
                MP_CHECKOK(mp_toradix(y, s, 16));
 
200
                printf("y   %s\n", s);
 
201
                res = MP_NO;
 
202
                goto CLEANUP;
 
203
        }
 
204
 
 
205
  CLEANUP:
 
206
        mp_clear(&rx);
 
207
        mp_clear(&ry);
 
208
        mp_clear(&rz);
 
209
        mp_clear(&rz2);
 
210
        mp_clear(&rz3);
 
211
        mp_clear(&test);
 
212
 
 
213
        return res;
 
214
}
 
215
 
 
216
/* Tests a point p in Modified Jacobian coordinates, comparing against the 
 
217
 * expected affine result (x, y). */
 
218
mp_err
 
219
testJmPoint(ecfp_jm_pt * r, mp_int *x, mp_int *y, ECGroup *ecgroup)
 
220
{
 
221
 
 
222
        char s[1000];
 
223
        mp_int rx, ry, rz, raz4, test;
 
224
        mp_err res = MP_OKAY;
 
225
 
 
226
        /* Initialization */
 
227
        MP_DIGITS(&rx) = 0;
 
228
        MP_DIGITS(&ry) = 0;
 
229
        MP_DIGITS(&rz) = 0;
 
230
        MP_DIGITS(&raz4) = 0;
 
231
        MP_DIGITS(&test) = 0;
 
232
 
 
233
        MP_CHECKOK(mp_init(&rx));
 
234
        MP_CHECKOK(mp_init(&ry));
 
235
        MP_CHECKOK(mp_init(&rz));
 
236
        MP_CHECKOK(mp_init(&raz4));
 
237
        MP_CHECKOK(mp_init(&test));
 
238
 
 
239
        /* Convert to integer */
 
240
        ecfp_fp2i(&rx, r->x, ecgroup);
 
241
        ecfp_fp2i(&ry, r->y, ecgroup);
 
242
        ecfp_fp2i(&rz, r->z, ecgroup);
 
243
        ecfp_fp2i(&raz4, r->az4, ecgroup);
 
244
 
 
245
        /* Verify raz4 = rz^4 * a */
 
246
        mp_sqrmod(&rz, &ecgroup->meth->irr, &test);
 
247
        mp_sqrmod(&test, &ecgroup->meth->irr, &test);
 
248
        mp_mulmod(&test, &ecgroup->curvea, &ecgroup->meth->irr, &test);
 
249
        if (mp_cmp(&test, &raz4) != 0) {
 
250
                printf("  Error: a*z^4 not valid\n");
 
251
                MP_CHECKOK(mp_toradix(&ecgroup->curvea, s, 16));
 
252
                printf("a    %s\n", s);
 
253
                MP_CHECKOK(mp_toradix(&rz, s, 16));
 
254
                printf("rz   %s\n", s);
 
255
                MP_CHECKOK(mp_toradix(&raz4, s, 16));
 
256
                printf("raz4    %s\n", s);
 
257
                res = MP_NO;
 
258
                goto CLEANUP;
 
259
        }
 
260
 
 
261
        /* convert result R to affine coordinates */
 
262
        ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup);
 
263
 
 
264
        /* Compare against expected result */
 
265
        if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) {
 
266
                printf("  Error: Modified Jacobian Floating Point Incorrect.\n");
 
267
                MP_CHECKOK(mp_toradix(&rx, s, 16));
 
268
                printf("floating point result\nrx    %s\n", s);
 
269
                MP_CHECKOK(mp_toradix(&ry, s, 16));
 
270
                printf("ry    %s\n", s);
 
271
                MP_CHECKOK(mp_toradix(x, s, 16));
 
272
                printf("integer result\nx   %s\n", s);
 
273
                MP_CHECKOK(mp_toradix(y, s, 16));
 
274
                printf("y   %s\n", s);
 
275
                res = MP_NO;
 
276
                goto CLEANUP;
 
277
        }
 
278
  CLEANUP:
 
279
        mp_clear(&rx);
 
280
        mp_clear(&ry);
 
281
        mp_clear(&rz);
 
282
        mp_clear(&raz4);
 
283
        mp_clear(&test);
 
284
 
 
285
        return res;
 
286
}
 
287
 
 
288
/* Tests point addition of Jacobian + Affine -> Jacobian */
 
289
mp_err
 
290
testPointAddJacAff(ECGroup *ecgroup)
 
291
{
 
292
        mp_err res;
 
293
        mp_int pz, rx2, ry2, rz2;
 
294
        ecfp_jac_pt p, r;
 
295
        ecfp_aff_pt q;
 
296
        EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
 
297
 
 
298
        /* Init */
 
299
        MP_DIGITS(&pz) = 0;
 
300
        MP_DIGITS(&rx2) = 0;
 
301
        MP_DIGITS(&ry2) = 0;
 
302
        MP_DIGITS(&rz2) = 0;
 
303
        MP_CHECKOK(mp_init(&pz));
 
304
        MP_CHECKOK(mp_init(&rx2));
 
305
        MP_CHECKOK(mp_init(&ry2));
 
306
        MP_CHECKOK(mp_init(&rz2));
 
307
 
 
308
        MP_CHECKOK(mp_set_int(&pz, 5));
 
309
 
 
310
        /* Set p */
 
311
        ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
 
312
        ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
 
313
        ecfp_i2fp(p.z, &pz, ecgroup);
 
314
        /* Set q */
 
315
        ecfp_i2fp(q.x, &ecgroup->geny, ecgroup);
 
316
        ecfp_i2fp(q.y, &ecgroup->genx, ecgroup);
 
317
 
 
318
        /* Do calculations */
 
319
        group->pt_add_jac_aff(&p, &q, &r, group);
 
320
 
 
321
        /* Do calculation in integer to compare against */
 
322
        MP_CHECKOK(ec_GFp_pt_add_jac_aff
 
323
                           (&ecgroup->genx, &ecgroup->geny, &pz, &ecgroup->geny,
 
324
                                &ecgroup->genx, &rx2, &ry2, &rz2, ecgroup));
 
325
        /* convert result R to affine coordinates */
 
326
        ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup);
 
327
 
 
328
        MP_CHECKOK(testJacPoint(&r, &rx2, &ry2, ecgroup));
 
329
 
 
330
  CLEANUP:
 
331
        if (res == MP_OKAY)
 
332
                printf("  Test Passed - Point Addition - Jacobian & Affine\n");
 
333
        else
 
334
                printf("TEST FAILED - Point Addition - Jacobian & Affine\n");
 
335
 
 
336
        mp_clear(&pz);
 
337
        mp_clear(&rx2);
 
338
        mp_clear(&ry2);
 
339
        mp_clear(&rz2);
 
340
 
 
341
        return res;
 
342
}
 
343
 
 
344
/* Tests point addition in Jacobian coordinates */
 
345
mp_err
 
346
testPointAddJac(ECGroup *ecgroup)
 
347
{
 
348
        mp_err res;
 
349
        mp_int pz, qz, qx, qy, rx2, ry2, rz2;
 
350
        ecfp_jac_pt p, q, r;
 
351
        EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
 
352
 
 
353
        /* Init */
 
354
        MP_DIGITS(&pz) = 0;
 
355
        MP_DIGITS(&qx) = 0;
 
356
        MP_DIGITS(&qy) = 0;
 
357
        MP_DIGITS(&qz) = 0;
 
358
        MP_DIGITS(&rx2) = 0;
 
359
        MP_DIGITS(&ry2) = 0;
 
360
        MP_DIGITS(&rz2) = 0;
 
361
        MP_CHECKOK(mp_init(&pz));
 
362
        MP_CHECKOK(mp_init(&qx));
 
363
        MP_CHECKOK(mp_init(&qy));
 
364
        MP_CHECKOK(mp_init(&qz));
 
365
        MP_CHECKOK(mp_init(&rx2));
 
366
        MP_CHECKOK(mp_init(&ry2));
 
367
        MP_CHECKOK(mp_init(&rz2));
 
368
 
 
369
        MP_CHECKOK(mp_set_int(&pz, 5));
 
370
        MP_CHECKOK(mp_set_int(&qz, 105));
 
371
 
 
372
        /* Set p */
 
373
        ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
 
374
        ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
 
375
        ecfp_i2fp(p.z, &pz, ecgroup);
 
376
        /* Set q */
 
377
        ecfp_i2fp(q.x, &ecgroup->geny, ecgroup);
 
378
        ecfp_i2fp(q.y, &ecgroup->genx, ecgroup);
 
379
        ecfp_i2fp(q.z, &qz, ecgroup);
 
380
 
 
381
        /* Do calculations */
 
382
        group->pt_add_jac(&p, &q, &r, group);
 
383
 
 
384
        /* Do calculation in integer to compare against */
 
385
        ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy,
 
386
                                          ecgroup);
 
387
        MP_CHECKOK(ec_GFp_pt_add_jac_aff
 
388
                           (&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy, &rx2, &ry2,
 
389
                                &rz2, ecgroup));
 
390
        /* convert result R to affine coordinates */
 
391
        ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup);
 
392
 
 
393
        MP_CHECKOK(testJacPoint(&r, &rx2, &ry2, ecgroup));
 
394
 
 
395
  CLEANUP:
 
396
        if (res == MP_OKAY)
 
397
                printf("  Test Passed - Point Addition - Jacobian\n");
 
398
        else
 
399
                printf("TEST FAILED - Point Addition - Jacobian\n");
 
400
 
 
401
        mp_clear(&pz);
 
402
        mp_clear(&qx);
 
403
        mp_clear(&qy);
 
404
        mp_clear(&qz);
 
405
        mp_clear(&rx2);
 
406
        mp_clear(&ry2);
 
407
        mp_clear(&rz2);
 
408
 
 
409
        return res;
 
410
}
 
411
 
 
412
/* Tests point addition in Chudnovsky Jacobian Coordinates */
 
413
mp_err
 
414
testPointAddChud(ECGroup *ecgroup)
 
415
{
 
416
        mp_err res;
 
417
        mp_int rx2, ry2, ix, iy, iz, test, pz, qx, qy, qz;
 
418
        ecfp_chud_pt p, q, r;
 
419
        EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
 
420
 
 
421
        MP_DIGITS(&qx) = 0;
 
422
        MP_DIGITS(&qy) = 0;
 
423
        MP_DIGITS(&qz) = 0;
 
424
        MP_DIGITS(&pz) = 0;
 
425
        MP_DIGITS(&rx2) = 0;
 
426
        MP_DIGITS(&ry2) = 0;
 
427
        MP_DIGITS(&ix) = 0;
 
428
        MP_DIGITS(&iy) = 0;
 
429
        MP_DIGITS(&iz) = 0;
 
430
        MP_DIGITS(&test) = 0;
 
431
 
 
432
        MP_CHECKOK(mp_init(&qx));
 
433
        MP_CHECKOK(mp_init(&qy));
 
434
        MP_CHECKOK(mp_init(&qz));
 
435
        MP_CHECKOK(mp_init(&pz));
 
436
        MP_CHECKOK(mp_init(&rx2));
 
437
        MP_CHECKOK(mp_init(&ry2));
 
438
        MP_CHECKOK(mp_init(&ix));
 
439
        MP_CHECKOK(mp_init(&iy));
 
440
        MP_CHECKOK(mp_init(&iz));
 
441
        MP_CHECKOK(mp_init(&test));
 
442
 
 
443
        /* Test Chudnovsky form addition */
 
444
        /* Set p */
 
445
        MP_CHECKOK(mp_set_int(&pz, 5));
 
446
        ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
 
447
        ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
 
448
        ecfp_i2fp(p.z, &pz, ecgroup);
 
449
        mp_sqrmod(&pz, &ecgroup->meth->irr, &test);
 
450
        ecfp_i2fp(p.z2, &test, ecgroup);
 
451
        mp_mulmod(&test, &pz, &ecgroup->meth->irr, &test);
 
452
        ecfp_i2fp(p.z3, &test, ecgroup);
 
453
 
 
454
        /* Set q */
 
455
        MP_CHECKOK(mp_set_int(&qz, 105));
 
456
        ecfp_i2fp(q.x, &ecgroup->geny, ecgroup);
 
457
        ecfp_i2fp(q.y, &ecgroup->genx, ecgroup);
 
458
        ecfp_i2fp(q.z, &qz, ecgroup);
 
459
        mp_sqrmod(&qz, &ecgroup->meth->irr, &test);
 
460
        ecfp_i2fp(q.z2, &test, ecgroup);
 
461
        mp_mulmod(&test, &qz, &ecgroup->meth->irr, &test);
 
462
        ecfp_i2fp(q.z3, &test, ecgroup);
 
463
 
 
464
        group->pt_add_chud(&p, &q, &r, group);
 
465
 
 
466
        /* Calculate addition to compare against */
 
467
        ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy,
 
468
                                          ecgroup);
 
469
        ec_GFp_pt_add_jac_aff(&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy,
 
470
                                                  &ix, &iy, &iz, ecgroup);
 
471
        ec_GFp_pt_jac2aff(&ix, &iy, &iz, &rx2, &ry2, ecgroup);
 
472
 
 
473
        MP_CHECKOK(testChudPoint(&r, &rx2, &ry2, ecgroup));
 
474
 
 
475
  CLEANUP:
 
476
        if (res == MP_OKAY)
 
477
                printf("  Test Passed - Point Addition - Chudnovsky Jacobian\n");
 
478
        else
 
479
                printf("TEST FAILED - Point Addition - Chudnovsky Jacobian\n");
 
480
 
 
481
        mp_clear(&qx);
 
482
        mp_clear(&qy);
 
483
        mp_clear(&qz);
 
484
        mp_clear(&pz);
 
485
        mp_clear(&rx2);
 
486
        mp_clear(&ry2);
 
487
        mp_clear(&ix);
 
488
        mp_clear(&iy);
 
489
        mp_clear(&iz);
 
490
        mp_clear(&test);
 
491
 
 
492
        return res;
 
493
}
 
494
 
 
495
/* Tests point addition in Modified Jacobian + Chudnovsky Jacobian ->
 
496
 * Modified Jacobian coordinates. */
 
497
mp_err
 
498
testPointAddJmChud(ECGroup *ecgroup)
 
499
{
 
500
        mp_err res;
 
501
        mp_int rx2, ry2, ix, iy, iz, test, pz, paz4, qx, qy, qz;
 
502
        ecfp_chud_pt q;
 
503
        ecfp_jm_pt p, r;
 
504
        EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
 
505
 
 
506
        MP_DIGITS(&qx) = 0;
 
507
        MP_DIGITS(&qy) = 0;
 
508
        MP_DIGITS(&qz) = 0;
 
509
        MP_DIGITS(&pz) = 0;
 
510
        MP_DIGITS(&paz4) = 0;
 
511
        MP_DIGITS(&iz) = 0;
 
512
        MP_DIGITS(&rx2) = 0;
 
513
        MP_DIGITS(&ry2) = 0;
 
514
        MP_DIGITS(&ix) = 0;
 
515
        MP_DIGITS(&iy) = 0;
 
516
        MP_DIGITS(&iz) = 0;
 
517
        MP_DIGITS(&test) = 0;
 
518
 
 
519
        MP_CHECKOK(mp_init(&qx));
 
520
        MP_CHECKOK(mp_init(&qy));
 
521
        MP_CHECKOK(mp_init(&qz));
 
522
        MP_CHECKOK(mp_init(&pz));
 
523
        MP_CHECKOK(mp_init(&paz4));
 
524
        MP_CHECKOK(mp_init(&rx2));
 
525
        MP_CHECKOK(mp_init(&ry2));
 
526
        MP_CHECKOK(mp_init(&ix));
 
527
        MP_CHECKOK(mp_init(&iy));
 
528
        MP_CHECKOK(mp_init(&iz));
 
529
        MP_CHECKOK(mp_init(&test));
 
530
 
 
531
        /* Test Modified Jacobian form addition */
 
532
        /* Set p */
 
533
        ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
 
534
        ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
 
535
        ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);
 
536
        /* paz4 = az^4 */
 
537
        MP_CHECKOK(mp_set_int(&pz, 5));
 
538
        mp_sqrmod(&pz, &ecgroup->meth->irr, &paz4);
 
539
        mp_sqrmod(&paz4, &ecgroup->meth->irr, &paz4);
 
540
        mp_mulmod(&paz4, &ecgroup->curvea, &ecgroup->meth->irr, &paz4);
 
541
        ecfp_i2fp(p.z, &pz, ecgroup);
 
542
        ecfp_i2fp(p.az4, &paz4, ecgroup);
 
543
 
 
544
        /* Set q */
 
545
        MP_CHECKOK(mp_set_int(&qz, 105));
 
546
        ecfp_i2fp(q.x, &ecgroup->geny, ecgroup);
 
547
        ecfp_i2fp(q.y, &ecgroup->genx, ecgroup);
 
548
        ecfp_i2fp(q.z, &qz, ecgroup);
 
549
        mp_sqrmod(&qz, &ecgroup->meth->irr, &test);
 
550
        ecfp_i2fp(q.z2, &test, ecgroup);
 
551
        mp_mulmod(&test, &qz, &ecgroup->meth->irr, &test);
 
552
        ecfp_i2fp(q.z3, &test, ecgroup);
 
553
 
 
554
        /* Do calculation */
 
555
        group->pt_add_jm_chud(&p, &q, &r, group);
 
556
 
 
557
        /* Calculate addition to compare against */
 
558
        ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy,
 
559
                                          ecgroup);
 
560
        ec_GFp_pt_add_jac_aff(&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy,
 
561
                                                  &ix, &iy, &iz, ecgroup);
 
562
        ec_GFp_pt_jac2aff(&ix, &iy, &iz, &rx2, &ry2, ecgroup);
 
563
 
 
564
        MP_CHECKOK(testJmPoint(&r, &rx2, &ry2, ecgroup));
 
565
 
 
566
  CLEANUP:
 
567
        if (res == MP_OKAY)
 
568
                printf
 
569
                        ("  Test Passed - Point Addition - Modified & Chudnovsky Jacobian\n");
 
570
        else
 
571
                printf
 
572
                        ("TEST FAILED - Point Addition - Modified & Chudnovsky Jacobian\n");
 
573
 
 
574
        mp_clear(&qx);
 
575
        mp_clear(&qy);
 
576
        mp_clear(&qz);
 
577
        mp_clear(&pz);
 
578
        mp_clear(&paz4);
 
579
        mp_clear(&rx2);
 
580
        mp_clear(&ry2);
 
581
        mp_clear(&ix);
 
582
        mp_clear(&iy);
 
583
        mp_clear(&iz);
 
584
        mp_clear(&test);
 
585
 
 
586
        return res;
 
587
}
 
588
 
 
589
/* Tests point doubling in Modified Jacobian coordinates */
 
590
mp_err
 
591
testPointDoubleJm(ECGroup *ecgroup)
 
592
{
 
593
        mp_err res;
 
594
        mp_int pz, paz4, rx2, ry2, rz2, raz4;
 
595
        ecfp_jm_pt p, r;
 
596
        EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
 
597
 
 
598
        MP_DIGITS(&pz) = 0;
 
599
        MP_DIGITS(&paz4) = 0;
 
600
        MP_DIGITS(&rx2) = 0;
 
601
        MP_DIGITS(&ry2) = 0;
 
602
        MP_DIGITS(&rz2) = 0;
 
603
        MP_DIGITS(&raz4) = 0;
 
604
 
 
605
        MP_CHECKOK(mp_init(&pz));
 
606
        MP_CHECKOK(mp_init(&paz4));
 
607
        MP_CHECKOK(mp_init(&rx2));
 
608
        MP_CHECKOK(mp_init(&ry2));
 
609
        MP_CHECKOK(mp_init(&rz2));
 
610
        MP_CHECKOK(mp_init(&raz4));
 
611
 
 
612
        /* Set p */
 
613
        ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
 
614
        ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
 
615
        ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);
 
616
 
 
617
        /* paz4 = az^4 */
 
618
        MP_CHECKOK(mp_set_int(&pz, 5));
 
619
        mp_sqrmod(&pz, &ecgroup->meth->irr, &paz4);
 
620
        mp_sqrmod(&paz4, &ecgroup->meth->irr, &paz4);
 
621
        mp_mulmod(&paz4, &ecgroup->curvea, &ecgroup->meth->irr, &paz4);
 
622
 
 
623
        ecfp_i2fp(p.z, &pz, ecgroup);
 
624
        ecfp_i2fp(p.az4, &paz4, ecgroup);
 
625
 
 
626
        group->pt_dbl_jm(&p, &r, group);
 
627
 
 
628
        M_TimeOperation(group->pt_dbl_jm(&p, &r, group), 100000);
 
629
 
 
630
        /* Calculate doubling to compare against */
 
631
        ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2,
 
632
                                          &rz2, ecgroup);
 
633
        ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup);
 
634
 
 
635
        /* Do comparison and check az^4 */
 
636
        MP_CHECKOK(testJmPoint(&r, &rx2, &ry2, ecgroup));
 
637
 
 
638
  CLEANUP:
 
639
        if (res == MP_OKAY)
 
640
                printf("  Test Passed - Point Doubling - Modified Jacobian\n");
 
641
        else
 
642
                printf("TEST FAILED - Point Doubling - Modified Jacobian\n");
 
643
        mp_clear(&pz);
 
644
        mp_clear(&paz4);
 
645
        mp_clear(&rx2);
 
646
        mp_clear(&ry2);
 
647
        mp_clear(&rz2);
 
648
        mp_clear(&raz4);
 
649
 
 
650
        return res;
 
651
 
 
652
}
 
653
 
 
654
/* Tests point doubling in Chudnovsky Jacobian coordinates */
 
655
mp_err
 
656
testPointDoubleChud(ECGroup *ecgroup)
 
657
{
 
658
        mp_err res;
 
659
        mp_int px, py, pz, rx2, ry2, rz2;
 
660
        ecfp_aff_pt p;
 
661
        ecfp_chud_pt p2;
 
662
        EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
 
663
 
 
664
        MP_DIGITS(&rx2) = 0;
 
665
        MP_DIGITS(&ry2) = 0;
 
666
        MP_DIGITS(&rz2) = 0;
 
667
        MP_DIGITS(&px) = 0;
 
668
        MP_DIGITS(&py) = 0;
 
669
        MP_DIGITS(&pz) = 0;
 
670
 
 
671
        MP_CHECKOK(mp_init(&rx2));
 
672
        MP_CHECKOK(mp_init(&ry2));
 
673
        MP_CHECKOK(mp_init(&rz2));
 
674
        MP_CHECKOK(mp_init(&px));
 
675
        MP_CHECKOK(mp_init(&py));
 
676
        MP_CHECKOK(mp_init(&pz));
 
677
 
 
678
        /* Set p2 = 2P */
 
679
        ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
 
680
        ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
 
681
        ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);
 
682
 
 
683
        group->pt_dbl_aff2chud(&p, &p2, group);
 
684
 
 
685
        /* Calculate doubling to compare against */
 
686
        MP_CHECKOK(mp_set_int(&pz, 1));
 
687
        ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2,
 
688
                                          &rz2, ecgroup);
 
689
        ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup);
 
690
 
 
691
        /* Do comparison and check az^4 */
 
692
        MP_CHECKOK(testChudPoint(&p2, &rx2, &ry2, ecgroup));
 
693
 
 
694
  CLEANUP:
 
695
        if (res == MP_OKAY)
 
696
                printf("  Test Passed - Point Doubling - Chudnovsky Jacobian\n");
 
697
        else
 
698
                printf("TEST FAILED - Point Doubling - Chudnovsky Jacobian\n");
 
699
 
 
700
        mp_clear(&rx2);
 
701
        mp_clear(&ry2);
 
702
        mp_clear(&rz2);
 
703
        mp_clear(&px);
 
704
        mp_clear(&py);
 
705
        mp_clear(&pz);
 
706
 
 
707
        return res;
 
708
}
 
709
 
 
710
/* Test point doubling in Jacobian coordinates */
 
711
mp_err
 
712
testPointDoubleJac(ECGroup *ecgroup)
 
713
{
 
714
        mp_err res;
 
715
        mp_int pz, rx, ry, rz, rx2, ry2, rz2;
 
716
        ecfp_jac_pt p, p2;
 
717
        EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
 
718
 
 
719
        MP_DIGITS(&pz) = 0;
 
720
        MP_DIGITS(&rx) = 0;
 
721
        MP_DIGITS(&ry) = 0;
 
722
        MP_DIGITS(&rz) = 0;
 
723
        MP_DIGITS(&rx2) = 0;
 
724
        MP_DIGITS(&ry2) = 0;
 
725
        MP_DIGITS(&rz2) = 0;
 
726
 
 
727
        MP_CHECKOK(mp_init(&pz));
 
728
        MP_CHECKOK(mp_init(&rx));
 
729
        MP_CHECKOK(mp_init(&ry));
 
730
        MP_CHECKOK(mp_init(&rz));
 
731
        MP_CHECKOK(mp_init(&rx2));
 
732
        MP_CHECKOK(mp_init(&ry2));
 
733
        MP_CHECKOK(mp_init(&rz2));
 
734
 
 
735
        MP_CHECKOK(mp_set_int(&pz, 5));
 
736
 
 
737
        /* Set p2 = 2P */
 
738
        ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
 
739
        ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
 
740
        ecfp_i2fp(p.z, &pz, ecgroup);
 
741
        ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);
 
742
 
 
743
        group->pt_dbl_jac(&p, &p2, group);
 
744
        M_TimeOperation(group->pt_dbl_jac(&p, &p2, group), 100000);
 
745
 
 
746
        /* Calculate doubling to compare against */
 
747
        ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2,
 
748
                                          &rz2, ecgroup);
 
749
        ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup);
 
750
 
 
751
        /* Do comparison */
 
752
        MP_CHECKOK(testJacPoint(&p2, &rx2, &ry2, ecgroup));
 
753
 
 
754
  CLEANUP:
 
755
        if (res == MP_OKAY)
 
756
                printf("  Test Passed - Point Doubling - Jacobian\n");
 
757
        else
 
758
                printf("TEST FAILED - Point Doubling - Jacobian\n");
 
759
 
 
760
        mp_clear(&pz);
 
761
        mp_clear(&rx);
 
762
        mp_clear(&ry);
 
763
        mp_clear(&rz);
 
764
        mp_clear(&rx2);
 
765
        mp_clear(&ry2);
 
766
        mp_clear(&rz2);
 
767
 
 
768
        return res;
 
769
}
 
770
 
 
771
/* Tests a point multiplication (various algorithms) */
 
772
mp_err
 
773
testPointMul(ECGroup *ecgroup)
 
774
{
 
775
        mp_err res;
 
776
        char s[1000];
 
777
        mp_int rx, ry, order_1;
 
778
 
 
779
        /* Init */
 
780
        MP_DIGITS(&rx) = 0;
 
781
        MP_DIGITS(&ry) = 0;
 
782
        MP_DIGITS(&order_1) = 0;
 
783
 
 
784
        MP_CHECKOK(mp_init(&rx));
 
785
        MP_CHECKOK(mp_init(&ry));
 
786
        MP_CHECKOK(mp_init(&order_1));
 
787
 
 
788
        MP_CHECKOK(mp_set_int(&order_1, 1));
 
789
        MP_CHECKOK(mp_sub(&ecgroup->order, &order_1, &order_1));
 
790
 
 
791
        /* Test Algorithm 1: Jacobian-Affine Double & Add */
 
792
        ec_GFp_pt_mul_jac_fp(&order_1, &ecgroup->genx, &ecgroup->geny, &rx,
 
793
                                                 &ry, ecgroup);
 
794
        MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth));
 
795
        if ((mp_cmp(&rx, &ecgroup->genx) != 0)
 
796
                || (mp_cmp(&ry, &ecgroup->geny) != 0)) {
 
797
                printf
 
798
                        ("  Error: ec_GFp_pt_mul_jac_fp invalid result (expected (- base point)).\n");
 
799
                MP_CHECKOK(mp_toradix(&rx, s, 16));
 
800
                printf("rx   %s\n", s);
 
801
                MP_CHECKOK(mp_toradix(&ry, s, 16));
 
802
                printf("ry   %s\n", s);
 
803
                res = MP_NO;
 
804
                goto CLEANUP;
 
805
        }
 
806
 
 
807
        ec_GFp_pt_mul_jac_fp(&ecgroup->order, &ecgroup->genx, &ecgroup->geny,
 
808
                                                 &rx, &ry, ecgroup);
 
809
        if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
 
810
                printf
 
811
                        ("  Error: ec_GFp_pt_mul_jac_fp invalid result (expected point at infinity.\n");
 
812
                MP_CHECKOK(mp_toradix(&rx, s, 16));
 
813
                printf("rx   %s\n", s);
 
814
                MP_CHECKOK(mp_toradix(&ry, s, 16));
 
815
                printf("ry   %s\n", s);
 
816
                res = MP_NO;
 
817
                goto CLEANUP;
 
818
        }
 
819
 
 
820
        /* Test Algorithm 2: 4-bit Window in Jacobian */
 
821
        ec_GFp_point_mul_jac_4w_fp(&order_1, &ecgroup->genx, &ecgroup->geny,
 
822
                                                           &rx, &ry, ecgroup);
 
823
        MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth));
 
824
        if ((mp_cmp(&rx, &ecgroup->genx) != 0)
 
825
                || (mp_cmp(&ry, &ecgroup->geny) != 0)) {
 
826
                printf
 
827
                        ("  Error: ec_GFp_point_mul_jac_4w_fp invalid result (expected (- base point)).\n");
 
828
                MP_CHECKOK(mp_toradix(&rx, s, 16));
 
829
                printf("rx   %s\n", s);
 
830
                MP_CHECKOK(mp_toradix(&ry, s, 16));
 
831
                printf("ry   %s\n", s);
 
832
                res = MP_NO;
 
833
                goto CLEANUP;
 
834
        }
 
835
 
 
836
        ec_GFp_point_mul_jac_4w_fp(&ecgroup->order, &ecgroup->genx,
 
837
                                                           &ecgroup->geny, &rx, &ry, ecgroup);
 
838
        if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
 
839
                printf
 
840
                        ("  Error: ec_GFp_point_mul_jac_4w_fp invalid result (expected point at infinity.\n");
 
841
                MP_CHECKOK(mp_toradix(&rx, s, 16));
 
842
                printf("rx   %s\n", s);
 
843
                MP_CHECKOK(mp_toradix(&ry, s, 16));
 
844
                printf("ry   %s\n", s);
 
845
                res = MP_NO;
 
846
                goto CLEANUP;
 
847
        }
 
848
 
 
849
        /* Test Algorithm 3: wNAF with modified Jacobian coordinates */
 
850
        ec_GFp_point_mul_wNAF_fp(&order_1, &ecgroup->genx, &ecgroup->geny, &rx,
 
851
                                                         &ry, ecgroup);
 
852
        MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth));
 
853
        if ((mp_cmp(&rx, &ecgroup->genx) != 0)
 
854
                || (mp_cmp(&ry, &ecgroup->geny) != 0)) {
 
855
                printf
 
856
                        ("  Error: ec_GFp_pt_mul_wNAF_fp invalid result (expected (- base point)).\n");
 
857
                MP_CHECKOK(mp_toradix(&rx, s, 16));
 
858
                printf("rx   %s\n", s);
 
859
                MP_CHECKOK(mp_toradix(&ry, s, 16));
 
860
                printf("ry   %s\n", s);
 
861
                res = MP_NO;
 
862
                goto CLEANUP;
 
863
        }
 
864
 
 
865
        ec_GFp_point_mul_wNAF_fp(&ecgroup->order, &ecgroup->genx,
 
866
                                                         &ecgroup->geny, &rx, &ry, ecgroup);
 
867
        if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
 
868
                printf
 
869
                        ("  Error: ec_GFp_pt_mul_wNAF_fp invalid result (expected point at infinity.\n");
 
870
                MP_CHECKOK(mp_toradix(&rx, s, 16));
 
871
                printf("rx   %s\n", s);
 
872
                MP_CHECKOK(mp_toradix(&ry, s, 16));
 
873
                printf("ry   %s\n", s);
 
874
                res = MP_NO;
 
875
                goto CLEANUP;
 
876
        }
 
877
 
 
878
  CLEANUP:
 
879
        if (res == MP_OKAY)
 
880
                printf("  Test Passed - Point Multiplication\n");
 
881
        else
 
882
                printf("TEST FAILED - Point Multiplication\n");
 
883
        mp_clear(&rx);
 
884
        mp_clear(&ry);
 
885
        mp_clear(&order_1);
 
886
 
 
887
        return res;
 
888
}
 
889
 
 
890
/* Tests point multiplication with a random scalar repeatedly, comparing
 
891
 * for consistency within different algorithms. */
 
892
mp_err
 
893
testPointMulRandom(ECGroup *ecgroup)
 
894
{
 
895
        mp_err res;
 
896
        mp_int rx, ry, rx2, ry2, n;
 
897
        int i, size;
 
898
        EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
 
899
 
 
900
        MP_DIGITS(&rx) = 0;
 
901
        MP_DIGITS(&ry) = 0;
 
902
        MP_DIGITS(&rx2) = 0;
 
903
        MP_DIGITS(&ry2) = 0;
 
904
        MP_DIGITS(&n) = 0;
 
905
 
 
906
        MP_CHECKOK(mp_init(&rx));
 
907
        MP_CHECKOK(mp_init(&ry));
 
908
        MP_CHECKOK(mp_init(&rx2));
 
909
        MP_CHECKOK(mp_init(&ry2));
 
910
        MP_CHECKOK(mp_init(&n));
 
911
 
 
912
        for (i = 0; i < 100; i++) {
 
913
                /* compute random scalar */
 
914
                size = mpl_significant_bits(&ecgroup->meth->irr);
 
915
                if (size < MP_OKAY) {
 
916
                        res = MP_NO;
 
917
                        goto CLEANUP;
 
918
                }
 
919
                MP_CHECKOK(mpp_random_size(&n, group->orderBitSize));
 
920
                MP_CHECKOK(mp_mod(&n, &ecgroup->order, &n));
 
921
 
 
922
                ec_GFp_pt_mul_jac(&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry,
 
923
                                                  ecgroup);
 
924
                ec_GFp_pt_mul_jac_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx2,
 
925
                                                         &ry2, ecgroup);
 
926
 
 
927
                if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) {
 
928
                        printf
 
929
                                ("  Error: different results for Point Multiplication - Double & Add.\n");
 
930
                        res = MP_NO;
 
931
                        goto CLEANUP;
 
932
                }
 
933
 
 
934
                ec_GFp_point_mul_wNAF_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx,
 
935
                                                                 &ry, ecgroup);
 
936
                if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) {
 
937
                        printf
 
938
                                ("  Error: different results for Point Multiplication - wNAF.\n");
 
939
                        res = MP_NO;
 
940
                        goto CLEANUP;
 
941
                }
 
942
 
 
943
                ec_GFp_point_mul_jac_4w_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx,
 
944
                                                                   &ry, ecgroup);
 
945
                if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) {
 
946
                        printf
 
947
                                ("  Error: different results for Point Multiplication - 4 bit window.\n");
 
948
                        res = MP_NO;
 
949
                        goto CLEANUP;
 
950
                }
 
951
 
 
952
        }
 
953
 
 
954
  CLEANUP:
 
955
        if (res == MP_OKAY)
 
956
                printf("  Test Passed - Point Random Multiplication\n");
 
957
        else
 
958
                printf("TEST FAILED - Point Random Multiplication\n");
 
959
        mp_clear(&rx);
 
960
        mp_clear(&ry);
 
961
        mp_clear(&rx2);
 
962
        mp_clear(&ry2);
 
963
        mp_clear(&n);
 
964
 
 
965
        return res;
 
966
}
 
967
 
 
968
/* Tests the time required for a point multiplication */
 
969
mp_err
 
970
testPointMulTime(ECGroup *ecgroup)
 
971
{
 
972
        mp_err res = MP_OKAY;
 
973
        mp_int rx, ry, n;
 
974
        int size;
 
975
 
 
976
        MP_DIGITS(&rx) = 0;
 
977
        MP_DIGITS(&ry) = 0;
 
978
        MP_DIGITS(&n) = 0;
 
979
 
 
980
        MP_CHECKOK(mp_init(&rx));
 
981
        MP_CHECKOK(mp_init(&ry));
 
982
        MP_CHECKOK(mp_init(&n));
 
983
 
 
984
        /* compute random scalar */
 
985
        size = mpl_significant_bits(&ecgroup->meth->irr);
 
986
        if (size < MP_OKAY) {
 
987
                res = MP_NO;
 
988
                goto CLEANUP;
 
989
        }
 
990
 
 
991
        MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS));
 
992
        MP_CHECKOK(ecgroup->meth->field_mod(&n, &n, ecgroup->meth));
 
993
 
 
994
        M_TimeOperation(ec_GFp_pt_mul_jac_fp
 
995
                                        (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry,
 
996
                                         ecgroup), 1000);
 
997
 
 
998
        M_TimeOperation(ec_GFp_point_mul_jac_4w_fp
 
999
                                        (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry,
 
1000
                                         ecgroup), 1000);
 
1001
 
 
1002
        M_TimeOperation(ec_GFp_point_mul_wNAF_fp
 
1003
                                        (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry,
 
1004
                                         ecgroup), 1000);
 
1005
 
 
1006
        M_TimeOperation(ec_GFp_pt_mul_jac
 
1007
                                        (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry,
 
1008
                                         ecgroup), 100);
 
1009
 
 
1010
  CLEANUP:
 
1011
        if (res == MP_OKAY)
 
1012
                printf("  Test Passed - Point Multiplication Timing\n");
 
1013
        else
 
1014
                printf("TEST FAILED - Point Multiplication Timing\n");
 
1015
        mp_clear(&rx);
 
1016
        mp_clear(&ry);
 
1017
        mp_clear(&n);
 
1018
 
 
1019
        return res;
 
1020
}
 
1021
 
 
1022
/* Tests pre computation of Chudnovsky Jacobian points used in wNAF form */
 
1023
mp_err
 
1024
testPreCompute(ECGroup *ecgroup)
 
1025
{
 
1026
        ecfp_chud_pt precomp[16];
 
1027
        ecfp_aff_pt p;
 
1028
        EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
 
1029
        int i;
 
1030
        mp_err res;
 
1031
 
 
1032
        mp_int x, y, ny, x2, y2;
 
1033
 
 
1034
        MP_DIGITS(&x) = 0;
 
1035
        MP_DIGITS(&y) = 0;
 
1036
        MP_DIGITS(&ny) = 0;
 
1037
        MP_DIGITS(&x2) = 0;
 
1038
        MP_DIGITS(&y2) = 0;
 
1039
 
 
1040
        MP_CHECKOK(mp_init(&x));
 
1041
        MP_CHECKOK(mp_init(&y));
 
1042
        MP_CHECKOK(mp_init(&ny));
 
1043
        MP_CHECKOK(mp_init(&x2));
 
1044
        MP_CHECKOK(mp_init(&y2));
 
1045
 
 
1046
        ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
 
1047
        ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
 
1048
        ecfp_i2fp(group->curvea, &(ecgroup->curvea), ecgroup);
 
1049
 
 
1050
        /* Perform precomputation */
 
1051
        group->precompute_chud(precomp, &p, group);
 
1052
 
 
1053
        M_TimeOperation(group->precompute_chud(precomp, &p, group), 10000);
 
1054
 
 
1055
        /* Calculate addition to compare against */
 
1056
        MP_CHECKOK(mp_copy(&ecgroup->genx, &x));
 
1057
        MP_CHECKOK(mp_copy(&ecgroup->geny, &y));
 
1058
        MP_CHECKOK(ecgroup->meth->field_neg(&y, &ny, ecgroup->meth));
 
1059
 
 
1060
        ec_GFp_pt_dbl_aff(&x, &y, &x2, &y2, ecgroup);
 
1061
 
 
1062
        for (i = 0; i < 8; i++) {
 
1063
                MP_CHECKOK(testChudPoint(&precomp[8 + i], &x, &y, ecgroup));
 
1064
                MP_CHECKOK(testChudPoint(&precomp[7 - i], &x, &ny, ecgroup));
 
1065
                ec_GFp_pt_add_aff(&x, &y, &x2, &y2, &x, &y, ecgroup);
 
1066
                MP_CHECKOK(ecgroup->meth->field_neg(&y, &ny, ecgroup->meth));
 
1067
        }
 
1068
 
 
1069
  CLEANUP:
 
1070
        if (res == MP_OKAY)
 
1071
                printf("  Test Passed - Precomputation\n");
 
1072
        else
 
1073
                printf("TEST FAILED - Precomputation\n");
 
1074
 
 
1075
        mp_clear(&x);
 
1076
        mp_clear(&y);
 
1077
        mp_clear(&ny);
 
1078
        mp_clear(&x2);
 
1079
        mp_clear(&y2);
 
1080
        return res;
 
1081
}
 
1082
 
 
1083
/* Given a curve using floating point arithmetic, test it. This method
 
1084
 * specifies which of the above tests to run. */
 
1085
mp_err
 
1086
testCurve(ECGroup *ecgroup)
 
1087
{
 
1088
        int res = MP_OKAY;
 
1089
 
 
1090
        MP_CHECKOK(testPointAddJacAff(ecgroup));
 
1091
        MP_CHECKOK(testPointAddJac(ecgroup));
 
1092
        MP_CHECKOK(testPointAddChud(ecgroup));
 
1093
        MP_CHECKOK(testPointAddJmChud(ecgroup));
 
1094
        MP_CHECKOK(testPointDoubleJac(ecgroup));
 
1095
        MP_CHECKOK(testPointDoubleChud(ecgroup));
 
1096
        MP_CHECKOK(testPointDoubleJm(ecgroup));
 
1097
        MP_CHECKOK(testPreCompute(ecgroup));
 
1098
        MP_CHECKOK(testPointMul(ecgroup));
 
1099
        MP_CHECKOK(testPointMulRandom(ecgroup));
 
1100
        MP_CHECKOK(testPointMulTime(ecgroup));
 
1101
  CLEANUP:
 
1102
        return res;
 
1103
}
 
1104
 
 
1105
/* Tests a number of curves optimized using floating point arithmetic */
 
1106
int
 
1107
main(void)
 
1108
{
 
1109
        mp_err res = MP_OKAY;
 
1110
        ECGroup *ecgroup = NULL;
 
1111
 
 
1112
        /* specific arithmetic tests */
 
1113
        M_TestCurve("SECG-160R1", ECCurve_SECG_PRIME_160R1);
 
1114
        M_TestCurve("SECG-192R1", ECCurve_SECG_PRIME_192R1);
 
1115
        M_TestCurve("SEGC-224R1", ECCurve_SECG_PRIME_224R1);
 
1116
 
 
1117
  CLEANUP:
 
1118
        ECGroup_free(ecgroup);
 
1119
        if (res != MP_OKAY) {
 
1120
                printf("Error: exiting with error value %i\n", res);
 
1121
        }
 
1122
        return res;
 
1123
}