]> git.saurik.com Git - apple/security.git/blob - libsecurity_cryptkit/lib/elliptic.c
Security-55178.0.1.tar.gz
[apple/security.git] / libsecurity_cryptkit / lib / elliptic.c
1 /* Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
2 *
3 * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT
4 * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE
5 * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE
6 * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER,
7 * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL
8 * EXPOSE YOU TO LIABILITY.
9 ***************************************************************************
10
11 elliptic.c - Library for Apple-proprietary Fast Elliptic
12 Encryption. The algebra in this module ignores elliptic point's
13 y-coordinates.
14
15 Patent information:
16
17 FEE is patented, U.S. Patents #5159632 (1992), #5271061 (1993),
18 #5463690 (1994). These patents are implemented
19 in various elliptic algebra functions such as
20 numer/denom_plus/times(), and in the fact of special
21 forms for primes: p = 2^q-k.
22
23 Digital signature using fast elliptic addition, in
24 U. S. Patent #5581616 (1996), is implemented in the
25 signature_compare() function.
26
27 FEED (Fast Elliptic Encryption) is patent pending (as of Jan 1998).
28 Various functions such as elliptic_add() implement the patent ideas.
29
30
31 Modification history since the U.S. Patent:
32 -------------------------------------------
33 10/06/98 ap
34 Changed to compile with C++.
35 9 Sep 98 Doug Mitchell at Apple
36 cp->curveType optimizations.
37 Removed code which handled "unknown" curve orders.
38 elliptic() now exported for timing measurements.
39 21 Apr 98 Doug Mitchell at Apple
40 Used inline platform-dependent giant arithmetic.
41 20 Jan 98 Doug Mitchell at Apple
42 feemod now handles PT_MERSENNE, PT_FEE, PT_GENERAL.
43 Added calcGiantSizes(), rewrote giantMinBytes(), giantMaxShorts().
44 Updated heading comments on FEE curve algebra.
45 11 Jan 98 Doug Mitchell and Richard Crandall at Apple
46 Microscopic feemod optimization.
47 10 Jan 98 Doug Mitchell and Richard Crandall at Apple
48 ell_odd, ell_even() Montgomery optimization.
49 09 Jan 98 Doug Mitchell and Richard Crandall at Apple
50 ell_odd, ell_even() Atkin3 optimization.
51 08 Jan 97 Doug Mitchell at Apple
52 Cleaned up some debugging code; added gsquareTime
53 11 Jun 97 Doug Mitchell and Richard Crandall at Apple
54 Mods for modg_via_recip(), divg_via_recip() math
55 Deleted a lot of obsolete code (previously ifdef'd out)
56 Added lesserX1OrderJustify(), x1OrderPlusJustify()
57 Added binvg_cp(), avoiding general modg in favor of feemod
58 05 Feb 97 Doug Mitchell and Richard Crandall at Apple
59 New optimized numer_plus(), denom_double(), and numer_times()
60 All calls to borrowGiant() and newGiant have explicit giant size
61 08 Jan 97 Doug Mitchell and Richard Crandall at NeXT
62 Major mods to accomodate IEEE-style curve parameters.
63 New functions feepowermodg() and curveOrderJustify();
64 elliptic_add(), elliptic(), signature_compare(), and
65 which_curve() completely rewritten.
66 19 Dec 96 Doug Mitchell at NeXT
67 Added mersennePrimes[24..26]
68 08 Aug 96 Doug Mitchell at NeXT
69 Fixed giant leak in elliptic_add()
70 05 Aug 96 Doug Mitchell at NeXT
71 Removed dead code
72 24 Jul 96 Doug Mitchell at NeXT
73 Added ENGINE_127_BITS dependency for use of security engine
74 24 Oct 92 Richard Crandall at NeXT
75 Modified new_public_from_private()
76 1991 Richard Crandall at NeXT
77 Created.
78
79
80 FEE curve algebra, Jan 1997.
81
82 Curves are:
83
84 y^2 = x^3 + c x^2 + a x + b
85
86 where useful parameterizations for practical purposes are:
87
88 Montgomery: a = 1, b = 0. (The original 1991 FEE system.)
89 Weierstrass: c = 0. (The basic IEEE form.)
90 Atkin3: c = a = 0.
91 Atkin4: c = b = 0.
92
93 However, the code is set up to work with any a, b, c.
94 The underlying fields F_{p^m} are of odd characteristic,
95 with all operations are (mod p). The special FEE-class
96 primes p are of the form:
97
98 p = 2^q - k = 3 (mod 4)
99
100 where k is single-precision. For such p, the mod operations
101 are especially fast (asymptotically vanishing time with respect
102 to a multiply). Note that the whole system
103 works equally well (except for slower execution) for arbitrary
104 primes p = 3 (mod 4) of the same bit length (q or q+1).
105
106 The elliptic arithmetic now proceeds on the basis of
107 five fundamental operations that calculate various
108 numerator/denominator parts of the elliptic terms:
109
110 numer_double(giant x, giant z, giant res, curveParams *par)
111 res := (x^2 - a z^2)^2 - 4 b (2 x + c z) z^3.
112
113 numer_plus(giant x1, giant x2, giant res, curveParams *par)
114 res = (x1 x2 + a)(x1 + x2) + 2(c x1 x2 + b).
115
116 denom_double(giant x, giant z, giant res, curveParams *par)
117 res = 4 z (x^3 + c x^2 z + a x z^2 + b z^3).
118
119 denom_times(giant x1, giant z1, giant x2, giant z2, giant res,
120 curveParams *par)
121 res := (x1 z2 - x2 z1)^2
122
123 numer_times(giant x1, giant z1, giant x2, giant z2, giant res,
124 curveParams *par)
125 res := (x1 x2 - a z1 z2)^2 - 4 b(x1 z2 + x2 z1 + c z1 z2) z1 z2
126
127 If x(+-) represent the sum and difference x-coordinates
128 respectively, then, in pseudocode,
129
130 For unequal starting coords:
131 x(+) + x(-) = U = 2 numer_plus/denom_times
132 x(+) x(-) = V = numer_times/denom_times
133
134 and for equal starting coords:
135 x(+) = numer_double/denom_double
136
137 The elliptic_add() function uses the fact that
138
139 x(+) = U/2 + s*Sqrt[U^2/4 - V]
140
141 where the sign s = +-1.
142
143 */
144
145 #include "ckconfig.h"
146 #include <stdio.h>
147 #include <stdlib.h>
148 #include <string.h>
149 #include "platform.h"
150
151 #include "giantIntegers.h"
152 #include "elliptic.h"
153 #include "ellipticProj.h"
154 #include "ckutilities.h"
155 #include "curveParams.h"
156 #include "feeDebug.h"
157 #include "ellipticMeasure.h"
158 #include "falloc.h"
159 #include "giantPortCommon.h"
160
161 #if FEE_PROFILE
162
163 unsigned numerDoubleTime;
164 unsigned numerPlusTime;
165 unsigned numerTimesTime;
166 unsigned denomDoubleTime;
167 unsigned denomTimesTime;
168 unsigned ellipticTime;
169 unsigned sigCompTime;
170 unsigned powerModTime;
171 unsigned ellAddTime;
172 unsigned whichCurveTime;
173 unsigned modgTime;
174 unsigned mulgTime;
175 unsigned binvauxTime;
176 unsigned gsquareTime;
177
178 unsigned numMulg;
179 unsigned numFeemod;
180 unsigned numGsquare;
181 unsigned numBorrows;
182
183 void clearProfile()
184 {
185 numerDoubleTime = 0;
186 numerPlusTime = 0;
187 numerTimesTime = 0;
188 denomDoubleTime = 0;
189 denomTimesTime = 0;
190 ellipticTime = 0;
191 sigCompTime = 0;
192 powerModTime = 0;
193 ellAddTime = 0;
194 whichCurveTime = 0;
195 modgTime = 0;
196 mulgTime = 0;
197 binvauxTime = 0;
198 gsquareTime = 0;
199 numMulg = 0;
200 numFeemod = 0;
201 numGsquare = 0;
202 numBorrows = 0;
203 }
204
205 #endif // FEE_PROFILE
206
207 #if ELL_PROFILE
208 unsigned ellOddTime;
209 unsigned ellEvenTime;
210 unsigned numEllOdds;
211 unsigned numEllEvens;
212
213 void clearEllProfile()
214 {
215 ellOddTime = 0;
216 ellEvenTime = 0;
217 numEllOdds = 0;
218 numEllEvens = 0;
219 }
220
221 #endif /* ELL_PROFILE */
222 #if ELLIPTIC_MEASURE
223
224 int doEllMeasure; // gather stats on/off */
225 int bitsInN;
226 int numFeeMods;
227 int numMulgs;
228
229 void dumpEll()
230 {
231 printf("\nbitlen(n) : %d\n", bitsInN);
232 printf("feemods : %d\n", numFeeMods);
233 printf("mulgs : %d\n", numMulgs);
234 }
235
236 #endif // ELLIPTIC_MEASURE
237
238 /********** Globals ********************************/
239
240 static void make_base(curveParams *par, giant result); // result = with 2^q-k
241 static int keys_inconsistent(key pub1, key pub2);
242 /* Return non-zero if pub1, pub2 have inconsistent parameters.
243 */
244
245
246 static void ell_even(giant x1, giant z1, giant x2, giant z2, curveParams *par);
247 static void ell_odd(giant x1, giant z1, giant x2, giant z2, giant xxor,
248 giant zor, curveParams *par);
249 static void numer_double(giant x, giant z, giant res, curveParams *par);
250 static void numer_plus(giant x1, giant x2, giant res, curveParams *par);
251 static void denom_double(giant x, giant z, giant res, curveParams *par);
252 static void denom_times(giant x1, giant z1, giant x2, giant z2, giant res,
253 curveParams *par);
254 static void numer_times(giant x1, giant z1, giant x2, giant z2, giant res,
255 curveParams *par);
256 static void feepowermodg(curveParams *par, giant x, giant n);
257 static void curveOrderJustifyWithRecip(giant g, giant curveOrder, giant recip);
258
259 /*
260 * Completely rewritten in CryptKit-18, 13 Jan 1997, for new IEEE-style
261 * curveParameters.
262 */
263 int which_curve(giant x, curveParams *par)
264 /* Returns (+-1) depending on whether x is on curve
265 (+-)y^2 = x^3 + c x^2 + a x + b.
266 */
267 {
268 giant t1;
269 giant t2;
270 giant t3;
271 int result;
272 PROF_START;
273
274 t1 = borrowGiant(par->maxDigits);
275 t2 = borrowGiant(par->maxDigits);
276 t3 = borrowGiant(par->maxDigits);
277
278 /* First, set t2:= x^3 + c x^2 + a x + b. */
279 gtog(x, t2); addg(par->c, t2);
280 mulg(x, t2); addg(par->a, t2); /* t2 := x^2 + c x + a. */
281 feemod(par, t2);
282 mulg(x, t2); addg(par->b, t2);
283 feemod(par, t2);
284 /* Next, test whether t2 is a square. */
285 gtog(t2, t1);
286 make_base(par, t3); iaddg(1, t3); gshiftright(1, t3); /* t3 = (p+1)/2. */
287 feepowermodg(par, t1, t3); /* t1 := t2^((p+1)/2) (mod p). */
288 if(gcompg(t1, t2) == 0)
289 result = CURVE_PLUS;
290 else
291 result = CURVE_MINUS;
292 returnGiant(t1);
293 returnGiant(t2);
294 returnGiant(t3);
295 PROF_END(whichCurveTime);
296 return result;
297 }
298
299 key new_public(curveParams *cp, int twist) {
300 key k;
301
302 k = (key) fmalloc(sizeof(keystruct));
303 k->cp = cp;
304 k->twist = twist;
305
306 k->x = newGiant(cp->maxDigits);
307 if((twist == CURVE_PLUS) && (cp->curveType == FCT_Weierstrass)) {
308 k->y = newGiant(cp->maxDigits);
309 }
310 else {
311 /*
312 * no projective algebra. We could optimize and save a few bytes
313 * here by setting y to NULL, but that really complicates things
314 * in may other places. Best to have a real giant.
315 */
316 k->y = newGiant(1);
317 }
318 return(k);
319 }
320
321 key new_public_with_key(key old_key, curveParams *cp)
322 {
323 key result;
324
325 result = new_public(cp, old_key->twist);
326 CKASSERT((old_key->x != NULL) && (old_key->y != NULL));
327 CKASSERT((result->x != NULL) && (result->y != NULL));
328 gtog(old_key->x, result->x);
329 gtog(old_key->y, result->y);
330 return result;
331 }
332
333 void free_key(key pub) {
334 if(!pub) {
335 return;
336 }
337 if (pub->x) {
338 freeGiant(pub->x);
339 }
340 if (pub->y) {
341 freeGiant(pub->y);
342 }
343 ffree(pub);
344 }
345
346 /*
347 * Specify private data for key created by new_public().
348 * Generates k->x.
349 */
350 void set_priv_key_giant(key k, giant privGiant)
351 {
352 curveParams *cp = k->cp;
353
354 /* elliptiy multiply of initial public point times private key */
355 #if CRYPTKIT_ELL_PROJ_ENABLE
356 if((k->twist == CURVE_PLUS) && (cp->curveType == FCT_Weierstrass)) {
357 /* projective */
358
359 pointProj pt1 = newPointProj(cp->maxDigits);
360
361 CKASSERT((cp->y1Plus != NULL) && (!isZero(cp->y1Plus)));
362 CKASSERT(k->y != NULL);
363
364 /* pt1 := {x1Plus, y1Plus, 1} */
365 gtog(cp->x1Plus, pt1->x);
366 gtog(cp->y1Plus, pt1->y);
367 int_to_giant(1, pt1->z);
368
369 /* pt1 := pt1 * privateKey */
370 ellMulProjSimple(pt1, privGiant, cp);
371
372 /* result back to {k->x, k->y} */
373 gtog(pt1->x, k->x);
374 gtog(pt1->y, k->y);
375 freePointProj(pt1); // FIXME - clear the giants
376 }
377 else {
378 #else
379 {
380 #endif /* CRYPTKIT_ELL_PROJ_ENABLE */
381 /* FEE */
382 if(k->twist == CURVE_PLUS) {
383 gtog(cp->x1Plus, k->x);
384 }
385 else {
386 gtog(cp->x1Minus, k->x);
387 }
388 elliptic_simple(k->x, privGiant, k->cp);
389 }
390 }
391
392 int key_equal(key one, key two) {
393 if (keys_inconsistent(one, two)) return 0;
394 return !gcompg(one->x, two->x);
395 }
396
397 static void make_base(curveParams *par, giant result)
398 /* Jams result with 2^q-k. */
399 {
400 gtog(par->basePrime, result);
401 }
402
403 void make_base_prim(curveParams *cp)
404 /* Jams cp->basePrime with 2^q-k. Assumes valid maxDigits, q, k. */
405 {
406 giant tmp = borrowGiant(cp->maxDigits);
407
408 CKASSERT(cp->primeType != FPT_General);
409 int_to_giant(1, cp->basePrime);
410 gshiftleft((int)cp->q, cp->basePrime);
411 int_to_giant(cp->k, tmp);
412 subg(tmp, cp->basePrime);
413 returnGiant(tmp);
414 }
415
416 static int sequalg(int n, giant g) {
417 if((g->sign == 1) && (g->n[0] == n)) return(1);
418 return(0);
419 }
420
421
422 /*
423 * Elliptic multiply: x := n * {x, 1}
424 */
425 void elliptic_simple(giant x, giant n, curveParams *par) {
426 giant ztmp = borrowGiant(par->maxDigits);
427 giant cur_n = borrowGiant(par->maxDigits);
428
429 START_ELL_MEASURE(n);
430 int_to_giant(1, ztmp);
431 elliptic(x, ztmp, n, par);
432 binvg_cp(par, ztmp);
433 mulg(ztmp, x);
434 feemod(par, x);
435 END_ELL_MEASURE;
436
437 returnGiant(cur_n);
438 returnGiant(ztmp);
439 }
440
441 /*
442 * General elliptic multiply.
443 *
444 * {xx, zz} := k * {xx, zz}
445 */
446 void elliptic(giant xx, giant zz, giant k, curveParams *par) {
447 int len = bitlen(k);
448 int pos = len - 2;
449 giant xs;
450 giant zs;
451 giant xorg;
452 giant zorg;
453
454 PROF_START;
455 if(sequalg(1,k)) return;
456 if(sequalg(2,k)) {
457 ell_even(xx, zz, xx, zz, par);
458 goto out;
459 }
460 zs = borrowGiant(par->maxDigits);
461 xs = borrowGiant(par->maxDigits);
462 zorg = borrowGiant(par->maxDigits);
463 xorg = borrowGiant(par->maxDigits);
464 gtog(xx, xorg); gtog(zz, zorg);
465 ell_even(xx, zz, xs, zs, par);
466 do {
467 if(bitval(k, pos--)) {
468 ell_odd(xs, zs, xx, zz, xorg, zorg, par);
469 ell_even(xs, zs, xs, zs, par);
470 } else {
471 ell_odd(xx, zz, xs, zs, xorg, zorg, par);
472 ell_even(xx, zz, xx, zz, par);
473 }
474 } while (pos >= 0); // REC fix 9/23/94
475 returnGiant(xs);
476 returnGiant(zs);
477 returnGiant(xorg);
478 returnGiant(zorg);
479 out:
480 PROF_END(ellipticTime);
481 }
482
483 /*
484 * Completely rewritten in CryptKit-18, 13 Jan 1997, for new IEEE-style
485 * curveParameters.
486 */
487 void elliptic_add(giant x1, giant x2, giant x3, curveParams *par, int s) {
488
489 /* Addition algorithm for x3 = x1 + x2 on the curve, with sign ambiguity s.
490 From theory, we know that if {x1,1} and {x2,1} are on a curve, then
491 their elliptic sum (x1,1} + {x2,1} = {x3,1} must have x3 as one of two
492 values:
493
494 x3 = U/2 + s*Sqrt[U^2/4 - V]
495
496 where sign s = +-1, and U,V are functions of x1,x2. Tho present function
497 is called a maximum of twice, to settle which of +- is s. When a call
498 is made, it is guaranteed already that x1, x2 both lie on the same curve
499 (+- curve); i.e., which curve (+-) is not connected at all with sign s of
500 the x3 relation.
501 */
502
503 giant cur_n;
504 giant t1;
505 giant t2;
506 giant t3;
507 giant t4;
508 giant t5;
509
510 PROF_START;
511 cur_n = borrowGiant(par->maxDigits);
512 t1 = borrowGiant(par->maxDigits);
513 t2 = borrowGiant(par->maxDigits);
514 t3 = borrowGiant(par->maxDigits);
515 t4 = borrowGiant(par->maxDigits);
516 t5 = borrowGiant(par->maxDigits);
517
518 if(gcompg(x1, x2)==0) {
519 int_to_giant(1, t1);
520 numer_double(x1, t1, x3, par);
521 denom_double(x1, t1, t2, par);
522 binvg_cp(par, t2);
523 mulg(t2, x3); feemod(par, x3);
524 goto out;
525 }
526 numer_plus(x1, x2, t1, par);
527 int_to_giant(1, t3);
528 numer_times(x1, t3, x2, t3, t2, par);
529 int_to_giant(1, t4); int_to_giant(1, t5);
530 denom_times(x1, t4, x2, t5, t3, par);
531 binvg_cp(par, t3);
532 mulg(t3, t1); feemod(par, t1); /* t1 := U/2. */
533 mulg(t3, t2); feemod(par, t2); /* t2 := V. */
534 /* Now x3 will be t1 +- Sqrt[t1^2 - t2]. */
535 gtog(t1, t4); gsquare(t4); feemod(par, t4);
536 subg(t2, t4);
537 make_base(par, cur_n); iaddg(1, cur_n); gshiftright(2, cur_n);
538 /* cur_n := (p+1)/4. */
539 feepowermodg(par, t4, cur_n); /* t4 := t2^((p+1)/4) (mod p). */
540 gtog(t1, x3);
541 if(s != SIGN_PLUS) negg(t4);
542 addg(t4, x3);
543 feemod(par, x3);
544
545 out:
546 returnGiant(cur_n);
547 returnGiant(t1);
548 returnGiant(t2);
549 returnGiant(t3);
550 returnGiant(t4);
551 returnGiant(t5);
552
553 PROF_END(ellAddTime);
554 }
555
556 /*
557 * Key exchange atom.
558 */
559 giant make_pad(giant privGiant, key publicKey) {
560 curveParams *par = publicKey->cp;
561 giant result = newGiant(par->maxDigits);
562
563 gtog(publicKey->x, result);
564 elliptic_simple(result, privGiant, par);
565 return result;
566 }
567
568 static void ell_even(giant x1, giant z1, giant x2, giant z2, curveParams *par) {
569 giant t1;
570 giant t2;
571 giant t3;
572
573 EPROF_START;
574
575 t1 = borrowGiant(par->maxDigits);
576 t2 = borrowGiant(par->maxDigits);
577 t3 = borrowGiant(par->maxDigits);
578
579 if(par->curveType == FCT_Montgomery) {
580 /* Begin Montgomery OPT: 10 Jan 98 REC. */
581 gtog(x1, t1); gsquare(t1); feemod(par, t1); /* t1 := x1^2. */
582 gtog(z1, t2); gsquare(t2); feemod(par, t2); /* t2 := z1^2. */
583
584 gtog(x1, t3); mulg(z1, t3); feemod(par, t3);
585 gtog(t3, z2); mulg(par->c, z2); feemod(par, z2);
586 addg(t1, z2); addg(t2, z2); mulg(t3, z2); gshiftleft(2, z2);
587 feemod(par, z2); /* z2 := 4 x1 z1 (x1^2 + c x1 z1 + z1^2). */
588 gtog(t1, x2); subg(t2, x2); gsquare(x2); feemod(par, x2);
589 /* x2 := (x1^2 - z1^2)^2. */
590 /* End OPT: 10 Jan 98 REC. */
591 }
592 else if((par->curveType == FCT_Weierstrass) && isZero(par->a)) {
593 /* Begin Atkin3 OPT: 9 Jan 98 REC. */
594 gtog(x1, t1);
595 gsquare(t1); feemod(par, t1);
596 mulg(x1, t1); feemod(par, t1); /* t1 := x^3. */
597 gtog(z1, t2);
598 gsquare(t2); feemod(par, t2);
599 mulg(z1, t2); feemod(par, t2); /* t2 := z1^3 */
600 mulg(par->b, t2); feemod(par, t2); /* t2 := b z1^3. */
601 gtog(t1, t3); addg(t2, t3); /* t3 := x^3 + b z1^3 */
602 mulg(z1, t3); feemod(par, t3); /* t3 *= z1
603 * = z1 ( x^3 + b z1^3 ) */
604 gshiftleft(2, t3); feemod(par, t3); /* t3 = 4 z1 (x1^3 + b z1^3) */
605
606 gshiftleft(3, t2); /* t2 = 8 b z1^3 */
607 subg(t2, t1); /* t1 = x^3 - 8 b z1^3 */
608 mulg(x1, t1); feemod(par, t1); /* t1 = x1 (x1^3 - 8 b z1^3) */
609
610 gtog(t3, z2);
611 gtog(t1, x2);
612 /* End OPT: 9 Jan 98 REC. */
613 }
614 else {
615 numer_double(x1, z1, t1, par);
616 denom_double(x1, z1, t2, par);
617 gtog(t1, x2); gtog(t2, z2);
618 }
619 returnGiant(t1);
620 returnGiant(t2);
621 returnGiant(t3);
622
623 EPROF_END(ellEvenTime);
624 EPROF_INCR(numEllEvens);
625
626 /*
627 printf("ell_even end\n");
628 printf(" x1 : "); printGiant(x1);
629 printf(" z1 : "); printGiant(z1);
630 printf(" x2 : "); printGiant(x2);
631 printf(" z2 : "); printGiant(z2);
632 */
633 }
634
635 static void ell_odd(giant x1, giant z1, giant x2, giant z2, giant xxor,
636 giant zor, curveParams *par)
637 {
638
639 giant t1;
640 giant t2;
641
642 EPROF_START;
643 t1 = borrowGiant(par->maxDigits);
644 t2 = borrowGiant(par->maxDigits);
645
646 if(par->curveType == FCT_Montgomery) {
647 /* Begin Montgomery OPT: 10 Jan 98 REC. */
648 giant t3 = borrowGiant(par->maxDigits);
649 giant t4 = borrowGiant(par->maxDigits);
650
651 gtog(x1, t1); addg(z1, t1); /* t1 := x1 + z1. */
652 gtog(x2, t2); subg(z2, t2); /* t2 := x2 - z2. */
653 gtog(x1, t3); subg(z1, t3); /* t3 := x1 - z1. */
654 gtog(x2, t4); addg(z2, t4); /* t4 := x2 + z2. */
655 mulg(t2, t1); feemod(par, t1); /* t1 := (x1 + z1)(x2 - z2) */
656 mulg(t4, t3); feemod(par, t3); /* t4 := (x2 + z2)(x1 - z1) */
657 gtog(t1, z2); subg(t3, z2); /*???gshiftright(1, z2);*/
658 /* z2 := ((x1 + z1)(x2 - z2) - x2)/2 */
659 gsquare(z2); feemod(par, z2);
660 mulg(xxor, z2); feemod(par, z2);
661 gtog(t1, x2); addg(t3, x2); /*????gshiftright(1, x2);*/
662 gsquare(x2); feemod(par, x2);
663 mulg(zor, x2); feemod(par, x2);
664
665 returnGiant(t3);
666 returnGiant(t4);
667 }
668 else if((par->curveType == FCT_Weierstrass) && isZero(par->a)) {
669 /* Begin Atkin3 OPT: 9 Jan 98 REC. */
670
671 giant t3 = borrowGiant(par->maxDigits);
672 giant t4 = borrowGiant(par->maxDigits);
673
674 gtog(x1, t1); mulg(x2, t1); feemod(par, t1); /* t1 := x1 x2. */
675 gtog(z1, t2); mulg(z2, t2); feemod(par, t2); /* t2 := z1 z2. */
676 gtog(x1, t3); mulg(z2, t3); feemod(par, t3); /* t3 := x1 z2. */
677 gtog(z1, t4); mulg(x2, t4); feemod(par, t4); /* t4 := x2 z1. */
678 gtog(t3, z2); subg(t4, z2); gsquare(z2); feemod(par, z2);
679 mulg(xxor, z2); feemod(par, z2);
680 gtog(t1, x2); gsquare(x2); feemod(par, x2);
681 addg(t4, t3); mulg(t2, t3); feemod(par, t3);
682 mulg(par->b, t3); feemod(par, t3);
683 addg(t3, t3); addg(t3, t3);
684 subg(t3, x2); mulg(zor, x2); feemod(par, x2);
685
686 returnGiant(t3);
687 returnGiant(t4);
688 /* End OPT: 9 Jan 98 REC. */
689 }
690 else {
691 numer_times(x1, z1, x2, z2, t1, par);
692 mulg(zor, t1); feemod(par, t1);
693 denom_times(x1, z1, x2, z2, t2, par);
694 mulg(xxor, t2); feemod(par, t2);
695
696 gtog(t1, x2); gtog(t2, z2);
697 }
698
699 returnGiant(t1);
700 returnGiant(t2);
701
702 EPROF_END(ellOddTime);
703 EPROF_INCR(numEllOdds);
704
705 /*
706 printf("ell_odd end\n");
707 printf(" x2 : "); printGiant(x2);
708 printf(" z2 : "); printGiant(z2);
709 */
710 }
711
712 /*
713 * return codes from keys_inconsistent() and signature_compare(). The actual
714 * values are not public; they are defined here for debugging.
715 */
716 #define CURVE_PARAM_MISMATCH 1
717 #define TWIST_PARAM_MISMATCH 2
718 #define SIGNATURE_INVALID 3
719
720
721 /*
722 * Determine whether two keystructs have compatible parameters (i.e., same
723 * twist and curveParams). Return 0 if compatible, else non-zero.
724 */
725 static int keys_inconsistent(key pub1, key pub2){
726 if(!curveParamsEquivalent(pub1->cp, pub2->cp)) {
727 return CURVE_PARAM_MISMATCH;
728 }
729 if(pub1->twist != pub2->twist) {
730 return TWIST_PARAM_MISMATCH;
731 }
732 return 0;
733 }
734
735 int signature_compare(giant p0x, giant p1x, giant p2x, curveParams *par)
736 /* Returns non-zero iff p0x cannot be the x-coordinate of the sum of two points whose respective x-coordinates are p1x, p2x. */
737 {
738 int ret = 0;
739 giant t1;
740 giant t2;
741 giant t3;
742 giant t4;
743 giant t5;
744
745 PROF_START;
746
747 t1 = borrowGiant(par->maxDigits);
748 t2 = borrowGiant(par->maxDigits);
749 t3 = borrowGiant(par->maxDigits);
750 t4 = borrowGiant(par->maxDigits);
751 t5 = borrowGiant(par->maxDigits);
752
753 if(gcompg(p1x, p2x) == 0) {
754 int_to_giant(1, t1);
755 numer_double(p1x, t1, t2, par);
756 denom_double(p1x, t1, t3, par);
757 mulg(p0x, t3); subg(t3, t2);
758 feemod(par, t2);
759 } else {
760 numer_plus(p1x, p2x, t1, par);
761 gshiftleft(1, t1); feemod(par, t1);
762 int_to_giant(1, t3);
763 numer_times(p1x, t3, p2x, t3, t2, par);
764 int_to_giant(1, t4); int_to_giant(1, t5);
765 denom_times(p1x, t4 , p2x, t5, t3, par);
766 /* Now we require t3 x0^2 - t1 x0 + t2 == 0. */
767 mulg(p0x, t3); feemod(par, t3);
768 subg(t1, t3); mulg(p0x, t3);
769 feemod(par, t3);
770 addg(t3, t2);
771 feemod(par, t2);
772 }
773
774 if(!isZero(t2)) ret = SIGNATURE_INVALID;
775 returnGiant(t1);
776 returnGiant(t2);
777 returnGiant(t3);
778 returnGiant(t4);
779 returnGiant(t5);
780 PROF_END(sigCompTime);
781 return(ret);
782 }
783
784
785 static void numer_double(giant x, giant z, giant res, curveParams *par)
786 /* Numerator algebra.
787 res := (x^2 - a z^2)^2 - 4 b (2 x + c z) z^3.
788 */
789 {
790 giant t1;
791 giant t2;
792
793 PROF_START;
794 t1 = borrowGiant(par->maxDigits);
795 t2 = borrowGiant(par->maxDigits);
796
797 gtog(x, t1); gsquare(t1); feemod(par, t1);
798 gtog(z, res); gsquare(res); feemod(par, res);
799 gtog(res, t2);
800 if(!isZero(par->a) ) {
801 if(!isone(par->a)) { /* Speedup - REC 17 Jan 1997. */
802 mulg(par->a, res); feemod(par, res);
803 }
804 subg(res, t1); feemod(par, t1);
805 }
806 gsquare(t1); feemod(par, t1);
807 /* t1 := (x^2 - a z^2)^2. */
808 if(isZero(par->b)) { /* Speedup - REC 17 Jan 1997. */
809 gtog(t1, res);
810 goto done;
811 }
812 if(par->curveType != FCT_Weierstrass) { // i.e., !isZero(par->c)
813 // Speedup - REC 17 Jan 1997.
814 gtog(z, res); mulg(par->c, res); feemod(par, res);
815 } else {
816 int_to_giant(0, res);
817 }
818 addg(x, res); addg(x, res); mulg(par->b, res);
819 feemod(par, res);
820 gshiftleft(2, res); mulg(z, res); feemod(par, res);
821 mulg(t2, res); feemod(par, res);
822 negg(res); addg(t1, res);
823 feemod(par, res);
824
825 done:
826 returnGiant(t1);
827 returnGiant(t2);
828 PROF_END(numerDoubleTime);
829 }
830
831 static void numer_plus(giant x1, giant x2, giant res, curveParams *par)
832 /* Numerator algebra.
833 res = (x1 x2 + a)(x1 + x2) + 2(c x1 x2 + b).
834 */
835 {
836 giant t1;
837 giant t2;
838
839 PROF_START;
840 t1 = borrowGiant(par->maxDigits);
841 t2 = borrowGiant(par->maxDigits);
842
843 gtog(x1, t1); mulg(x2, t1); feemod(par, t1);
844 gtog(x2, t2); addg(x1, t2); feemod(par, t2);
845 gtog(t1, res);
846 if(!isZero(par->a))
847 addg(par->a, res);
848 mulg(t2, res); feemod(par, res);
849 if(par->curveType == FCT_Weierstrass) { // i.e., isZero(par->c)
850 int_to_giant(0, t1);
851 }
852 else {
853 mulg(par->c, t1); feemod(par, t1);
854 }
855 if(!isZero(par->b))
856 addg(par->b, t1);
857 gshiftleft(1, t1);
858 addg(t1, res); feemod(par, res);
859
860 returnGiant(t1);
861 returnGiant(t2);
862 PROF_END(numerPlusTime);
863 }
864
865 static void denom_double(giant x, giant z, giant res, curveParams *par)
866 /* Denominator algebra.
867 res = 4 z (x^3 + c x^2 z + a x z^2 + b z^3). */
868 {
869 giant t1;
870 giant t2;
871
872 PROF_START;
873 t1 = borrowGiant(par->maxDigits);
874 t2 = borrowGiant(par->maxDigits);
875
876 gtog(x, res); gtog(z, t1);
877 if(par->curveType != FCT_Weierstrass) { // i.e., !isZero(par->c)
878 gtog(par->c, t2); mulg(t1, t2); feemod(par, t2);
879 addg(t2, res);
880 }
881 mulg(x, res); feemod(par, res);
882 gsquare(t1); feemod(par, t1);
883 if(!isZero(par->a)) {
884 gtog(t1, t2);
885 mulg(par->a, t2); feemod(par, t2);
886 addg(t2, res);
887 }
888 mulg(x, res); feemod(par, res);
889 if(!isZero(par->b)) {
890 mulg(z, t1); feemod(par, t1);
891 mulg(par->b, t1); feemod(par, t1);
892 addg(t1, res);
893 }
894 mulg(z, res); gshiftleft(2, res);
895 feemod(par, res);
896
897 returnGiant(t1);
898 returnGiant(t2);
899 PROF_END(denomDoubleTime);
900 }
901
902
903
904 static void denom_times(giant x1, giant z1, giant x2, giant z2, giant res,
905 curveParams *par)
906 /* Denominator algebra.
907 res := (x1 z2 - x2 z1)^2
908 */
909 {
910 giant t1;
911
912 PROF_START;
913 t1 = borrowGiant(par->maxDigits);
914
915 gtog(x1, res); mulg(z2, res); feemod(par, res);
916 gtog(z1, t1); mulg(x2, t1); feemod(par, t1);
917 subg(t1, res); gsquare(res); feemod(par, res);
918
919 returnGiant(t1);
920 PROF_END(denomTimesTime);
921 }
922
923 static void numer_times(giant x1, giant z1, giant x2, giant z2, giant res,
924 curveParams *par)
925 /* Numerator algebra.
926 res := (x1 x2 - a z1 z2)^2 -
927 4 b(x1 z2 + x2 z1 + c z1 z2) z1 z2
928 */
929 {
930 giant t1;
931 giant t2;
932 giant t3;
933 giant t4;
934
935 PROF_START;
936 t1 = borrowGiant(par->maxDigits);
937 t2 = borrowGiant(par->maxDigits);
938 t3 = borrowGiant(par->maxDigits);
939 t4 = borrowGiant(par->maxDigits);
940
941 gtog(x1, t1); mulg(x2, t1); feemod(par, t1);
942 gtog(z1, t2); mulg(z2, t2); feemod(par, t2);
943 gtog(t1, res);
944 if(!isZero(par->a)) {
945 gtog(par->a, t3);
946 mulg(t2, t3); feemod(par, t3);
947 subg(t3, res);
948 }
949 gsquare(res); feemod(par, res);
950 if(isZero(par->b))
951 goto done;
952 if(par->curveType != FCT_Weierstrass) { // i.e., !isZero(par->c)
953 gtog(par->c, t3);
954 mulg(t2, t3); feemod(par, t3);
955 } else int_to_giant(0, t3);
956 gtog(z1, t4); mulg(x2, t4); feemod(par, t4);
957 addg(t4, t3);
958 gtog(x1, t4); mulg(z2, t4); feemod(par, t4);
959 addg(t4, t3); mulg(par->b, t3); feemod(par, t3);
960 mulg(t2, t3); gshiftleft(2, t3); feemod(par, t3);
961 subg(t3, res);
962 feemod(par, res);
963
964 done:
965 returnGiant(t1);
966 returnGiant(t2);
967 returnGiant(t3);
968 returnGiant(t4);
969 PROF_END(numerTimesTime);
970 }
971
972 /*
973 * New, 13 Jan 1997.
974 */
975 static void feepowermodg(curveParams *par, giant x, giant n)
976 /* Power ladder.
977 x := x^n (mod 2^q-k)
978 */
979 {
980 int len, pos;
981 giant t1;
982
983 PROF_START;
984 t1 = borrowGiant(par->maxDigits);
985 gtog(x, t1);
986 int_to_giant(1, x);
987 len = bitlen(n);
988 pos = 0;
989 while(1) {
990 if(bitval(n, pos++)) {
991 mulg(t1, x);
992 feemod(par, x);
993 }
994 if(pos>=len) break;
995 gsquare(t1);
996 feemod(par, t1);
997 }
998 returnGiant(t1);
999 PROF_END(powerModTime);
1000 }
1001
1002 /*
1003 * Set g := g mod curveOrder;
1004 * force g to be between 2 and (curveOrder-2), inclusive.
1005 *
1006 * Tolerates zero curve orders (indicating "not known").
1007 */
1008
1009 /*
1010 * This version is not normally used; it's for when the reciprocal of
1011 * curveOrder is not known and won't be used again.
1012 */
1013 void curveOrderJustify(giant g, giant curveOrder)
1014 {
1015 giant recip;
1016
1017 CKASSERT(!isZero(curveOrder));
1018
1019 recip = borrowGiant(2 * abs(g->sign));
1020 make_recip(curveOrder, recip);
1021 curveOrderJustifyWithRecip(g, curveOrder, recip);
1022 returnGiant(recip);
1023 }
1024
1025 /*
1026 * New optimzation of curveOrderJustify using known reciprocal, 11 June 1997.
1027 * g is set to be within [2, curveOrder-2].
1028 */
1029 static void curveOrderJustifyWithRecip(giant g, giant curveOrder, giant recip)
1030 {
1031 giant tmp;
1032
1033 CKASSERT(!isZero(curveOrder));
1034
1035 modg_via_recip(curveOrder, recip, g); // g now in [0, curveOrder-1]
1036
1037 if(isZero(g)) {
1038 /*
1039 * First degenerate case - (g == 0) : set g := 2
1040 */
1041 dbgLog(("curveOrderJustify: case 1\n"));
1042 int_to_giant(2, g);
1043 return;
1044 }
1045 if(isone(g)) {
1046 /*
1047 * Second case - (g == 1) : set g := 2
1048 */
1049 dbgLog(("curveOrderJustify: case 2\n"));
1050 int_to_giant(2, g);
1051 return;
1052 }
1053 tmp = borrowGiant(g->capacity);
1054 gtog(g, tmp);
1055 iaddg(1, tmp);
1056 if(gcompg(tmp, curveOrder) == 0) {
1057 /*
1058 * Third degenerate case - (g == (curveOrder-1)) : set g -= 1
1059 */
1060 dbgLog(("curveOrderJustify: case 3\n"));
1061 int_to_giant(1, tmp);
1062 subg(tmp, g);
1063 }
1064 returnGiant(tmp);
1065 return;
1066 }
1067
1068 #define RECIP_DEBUG 0
1069 #if RECIP_DEBUG
1070 #define recipLog(x) printf x
1071 #else // RECIP_DEBUG
1072 #define recipLog(x)
1073 #endif // RECIP_DEBUG
1074
1075 /*
1076 * curveOrderJustify routines with specific orders, using (and possibly
1077 * generating) associated reciprocals.
1078 */
1079 void lesserX1OrderJustify(giant g, curveParams *cp)
1080 {
1081 /*
1082 * Note this is a pointer to a giant in *cp, not a newly
1083 * malloc'd giant!
1084 */
1085 giant lesserX1Ord = lesserX1Order(cp);
1086
1087 if(isZero(lesserX1Ord)) {
1088 return;
1089 }
1090
1091 /*
1092 * Calculate reciprocal if we don't have it
1093 */
1094 if(isZero(cp->lesserX1OrderRecip)) {
1095 if((lesserX1Ord == cp->x1OrderPlus) &&
1096 (!isZero(cp->x1OrderPlusRecip))) {
1097 /*
1098 * lesserX1Ord happens to be x1OrderPlus, and we
1099 * have a reciprocal for x1OrderPlus. Copy it over.
1100 */
1101 recipLog((
1102 "x1OrderPlusRecip --> lesserX1OrderRecip\n"));
1103 gtog(cp->x1OrderPlusRecip, cp->lesserX1OrderRecip);
1104 }
1105 else {
1106 /* Calculate the reciprocal. */
1107 recipLog(("calc lesserX1OrderRecip\n"));
1108 make_recip(lesserX1Ord, cp->lesserX1OrderRecip);
1109 }
1110 }
1111 else {
1112 recipLog(("using existing lesserX1OrderRecip\n"));
1113 }
1114 curveOrderJustifyWithRecip(g, lesserX1Ord, cp->lesserX1OrderRecip);
1115 }
1116
1117 /*
1118 * Common code used by x1OrderPlusJustify() and x1OrderPlusMod() to generate
1119 * reciprocal of x1OrderPlus.
1120 * 8 Sep 1998 - also used by feeSigSign().
1121 */
1122 void calcX1OrderPlusRecip(curveParams *cp)
1123 {
1124 if(isZero(cp->x1OrderPlusRecip)) {
1125 if((cp->x1OrderPlus == lesserX1Order(cp)) &&
1126 (!isZero(cp->lesserX1OrderRecip))) {
1127 /*
1128 * lesserX1Order happens to be x1OrderPlus, and we
1129 * have a reciprocal for lesserX1Order. Copy it over.
1130 */
1131 recipLog((
1132 "lesserX1OrderRecip --> x1OrderPlusRecip\n"));
1133 gtog(cp->lesserX1OrderRecip, cp->x1OrderPlusRecip);
1134 }
1135 else {
1136 /* Calculate the reciprocal. */
1137 recipLog(("calc x1OrderPlusRecip\n"));
1138 make_recip(cp->x1OrderPlus, cp->x1OrderPlusRecip);
1139 }
1140 }
1141 else {
1142 recipLog(("using existing x1OrderPlusRecip\n"));
1143 }
1144 }
1145
1146 void x1OrderPlusJustify(giant g, curveParams *cp)
1147 {
1148 CKASSERT(!isZero(cp->x1OrderPlus));
1149
1150 /*
1151 * Calculate reciprocal if we don't have it
1152 */
1153 calcX1OrderPlusRecip(cp);
1154 curveOrderJustifyWithRecip(g, cp->x1OrderPlus, cp->x1OrderPlusRecip);
1155 }
1156
1157 /*
1158 * g := g mod x1OrderPlus. Result may be zero.
1159 */
1160 void x1OrderPlusMod(giant g, curveParams *cp)
1161 {
1162 CKASSERT(!isZero(cp->x1OrderPlus));
1163
1164 /*
1165 * Calculate reciprocal if we don't have it
1166 */
1167 calcX1OrderPlusRecip(cp);
1168 modg_via_recip(cp->x1OrderPlus, cp->x1OrderPlusRecip, g);
1169 }
1170
1171 /*
1172 * New general-purpose giant mod routine, 8 Jan 97.
1173 * x := x mod basePrime.
1174 */
1175
1176 /*
1177 * This stuff is used to analyze the critical loop behavior inside feemod().
1178 */
1179 #define FEEMOD_LOOP_TEST 0
1180 #if FEEMOD_LOOP_TEST
1181 /*
1182 * these two are only examined via debugger
1183 */
1184 unsigned feemodCalls = 0; // calls to feemod()
1185 unsigned feemodMultLoops = 0; // times while() loop runs > once
1186 #define FEEMOD_LOOP_INCR feemodLoops++
1187 #define FEEMOD_CALL_INCR feemodCalls++
1188 #else // FEEMOD_LOOP_TEST
1189 #define FEEMOD_LOOP_INCR
1190 #define FEEMOD_CALL_INCR
1191 #endif // FEEMOD_LOOP_TEST
1192
1193
1194 void
1195 feemod(curveParams *par, giant x)
1196 {
1197 int sign, sign2;
1198 giant t1;
1199 giant t3;
1200 giant t4;
1201 giant t5;
1202 #if FEEMOD_LOOP_TEST
1203 unsigned feemodLoops = 0;
1204 #endif // FEEMOD_LOOP_TEST
1205
1206 FEEMOD_CALL_INCR; // for FEEMOD_LOOP_TEST
1207 INCR_FEEMODS; // for ellipticMeasure
1208 PROF_INCR(numFeemod); // for general profiling
1209
1210 switch(par->primeType) {
1211 case FPT_Mersenne:
1212 /*
1213 * Super-optimized Mersenne prime modulus case
1214 */
1215 gmersennemod(par->q, x);
1216 break;
1217
1218 case FPT_FEE:
1219 /*
1220 * General 2**q-k case
1221 */
1222 sign = (x->sign < 0) ? -1 : 1;
1223 sign2 = 1;
1224 x->sign = abs(x->sign);
1225 if(gcompg(par->basePrime, x) >= 0) {
1226 goto outFee;
1227 }
1228 t1 = borrowGiant(par->maxDigits);
1229 t3 = borrowGiant(par->maxDigits);
1230 t4 = borrowGiant(par->maxDigits);
1231 t5 = borrowGiant(par->maxDigits);
1232
1233 /* Begin OPT: 11 Jan 98 REC. */
1234 if( ((par->q & (GIANT_BITS_PER_DIGIT - 1)) == 0) &&
1235 (par->k >= 0) &&
1236 (par->k < GIANT_DIGIT_MASK)) {
1237
1238 /*
1239 * Microscopic mod for certain regions of {q,k}
1240 * parameter space.
1241 */
1242 int j, digits, excess, max;
1243 giantDigit carry;
1244 giantDigit termHi; // double precision
1245 giantDigit termLo;
1246 giantDigit *p1, *p2;
1247
1248 digits = par->q >> GIANT_LOG2_BITS_PER_DIGIT;
1249 while(bitlen(x) > par->q) {
1250 excess = (x->sign) - digits;
1251 max = (excess > digits) ? excess : digits;
1252 carry = 0;
1253
1254 p1 = &x->n[0];
1255 p2 = &x->n[digits];
1256
1257 if(excess <= digits) {
1258 carry = VectorMultiply(par->k,
1259 p2,
1260 excess,
1261 p1);
1262
1263 /* propagate final carry */
1264 p1 += excess;
1265 for(j = excess; j < digits; j++) {
1266
1267 /*
1268 * term = *p1 + carry;
1269 * *p1++ = term & 65535;
1270 * carry = term >> 16;
1271 */
1272 termLo = giantAddDigits(*p1, carry, &carry);
1273 *p1++ = termLo;
1274 }
1275 } else {
1276 carry = VectorMultiply(par->k,
1277 p2,
1278 digits,
1279 p1);
1280 p1 += digits;
1281 p2 += digits;
1282 for(j = digits; j < excess; j++) {
1283 /*
1284 * term = (par->k)*(*p2++) + carry;
1285 */
1286 giantMulDigits(par->k,
1287 *p2++,
1288 &termLo,
1289 &termHi);
1290 giantAddDouble(&termLo, &termHi, carry);
1291
1292 /*
1293 * *p1++ = term & 65535;
1294 * carry = term >> 16;
1295 */
1296 *p1++ = termLo;
1297 carry = termHi;
1298 }
1299 }
1300
1301 if(carry > 0) {
1302 x->n[max] = carry;
1303 } else {
1304 while(--max){
1305 if(x->n[max] != 0) break;
1306 }
1307 }
1308 x->sign = max + 1;
1309 FEEMOD_LOOP_INCR;
1310 }
1311 } else { /* Macroscopic mod for general PT_FEE case. */
1312 int_to_giant(par->k, t4);
1313 while(bitlen(x) > par->q) {
1314 /* Enter fast loop, as in FEE patent. */
1315 int_to_giant(1, t5);
1316 gtog(x, t3);
1317 extractbits(par->q, t3, x);
1318 while(bitlen(t3) > par->q) {
1319 gshiftright(par->q, t3);
1320 extractbits(par->q, t3, t1);
1321 PAUSE_ELL_MEASURE;
1322 mulg(t4, t5);
1323 mulg(t5, t1);
1324 RESUME_ELL_MEASURE;
1325 addg(t1, x);
1326 }
1327 FEEMOD_LOOP_INCR;
1328 }
1329 }
1330 /* End OPT: 11 Jan 98 REC. */
1331
1332 sign2 = (x->sign < 0)? -1: 1;
1333 x->sign = abs(x->sign);
1334 returnGiant(t1);
1335 returnGiant(t3);
1336 returnGiant(t4);
1337 returnGiant(t5);
1338 outFee:
1339 if(gcompg(x, par->basePrime) >=0) subg(par->basePrime, x);
1340 if(sign != sign2) {
1341 giant t2 = borrowGiant(par->maxDigits);
1342 gtog(par->basePrime, t2);
1343 subg(x, t2);
1344 gtog(t2, x);
1345 returnGiant(t2);
1346 }
1347 break;
1348 /* end case PT_FEE */
1349
1350 case FPT_General:
1351 /*
1352 * Use brute-force modg.
1353 */
1354 #if FEE_DEBUG
1355 if(par->basePrimeRecip == NULL) {
1356 CKRaise("feemod(PT_GENERAL): No basePrimeRecip!\n");
1357 }
1358 #endif /* FEE_DEBUG */
1359 modg_via_recip(par->basePrime, par->basePrimeRecip, x);
1360 break;
1361
1362 case FPT_Default:
1363 /* never appears here */
1364 CKASSERT(0);
1365 break;
1366 } /* switch primeType */
1367
1368 #if FEEMOD_LOOP_TEST
1369 if(feemodLoops > 1) {
1370 feemodMultLoops++;
1371 if(feemodLoops > 2) {
1372 printf("feemod while loop executed %d times\n", feemodLoops);
1373 }
1374 }
1375 #endif // FEEMOD_LOOP_TEST
1376
1377 return;
1378 }
1379
1380 /*
1381 * For a given curveParams, calculate minBytes and maxDigits.
1382 * Assumes valid primeType, and also a valid basePrime for PT_GENERAL.
1383 */
1384 void calcGiantSizes(curveParams *cp)
1385 {
1386
1387 if(cp->primeType == FPT_General) {
1388 cp->minBytes = (bitlen(cp->basePrime) + 7) / 8;
1389 }
1390 else {
1391 cp->minBytes = giantMinBytes(cp->q, cp->k);
1392 }
1393 cp->maxDigits = giantMaxDigits(cp->minBytes);
1394 }
1395
1396 unsigned giantMinBytes(unsigned q, int k)
1397 {
1398 unsigned kIsNeg = (k < 0) ? 1 : 0;
1399
1400 return (q + 7 + kIsNeg) / 8;
1401 }
1402
1403 /*
1404 * min value for "extra" bytes. Derived from the fact that during sig verify,
1405 * we have to multiply a giant representing a digest - which may be
1406 * 20 bytes for SHA1 - by a giant of minBytes.
1407 */
1408 #define MIN_EXTRA_BYTES 20
1409
1410 unsigned giantMaxDigits(unsigned minBytes)
1411 {
1412 unsigned maxBytes = 4 * minBytes;
1413
1414 if((maxBytes - minBytes) < MIN_EXTRA_BYTES) {
1415 maxBytes = minBytes + MIN_EXTRA_BYTES;
1416 }
1417 return BYTES_TO_GIANT_DIGITS(maxBytes);
1418 }
1419
1420
1421 /*
1422 * Optimized binvg(basePrime, x). Avoids the general modg() in favor of
1423 * feemod.
1424 */
1425 int binvg_cp(curveParams *cp, giant x)
1426 {
1427 feemod(cp, x);
1428 return(binvaux(cp->basePrime, x));
1429 }
1430
1431 /*
1432 * Optimized binvg(x1OrderPlus, x). Uses x1OrderPlusMod().
1433 */
1434 int binvg_x1OrderPlus(curveParams *cp, giant x)
1435 {
1436 x1OrderPlusMod(x, cp);
1437 return(binvaux(cp->x1OrderPlus, x));
1438 }