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 CRYPTKIT_ELL_PROJ_ENABLE
355 if((k
->twist
== CURVE_PLUS
) && (cp
->curveType
== FCT_Weierstrass
)) {
358 pointProj pt1
= newPointProj(cp
->maxDigits
);
360 CKASSERT((cp
->y1Plus
!= NULL
) && (!isZero(cp
->y1Plus
)));
361 CKASSERT(k
->y
!= NULL
);
363 /* pt1 := {x1Plus, y1Plus, 1} */
364 gtog(cp
->x1Plus
, pt1
->x
);
365 gtog(cp
->y1Plus
, pt1
->y
);
366 int_to_giant(1, pt1
->z
);
368 /* pt1 := pt1 * privateKey */
369 ellMulProjSimple(pt1
, privGiant
, cp
);
371 /* result back to {k->x, k->y} */
374 freePointProj(pt1
); // FIXME - clear the giants
379 #endif /* CRYPTKIT_ELL_PROJ_ENABLE */
381 if(k
->twist
== CURVE_PLUS
) {
382 gtog(cp
->x1Plus
, k
->x
);
385 gtog(cp
->x1Minus
, k
->x
);
387 elliptic_simple(k
->x
, privGiant
, k
->cp
);
391 int key_equal(key one
, key two
) {
392 if (keys_inconsistent(one
, two
)) return 0;
393 return !gcompg(one
->x
, two
->x
);
396 static void make_base(curveParams
*par
, giant result
)
397 /* Jams result with 2^q-k. */
399 gtog(par
->basePrime
, result
);
402 void make_base_prim(curveParams
*cp
)
403 /* Jams cp->basePrime with 2^q-k. Assumes valid maxDigits, q, k. */
405 giant tmp
= borrowGiant(cp
->maxDigits
);
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
);
415 static int sequalg(int n
, giant g
) {
416 if((g
->sign
== 1) && (g
->n
[0] == n
)) return(1);
422 * Elliptic multiply: x := n * {x, 1}
424 void elliptic_simple(giant x
, giant n
, curveParams
*par
) {
425 giant ztmp
= borrowGiant(par
->maxDigits
);
426 giant cur_n
= borrowGiant(par
->maxDigits
);
428 START_ELL_MEASURE(n
);
429 int_to_giant(1, ztmp
);
430 elliptic(x
, ztmp
, n
, par
);
441 * General elliptic multiply.
443 * {xx, zz} := k * {xx, zz}
445 void elliptic(giant xx
, giant zz
, giant k
, curveParams
*par
) {
454 if(sequalg(1,k
)) return;
456 ell_even(xx
, zz
, xx
, zz
, par
);
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
);
466 if(bitval(k
, pos
--)) {
467 ell_odd(xs
, zs
, xx
, zz
, xorg
, zorg
, par
);
468 ell_even(xs
, zs
, xs
, zs
, par
);
470 ell_odd(xx
, zz
, xs
, zs
, xorg
, zorg
, par
);
471 ell_even(xx
, zz
, xx
, zz
, par
);
473 } while (pos
>= 0); // REC fix 9/23/94
479 PROF_END(ellipticTime
);
483 * Completely rewritten in CryptKit-18, 13 Jan 1997, for new IEEE-style
486 void elliptic_add(giant x1
, giant x2
, giant x3
, curveParams
*par
, int s
) {
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
493 x3 = U/2 + s*Sqrt[U^2/4 - V]
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
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
);
517 if(gcompg(x1
, x2
)==0) {
519 numer_double(x1
, t1
, x3
, par
);
520 denom_double(x1
, t1
, t2
, par
);
522 mulg(t2
, x3
); feemod(par
, x3
);
525 numer_plus(x1
, x2
, t1
, par
);
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
);
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
);
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). */
540 if(s
!= SIGN_PLUS
) negg(t4
);
552 PROF_END(ellAddTime
);
558 giant
make_pad(giant privGiant
, key publicKey
) {
559 curveParams
*par
= publicKey
->cp
;
560 giant result
= newGiant(par
->maxDigits
);
562 gtog(publicKey
->x
, result
);
563 elliptic_simple(result
, privGiant
, par
);
567 static void ell_even(giant x1
, giant z1
, giant x2
, giant z2
, curveParams
*par
) {
574 t1
= borrowGiant(par
->maxDigits
);
575 t2
= borrowGiant(par
->maxDigits
);
576 t3
= borrowGiant(par
->maxDigits
);
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. */
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. */
591 else if((par
->curveType
== FCT_Weierstrass
) && isZero(par
->a
)) {
592 /* Begin Atkin3 OPT: 9 Jan 98 REC. */
594 gsquare(t1
); feemod(par
, t1
);
595 mulg(x1
, t1
); feemod(par
, t1
); /* t1 := x^3. */
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) */
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) */
611 /* End OPT: 9 Jan 98 REC. */
614 numer_double(x1
, z1
, t1
, par
);
615 denom_double(x1
, z1
, t2
, par
);
616 gtog(t1
, x2
); gtog(t2
, z2
);
622 EPROF_END(ellEvenTime
);
623 EPROF_INCR(numEllEvens
);
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);
634 static void ell_odd(giant x1
, giant z1
, giant x2
, giant z2
, giant xxor
,
635 giant zor
, curveParams
*par
)
642 t1
= borrowGiant(par
->maxDigits
);
643 t2
= borrowGiant(par
->maxDigits
);
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
);
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
);
667 else if((par
->curveType
== FCT_Weierstrass
) && isZero(par
->a
)) {
668 /* Begin Atkin3 OPT: 9 Jan 98 REC. */
670 giant t3
= borrowGiant(par
->maxDigits
);
671 giant t4
= borrowGiant(par
->maxDigits
);
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
);
687 /* End OPT: 9 Jan 98 REC. */
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
);
695 gtog(t1
, x2
); gtog(t2
, z2
);
701 EPROF_END(ellOddTime
);
702 EPROF_INCR(numEllOdds
);
705 printf("ell_odd end\n");
706 printf(" x2 : "); printGiant(x2);
707 printf(" z2 : "); printGiant(z2);
712 * return codes from keys_inconsistent() and signature_compare(). The actual
713 * values are not public; they are defined here for debugging.
715 #define CURVE_PARAM_MISMATCH 1
716 #define TWIST_PARAM_MISMATCH 2
717 #define SIGNATURE_INVALID 3
721 * Determine whether two keystructs have compatible parameters (i.e., same
722 * twist and curveParams). Return 0 if compatible, else non-zero.
724 static int keys_inconsistent(key pub1
, key pub2
){
725 if(!curveParamsEquivalent(pub1
->cp
, pub2
->cp
)) {
726 return CURVE_PARAM_MISMATCH
;
728 if(pub1
->twist
!= pub2
->twist
) {
729 return TWIST_PARAM_MISMATCH
;
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. */
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
);
752 if(gcompg(p1x
, p2x
) == 0) {
754 numer_double(p1x
, t1
, t2
, par
);
755 denom_double(p1x
, t1
, t3
, par
);
756 mulg(p0x
, t3
); subg(t3
, t2
);
759 numer_plus(p1x
, p2x
, t1
, par
);
760 gshiftleft(1, t1
); feemod(par
, t1
);
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
);
773 if(!isZero(t2
)) ret
= SIGNATURE_INVALID
;
779 PROF_END(sigCompTime
);
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.
793 t1
= borrowGiant(par
->maxDigits
);
794 t2
= borrowGiant(par
->maxDigits
);
796 gtog(x
, t1
); gsquare(t1
); feemod(par
, t1
);
797 gtog(z
, res
); gsquare(res
); feemod(par
, res
);
799 if(!isZero(par
->a
) ) {
800 if(!isone(par
->a
)) { /* Speedup - REC 17 Jan 1997. */
801 mulg(par
->a
, res
); feemod(par
, res
);
803 subg(res
, t1
); feemod(par
, t1
);
805 gsquare(t1
); feemod(par
, t1
);
806 /* t1 := (x^2 - a z^2)^2. */
807 if(isZero(par
->b
)) { /* Speedup - REC 17 Jan 1997. */
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
);
815 int_to_giant(0, res
);
817 addg(x
, res
); addg(x
, res
); mulg(par
->b
, res
);
819 gshiftleft(2, res
); mulg(z
, res
); feemod(par
, res
);
820 mulg(t2
, res
); feemod(par
, res
);
821 negg(res
); addg(t1
, res
);
827 PROF_END(numerDoubleTime
);
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).
839 t1
= borrowGiant(par
->maxDigits
);
840 t2
= borrowGiant(par
->maxDigits
);
842 gtog(x1
, t1
); mulg(x2
, t1
); feemod(par
, t1
);
843 gtog(x2
, t2
); addg(x1
, t2
); feemod(par
, t2
);
847 mulg(t2
, res
); feemod(par
, res
);
848 if(par
->curveType
== FCT_Weierstrass
) { // i.e., isZero(par->c)
852 mulg(par
->c
, t1
); feemod(par
, t1
);
857 addg(t1
, res
); feemod(par
, res
);
861 PROF_END(numerPlusTime
);
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). */
872 t1
= borrowGiant(par
->maxDigits
);
873 t2
= borrowGiant(par
->maxDigits
);
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
);
880 mulg(x
, res
); feemod(par
, res
);
881 gsquare(t1
); feemod(par
, t1
);
882 if(!isZero(par
->a
)) {
884 mulg(par
->a
, t2
); feemod(par
, t2
);
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
);
893 mulg(z
, res
); gshiftleft(2, res
);
898 PROF_END(denomDoubleTime
);
903 static void denom_times(giant x1
, giant z1
, giant x2
, giant z2
, giant res
,
905 /* Denominator algebra.
906 res := (x1 z2 - x2 z1)^2
912 t1
= borrowGiant(par
->maxDigits
);
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
);
919 PROF_END(denomTimesTime
);
922 static void numer_times(giant x1
, giant z1
, giant x2
, giant z2
, giant res
,
924 /* Numerator algebra.
925 res := (x1 x2 - a z1 z2)^2 -
926 4 b(x1 z2 + x2 z1 + c z1 z2) z1 z2
935 t1
= borrowGiant(par
->maxDigits
);
936 t2
= borrowGiant(par
->maxDigits
);
937 t3
= borrowGiant(par
->maxDigits
);
938 t4
= borrowGiant(par
->maxDigits
);
940 gtog(x1
, t1
); mulg(x2
, t1
); feemod(par
, t1
);
941 gtog(z1
, t2
); mulg(z2
, t2
); feemod(par
, t2
);
943 if(!isZero(par
->a
)) {
945 mulg(t2
, t3
); feemod(par
, t3
);
948 gsquare(res
); feemod(par
, res
);
951 if(par
->curveType
!= FCT_Weierstrass
) { // i.e., !isZero(par->c)
953 mulg(t2
, t3
); feemod(par
, t3
);
954 } else int_to_giant(0, t3
);
955 gtog(z1
, t4
); mulg(x2
, t4
); feemod(par
, t4
);
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
);
968 PROF_END(numerTimesTime
);
974 static void feepowermodg(curveParams
*par
, giant x
, giant n
)
983 t1
= borrowGiant(par
->maxDigits
);
989 if(bitval(n
, pos
++)) {
998 PROF_END(powerModTime
);
1002 * Set g := g mod curveOrder;
1003 * force g to be between 2 and (curveOrder-2), inclusive.
1005 * Tolerates zero curve orders (indicating "not known").
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.
1012 void curveOrderJustify(giant g
, giant curveOrder
)
1016 CKASSERT(!isZero(curveOrder
));
1018 recip
= borrowGiant(2 * abs(g
->sign
));
1019 make_recip(curveOrder
, recip
);
1020 curveOrderJustifyWithRecip(g
, curveOrder
, recip
);
1025 * New optimzation of curveOrderJustify using known reciprocal, 11 June 1997.
1026 * g is set to be within [2, curveOrder-2].
1028 static void curveOrderJustifyWithRecip(giant g
, giant curveOrder
, giant recip
)
1032 CKASSERT(!isZero(curveOrder
));
1034 modg_via_recip(curveOrder
, recip
, g
); // g now in [0, curveOrder-1]
1038 * First degenerate case - (g == 0) : set g := 2
1040 dbgLog(("curveOrderJustify: case 1\n"));
1046 * Second case - (g == 1) : set g := 2
1048 dbgLog(("curveOrderJustify: case 2\n"));
1052 tmp
= borrowGiant(g
->capacity
);
1055 if(gcompg(tmp
, curveOrder
) == 0) {
1057 * Third degenerate case - (g == (curveOrder-1)) : set g -= 1
1059 dbgLog(("curveOrderJustify: case 3\n"));
1060 int_to_giant(1, tmp
);
1067 #define RECIP_DEBUG 0
1069 #define recipLog(x) printf x
1070 #else // RECIP_DEBUG
1072 #endif // RECIP_DEBUG
1075 * curveOrderJustify routines with specific orders, using (and possibly
1076 * generating) associated reciprocals.
1078 void lesserX1OrderJustify(giant g
, curveParams
*cp
)
1081 * Note this is a pointer to a giant in *cp, not a newly
1084 giant lesserX1Ord
= lesserX1Order(cp
);
1086 if(isZero(lesserX1Ord
)) {
1091 * Calculate reciprocal if we don't have it
1093 if(isZero(cp
->lesserX1OrderRecip
)) {
1094 if((lesserX1Ord
== cp
->x1OrderPlus
) &&
1095 (!isZero(cp
->x1OrderPlusRecip
))) {
1097 * lesserX1Ord happens to be x1OrderPlus, and we
1098 * have a reciprocal for x1OrderPlus. Copy it over.
1101 "x1OrderPlusRecip --> lesserX1OrderRecip\n"));
1102 gtog(cp
->x1OrderPlusRecip
, cp
->lesserX1OrderRecip
);
1105 /* Calculate the reciprocal. */
1106 recipLog(("calc lesserX1OrderRecip\n"));
1107 make_recip(lesserX1Ord
, cp
->lesserX1OrderRecip
);
1111 recipLog(("using existing lesserX1OrderRecip\n"));
1113 curveOrderJustifyWithRecip(g
, lesserX1Ord
, cp
->lesserX1OrderRecip
);
1117 * Common code used by x1OrderPlusJustify() and x1OrderPlusMod() to generate
1118 * reciprocal of x1OrderPlus.
1119 * 8 Sep 1998 - also used by feeSigSign().
1121 void calcX1OrderPlusRecip(curveParams
*cp
)
1123 if(isZero(cp
->x1OrderPlusRecip
)) {
1124 if((cp
->x1OrderPlus
== lesserX1Order(cp
)) &&
1125 (!isZero(cp
->lesserX1OrderRecip
))) {
1127 * lesserX1Order happens to be x1OrderPlus, and we
1128 * have a reciprocal for lesserX1Order. Copy it over.
1131 "lesserX1OrderRecip --> x1OrderPlusRecip\n"));
1132 gtog(cp
->lesserX1OrderRecip
, cp
->x1OrderPlusRecip
);
1135 /* Calculate the reciprocal. */
1136 recipLog(("calc x1OrderPlusRecip\n"));
1137 make_recip(cp
->x1OrderPlus
, cp
->x1OrderPlusRecip
);
1141 recipLog(("using existing x1OrderPlusRecip\n"));
1145 void x1OrderPlusJustify(giant g
, curveParams
*cp
)
1147 CKASSERT(!isZero(cp
->x1OrderPlus
));
1150 * Calculate reciprocal if we don't have it
1152 calcX1OrderPlusRecip(cp
);
1153 curveOrderJustifyWithRecip(g
, cp
->x1OrderPlus
, cp
->x1OrderPlusRecip
);
1157 * g := g mod x1OrderPlus. Result may be zero.
1159 void x1OrderPlusMod(giant g
, curveParams
*cp
)
1161 CKASSERT(!isZero(cp
->x1OrderPlus
));
1164 * Calculate reciprocal if we don't have it
1166 calcX1OrderPlusRecip(cp
);
1167 modg_via_recip(cp
->x1OrderPlus
, cp
->x1OrderPlusRecip
, g
);
1171 * New general-purpose giant mod routine, 8 Jan 97.
1172 * x := x mod basePrime.
1176 * This stuff is used to analyze the critical loop behavior inside feemod().
1178 #define FEEMOD_LOOP_TEST 0
1179 #if FEEMOD_LOOP_TEST
1181 * these two are only examined via debugger
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
1194 feemod(curveParams
*par
, giant x
)
1201 #if FEEMOD_LOOP_TEST
1202 unsigned feemodLoops
= 0;
1203 #endif // FEEMOD_LOOP_TEST
1205 FEEMOD_CALL_INCR
; // for FEEMOD_LOOP_TEST
1206 INCR_FEEMODS
; // for ellipticMeasure
1207 PROF_INCR(numFeemod
); // for general profiling
1209 switch(par
->primeType
) {
1212 * Super-optimized Mersenne prime modulus case
1214 gmersennemod(par
->q
, x
);
1219 * General 2**q-k case
1221 sign
= (x
->sign
< 0) ? -1 : 1;
1223 x
->sign
= abs(x
->sign
);
1224 if(gcompg(par
->basePrime
, x
) >= 0) {
1227 t1
= borrowGiant(par
->maxDigits
);
1228 t3
= borrowGiant(par
->maxDigits
);
1229 t4
= borrowGiant(par
->maxDigits
);
1230 t5
= borrowGiant(par
->maxDigits
);
1232 /* Begin OPT: 11 Jan 98 REC. */
1233 if( ((par
->q
& (GIANT_BITS_PER_DIGIT
- 1)) == 0) &&
1235 (par
->k
< GIANT_DIGIT_MASK
)) {
1238 * Microscopic mod for certain regions of {q,k}
1241 int j
, digits
, excess
, max
;
1243 giantDigit termHi
; // double precision
1245 giantDigit
*p1
, *p2
;
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
;
1256 if(excess
<= digits
) {
1257 carry
= VectorMultiply(par
->k
,
1262 /* propagate final carry */
1264 for(j
= excess
; j
< digits
; j
++) {
1267 * term = *p1 + carry;
1268 * *p1++ = term & 65535;
1269 * carry = term >> 16;
1271 termLo
= giantAddDigits(*p1
, carry
, &carry
);
1275 carry
= VectorMultiply(par
->k
,
1281 for(j
= digits
; j
< excess
; j
++) {
1283 * term = (par->k)*(*p2++) + carry;
1285 giantMulDigits(par
->k
,
1289 giantAddDouble(&termLo
, &termHi
, carry
);
1292 * *p1++ = term & 65535;
1293 * carry = term >> 16;
1304 if(x
->n
[max
] != 0) break;
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
);
1316 extractbits(par
->q
, t3
, x
);
1317 while(bitlen(t3
) > par
->q
) {
1318 gshiftright(par
->q
, t3
);
1319 extractbits(par
->q
, t3
, t1
);
1329 /* End OPT: 11 Jan 98 REC. */
1331 sign2
= (x
->sign
< 0)? -1: 1;
1332 x
->sign
= abs(x
->sign
);
1338 if(gcompg(x
, par
->basePrime
) >=0) subg(par
->basePrime
, x
);
1340 giant t2
= borrowGiant(par
->maxDigits
);
1341 gtog(par
->basePrime
, t2
);
1347 /* end case PT_FEE */
1351 * Use brute-force modg.
1354 if(par
->basePrimeRecip
== NULL
) {
1355 CKRaise("feemod(PT_GENERAL): No basePrimeRecip!\n");
1357 #endif /* FEE_DEBUG */
1358 modg_via_recip(par
->basePrime
, par
->basePrimeRecip
, x
);
1362 /* never appears here */
1365 } /* switch primeType */
1367 #if FEEMOD_LOOP_TEST
1368 if(feemodLoops
> 1) {
1370 if(feemodLoops
> 2) {
1371 printf("feemod while loop executed %d times\n", feemodLoops
);
1374 #endif // FEEMOD_LOOP_TEST
1380 * For a given curveParams, calculate minBytes and maxDigits.
1381 * Assumes valid primeType, and also a valid basePrime for PT_GENERAL.
1383 void calcGiantSizes(curveParams
*cp
)
1386 if(cp
->primeType
== FPT_General
) {
1387 cp
->minBytes
= (bitlen(cp
->basePrime
) + 7) / 8;
1390 cp
->minBytes
= giantMinBytes(cp
->q
, cp
->k
);
1392 cp
->maxDigits
= giantMaxDigits(cp
->minBytes
);
1395 unsigned giantMinBytes(unsigned q
, int k
)
1397 unsigned kIsNeg
= (k
< 0) ? 1 : 0;
1399 return (q
+ 7 + kIsNeg
) / 8;
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.
1407 #define MIN_EXTRA_BYTES 20
1409 unsigned giantMaxDigits(unsigned minBytes
)
1411 unsigned maxBytes
= 4 * minBytes
;
1413 if((maxBytes
- minBytes
) < MIN_EXTRA_BYTES
) {
1414 maxBytes
= minBytes
+ MIN_EXTRA_BYTES
;
1416 return BYTES_TO_GIANT_DIGITS(maxBytes
);
1421 * Optimized binvg(basePrime, x). Avoids the general modg() in favor of
1424 int binvg_cp(curveParams
*cp
, giant x
)
1427 return(binvaux(cp
->basePrime
, x
));
1431 * Optimized binvg(x1OrderPlus, x). Uses x1OrderPlusMod().
1433 int binvg_x1OrderPlus(curveParams
*cp
, giant x
)
1435 x1OrderPlusMod(x
, cp
);
1436 return(binvaux(cp
->x1OrderPlus
, x
));