1 /* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved.
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 ***************************************************************************
11 elliptic.c - Library for Apple-proprietary Fast Elliptic
12 Encryption. The algebra in this module ignores elliptic point's
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.
23 Digital signature using fast elliptic addition, in
24 U. S. Patent #5581616 (1996), is implemented in the
25 signature_compare() function.
27 FEED (Fast Elliptic Encryption) is patent pending (as of Jan 1998).
28 Various functions such as elliptic_add() implement the patent ideas.
31 Modification history since the U.S. Patent:
32 -------------------------------------------
34 Changed to compile with C++.
36 cp->curveType optimizations.
37 Removed code which handled "unknown" curve orders.
38 elliptic() now exported for timing measurements.
40 Used inline platform-dependent giant arithmetic.
42 feemod now handles PT_MERSENNE, PT_FEE, PT_GENERAL.
43 Added calcGiantSizes(), rewrote giantMinBytes(), giantMaxShorts().
44 Updated heading comments on FEE curve algebra.
46 Microscopic feemod optimization.
48 ell_odd, ell_even() Montgomery optimization.
50 ell_odd, ell_even() Atkin3 optimization.
52 Cleaned up some debugging code; added gsquareTime
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
59 New optimized numer_plus(), denom_double(), and numer_times()
60 All calls to borrowGiant() and newGiant have explicit giant size
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.
67 Added mersennePrimes[24..26]
69 Fixed giant leak in elliptic_add()
73 Added ENGINE_127_BITS dependency for use of security engine
75 Modified new_public_from_private()
79 FEE curve algebra, Jan 1997.
83 y^2 = x^3 + c x^2 + a x + b
85 where useful parameterizations for practical purposes are:
87 Montgomery: a = 1, b = 0. (The original 1991 FEE system.)
88 Weierstrass: c = 0. (The basic IEEE form.)
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:
97 p = 2^q - k = 3 (mod 4)
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).
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:
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.
112 numer_plus(giant x1, giant x2, giant res, curveParams *par)
113 res = (x1 x2 + a)(x1 + x2) + 2(c x1 x2 + b).
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).
118 denom_times(giant x1, giant z1, giant x2, giant z2, giant res,
120 res := (x1 z2 - x2 z1)^2
122 numer_times(giant x1, giant z1, giant x2, giant z2, giant res,
124 res := (x1 x2 - a z1 z2)^2 - 4 b(x1 z2 + x2 z1 + c z1 z2) z1 z2
126 If x(+-) represent the sum and difference x-coordinates
127 respectively, then, in pseudocode,
129 For unequal starting coords:
130 x(+) + x(-) = U = 2 numer_plus/denom_times
131 x(+) x(-) = V = numer_times/denom_times
133 and for equal starting coords:
134 x(+) = numer_double/denom_double
136 The elliptic_add() function uses the fact that
138 x(+) = U/2 + s*Sqrt[U^2/4 - V]
140 where the sign s = +-1.
144 #include "ckconfig.h"
148 #include "platform.h"
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"
158 #include "giantPortCommon.h"
162 unsigned numerDoubleTime
;
163 unsigned numerPlusTime
;
164 unsigned numerTimesTime
;
165 unsigned denomDoubleTime
;
166 unsigned denomTimesTime
;
167 unsigned ellipticTime
;
168 unsigned sigCompTime
;
169 unsigned powerModTime
;
171 unsigned whichCurveTime
;
174 unsigned binvauxTime
;
175 unsigned gsquareTime
;
204 #endif // FEE_PROFILE
208 unsigned ellEvenTime
;
210 unsigned numEllEvens
;
212 void clearEllProfile()
220 #endif /* ELL_PROFILE */
223 int doEllMeasure
; // gather stats on/off */
230 printf("\nbitlen(n) : %d\n", bitsInN
);
231 printf("feemods : %d\n", numFeeMods
);
232 printf("mulgs : %d\n", numMulgs
);
235 #endif // ELLIPTIC_MEASURE
237 /********** Globals ********************************/
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.
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
,
253 static void numer_times(giant x1
, giant z1
, giant x2
, giant z2
, giant res
,
255 static void feepowermodg(curveParams
*par
, giant x
, giant n
);
256 static void curveOrderJustifyWithRecip(giant g
, giant curveOrder
, giant recip
);
259 * Completely rewritten in CryptKit-18, 13 Jan 1997, for new IEEE-style
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.
273 t1
= borrowGiant(par
->maxDigits
);
274 t2
= borrowGiant(par
->maxDigits
);
275 t3
= borrowGiant(par
->maxDigits
);
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. */
281 mulg(x
, t2
); addg(par
->b
, t2
);
283 /* Next, test whether t2 is a square. */
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)
290 result
= CURVE_MINUS
;
294 PROF_END(whichCurveTime
);
298 key
new_public(curveParams
*cp
, int twist
) {
301 k
= (key
) fmalloc(sizeof(keystruct
));
305 k
->x
= newGiant(cp
->maxDigits
);
306 if((twist
== CURVE_PLUS
) && (cp
->curveType
== FCT_Weierstrass
)) {
307 k
->y
= newGiant(cp
->maxDigits
);
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.
320 key
new_public_with_key(key old_key
, curveParams
*cp
)
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
);
332 void free_key(key pub
) {
346 * Specify private data for key created by new_public().
349 void set_priv_key_giant(key k
, giant privGiant
)
351 curveParams
*cp
= k
->cp
;
353 /* elliptiy multiply of initial public point times private key */
354 if((k
->twist
== CURVE_PLUS
) && (cp
->curveType
== FCT_Weierstrass
)) {
357 pointProj pt1
= newPointProj(cp
->maxDigits
);
359 CKASSERT((cp
->y1Plus
!= NULL
) && (!isZero(cp
->y1Plus
)));
360 CKASSERT(k
->y
!= NULL
);
362 /* pt1 := {x1Plus, y1Plus, 1} */
363 gtog(cp
->x1Plus
, pt1
->x
);
364 gtog(cp
->y1Plus
, pt1
->y
);
365 int_to_giant(1, pt1
->z
);
367 /* pt1 := pt1 * privateKey */
368 ellMulProjSimple(pt1
, privGiant
, cp
);
370 /* result back to {k->x, k->y} */
373 freePointProj(pt1
); // FIXME - clear the giants
378 if(k
->twist
== CURVE_PLUS
) {
379 gtog(cp
->x1Plus
, k
->x
);
382 gtog(cp
->x1Minus
, k
->x
);
384 elliptic_simple(k
->x
, privGiant
, k
->cp
);
388 int key_equal(key one
, key two
) {
389 if (keys_inconsistent(one
, two
)) return 0;
390 return !gcompg(one
->x
, two
->x
);
393 static void make_base(curveParams
*par
, giant result
)
394 /* Jams result with 2^q-k. */
396 gtog(par
->basePrime
, result
);
399 void make_base_prim(curveParams
*cp
)
400 /* Jams cp->basePrime with 2^q-k. Assumes valid maxDigits, q, k. */
402 giant tmp
= borrowGiant(cp
->maxDigits
);
404 CKASSERT(cp
->primeType
!= FPT_General
);
405 int_to_giant(1, cp
->basePrime
);
406 gshiftleft((int)cp
->q
, cp
->basePrime
);
407 int_to_giant(cp
->k
, tmp
);
408 subg(tmp
, cp
->basePrime
);
412 static int sequalg(int n
, giant g
) {
413 if((g
->sign
== 1) && (g
->n
[0] == n
)) return(1);
419 * Elliptic multiply: x := n * {x, 1}
421 void elliptic_simple(giant x
, giant n
, curveParams
*par
) {
422 giant ztmp
= borrowGiant(par
->maxDigits
);
423 giant cur_n
= borrowGiant(par
->maxDigits
);
425 START_ELL_MEASURE(n
);
426 int_to_giant(1, ztmp
);
427 elliptic(x
, ztmp
, n
, par
);
438 * General elliptic multiply.
440 * {xx, zz} := k * {xx, zz}
442 void elliptic(giant xx
, giant zz
, giant k
, curveParams
*par
) {
451 if(sequalg(1,k
)) return;
453 ell_even(xx
, zz
, xx
, zz
, par
);
456 zs
= borrowGiant(par
->maxDigits
);
457 xs
= borrowGiant(par
->maxDigits
);
458 zorg
= borrowGiant(par
->maxDigits
);
459 xorg
= borrowGiant(par
->maxDigits
);
460 gtog(xx
, xorg
); gtog(zz
, zorg
);
461 ell_even(xx
, zz
, xs
, zs
, par
);
463 if(bitval(k
, pos
--)) {
464 ell_odd(xs
, zs
, xx
, zz
, xorg
, zorg
, par
);
465 ell_even(xs
, zs
, xs
, zs
, par
);
467 ell_odd(xx
, zz
, xs
, zs
, xorg
, zorg
, par
);
468 ell_even(xx
, zz
, xx
, zz
, par
);
470 } while (pos
>= 0); // REC fix 9/23/94
476 PROF_END(ellipticTime
);
480 * Completely rewritten in CryptKit-18, 13 Jan 1997, for new IEEE-style
483 void elliptic_add(giant x1
, giant x2
, giant x3
, curveParams
*par
, int s
) {
485 /* Addition algorithm for x3 = x1 + x2 on the curve, with sign ambiguity s.
486 From theory, we know that if {x1,1} and {x2,1} are on a curve, then
487 their elliptic sum (x1,1} + {x2,1} = {x3,1} must have x3 as one of two
490 x3 = U/2 + s*Sqrt[U^2/4 - V]
492 where sign s = +-1, and U,V are functions of x1,x2. Tho present function
493 is called a maximum of twice, to settle which of +- is s. When a call
494 is made, it is guaranteed already that x1, x2 both lie on the same curve
495 (+- curve); i.e., which curve (+-) is not connected at all with sign s of
507 cur_n
= borrowGiant(par
->maxDigits
);
508 t1
= borrowGiant(par
->maxDigits
);
509 t2
= borrowGiant(par
->maxDigits
);
510 t3
= borrowGiant(par
->maxDigits
);
511 t4
= borrowGiant(par
->maxDigits
);
512 t5
= borrowGiant(par
->maxDigits
);
514 if(gcompg(x1
, x2
)==0) {
516 numer_double(x1
, t1
, x3
, par
);
517 denom_double(x1
, t1
, t2
, par
);
519 mulg(t2
, x3
); feemod(par
, x3
);
522 numer_plus(x1
, x2
, t1
, par
);
524 numer_times(x1
, t3
, x2
, t3
, t2
, par
);
525 int_to_giant(1, t4
); int_to_giant(1, t5
);
526 denom_times(x1
, t4
, x2
, t5
, t3
, par
);
528 mulg(t3
, t1
); feemod(par
, t1
); /* t1 := U/2. */
529 mulg(t3
, t2
); feemod(par
, t2
); /* t2 := V. */
530 /* Now x3 will be t1 +- Sqrt[t1^2 - t2]. */
531 gtog(t1
, t4
); gsquare(t4
); feemod(par
, t4
);
533 make_base(par
, cur_n
); iaddg(1, cur_n
); gshiftright(2, cur_n
);
534 /* cur_n := (p+1)/4. */
535 feepowermodg(par
, t4
, cur_n
); /* t4 := t2^((p+1)/4) (mod p). */
537 if(s
!= SIGN_PLUS
) negg(t4
);
549 PROF_END(ellAddTime
);
555 giant
make_pad(giant privGiant
, key publicKey
) {
556 curveParams
*par
= publicKey
->cp
;
557 giant result
= newGiant(par
->maxDigits
);
559 gtog(publicKey
->x
, result
);
560 elliptic_simple(result
, privGiant
, par
);
564 static void ell_even(giant x1
, giant z1
, giant x2
, giant z2
, curveParams
*par
) {
571 t1
= borrowGiant(par
->maxDigits
);
572 t2
= borrowGiant(par
->maxDigits
);
573 t3
= borrowGiant(par
->maxDigits
);
575 if(par
->curveType
== FCT_Montgomery
) {
576 /* Begin Montgomery OPT: 10 Jan 98 REC. */
577 gtog(x1
, t1
); gsquare(t1
); feemod(par
, t1
); /* t1 := x1^2. */
578 gtog(z1
, t2
); gsquare(t2
); feemod(par
, t2
); /* t2 := z1^2. */
580 gtog(x1
, t3
); mulg(z1
, t3
); feemod(par
, t3
);
581 gtog(t3
, z2
); mulg(par
->c
, z2
); feemod(par
, z2
);
582 addg(t1
, z2
); addg(t2
, z2
); mulg(t3
, z2
); gshiftleft(2, z2
);
583 feemod(par
, z2
); /* z2 := 4 x1 z1 (x1^2 + c x1 z1 + z1^2). */
584 gtog(t1
, x2
); subg(t2
, x2
); gsquare(x2
); feemod(par
, x2
);
585 /* x2 := (x1^2 - z1^2)^2. */
586 /* End OPT: 10 Jan 98 REC. */
588 else if((par
->curveType
== FCT_Weierstrass
) && isZero(par
->a
)) {
589 /* Begin Atkin3 OPT: 9 Jan 98 REC. */
591 gsquare(t1
); feemod(par
, t1
);
592 mulg(x1
, t1
); feemod(par
, t1
); /* t1 := x^3. */
594 gsquare(t2
); feemod(par
, t2
);
595 mulg(z1
, t2
); feemod(par
, t2
); /* t2 := z1^3 */
596 mulg(par
->b
, t2
); feemod(par
, t2
); /* t2 := b z1^3. */
597 gtog(t1
, t3
); addg(t2
, t3
); /* t3 := x^3 + b z1^3 */
598 mulg(z1
, t3
); feemod(par
, t3
); /* t3 *= z1
599 * = z1 ( x^3 + b z1^3 ) */
600 gshiftleft(2, t3
); feemod(par
, t3
); /* t3 = 4 z1 (x1^3 + b z1^3) */
602 gshiftleft(3, t2
); /* t2 = 8 b z1^3 */
603 subg(t2
, t1
); /* t1 = x^3 - 8 b z1^3 */
604 mulg(x1
, t1
); feemod(par
, t1
); /* t1 = x1 (x1^3 - 8 b z1^3) */
608 /* End OPT: 9 Jan 98 REC. */
611 numer_double(x1
, z1
, t1
, par
);
612 denom_double(x1
, z1
, t2
, par
);
613 gtog(t1
, x2
); gtog(t2
, z2
);
619 EPROF_END(ellEvenTime
);
620 EPROF_INCR(numEllEvens
);
623 printf("ell_even end\n");
624 printf(" x1 : "); printGiant(x1);
625 printf(" z1 : "); printGiant(z1);
626 printf(" x2 : "); printGiant(x2);
627 printf(" z2 : "); printGiant(z2);
631 static void ell_odd(giant x1
, giant z1
, giant x2
, giant z2
, giant xxor
,
632 giant zor
, curveParams
*par
)
639 t1
= borrowGiant(par
->maxDigits
);
640 t2
= borrowGiant(par
->maxDigits
);
642 if(par
->curveType
== FCT_Montgomery
) {
643 /* Begin Montgomery OPT: 10 Jan 98 REC. */
644 giant t3
= borrowGiant(par
->maxDigits
);
645 giant t4
= borrowGiant(par
->maxDigits
);
647 gtog(x1
, t1
); addg(z1
, t1
); /* t1 := x1 + z1. */
648 gtog(x2
, t2
); subg(z2
, t2
); /* t2 := x2 - z2. */
649 gtog(x1
, t3
); subg(z1
, t3
); /* t3 := x1 - z1. */
650 gtog(x2
, t4
); addg(z2
, t4
); /* t4 := x2 + z2. */
651 mulg(t2
, t1
); feemod(par
, t1
); /* t1 := (x1 + z1)(x2 - z2) */
652 mulg(t4
, t3
); feemod(par
, t3
); /* t4 := (x2 + z2)(x1 - z1) */
653 gtog(t1
, z2
); subg(t3
, z2
); /*???gshiftright(1, z2);*/
654 /* z2 := ((x1 + z1)(x2 - z2) - x2)/2 */
655 gsquare(z2
); feemod(par
, z2
);
656 mulg(xxor
, z2
); feemod(par
, z2
);
657 gtog(t1
, x2
); addg(t3
, x2
); /*????gshiftright(1, x2);*/
658 gsquare(x2
); feemod(par
, x2
);
659 mulg(zor
, x2
); feemod(par
, x2
);
664 else if((par
->curveType
== FCT_Weierstrass
) && isZero(par
->a
)) {
665 /* Begin Atkin3 OPT: 9 Jan 98 REC. */
667 giant t3
= borrowGiant(par
->maxDigits
);
668 giant t4
= borrowGiant(par
->maxDigits
);
670 gtog(x1
, t1
); mulg(x2
, t1
); feemod(par
, t1
); /* t1 := x1 x2. */
671 gtog(z1
, t2
); mulg(z2
, t2
); feemod(par
, t2
); /* t2 := z1 z2. */
672 gtog(x1
, t3
); mulg(z2
, t3
); feemod(par
, t3
); /* t3 := x1 z2. */
673 gtog(z1
, t4
); mulg(x2
, t4
); feemod(par
, t4
); /* t4 := x2 z1. */
674 gtog(t3
, z2
); subg(t4
, z2
); gsquare(z2
); feemod(par
, z2
);
675 mulg(xxor
, z2
); feemod(par
, z2
);
676 gtog(t1
, x2
); gsquare(x2
); feemod(par
, x2
);
677 addg(t4
, t3
); mulg(t2
, t3
); feemod(par
, t3
);
678 mulg(par
->b
, t3
); feemod(par
, t3
);
679 addg(t3
, t3
); addg(t3
, t3
);
680 subg(t3
, x2
); mulg(zor
, x2
); feemod(par
, x2
);
684 /* End OPT: 9 Jan 98 REC. */
687 numer_times(x1
, z1
, x2
, z2
, t1
, par
);
688 mulg(zor
, t1
); feemod(par
, t1
);
689 denom_times(x1
, z1
, x2
, z2
, t2
, par
);
690 mulg(xxor
, t2
); feemod(par
, t2
);
692 gtog(t1
, x2
); gtog(t2
, z2
);
698 EPROF_END(ellOddTime
);
699 EPROF_INCR(numEllOdds
);
702 printf("ell_odd end\n");
703 printf(" x2 : "); printGiant(x2);
704 printf(" z2 : "); printGiant(z2);
709 * return codes from keys_inconsistent() and signature_compare(). The actual
710 * values are not public; they are defined here for debugging.
712 #define CURVE_PARAM_MISMATCH 1
713 #define TWIST_PARAM_MISMATCH 2
714 #define SIGNATURE_INVALID 3
718 * Determine whether two keystructs have compatible parameters (i.e., same
719 * twist and curveParams). Return 0 if compatible, else non-zero.
721 static int keys_inconsistent(key pub1
, key pub2
){
722 if(!curveParamsEquivalent(pub1
->cp
, pub2
->cp
)) {
723 return CURVE_PARAM_MISMATCH
;
725 if(pub1
->twist
!= pub2
->twist
) {
726 return TWIST_PARAM_MISMATCH
;
731 int signature_compare(giant p0x
, giant p1x
, giant p2x
, curveParams
*par
)
732 /* Returns non-zero iff p0x cannot be the x-coordinate of the sum of two points whose respective x-coordinates are p1x, p2x. */
743 t1
= borrowGiant(par
->maxDigits
);
744 t2
= borrowGiant(par
->maxDigits
);
745 t3
= borrowGiant(par
->maxDigits
);
746 t4
= borrowGiant(par
->maxDigits
);
747 t5
= borrowGiant(par
->maxDigits
);
749 if(gcompg(p1x
, p2x
) == 0) {
751 numer_double(p1x
, t1
, t2
, par
);
752 denom_double(p1x
, t1
, t3
, par
);
753 mulg(p0x
, t3
); subg(t3
, t2
);
756 numer_plus(p1x
, p2x
, t1
, par
);
757 gshiftleft(1, t1
); feemod(par
, t1
);
759 numer_times(p1x
, t3
, p2x
, t3
, t2
, par
);
760 int_to_giant(1, t4
); int_to_giant(1, t5
);
761 denom_times(p1x
, t4
, p2x
, t5
, t3
, par
);
762 /* Now we require t3 x0^2 - t1 x0 + t2 == 0. */
763 mulg(p0x
, t3
); feemod(par
, t3
);
764 subg(t1
, t3
); mulg(p0x
, t3
);
770 if(!isZero(t2
)) ret
= SIGNATURE_INVALID
;
776 PROF_END(sigCompTime
);
781 static void numer_double(giant x
, giant z
, giant res
, curveParams
*par
)
782 /* Numerator algebra.
783 res := (x^2 - a z^2)^2 - 4 b (2 x + c z) z^3.
790 t1
= borrowGiant(par
->maxDigits
);
791 t2
= borrowGiant(par
->maxDigits
);
793 gtog(x
, t1
); gsquare(t1
); feemod(par
, t1
);
794 gtog(z
, res
); gsquare(res
); feemod(par
, res
);
796 if(!isZero(par
->a
) ) {
797 if(!isone(par
->a
)) { /* Speedup - REC 17 Jan 1997. */
798 mulg(par
->a
, res
); feemod(par
, res
);
800 subg(res
, t1
); feemod(par
, t1
);
802 gsquare(t1
); feemod(par
, t1
);
803 /* t1 := (x^2 - a z^2)^2. */
804 if(isZero(par
->b
)) { /* Speedup - REC 17 Jan 1997. */
808 if(par
->curveType
!= FCT_Weierstrass
) { // i.e., !isZero(par->c)
809 // Speedup - REC 17 Jan 1997.
810 gtog(z
, res
); mulg(par
->c
, res
); feemod(par
, res
);
812 int_to_giant(0, res
);
814 addg(x
, res
); addg(x
, res
); mulg(par
->b
, res
);
816 gshiftleft(2, res
); mulg(z
, res
); feemod(par
, res
);
817 mulg(t2
, res
); feemod(par
, res
);
818 negg(res
); addg(t1
, res
);
824 PROF_END(numerDoubleTime
);
827 static void numer_plus(giant x1
, giant x2
, giant res
, curveParams
*par
)
828 /* Numerator algebra.
829 res = (x1 x2 + a)(x1 + x2) + 2(c x1 x2 + b).
836 t1
= borrowGiant(par
->maxDigits
);
837 t2
= borrowGiant(par
->maxDigits
);
839 gtog(x1
, t1
); mulg(x2
, t1
); feemod(par
, t1
);
840 gtog(x2
, t2
); addg(x1
, t2
); feemod(par
, t2
);
844 mulg(t2
, res
); feemod(par
, res
);
845 if(par
->curveType
== FCT_Weierstrass
) { // i.e., isZero(par->c)
849 mulg(par
->c
, t1
); feemod(par
, t1
);
854 addg(t1
, res
); feemod(par
, res
);
858 PROF_END(numerPlusTime
);
861 static void denom_double(giant x
, giant z
, giant res
, curveParams
*par
)
862 /* Denominator algebra.
863 res = 4 z (x^3 + c x^2 z + a x z^2 + b z^3). */
869 t1
= borrowGiant(par
->maxDigits
);
870 t2
= borrowGiant(par
->maxDigits
);
872 gtog(x
, res
); gtog(z
, t1
);
873 if(par
->curveType
!= FCT_Weierstrass
) { // i.e., !isZero(par->c)
874 gtog(par
->c
, t2
); mulg(t1
, t2
); feemod(par
, t2
);
877 mulg(x
, res
); feemod(par
, res
);
878 gsquare(t1
); feemod(par
, t1
);
879 if(!isZero(par
->a
)) {
881 mulg(par
->a
, t2
); feemod(par
, t2
);
884 mulg(x
, res
); feemod(par
, res
);
885 if(!isZero(par
->b
)) {
886 mulg(z
, t1
); feemod(par
, t1
);
887 mulg(par
->b
, t1
); feemod(par
, t1
);
890 mulg(z
, res
); gshiftleft(2, res
);
895 PROF_END(denomDoubleTime
);
900 static void denom_times(giant x1
, giant z1
, giant x2
, giant z2
, giant res
,
902 /* Denominator algebra.
903 res := (x1 z2 - x2 z1)^2
909 t1
= borrowGiant(par
->maxDigits
);
911 gtog(x1
, res
); mulg(z2
, res
); feemod(par
, res
);
912 gtog(z1
, t1
); mulg(x2
, t1
); feemod(par
, t1
);
913 subg(t1
, res
); gsquare(res
); feemod(par
, res
);
916 PROF_END(denomTimesTime
);
919 static void numer_times(giant x1
, giant z1
, giant x2
, giant z2
, giant res
,
921 /* Numerator algebra.
922 res := (x1 x2 - a z1 z2)^2 -
923 4 b(x1 z2 + x2 z1 + c z1 z2) z1 z2
932 t1
= borrowGiant(par
->maxDigits
);
933 t2
= borrowGiant(par
->maxDigits
);
934 t3
= borrowGiant(par
->maxDigits
);
935 t4
= borrowGiant(par
->maxDigits
);
937 gtog(x1
, t1
); mulg(x2
, t1
); feemod(par
, t1
);
938 gtog(z1
, t2
); mulg(z2
, t2
); feemod(par
, t2
);
940 if(!isZero(par
->a
)) {
942 mulg(t2
, t3
); feemod(par
, t3
);
945 gsquare(res
); feemod(par
, res
);
948 if(par
->curveType
!= FCT_Weierstrass
) { // i.e., !isZero(par->c)
950 mulg(t2
, t3
); feemod(par
, t3
);
951 } else int_to_giant(0, t3
);
952 gtog(z1
, t4
); mulg(x2
, t4
); feemod(par
, t4
);
954 gtog(x1
, t4
); mulg(z2
, t4
); feemod(par
, t4
);
955 addg(t4
, t3
); mulg(par
->b
, t3
); feemod(par
, t3
);
956 mulg(t2
, t3
); gshiftleft(2, t3
); feemod(par
, t3
);
965 PROF_END(numerTimesTime
);
971 static void feepowermodg(curveParams
*par
, giant x
, giant n
)
980 t1
= borrowGiant(par
->maxDigits
);
986 if(bitval(n
, pos
++)) {
995 PROF_END(powerModTime
);
999 * Set g := g mod curveOrder;
1000 * force g to be between 2 and (curveOrder-2), inclusive.
1002 * Tolerates zero curve orders (indicating "not known").
1006 * This version is not normally used; it's for when the reciprocal of
1007 * curveOrder is not known and won't be used again.
1009 void curveOrderJustify(giant g
, giant curveOrder
)
1013 CKASSERT(!isZero(curveOrder
));
1015 recip
= borrowGiant(2 * abs(g
->sign
));
1016 make_recip(curveOrder
, recip
);
1017 curveOrderJustifyWithRecip(g
, curveOrder
, recip
);
1022 * New optimzation of curveOrderJustify using known reciprocal, 11 June 1997.
1023 * g is set to be within [2, curveOrder-2].
1025 static void curveOrderJustifyWithRecip(giant g
, giant curveOrder
, giant recip
)
1029 CKASSERT(!isZero(curveOrder
));
1031 modg_via_recip(curveOrder
, recip
, g
); // g now in [0, curveOrder-1]
1035 * First degenerate case - (g == 0) : set g := 2
1037 dbgLog(("curveOrderJustify: case 1\n"));
1043 * Second case - (g == 1) : set g := 2
1045 dbgLog(("curveOrderJustify: case 2\n"));
1049 tmp
= borrowGiant(g
->capacity
);
1052 if(gcompg(tmp
, curveOrder
) == 0) {
1054 * Third degenerate case - (g == (curveOrder-1)) : set g -= 1
1056 dbgLog(("curveOrderJustify: case 3\n"));
1057 int_to_giant(1, tmp
);
1064 #define RECIP_DEBUG 0
1066 #define recipLog(x) printf x
1067 #else // RECIP_DEBUG
1069 #endif // RECIP_DEBUG
1072 * curveOrderJustify routines with specific orders, using (and possibly
1073 * generating) associated reciprocals.
1075 void lesserX1OrderJustify(giant g
, curveParams
*cp
)
1078 * Note this is a pointer to a giant in *cp, not a newly
1081 giant lesserX1Ord
= lesserX1Order(cp
);
1083 if(isZero(lesserX1Ord
)) {
1088 * Calculate reciprocal if we don't have it
1090 if(isZero(cp
->lesserX1OrderRecip
)) {
1091 if((lesserX1Ord
== cp
->x1OrderPlus
) &&
1092 (!isZero(cp
->x1OrderPlusRecip
))) {
1094 * lesserX1Ord happens to be x1OrderPlus, and we
1095 * have a reciprocal for x1OrderPlus. Copy it over.
1098 "x1OrderPlusRecip --> lesserX1OrderRecip\n"));
1099 gtog(cp
->x1OrderPlusRecip
, cp
->lesserX1OrderRecip
);
1102 /* Calculate the reciprocal. */
1103 recipLog(("calc lesserX1OrderRecip\n"));
1104 make_recip(lesserX1Ord
, cp
->lesserX1OrderRecip
);
1108 recipLog(("using existing lesserX1OrderRecip\n"));
1110 curveOrderJustifyWithRecip(g
, lesserX1Ord
, cp
->lesserX1OrderRecip
);
1114 * Common code used by x1OrderPlusJustify() and x1OrderPlusMod() to generate
1115 * reciprocal of x1OrderPlus.
1116 * 8 Sep 1998 - also used by feeSigSign().
1118 void calcX1OrderPlusRecip(curveParams
*cp
)
1120 if(isZero(cp
->x1OrderPlusRecip
)) {
1121 if((cp
->x1OrderPlus
== lesserX1Order(cp
)) &&
1122 (!isZero(cp
->lesserX1OrderRecip
))) {
1124 * lesserX1Order happens to be x1OrderPlus, and we
1125 * have a reciprocal for lesserX1Order. Copy it over.
1128 "lesserX1OrderRecip --> x1OrderPlusRecip\n"));
1129 gtog(cp
->lesserX1OrderRecip
, cp
->x1OrderPlusRecip
);
1132 /* Calculate the reciprocal. */
1133 recipLog(("calc x1OrderPlusRecip\n"));
1134 make_recip(cp
->x1OrderPlus
, cp
->x1OrderPlusRecip
);
1138 recipLog(("using existing x1OrderPlusRecip\n"));
1142 void x1OrderPlusJustify(giant g
, curveParams
*cp
)
1144 CKASSERT(!isZero(cp
->x1OrderPlus
));
1147 * Calculate reciprocal if we don't have it
1149 calcX1OrderPlusRecip(cp
);
1150 curveOrderJustifyWithRecip(g
, cp
->x1OrderPlus
, cp
->x1OrderPlusRecip
);
1154 * g := g mod x1OrderPlus. Result may be zero.
1156 void x1OrderPlusMod(giant g
, curveParams
*cp
)
1158 CKASSERT(!isZero(cp
->x1OrderPlus
));
1161 * Calculate reciprocal if we don't have it
1163 calcX1OrderPlusRecip(cp
);
1164 modg_via_recip(cp
->x1OrderPlus
, cp
->x1OrderPlusRecip
, g
);
1168 * New general-purpose giant mod routine, 8 Jan 97.
1169 * x := x mod basePrime.
1173 * This stuff is used to analyze the critical loop behavior inside feemod().
1175 #define FEEMOD_LOOP_TEST 0
1176 #if FEEMOD_LOOP_TEST
1178 * these two are only examined via debugger
1180 unsigned feemodCalls
= 0; // calls to feemod()
1181 unsigned feemodMultLoops
= 0; // times while() loop runs > once
1182 #define FEEMOD_LOOP_INCR feemodLoops++
1183 #define FEEMOD_CALL_INCR feemodCalls++
1184 #else // FEEMOD_LOOP_TEST
1185 #define FEEMOD_LOOP_INCR
1186 #define FEEMOD_CALL_INCR
1187 #endif // FEEMOD_LOOP_TEST
1191 feemod(curveParams
*par
, giant x
)
1198 #if FEEMOD_LOOP_TEST
1199 unsigned feemodLoops
= 0;
1200 #endif // FEEMOD_LOOP_TEST
1202 FEEMOD_CALL_INCR
; // for FEEMOD_LOOP_TEST
1203 INCR_FEEMODS
; // for ellipticMeasure
1204 PROF_INCR(numFeemod
); // for general profiling
1206 switch(par
->primeType
) {
1209 * Super-optimized Mersenne prime modulus case
1211 gmersennemod(par
->q
, x
);
1216 * General 2**q-k case
1218 sign
= (x
->sign
< 0) ? -1 : 1;
1220 x
->sign
= abs(x
->sign
);
1221 if(gcompg(par
->basePrime
, x
) >= 0) {
1224 t1
= borrowGiant(par
->maxDigits
);
1225 t3
= borrowGiant(par
->maxDigits
);
1226 t4
= borrowGiant(par
->maxDigits
);
1227 t5
= borrowGiant(par
->maxDigits
);
1229 /* Begin OPT: 11 Jan 98 REC. */
1230 if( ((par
->q
& (GIANT_BITS_PER_DIGIT
- 1)) == 0) &&
1232 (par
->k
< GIANT_DIGIT_MASK
)) {
1235 * Microscopic mod for certain regions of {q,k}
1238 int j
, digits
, excess
, max
;
1240 giantDigit termHi
; // double precision
1242 giantDigit
*p1
, *p2
;
1244 digits
= par
->q
>> GIANT_LOG2_BITS_PER_DIGIT
;
1245 while(bitlen(x
) > par
->q
) {
1246 excess
= (x
->sign
) - digits
;
1247 max
= (excess
> digits
) ? excess
: digits
;
1253 if(excess
<= digits
) {
1254 carry
= VectorMultiply(par
->k
,
1259 /* propagate final carry */
1261 for(j
= excess
; j
< digits
; j
++) {
1264 * term = *p1 + carry;
1265 * *p1++ = term & 65535;
1266 * carry = term >> 16;
1268 termLo
= giantAddDigits(*p1
, carry
, &carry
);
1272 carry
= VectorMultiply(par
->k
,
1278 for(j
= digits
; j
< excess
; j
++) {
1280 * term = (par->k)*(*p2++) + carry;
1282 giantMulDigits(par
->k
,
1286 giantAddDouble(&termLo
, &termHi
, carry
);
1289 * *p1++ = term & 65535;
1290 * carry = term >> 16;
1301 if(x
->n
[max
] != 0) break;
1307 } else { /* Macroscopic mod for general PT_FEE case. */
1308 int_to_giant(par
->k
, t4
);
1309 while(bitlen(x
) > par
->q
) {
1310 /* Enter fast loop, as in FEE patent. */
1311 int_to_giant(1, t5
);
1313 extractbits(par
->q
, t3
, x
);
1314 while(bitlen(t3
) > par
->q
) {
1315 gshiftright(par
->q
, t3
);
1316 extractbits(par
->q
, t3
, t1
);
1326 /* End OPT: 11 Jan 98 REC. */
1328 sign2
= (x
->sign
< 0)? -1: 1;
1329 x
->sign
= abs(x
->sign
);
1335 if(gcompg(x
, par
->basePrime
) >=0) subg(par
->basePrime
, x
);
1337 giant t2
= borrowGiant(par
->maxDigits
);
1338 gtog(par
->basePrime
, t2
);
1344 /* end case PT_FEE */
1348 * Use brute-force modg.
1351 if(par
->basePrimeRecip
== NULL
) {
1352 CKRaise("feemod(PT_GENERAL): No basePrimeRecip!\n");
1354 #endif /* FEE_DEBUG */
1355 modg_via_recip(par
->basePrime
, par
->basePrimeRecip
, x
);
1359 /* never appears here */
1362 } /* switch primeType */
1364 #if FEEMOD_LOOP_TEST
1365 if(feemodLoops
> 1) {
1367 if(feemodLoops
> 2) {
1368 printf("feemod while loop executed %d times\n", feemodLoops
);
1371 #endif // FEEMOD_LOOP_TEST
1377 * For a given curveParams, calculate minBytes and maxDigits.
1378 * Assumes valid primeType, and also a valid basePrime for PT_GENERAL.
1380 void calcGiantSizes(curveParams
*cp
)
1383 if(cp
->primeType
== FPT_General
) {
1384 cp
->minBytes
= (bitlen(cp
->basePrime
) + 7) / 8;
1387 cp
->minBytes
= giantMinBytes(cp
->q
, cp
->k
);
1389 cp
->maxDigits
= giantMaxDigits(cp
->minBytes
);
1392 unsigned giantMinBytes(unsigned q
, int k
)
1394 unsigned kIsNeg
= (k
< 0) ? 1 : 0;
1396 return (q
+ 7 + kIsNeg
) / 8;
1400 * min value for "extra" bytes. Derived from the fact that during sig verify,
1401 * we have to multiply a giant representing a digest - which may be
1402 * 20 bytes for SHA1 - by a giant of minBytes.
1404 #define MIN_EXTRA_BYTES 20
1406 unsigned giantMaxDigits(unsigned minBytes
)
1408 unsigned maxBytes
= 4 * minBytes
;
1410 if((maxBytes
- minBytes
) < MIN_EXTRA_BYTES
) {
1411 maxBytes
= minBytes
+ MIN_EXTRA_BYTES
;
1413 return BYTES_TO_GIANT_DIGITS(maxBytes
);
1418 * Optimized binvg(basePrime, x). Avoids the general modg() in favor of
1421 int binvg_cp(curveParams
*cp
, giant x
)
1424 return(binvaux(cp
->basePrime
, x
));
1428 * Optimized binvg(x1OrderPlus, x). Uses x1OrderPlusMod().
1430 int binvg_x1OrderPlus(curveParams
*cp
, giant x
)
1432 x1OrderPlusMod(x
, cp
);
1433 return(binvaux(cp
->x1OrderPlus
, x
));