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