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 * curveParams.c - FEE curve parameter static data and functions
16 * Changed to compile with C++.
18 * Added y1Plus for IEEE P1363 compliance.
19 * Added curveParamsInferFields().
21 * Mods for giantDigit.
23 * Added primeType, m, basePrimeRecip; added a few PT_GENERAL curves.
24 * 19 Jan 1998 at Apple
25 * New curve: q=160, k=57
26 * 09 Jan 1998 at Apple
27 * Removed obsolete (i.e., incomplete) curves parameters.
28 * 11 Jun 1997 at Apple
29 * Added x1OrderPlusRecip and lesserX1OrderRecip fields
30 * Added curveParamsInitGiants()
32 * Major mods for IEEE-style parameters.
37 #include "curveParams.h"
38 #include "giantIntegers.h"
40 #include "ellipticProj.h"
46 typedef unsigned short arrayDigit
;
48 static giant
arrayToGiant(const arrayDigit
*array
);
51 * Can't declare giants statically; we declare them here via static arrayDigit
52 * arrays which contain the 'digits' in base 65536 of a giant
53 * used as a curve parameter. First element is sign; next element is
54 * l.s. digit; size of each array is abs(sign) + 1. These arrays are
55 * converted to a giant via arrayToGiant().
57 * Static q and k values, as well as pointers to the arrayDigit arrays
58 * associated with the various giants for a given curve, are kept in an
59 * array of curveParamsStatic structs; a feeDepth is an index into this
60 * array. A curveParamsStatic struct is converted to a curveParams struct in
61 * curveParamsForDepth().
64 feePrimeType primeType
;
65 feeCurveType curveType
;
68 const arrayDigit
*basePrime
; // FPT_General only
69 arrayDigit m
; // must be 1 for current release
73 const arrayDigit
*x1Plus
;
74 const arrayDigit
*y1Plus
; // optional, currently only used for ECDSA curves
75 const arrayDigit
*x1Minus
; // optional, not used for ECDSA curves
76 const arrayDigit
*cOrderPlus
;
77 const arrayDigit
*cOrderMinus
; // optional, not used for ECDSA curves
78 const arrayDigit
*x1OrderPlus
;
79 const arrayDigit
*x1OrderMinus
; // optional, not used for ECDSA curves
80 const arrayDigit
*x1OrderPlusRecip
;
83 * A null lesserX1OrderRecip when x1OrderPlusRecip is non-null
84 * means that the two values are identical; in this case, only
85 * one giant is alloc'd in the actual curveParams struct.
87 const arrayDigit
*lesserX1OrderRecip
;
91 * First some common giant-arrays used in lots of curveGiants.
93 static const arrayDigit ga_666
[] = {1, 666 }; // a common value for 'c'
94 static const arrayDigit ga_zero
[] = {1, 0 }; // (giant)0
95 static const arrayDigit ga_one
[] = {1, 1 }; // (giant)1
98 * Here are the actual static arrays, one for each giant we know about.
99 * Since they're variable size, we have to allocate and name each one
103 #include "curveParamData.h"
107 * Now the curveParamsStatic structs, which provide templates for creating the
108 * fields in a specific curveParams struct.
110 * All giants in a curveParamsStatic struct except for basePrime are
113 * Note these are stored as an array, an index into which is a feeDepth
118 static const curveParamsStatic curveParamsArray
[] = {
122 * FEE CURVE: USE FOR FEE SIG. & FEED ONLY.
123 * primeType->Mersenne
124 * curveType->Montgomery
125 * q = 31; k = 1; p = 2^q - k;
126 * a = 1; b = 0; c = 666;
127 * Both orders composite.
132 NULL
, // basePrime only used for FPT_General
144 ga_31m_x1OrderPlusRecip
,
145 ga_31m_lesserX1OrderRecip
150 * IEEE P1363 COMPATIBLE.
151 * primeType->Mersenne
152 * curveType->Weierstrass
153 * q = 31; k = 1; p = 2^q-k;
154 * a = 5824692 b = 2067311435 c = 0
160 NULL
, // basePrime only used for FPT_General
172 ga_31w_x1OrderPlusRecip
,
173 NULL
// x1PlusOrder is lesser
178 * FEE CURVE: USE FOR FEE SIG. & FEED ONLY.
179 * primeType->Mersenne
180 * curveType->Montgomery
181 * q = 127; k = 1; p = 2^q - k;
182 * a = 1; b = 0; c = 666;
183 * Both orders composite.
187 127, 1, // q = 127; k = 1
188 NULL
, // basePrime only used for FPT_General
199 ga_127m_x1OrderMinus
,
200 ga_127m_x1OrderPlusRecip
,
201 ga_127m_lesserX1OrderRecip
206 * IEEE P1363 COMPATIBLE.
208 * curveType->Weierstrass
209 * q = 127; k = -57675; p = 2^q - k;
210 * a = 170141183460469025572049133804586627403;
211 * b = 170105154311605172483148226534443139403; c = 0;
216 127, -57675, // q = 127; k = -57675
217 NULL
, // basePrime only used for FPT_General
228 ga_128w_x1OrderMinus
,
229 ga_128w_x1OrderPlusRecip
,
230 /* REC said NULL, dmitch says: */
231 ga_128w_lesserX1OrderRecip
// x1PlusOrder is lesser
236 * IEEE P1363 COMPATIBLE.
238 * curveType->Weierstrass
239 * q = 160; k = -5875; p = 2^q - k;
240 * a = 1461501637330902918203684832716283019448563798259;
241 * b = 36382017816364032; c = 0;
242 * Both orders prime.:
246 160, -5875, // q = 160; k = -5875
247 NULL
, // basePrime only used for FPT_General
258 ga_161w_x1OrderMinus
,
259 ga_161w_x1OrderPlusRecip
,
260 /* dmitch addenda - REC said NULL */
261 ga_161w_lesserX1OrderRecip
266 * IEEE P1363 COMPATIBLE.
268 * curveType->Weierstrass
269 * p is a 161-bit random prime (below, ga_161_gen_bp[]);
270 * a = -152; b = 722; c = 0;
271 * Both orders composite.
276 ga_161_gen_bp
, // basePrime
284 ga_161_gen_plusOrder
,
285 ga_161_gen_minusOrder
,
286 ga_161_gen_x1OrderPlus
,
287 ga_161_gen_x1OrderMinus
,
288 ga_161_gen_x1OrderPlusRecip
,
289 NULL
// x1PlusOrder is lesser
294 * IEEE P1363 COMPATIBLE.
295 * (NIST-P-192 RECOMMENDED PRIME)
297 * curveType->Weierstrass
298 * p is a 192-bit random prime (below, ga_161_gen_bp[]);
300 * b = 2455155546008943817740293915197451784769108058161191238065;
302 * Plus-order is prime, minus-order is composite.
306 192, 0, // only used for initGiantStacks(giantMaxDigits())
307 ga_192_gen_bp
, // basePrime
315 ga_192_gen_plusOrder
,
316 ga_192_gen_minusOrder
,
317 ga_192_gen_x1OrderPlus
,
318 ga_192_gen_x1OrderMinus
,
319 ga_192_gen_x1OrderPlusRecip
,
320 ga_192_gen_lesserX1OrderRecip
323 /* ANSI X9.62/Certicom curves */
327 * ANSI X9.62/Certicom secp192r1
331 192, 0, // only used for initGiantStacks(giantMaxDigits())
332 ga_192_secp_bp
, // basePrime
340 ga_192_secp_plusOrder
,
342 ga_192_secp_x1OrderPlus
,
343 NULL
, // x1OrderMinus,
344 ga_192_secp_x1OrderPlusRecip
,
349 * ANSI X9.62/Certicom secp256r1
353 256, 0, // only used for initGiantStacks(giantMaxDigits())
354 ga_256_secp_bp
, // basePrime
362 ga_256_secp_plusOrder
,
364 ga_256_secp_x1OrderPlus
,
366 ga_256_secp_x1OrderPlusRecip
,
372 * ANSI X9.62/Certicom secp384r1
376 384, 0, // only used for initGiantStacks(giantMaxDigits())
377 ga_384_secp_bp
, // basePrime
385 ga_384_secp_plusOrder
,
387 ga_384_secp_x1OrderPlus
,
389 ga_384_secp_x1OrderPlusRecip
,
395 * ANSI X9.62/Certicom secp521r1
400 ga_521_secp_bp
, // basePrime
408 ga_521_secp_plusOrder
,
410 ga_521_secp_x1OrderPlus
,
412 ga_521_secp_x1OrderPlusRecip
,
418 * Convert the static form of a giant - i.e., an array of arrayDigits,
419 * the first of which is the sign, the remainder of which are base 65536
420 * digits - into a giant. A null pointer on input results in a null return.
422 static giant
arrayToGiant(const arrayDigit
*array
)
424 unsigned numBytes
; // in result->n[]
425 int numDigits
; // ditto
430 unsigned digitDex
; // index into result->n[]
431 unsigned digitByte
; // byte selector in digit
432 const arrayDigit
*ap
; // running ptr into array
436 CKRaise("arrayToGiant: NULL array");
438 sign
= (short)array
[0];
439 numBytes
= abs(sign
) * sizeof(unsigned short);
440 numDigits
= BYTES_TO_GIANT_DIGITS(numBytes
);
442 /* note giantstruct has one explicit giantDigit */
443 result
= (giant
) fmalloc(sizeof(giantstruct
) +
444 ((numDigits
- 1) * GIANT_BYTES_PER_DIGIT
));
445 result
->capacity
= numDigits
;
451 for(i
=0; i
<numBytes
;) {
452 for(digitByte
=0; digitByte
<GIANT_BYTES_PER_DIGIT
; digitByte
++) {
453 /* grab a byte from the array */
455 /* odd byte - snag it and advance to next array digit */
456 byte
= (unsigned char)(*ap
++ >> 8);
459 /* even, i.e., l.s. byte */
460 byte
= (unsigned char)(*ap
);
463 /* add byte to current digit */
464 digit
|= (byte
<< (8 * digitByte
));
465 if(++i
== numBytes
) {
466 /* end of array, perhaps in the midst of a digit */
470 result
->n
[digitDex
++] = digit
;
475 * -- array elements are unsigned. The first element is
476 * he number of SHORTS in the array; convert to native
478 * -- in the very odd (test only) case of giantDigit = unsigned char,
479 * we might have fewer valid digits than numDigits (might have
483 result
->sign
= -numDigits
;
486 result
->sign
= numDigits
;
493 * Obtain a malloc'd and uninitialized curveParams, to be init'd by caller.
495 curveParams
*newCurveParams(void)
497 curveParams
*params
= (curveParams
*) fmalloc(sizeof(curveParams
));
499 bzero(params
, sizeof(curveParams
));
504 * Alloc and zero reciprocal giants, when maxDigits is known.
505 * Currently only called when creating a curveParams from a public key.
506 * cp->primeType must be valid on input.
508 void allocRecipGiants(curveParams
*cp
)
510 cp
->lesserX1OrderRecip
= newGiant(cp
->maxDigits
);
511 cp
->x1OrderPlusRecip
= newGiant(cp
->maxDigits
);
512 int_to_giant(0, cp
->lesserX1OrderRecip
);
513 int_to_giant(0, cp
->x1OrderPlusRecip
);
517 * Obtain a malloc'd curveParams for a specified feeDepth.
519 curveParams
*curveParamsForDepth(feeDepth depth
)
522 const curveParamsStatic
*cps
= &curveParamsArray
[depth
];
524 if(depth
> FEE_DEPTH_MAX
) {
528 cp
= newCurveParams();
529 cp
->primeType
= cps
->primeType
;
530 cp
->curveType
= cps
->curveType
;
534 if(cp
->primeType
== FPT_General
) {
535 cp
->basePrime
= arrayToGiant(cps
->basePrime
);
537 cp
->a
= arrayToGiant(cps
->a
);
538 cp
->b
= arrayToGiant(cps
->b
);
539 cp
->c
= arrayToGiant(cps
->c
);
540 cp
->x1Plus
= arrayToGiant(cps
->x1Plus
);
542 cp
->y1Plus
= arrayToGiant(cps
->y1Plus
);
545 cp
->x1Minus
= arrayToGiant(cps
->x1Minus
);
547 cp
->cOrderPlus
= arrayToGiant(cps
->cOrderPlus
);
548 if(cps
->cOrderMinus
) {
549 cp
->cOrderMinus
= arrayToGiant(cps
->cOrderMinus
);
551 cp
->x1OrderPlus
= arrayToGiant(cps
->x1OrderPlus
);
552 if(cps
->x1OrderMinus
) {
553 cp
->x1OrderMinus
= arrayToGiant(cps
->x1OrderMinus
);
555 cp
->x1OrderPlusRecip
= arrayToGiant(cps
->x1OrderPlusRecip
);
558 * Special case optimization for equal reciprocals.
560 if(cps
->lesserX1OrderRecip
== NULL
) {
561 cp
->lesserX1OrderRecip
= cp
->x1OrderPlusRecip
;
564 cp
->lesserX1OrderRecip
= arrayToGiant(cps
->lesserX1OrderRecip
);
567 /* remainder calculated at runtime */
568 curveParamsInferFields(cp
);
573 * Alloc a new curveParams struct as a copy of specified instance.
574 * This is the only way we can create a curveParams struct which doesn't
575 * match any existing known curve params.
577 curveParams
*curveParamsCopy(curveParams
*cp
)
579 curveParams
*newcp
= newCurveParams();
581 newcp
->primeType
= cp
->primeType
;
582 newcp
->curveType
= cp
->curveType
;
586 newcp
->basePrime
= copyGiant(cp
->basePrime
);
587 newcp
->minBytes
= cp
->minBytes
;
588 newcp
->maxDigits
= cp
->maxDigits
;
590 newcp
->a
= copyGiant(cp
->a
);
591 newcp
->b
= copyGiant(cp
->b
);
592 newcp
->c
= copyGiant(cp
->c
);
593 newcp
->x1Plus
= copyGiant(cp
->x1Plus
);
595 newcp
->x1Minus
= copyGiant(cp
->x1Minus
);
597 newcp
->y1Plus
= copyGiant(cp
->y1Plus
);
598 newcp
->cOrderPlus
= copyGiant(cp
->cOrderPlus
);
599 if(cp
->cOrderMinus
) {
600 newcp
->cOrderMinus
= copyGiant(cp
->cOrderMinus
);
602 newcp
->x1OrderPlus
= copyGiant(cp
->x1OrderPlus
);
603 if(cp
->x1OrderMinus
) {
604 newcp
->x1OrderMinus
= copyGiant(cp
->x1OrderMinus
);
607 newcp
->x1OrderPlusRecip
= copyGiant(cp
->x1OrderPlusRecip
);
608 if(cp
->x1OrderPlusRecip
== cp
->lesserX1OrderRecip
) {
610 * Equal reciprocals; avoid new malloc
612 newcp
->lesserX1OrderRecip
= newcp
->x1OrderPlusRecip
;
615 newcp
->lesserX1OrderRecip
= copyGiant(cp
->lesserX1OrderRecip
);
617 if(cp
->primeType
== FPT_General
) {
618 newcp
->basePrimeRecip
= copyGiant(cp
->basePrimeRecip
);
624 * Free a curveParams struct.
626 void freeCurveParams(curveParams
*cp
)
628 if(cp
->basePrime
!= NULL
) {
629 freeGiant(cp
->basePrime
);
640 if(cp
->x1Plus
!= NULL
) {
641 freeGiant(cp
->x1Plus
);
643 if(cp
->x1Minus
!= NULL
) {
644 freeGiant(cp
->x1Minus
);
646 if(cp
->y1Plus
!= NULL
) {
647 freeGiant(cp
->y1Plus
);
649 if(cp
->cOrderPlus
!= NULL
) {
650 freeGiant(cp
->cOrderPlus
);
652 if(cp
->cOrderMinus
!= NULL
) {
653 freeGiant(cp
->cOrderMinus
);
655 if(cp
->x1OrderPlus
!= NULL
) {
656 freeGiant(cp
->x1OrderPlus
);
658 if(cp
->x1OrderMinus
!= NULL
) {
659 freeGiant(cp
->x1OrderMinus
);
661 if(cp
->x1OrderPlusRecip
!= NULL
) {
662 freeGiant(cp
->x1OrderPlusRecip
);
666 * Special case - if these are equal, we only alloc'd one giant
668 if(cp
->lesserX1OrderRecip
!= cp
->x1OrderPlusRecip
) {
669 freeGiant(cp
->lesserX1OrderRecip
);
671 if(cp
->basePrimeRecip
!= NULL
) {
672 freeGiant(cp
->basePrimeRecip
);
678 * Returns 1 if two sets of curve parameters are equivalent, else returns 0.
680 int curveParamsEquivalent(curveParams
*cp1
, curveParams
*cp2
)
684 * Trivial case, actually common for signature verify
688 if(cp1
->primeType
!= cp2
->primeType
) {
691 if(cp1
->curveType
!= cp2
->curveType
) {
694 if(cp1
->k
!= cp2
->k
) {
697 if(cp1
->q
!= cp2
->q
) {
700 if(cp1
->m
!= cp2
->m
) {
703 if(gcompg(cp1
->basePrime
, cp2
->basePrime
)) {
706 if(gcompg(cp1
->a
, cp2
->a
)) {
709 if(gcompg(cp1
->b
, cp2
->b
)) {
712 if(gcompg(cp1
->c
, cp2
->c
)) {
715 if(gcompg(cp1
->x1Plus
, cp2
->x1Plus
)) {
718 if((cp1
->x1Minus
!= NULL
) && (cp2
->x1Minus
!= NULL
)) {
719 if(gcompg(cp1
->x1Minus
, cp2
->x1Minus
)) {
723 if(gcompg(cp1
->cOrderPlus
, cp2
->cOrderPlus
)) {
726 if((cp1
->cOrderMinus
!= NULL
) && (cp2
->cOrderMinus
!= NULL
)) {
727 if(gcompg(cp1
->cOrderMinus
, cp2
->cOrderMinus
)) {
731 if(gcompg(cp1
->x1OrderPlus
, cp2
->x1OrderPlus
)) {
734 if((cp1
->x1OrderMinus
!= NULL
) && (cp2
->x1OrderMinus
!= NULL
)) {
735 if(gcompg(cp1
->x1OrderMinus
, cp2
->x1OrderMinus
)) {
740 * If we got this far, reciprocals can't possibly be different
746 * Obtain the lesser of {x1OrderPlus, x1OrderMinus}. Returned value is not
747 * malloc'd; it's a pointer to one of the orders in *cp.
749 giant
lesserX1Order(curveParams
*cp
)
751 CKASSERT(!isZero(cp
->x1OrderPlus
));
753 if(cp
->x1OrderMinus
== NULL
) {
754 return(cp
->x1OrderPlus
);
756 else if(gcompg(cp
->x1OrderPlus
, cp
->x1OrderMinus
) >= 0) {
757 return(cp
->x1OrderMinus
);
760 return(cp
->x1OrderPlus
);
766 * Infer the following fields from a partially constructed curveParams:
768 * basePrimeRecip if primeType == FPT_General
769 * basePrime if primeType != FPT_General
770 * y1Plus if curveType == FCT_Weierstrass and not pre-calculated
774 * Assumes the following valid on entry:
777 * basePrime if primeType == FPT_General
778 * q, k if primeType != FPT_General
780 void curveParamsInferFields(curveParams
*cp
)
782 /* calc maxDigits, minBytes */
785 /* basePrime or its reciprocal */
786 if(cp
->primeType
== FPT_General
) {
787 /* FIXME this should be declared statically! */
788 cp
->basePrimeRecip
= newGiant(cp
->maxDigits
);
789 make_recip(cp
->basePrime
, cp
->basePrimeRecip
);
793 * FPT_FEE, FPT_Mersenne
795 cp
->basePrime
= newGiant(cp
->maxDigits
);
800 if(cp
->curveType
== FCT_Weierstrass
) {
801 if(cp
->y1Plus
== NULL
) {
802 /* ECDSA Curves already have this */
803 pointProj pt
= newPointProj(cp
->maxDigits
);
804 findPointProj(pt
, cp
->x1Plus
, cp
);
806 /* initial point is supposed to be on curve! */
807 if(gcompg(pt
->x
, cp
->x1Plus
)) {
808 CKRaise("curveParamsInferFields failure");
810 cp
->y1Plus
= copyGiant(pt
->y
);
815 cp
->y1Plus
= newGiant(1);
819 if((cp
->x1OrderPlusRecip
== NULL
) || isZero(cp
->x1OrderPlusRecip
)) {
821 * an easy way of figuring this one out, this should not
824 cp
->x1OrderPlusRecip
= newGiant(cp
->maxDigits
);
825 make_recip(cp
->x1OrderPlus
, cp
->x1OrderPlusRecip
);
826 if(cp
->lesserX1OrderRecip
!= NULL
) {
827 freeGiant(cp
->lesserX1OrderRecip
);
829 cp
->lesserX1OrderRecip
= cp
->x1OrderPlusRecip
;
834 * Given key size in bits, obtain the asssociated depth.
835 * Returns FR_IllegalDepth if specify key size not found
836 * in current curve tables.
840 feeReturn
feeKeyBitsToDepth(unsigned keySize
,
841 feePrimeType primeType
, /* FPT_Fefault means "best one" */
842 feeCurveType curveType
, /* FCT_Default means "best one" */
845 feeReturn frtn
= FR_Success
;
848 if(primeType
== FPT_General
) {
849 return FR_IllegalDepth
;
851 /* note we cut a request for FPT_FEE some slack...this is actually
852 * FPT_Mersenne, but that is technically a subset of FEE. */
855 *depth
= FEE_DEPTH_31M
;
857 case FCT_Weierstrass
:
859 *depth
= FEE_DEPTH_31W
;
862 return FR_IllegalDepth
;
866 /* Montgomery only */
867 if(primeType
== FPT_General
) {
868 return FR_IllegalDepth
;
870 /* note we cut a request for FPT_FEE some slack...this is actually
871 * FPT_Mersenne, but that is technically a subset of FEE. */
875 *depth
= FEE_DEPTH_127M
;
877 case FCT_Weierstrass
:
879 return FR_IllegalDepth
;
883 /* Weierstrass/feemod only */
887 return FR_IllegalDepth
;
889 /* FPT_Default, FPT_FEE */
893 case FCT_Weierstrass
:
895 *depth
= FEE_DEPTH_128W
;
898 return FR_IllegalDepth
;
903 case FCT_Weierstrass
:
907 *depth
= FEE_DEPTH_161G
;
911 *depth
= FEE_DEPTH_161W
;
914 /* i.e., FPT_Mersenne */
915 return FR_IllegalDepth
;
919 return FR_IllegalDepth
;
926 return FR_IllegalDepth
;
927 case FCT_Weierstrass
:
932 *depth
= FEE_DEPTH_192G
;
935 /* i.e., FPT_Mersenne, FPT_FEE */
936 return FR_IllegalDepth
;
945 return FR_IllegalDepth
;
947 *depth
= FEE_DEPTH_secp192r1
;
957 return FR_IllegalDepth
;
964 return FR_IllegalDepth
;
966 *depth
= FEE_DEPTH_secp256r1
;
974 return FR_IllegalDepth
;
981 return FR_IllegalDepth
;
983 *depth
= FEE_DEPTH_secp384r1
;
991 return FR_IllegalDepth
;
998 return FR_IllegalDepth
;
1000 *depth
= FEE_DEPTH_secp521r1
;
1004 frtn
= FR_IllegalDepth
;
1008 printf("feeKeyBitsToDepth: depth %d\n", *depth
);
1014 * Obtain depth for specified curveParams
1016 feeReturn
curveParamsDepth(
1021 return FR_IllegalArg
;
1024 /* We do it this way to allow reconstructing depth from an encoded curveParams */
1025 feeCurveType curveType
= cp
->curveType
;
1026 if((curveType
== FCT_Weierstrass
) && (cp
->x1Minus
== NULL
)) {
1027 /* actually an ANSI curve */
1028 curveType
= FCT_ANSI
;
1030 return feeKeyBitsToDepth(cp
->q
, cp
->primeType
, curveType
, depth
);