+/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved.
+ *
+ * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT
+ * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE
+ * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE
+ * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE,
+ * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL
+ * EXPOSE YOU TO LIABILITY.
+ ***************************************************************************
+ *
+ * curveParams.c - FEE curve parameter static data and functions
+ *
+ * Revision History
+ * ----------------
+ * 10/06/98 ap
+ * Changed to compile with C++.
+ * 9 Sep 98 at NeXT
+ * Added y1Plus for IEEE P1363 compliance.
+ * Added curveParamsInferFields().
+ * 08 Apr 98 at Apple
+ * Mods for giantDigit.
+ * 20 Jan 98 at Apple
+ * Added primeType, m, basePrimeRecip; added a few PT_GENERAL curves.
+ * 19 Jan 1998 at Apple
+ * New curve: q=160, k=57
+ * 09 Jan 1998 at Apple
+ * Removed obsolete (i.e., incomplete) curves parameters.
+ * 11 Jun 1997 at Apple
+ * Added x1OrderPlusRecip and lesserX1OrderRecip fields
+ * Added curveParamsInitGiants()
+ * 9 Jan 1997 at NeXT
+ * Major mods for IEEE-style parameters.
+ * 7 Aug 1996 at NeXT
+ * Created.
+ */
+
+#include "curveParams.h"
+#include "giantIntegers.h"
+#include "elliptic.h"
+#include "ellipticProj.h"
+#include "platform.h"
+#include "falloc.h"
+#include "feeDebug.h"
+#include <stdlib.h>
+
+typedef unsigned short arrayDigit;
+
+static giant arrayToGiant(const arrayDigit *array);
+
+/*
+ * Can't declare giants statically; we declare them here via static arrayDigit
+ * arrays which contain the 'digits' in base 65536 of a giant
+ * used as a curve parameter. First element is sign; next element is
+ * l.s. digit; size of each array is abs(sign) + 1. These arrays are
+ * converted to a giant via arrayToGiant().
+ *
+ * Static q and k values, as well as pointers to the arrayDigit arrays
+ * associated with the various giants for a given curve, are kept in an
+ * array of curveParamsStatic structs; a feeDepth is an index into this
+ * array. A curveParamsStatic struct is converted to a curveParams struct in
+ * curveParamsForDepth().
+ */
+typedef struct {
+ feePrimeType primeType;
+ feeCurveType curveType;
+ unsigned q;
+ int k;
+ const arrayDigit *basePrime; // FPT_General only
+ arrayDigit m; // must be 1 for current release
+ const arrayDigit *a;
+ const arrayDigit *b;
+ const arrayDigit *c;
+ const arrayDigit *x1Plus;
+ const arrayDigit *y1Plus; // optional, currently only used for ECDSA curves
+ const arrayDigit *x1Minus; // optional, not used for ECDSA curves
+ const arrayDigit *cOrderPlus;
+ const arrayDigit *cOrderMinus; // optional, not used for ECDSA curves
+ const arrayDigit *x1OrderPlus;
+ const arrayDigit *x1OrderMinus; // optional, not used for ECDSA curves
+ const arrayDigit *x1OrderPlusRecip;
+
+ /*
+ * A null lesserX1OrderRecip when x1OrderPlusRecip is non-null
+ * means that the two values are identical; in this case, only
+ * one giant is alloc'd in the actual curveParams struct.
+ */
+ const arrayDigit *lesserX1OrderRecip;
+} curveParamsStatic;
+
+/*
+ * First some common giant-arrays used in lots of curveGiants.
+ */
+static const arrayDigit ga_666[] = {1, 666 }; // a common value for 'c'
+static const arrayDigit ga_zero[] = {1, 0 }; // (giant)0
+static const arrayDigit ga_one[] = {1, 1 }; // (giant)1
+
+/*
+ * Here are the actual static arrays, one for each giant we know about.
+ * Since they're variable size, we have to allocate and name each one
+ * individually....
+ */
+
+#if FEE_PROTOTYPE_CURVES
+#include "curveParamDataOld.h"
+#else
+#include "curveParamData.h"
+#endif
+
+/*
+ * Now the curveParamsStatic structs, which provide templates for creating the
+ * fields in a specific curveParams struct.
+ *
+ * All giants in a curveParamsStatic struct except for basePrime are
+ * guaranteed valid.
+ *
+ * Note these are stored as an array, an index into which is a feeDepth
+ * parameter.
+ */
+#if FEE_PROTOTYPE_CURVES
+static curveParamsStatic curveParamsArray[] = {
+ { // depth=0
+ FPT_Mersenne,
+ FCT_Weierstrass,
+ 31, 1, // q=31, k=1
+ NULL, // basePrime only used for FPT_General
+ 1, // m = 1
+ ga_w31_1_a, // a = 7
+ ga_one, // b = 1
+ ga_zero, // c = 0
+ ga_w31_1_x1Plus,
+ NULL, // y1Plus
+ ga_w31_1_x1Minus,
+ ga_w31_1_plusOrder,
+ ga_w31_1_minusOrder,
+ ga_w31_1_x1OrderPlus,
+ ga_w31_1_x1OrderMinus,
+ ga_w31_1_x1OrderPlusRecip,
+ ga_w31_1_lesserX1OrderRecip
+ },
+ { // depth=1
+ FPT_Mersenne,
+ FCT_Montgomery,
+ 31, 1, // q=31, k=1
+ NULL,
+ 1, // m = 1
+ ga_one, // a = 1
+ ga_zero, // b = 0
+ ga_666, // c = 666
+ ga_m31_1_x1Plus,
+ NULL, // y1Plus
+ ga_m31_1_x1Minus,
+ ga_m31_1_plusOrder,
+ ga_m31_1_minusOrder,
+ ga_m31_1_x1OrderPlus,
+ ga_m31_1_x1OrderMinus,
+ ga_m31_1_x1OrderPlusRecip,
+ ga_m31_1_lesserX1OrderRecip
+
+ },
+ { // depth=2
+ FPT_Mersenne,
+ FCT_Weierstrass,
+ 31, 1, // q=31, k=1, prime curve orders
+ NULL,
+ 1, // m = 1
+ ga_31_1P_a, // a = 5824692
+ ga_31_1P_b, // b = 2067311435
+ ga_zero, // c = 0
+ ga_31_1P_x1Plus,
+ NULL, // y1Plus
+ ga_31_1P_x1Minus,
+ ga_31_1P_plusOrder,
+ ga_31_1P_minusOrder,
+ ga_31_1P_x1OrderPlus,
+ ga_31_1P_x1OrderMinus,
+ ga_31_1P_x1OrderPlusRecip,
+ NULL // x1PlusOrder is lesser
+
+ },
+ { // depth=3
+ FPT_FEE,
+ FCT_Weierstrass,
+ 40, 213, // q=40, k=213, prime curve orders
+ NULL,
+ 1, // m = 1
+ ga_40_213_a, // a = 1627500953
+ ga_40_213_b, // b = 523907505
+ ga_zero, // c = 0
+ ga_40_213_x1Plus,
+ NULL, // y1Plus
+ ga_40_213_x1Minus,
+ ga_40_213_plusOrder,
+ ga_40_213_minusOrder,
+ ga_40_213_x1OrderPlus,
+ ga_40_213_x1OrderMinus,
+ ga_40_213_x1OrderPlusRecip,
+ ga_40_213_lesserX1OrderRecip
+
+ },
+ { // depth=4
+ FPT_Mersenne,
+ FCT_Montgomery,
+ 127, 1,
+ NULL,
+ 1, // m = 1
+ ga_one, // a = 1
+ ga_zero, // b = 0
+ ga_666, // c = 666
+ ga_127_1_x1Plus,
+ NULL, // y1Plus
+ ga_127_1_x1Minus,
+ ga_127_1_plusOrder,
+ ga_127_1_minusOrder,
+ ga_127_1_x1OrderPlus,
+ ga_127_1_x1OrderMinus,
+ ga_127_1_x1OrderPlusRecip,
+ ga_127_1_lesserX1OrderRecip
+
+ },
+ { // depth=5
+ FPT_Mersenne,
+ FCT_Weierstrass,
+ 127, 1, // q=127, k=1 Weierstrass
+ NULL,
+ 1, // m = 1
+ ga_666, // a = 666
+ ga_one, // b = 1
+ ga_zero, // c = 0
+ ga_127_1W_x1Plus,
+ NULL, // y1Plus
+ ga_127_1W_x1Minus,
+ ga_127_1W_plusOrder,
+ ga_127_1W_minusOrder,
+ ga_127_1W_x1OrderPlus,
+ ga_127_1W_x1OrderMinus,
+ ga_127_1W_x1OrderPlusRecip,
+ NULL // x1PlusOrder is lesser
+
+ },
+ { // depth=6
+ FPT_FEE,
+ FCT_Weierstrass, // also Atkin3
+ 160, 57,
+ NULL,
+ 1, // m = 1
+ ga_zero, // a = 0
+ ga_160_57_b, // b = 3
+ ga_zero, // c = 0
+ ga_160_57_x1Plus,
+ NULL, // y1Plus
+ ga_160_57_x1Minus,
+ ga_160_57_plusOrder,
+ ga_160_57_minusOrder,
+ ga_160_57_x1OrderPlus,
+ ga_160_57_x1OrderMinus,
+ ga_160_57_x1OrderPlusRecip,
+ NULL // x1PlusOrder is lesser
+ },
+ { // depth=7
+ FPT_FEE,
+ FCT_Weierstrass, // also Atkin3
+ 192, 1425,
+ NULL,
+ 1, // m = 1
+ ga_zero, // a = 0
+ ga_192_1425_b, // b = -11
+ ga_zero, // c = 0
+ ga_192_1425_x1Plus,
+ NULL, // y1Plus
+ ga_192_1425_x1Minus,
+ ga_192_1425_plusOrder,
+ ga_192_1425_minusOrder,
+ ga_192_1425_x1OrderPlus,
+ ga_192_1425_x1OrderMinus,
+ ga_192_1425_x1OrderPlusRecip,
+ NULL // x1PlusOrder is lesser
+
+ },
+ { // depth=8
+ FPT_FEE,
+ FCT_Weierstrass,
+ 192, -529891,
+ NULL,
+ 1, // m = 1
+ ga_192_M529891_a, // a = -152
+ ga_192_M529891_b, // b = 722
+ ga_zero, // c = 0
+ ga_192_M529891_x1Plus,
+ NULL, // y1Plus
+ ga_192_M529891_x1Minus,
+ ga_192_M529891_plusOrder,
+ ga_192_M529891_minusOrder,
+ ga_192_M529891_x1OrderPlus,
+ ga_192_M529891_x1OrderMinus,
+ ga_192_M529891_x1OrderPlusRecip,
+ ga_192_M529891_lesserX1OrderRecip
+
+ },
+ /*
+ * FPT_General curves, currently just copies of known FPT_FEE or FPT_Mersenne
+ * curves with primeType set to FPT_General. These are just for
+ * verification the general curve are handled properly.
+ * We include the q parameter here for use by feeKeyBitsToDepth().
+ */
+ { // depth=9
+ FPT_General,
+ FCT_General,
+ 127, 0,
+ ga_127_1_bp, // explicit basePrime
+ 1, // m = 1
+ ga_one, // a = 1
+ ga_zero, // b = 0
+ ga_666, // c = 666
+ ga_127_1_x1Plus,
+ NULL, // y1Plus
+ ga_127_1_x1Minus,
+ ga_127_1_plusOrder,
+ ga_127_1_minusOrder,
+ ga_127_1_x1OrderPlus,
+ ga_127_1_x1OrderMinus,
+ ga_127_1_x1OrderPlusRecip,
+ ga_127_1_lesserX1OrderRecip
+
+ },
+
+ { // depth=10, FPT_General version of q=160
+ FPT_General,
+ FCT_Weierstrass,
+ 160, 0, // we don't use these...
+ ga_160_57_bp, // explicit basePrime
+ 1, // m = 1
+ ga_zero, // a = 0
+ ga_160_57_b, // b = 3
+ ga_zero,
+ ga_160_57_x1Plus,
+ NULL, // y1Plus
+ ga_160_57_x1Minus,
+ ga_160_57_plusOrder,
+ ga_160_57_minusOrder,
+ ga_160_57_x1OrderPlus,
+ ga_160_57_x1OrderMinus,
+ ga_160_57_x1OrderPlusRecip,
+ NULL // x1PlusOrder is lesser
+ },
+
+ { // depth=11, FPT_General, 161 bits
+ FPT_General,
+ FCT_Weierstrass,
+ //161, 0,
+ 161, 0, // for verifying we don't use these...
+ ga_161_gen_bp, // explicit basePrime
+ 1, // m = 1
+ ga_161_gen_a, // a = -152
+ ga_161_gen_b, // b = 722
+ ga_zero, // c = 0
+ ga_161_gen_x1Plus,
+ NULL, // y1Plus
+ ga_161_gen_x1Minus,
+ ga_161_gen_plusOrder,
+ ga_161_gen_minusOrder,
+ ga_161_gen_x1OrderPlus,
+ ga_161_gen_x1OrderMinus,
+ ga_161_gen_x1OrderPlusRecip,
+ NULL // x1PlusOrder is lesser
+ },
+
+};
+
+#else /* FEE_PROTOTYPE_CURVES */
+
+static const curveParamsStatic curveParamsArray[] = {
+{
+ /*
+ * depth = 0
+ * FEE CURVE: USE FOR FEE SIG. & FEED ONLY.
+ * primeType->Mersenne
+ * curveType->Montgomery
+ * q = 31; k = 1; p = 2^q - k;
+ * a = 1; b = 0; c = 666;
+ * Both orders composite.
+ */
+ FPT_Mersenne,
+ FCT_Montgomery,
+ 31, 1, // q=31, k=1
+ NULL, // basePrime only used for FPT_General
+ 1, // m = 1
+ ga_one, // a = 1
+ ga_zero, // b = 0
+ ga_666, // c = 666
+ ga_31m_x1Plus,
+ NULL, // y1Plus
+ ga_31m_x1Minus,
+ ga_31m_plusOrder,
+ ga_31m_minusOrder,
+ ga_31m_x1OrderPlus,
+ ga_31m_x1OrderMinus,
+ ga_31m_x1OrderPlusRecip,
+ ga_31m_lesserX1OrderRecip
+},
+{
+ /*
+ * depth = 1
+ * IEEE P1363 COMPATIBLE.
+ * primeType->Mersenne
+ * curveType->Weierstrass
+ * q = 31; k = 1; p = 2^q-k;
+ * a = 5824692 b = 2067311435 c = 0
+ * Both orders prime.
+ */
+ FPT_Mersenne,
+ FCT_Weierstrass,
+ 31, 1, // q=31, k=1
+ NULL, // basePrime only used for FPT_General
+ 1, // m = 1
+ ga_31w_a,
+ ga_31w_b,
+ ga_zero, // c = 0
+ ga_31w_x1Plus,
+ NULL, // y1Plus
+ ga_31w_x1Minus,
+ ga_31w_plusOrder,
+ ga_31w_minusOrder,
+ ga_31w_x1OrderPlus,
+ ga_31w_x1OrderMinus,
+ ga_31w_x1OrderPlusRecip,
+ NULL // x1PlusOrder is lesser
+},
+{
+ /*
+ * depth = 2
+ * FEE CURVE: USE FOR FEE SIG. & FEED ONLY.
+ * primeType->Mersenne
+ * curveType->Montgomery
+ * q = 127; k = 1; p = 2^q - k;
+ * a = 1; b = 0; c = 666;
+ * Both orders composite.
+ */
+ FPT_Mersenne,
+ FCT_Montgomery,
+ 127, 1, // q = 127; k = 1
+ NULL, // basePrime only used for FPT_General
+ 1, // m = 1
+ ga_one,
+ ga_zero,
+ ga_666,
+ ga_127m_x1Plus,
+ NULL, // y1Plus
+ ga_127m_x1Minus,
+ ga_127m_plusOrder,
+ ga_127m_minusOrder,
+ ga_127m_x1OrderPlus,
+ ga_127m_x1OrderMinus,
+ ga_127m_x1OrderPlusRecip,
+ ga_127m_lesserX1OrderRecip
+},
+{
+ /*
+ * depth = 3
+ * IEEE P1363 COMPATIBLE.
+ * primeType->feemod
+ * curveType->Weierstrass
+ * q = 127; k = -57675; p = 2^q - k;
+ * a = 170141183460469025572049133804586627403;
+ * b = 170105154311605172483148226534443139403; c = 0;
+ * Both orders prime.
+ */
+ FPT_FEE,
+ FCT_Weierstrass,
+ 127, -57675, // q = 127; k = -57675
+ NULL, // basePrime only used for FPT_General
+ 1, // m = 1
+ ga_128w_a,
+ ga_128w_b,
+ ga_zero,
+ ga_128w_x1Plus,
+ NULL, // y1Plus
+ ga_128w_x1Minus,
+ ga_128w_plusOrder,
+ ga_128w_minusOrder,
+ ga_128w_x1OrderPlus,
+ ga_128w_x1OrderMinus,
+ ga_128w_x1OrderPlusRecip,
+ /* REC said NULL, dmitch says: */
+ ga_128w_lesserX1OrderRecip // x1PlusOrder is lesser
+},
+{
+ /*
+ * depth = 4
+ * IEEE P1363 COMPATIBLE.
+ * primeType->feemod
+ * curveType->Weierstrass
+ * q = 160; k = -5875; p = 2^q - k;
+ * a = 1461501637330902918203684832716283019448563798259;
+ * b = 36382017816364032; c = 0;
+ * Both orders prime.:
+ */
+ FPT_FEE,
+ FCT_Weierstrass,
+ 160, -5875, // q = 160; k = -5875
+ NULL, // basePrime only used for FPT_General
+ 1, // m = 1
+ ga_161w_a,
+ ga_161w_b,
+ ga_zero,
+ ga_161w_x1Plus,
+ NULL, // y1Plus
+ ga_161w_x1Minus,
+ ga_161w_plusOrder,
+ ga_161w_minusOrder,
+ ga_161w_x1OrderPlus,
+ ga_161w_x1OrderMinus,
+ ga_161w_x1OrderPlusRecip,
+ /* dmitch addenda - REC said NULL */
+ ga_161w_lesserX1OrderRecip
+},
+{
+ /*
+ * depth = 5
+ * IEEE P1363 COMPATIBLE.
+ * primeType->General
+ * curveType->Weierstrass
+ * p is a 161-bit random prime (below, ga_161_gen_bp[]);
+ * a = -152; b = 722; c = 0;
+ * Both orders composite.
+ */
+ FPT_General,
+ FCT_Weierstrass,
+ 161, 0, // not used
+ ga_161_gen_bp, // basePrime
+ 1, // m = 1
+ ga_161_gen_a,
+ ga_161_gen_b,
+ ga_zero,
+ ga_161_gen_x1Plus,
+ NULL, // y1Plus
+ ga_161_gen_x1Minus,
+ ga_161_gen_plusOrder,
+ ga_161_gen_minusOrder,
+ ga_161_gen_x1OrderPlus,
+ ga_161_gen_x1OrderMinus,
+ ga_161_gen_x1OrderPlusRecip,
+ NULL // x1PlusOrder is lesser
+},
+{
+ /*
+ * depth = 6
+ * IEEE P1363 COMPATIBLE.
+ * (NIST-P-192 RECOMMENDED PRIME)
+ * primeType->General
+ * curveType->Weierstrass
+ * p is a 192-bit random prime (below, ga_161_gen_bp[]);
+ * a = -3;
+ * b = 2455155546008943817740293915197451784769108058161191238065;
+ * c = 0;
+ * Plus-order is prime, minus-order is composite.
+ */
+ FPT_General,
+ FCT_Weierstrass,
+ 192, 0, // only used for initGiantStacks(giantMaxDigits())
+ ga_192_gen_bp, // basePrime
+ 1, // m = 1
+ ga_192_gen_a,
+ ga_192_gen_b,
+ ga_zero,
+ ga_192_gen_x1Plus,
+ NULL, // y1Plus
+ ga_192_gen_x1Minus,
+ ga_192_gen_plusOrder,
+ ga_192_gen_minusOrder,
+ ga_192_gen_x1OrderPlus,
+ ga_192_gen_x1OrderMinus,
+ ga_192_gen_x1OrderPlusRecip,
+ ga_192_gen_lesserX1OrderRecip
+},
+
+/* ANSI X9.62/Certicom curves */
+{
+ /*
+ * depth = 7
+ * ANSI X9.62/Certicom secp192r1
+ */
+ FPT_General,
+ FCT_Weierstrass,
+ 192, 0, // only used for initGiantStacks(giantMaxDigits())
+ ga_192_secp_bp, // basePrime
+ 1, // m = 1
+ ga_192_secp_a,
+ ga_192_secp_b,
+ ga_zero,
+ ga_192_secp_x1Plus,
+ ga_192_secp_y1Plus,
+ NULL, // x1Minus
+ ga_192_secp_plusOrder,
+ NULL, // minusOrder,
+ ga_192_secp_x1OrderPlus,
+ NULL, // x1OrderMinus,
+ ga_192_secp_x1OrderPlusRecip,
+},
+{
+ /*
+ * depth = 8
+ * ANSI X9.62/Certicom secp256r1
+ */
+ FPT_General,
+ FCT_Weierstrass,
+ 256, 0, // only used for initGiantStacks(giantMaxDigits())
+ ga_256_secp_bp, // basePrime
+ 1, // m = 1
+ ga_256_secp_a,
+ ga_256_secp_b,
+ ga_zero,
+ ga_256_secp_x1Plus,
+ ga_256_secp_y1Plus,
+ NULL,
+ ga_256_secp_plusOrder,
+ NULL,
+ ga_256_secp_x1OrderPlus,
+ NULL,
+ ga_256_secp_x1OrderPlusRecip,
+ NULL
+},
+{
+ /*
+ * depth = 9
+ * ANSI X9.62/Certicom secp384r1
+ */
+ FPT_General,
+ FCT_Weierstrass,
+ 384, 0, // only used for initGiantStacks(giantMaxDigits())
+ ga_384_secp_bp, // basePrime
+ 1, // m = 1
+ ga_384_secp_a,
+ ga_384_secp_b,
+ ga_zero,
+ ga_384_secp_x1Plus,
+ ga_384_secp_y1Plus,
+ NULL,
+ ga_384_secp_plusOrder,
+ NULL,
+ ga_384_secp_x1OrderPlus,
+ NULL,
+ ga_384_secp_x1OrderPlusRecip,
+ NULL
+},
+{
+ /*
+ * depth = 10
+ * ANSI X9.62/Certicom secp521r1
+ */
+ FPT_General,
+ FCT_Weierstrass,
+ 521, 0,
+ ga_521_secp_bp, // basePrime
+ 1, // m = 1
+ ga_521_secp_a,
+ ga_521_secp_b,
+ ga_zero,
+ ga_521_secp_x1Plus,
+ ga_521_secp_y1Plus,
+ NULL,
+ ga_521_secp_plusOrder,
+ NULL,
+ ga_521_secp_x1OrderPlus,
+ NULL,
+ ga_521_secp_x1OrderPlusRecip,
+ NULL
+}
+};
+#endif /* FEE_PROTOTYPE_CURVES */
+
+/*
+ * Convert the static form of a giant - i.e., an array of arrayDigits,
+ * the first of which is the sign, the remainder of which are base 65536
+ * digits - into a giant. A null pointer on input results in a null return.
+ */
+static giant arrayToGiant(const arrayDigit *array)
+{
+ unsigned numBytes; // in result->n[]
+ int numDigits; // ditto
+ giant result;
+ giantDigit digit;
+ unsigned char byte;
+ unsigned i;
+ unsigned digitDex; // index into result->n[]
+ unsigned digitByte; // byte selector in digit
+ const arrayDigit *ap; // running ptr into array
+ short sign;
+
+ if(array == NULL) {
+ CKRaise("arrayToGiant: NULL array");
+ }
+ sign = (short)array[0];
+ numBytes = abs(sign) * sizeof(unsigned short);
+ numDigits = BYTES_TO_GIANT_DIGITS(numBytes);
+
+ /* note giantstruct has one explicit giantDigit */
+ result = (giant) fmalloc(sizeof(giantstruct) +
+ ((numDigits - 1) * GIANT_BYTES_PER_DIGIT));
+ result->capacity = numDigits;
+
+ ap = array + 1;
+ digit = 0;
+ digitDex = 0;
+
+ for(i=0; i<numBytes;) {
+ for(digitByte=0; digitByte<GIANT_BYTES_PER_DIGIT; digitByte++) {
+ /* grab a byte from the array */
+ if(i & 1) {
+ /* odd byte - snag it and advance to next array digit */
+ byte = (unsigned char)(*ap++ >> 8);
+ }
+ else {
+ /* even, i.e., l.s. byte */
+ byte = (unsigned char)(*ap);
+ }
+
+ /* add byte to current digit */
+ digit |= (byte << (8 * digitByte));
+ if(++i == numBytes) {
+ /* end of array, perhaps in the midst of a digit */
+ break;
+ }
+ }
+ result->n[digitDex++] = digit;
+ digit = 0;
+ };
+
+ /* Careful:
+ * -- array elements are unsigned. The first element is
+ * he number of SHORTS in the array; convert to native
+ * digits.
+ * -- in the very odd (test only) case of giantDigit = unsigned char,
+ * we might have fewer valid digits than numDigits (might have
+ * leading zeros).
+ */
+ if(sign < 0) {
+ result->sign = -numDigits;
+ }
+ else {
+ result->sign = numDigits;
+ }
+ gtrimSign(result);
+ return result;
+}
+
+/*
+ * Obtain a malloc'd and uninitialized curveParams, to be init'd by caller.
+ */
+curveParams *newCurveParams(void)
+{
+ curveParams *params = (curveParams*) fmalloc(sizeof(curveParams));
+
+ bzero(params, sizeof(curveParams));
+ return params;
+}
+
+/*
+ * Alloc and zero reciprocal giants, when maxDigits is known.
+ * Currently only called when creating a curveParams from a public key.
+ * cp->primeType must be valid on input.
+ */
+void allocRecipGiants(curveParams *cp)
+{
+ cp->lesserX1OrderRecip = newGiant(cp->maxDigits);
+ cp->x1OrderPlusRecip = newGiant(cp->maxDigits);
+ int_to_giant(0, cp->lesserX1OrderRecip);
+ int_to_giant(0, cp->x1OrderPlusRecip);
+}
+
+/*
+ * Obtain a malloc'd curveParams for a specified feeDepth.
+ */
+curveParams *curveParamsForDepth(feeDepth depth)
+{
+ curveParams *cp;
+ const curveParamsStatic *cps = &curveParamsArray[depth];
+
+ if(depth > FEE_DEPTH_MAX) {
+ return NULL;
+ }
+ #if GIANTS_VIA_STACK
+ curveParamsInitGiants();
+ #endif
+ cp = newCurveParams();
+ cp->primeType = cps->primeType;
+ cp->curveType = cps->curveType;
+ cp->q = cps->q;
+ cp->k = cps->k;
+ cp->m = cps->m;
+ if(cp->primeType == FPT_General) {
+ cp->basePrime = arrayToGiant(cps->basePrime);
+ }
+ cp->a = arrayToGiant(cps->a);
+ cp->b = arrayToGiant(cps->b);
+ cp->c = arrayToGiant(cps->c);
+ cp->x1Plus = arrayToGiant(cps->x1Plus);
+ if(cps->y1Plus) {
+ cp->y1Plus = arrayToGiant(cps->y1Plus);
+ }
+ if(cps->x1Minus) {
+ cp->x1Minus = arrayToGiant(cps->x1Minus);
+ }
+ cp->cOrderPlus = arrayToGiant(cps->cOrderPlus);
+ if(cps->cOrderMinus) {
+ cp->cOrderMinus = arrayToGiant(cps->cOrderMinus);
+ }
+ cp->x1OrderPlus = arrayToGiant(cps->x1OrderPlus);
+ if(cps->x1OrderMinus) {
+ cp->x1OrderMinus = arrayToGiant(cps->x1OrderMinus);
+ }
+ cp->x1OrderPlusRecip = arrayToGiant(cps->x1OrderPlusRecip);
+
+ /*
+ * Special case optimization for equal reciprocals.
+ */
+ if(cps->lesserX1OrderRecip == NULL) {
+ cp->lesserX1OrderRecip = cp->x1OrderPlusRecip;
+ }
+ else {
+ cp->lesserX1OrderRecip = arrayToGiant(cps->lesserX1OrderRecip);
+ }
+
+ /* remainder calculated at runtime */
+ curveParamsInferFields(cp);
+ return cp;
+}
+
+/*
+ * Alloc a new curveParams struct as a copy of specified instance.
+ * This is the only way we can create a curveParams struct which doesn't
+ * match any existing known curve params.
+ */
+curveParams *curveParamsCopy(curveParams *cp)
+{
+ curveParams *newcp = newCurveParams();
+
+ newcp->primeType = cp->primeType;
+ newcp->curveType = cp->curveType;
+ newcp->q = cp->q;
+ newcp->k = cp->k;
+ newcp->m = cp->m;
+ newcp->basePrime = copyGiant(cp->basePrime);
+ newcp->minBytes = cp->minBytes;
+ newcp->maxDigits = cp->maxDigits;
+
+ newcp->a = copyGiant(cp->a);
+ newcp->b = copyGiant(cp->b);
+ newcp->c = copyGiant(cp->c);
+ newcp->x1Plus = copyGiant(cp->x1Plus);
+ if(cp->x1Minus) {
+ newcp->x1Minus = copyGiant(cp->x1Minus);
+ }
+ newcp->y1Plus = copyGiant(cp->y1Plus);
+ newcp->cOrderPlus = copyGiant(cp->cOrderPlus);
+ if(cp->cOrderMinus) {
+ newcp->cOrderMinus = copyGiant(cp->cOrderMinus);
+ }
+ newcp->x1OrderPlus = copyGiant(cp->x1OrderPlus);
+ if(cp->x1OrderMinus) {
+ newcp->x1OrderMinus = copyGiant(cp->x1OrderMinus);
+ }
+
+ newcp->x1OrderPlusRecip = copyGiant(cp->x1OrderPlusRecip);
+ if(cp->x1OrderPlusRecip == cp->lesserX1OrderRecip) {
+ /*
+ * Equal reciprocals; avoid new malloc
+ */
+ newcp->lesserX1OrderRecip = newcp->x1OrderPlusRecip;
+ }
+ else {
+ newcp->lesserX1OrderRecip = copyGiant(cp->lesserX1OrderRecip);
+ }
+ if(cp->primeType == FPT_General) {
+ newcp->basePrimeRecip = copyGiant(cp->basePrimeRecip);
+ }
+ return newcp;
+}
+
+/*
+ * Free a curveParams struct.
+ */
+void freeCurveParams(curveParams *cp)
+{
+ if(cp->basePrime != NULL) {
+ freeGiant(cp->basePrime);
+ }
+ if(cp->a != NULL) {
+ freeGiant(cp->a);
+ }
+ if(cp->b != NULL) {
+ freeGiant(cp->b);
+ }
+ if(cp->c != NULL) {
+ freeGiant(cp->c);
+ }
+ if(cp->x1Plus != NULL) {
+ freeGiant(cp->x1Plus);
+ }
+ if(cp->x1Minus != NULL) {
+ freeGiant(cp->x1Minus);
+ }
+ if(cp->y1Plus != NULL) {
+ freeGiant(cp->y1Plus);
+ }
+ if(cp->cOrderPlus != NULL) {
+ freeGiant(cp->cOrderPlus);
+ }
+ if(cp->cOrderMinus != NULL) {
+ freeGiant(cp->cOrderMinus);
+ }
+ if(cp->x1OrderPlus != NULL) {
+ freeGiant(cp->x1OrderPlus);
+ }
+ if(cp->x1OrderMinus != NULL) {
+ freeGiant(cp->x1OrderMinus);
+ }
+ if(cp->x1OrderPlusRecip != NULL) {
+ freeGiant(cp->x1OrderPlusRecip);
+ }
+
+ /*
+ * Special case - if these are equal, we only alloc'd one giant
+ */
+ if(cp->lesserX1OrderRecip != cp->x1OrderPlusRecip) {
+ freeGiant(cp->lesserX1OrderRecip);
+ }
+ if(cp->basePrimeRecip != NULL) {
+ freeGiant(cp->basePrimeRecip);
+ }
+ ffree(cp);
+}
+
+/*
+ * Returns 1 if two sets of curve parameters are equivalent, else returns 0.
+ */
+int curveParamsEquivalent(curveParams *cp1, curveParams *cp2)
+{
+ if(cp1 == cp2) {
+ /*
+ * Trivial case, actually common for signature verify
+ */
+ return 1;
+ }
+ if(cp1->primeType != cp2->primeType) {
+ return 0;
+ }
+ if(cp1->curveType != cp2->curveType) {
+ return 0;
+ }
+ if(cp1->k != cp2->k) {
+ return 0;
+ }
+ if(cp1->q != cp2->q) {
+ return 0;
+ }
+ if(cp1->m != cp2->m) {
+ return 0;
+ }
+ if(gcompg(cp1->basePrime, cp2->basePrime)) {
+ return 0;
+ }
+ if(gcompg(cp1->a, cp2->a)) {
+ return 0;
+ }
+ if(gcompg(cp1->b, cp2->b)) {
+ return 0;
+ }
+ if(gcompg(cp1->c, cp2->c)) {
+ return 0;
+ }
+ if(gcompg(cp1->x1Plus, cp2->x1Plus)) {
+ return 0;
+ }
+ if((cp1->x1Minus != NULL) && (cp2->x1Minus != NULL)) {
+ if(gcompg(cp1->x1Minus, cp2->x1Minus)) {
+ return 0;
+ }
+ }
+ if(gcompg(cp1->cOrderPlus, cp2->cOrderPlus)) {
+ return 0;
+ }
+ if((cp1->cOrderMinus != NULL) && (cp2->cOrderMinus != NULL)) {
+ if(gcompg(cp1->cOrderMinus, cp2->cOrderMinus)) {
+ return 0;
+ }
+ }
+ if(gcompg(cp1->x1OrderPlus, cp2->x1OrderPlus)) {
+ return 0;
+ }
+ if((cp1->x1OrderMinus != NULL) && (cp2->x1OrderMinus != NULL)) {
+ if(gcompg(cp1->x1OrderMinus, cp2->x1OrderMinus)) {
+ return 0;
+ }
+ }
+ /*
+ * If we got this far, reciprocals can't possibly be different
+ */
+ return 1;
+}
+
+/*
+ * Obtain the lesser of {x1OrderPlus, x1OrderMinus}. Returned value is not
+ * malloc'd; it's a pointer to one of the orders in *cp.
+ */
+giant lesserX1Order(curveParams *cp)
+{
+ CKASSERT(!isZero(cp->x1OrderPlus));
+
+ if(cp->x1OrderMinus == NULL) {
+ return(cp->x1OrderPlus);
+ }
+ else if(gcompg(cp->x1OrderPlus, cp->x1OrderMinus) >= 0) {
+ return(cp->x1OrderMinus);
+ }
+ else {
+ return(cp->x1OrderPlus);
+ }
+}
+
+#if GIANTS_VIA_STACK
+
+/*
+ * Prime the curveParams and giants modules for quick allocs of giants.
+ */
+static int giantsInitd = 0;
+
+void curveParamsInitGiants(void)
+{
+ const curveParamsStatic *cps = &curveParamsArray[FEE_DEPTH_MAX];
+
+ if(giantsInitd) {
+ return;
+ }
+
+ /*
+ * Figure the max giant size of the largest depth we know about...
+ */
+ initGiantStacks(giantMaxDigits(giantMinBytes(cps->q, cps->k)));
+ giantsInitd = 1;
+}
+
+#endif // GIANTS_VIA_STACK
+
+/*
+ * Infer the following fields from a partially constructed curveParams:
+ *
+ * basePrimeRecip if primeType == FPT_General
+ * basePrime if primeType != FPT_General
+ * y1Plus if curveType == FCT_Weierstrass and not pre-calculated
+ * minBytes
+ * maxDigits
+ *
+ * Assumes the following valid on entry:
+ * curveType
+ * primeType
+ * basePrime if primeType == FPT_General
+ * q, k if primeType != FPT_General
+ */
+void curveParamsInferFields(curveParams *cp)
+{
+ /* calc maxDigits, minBytes */
+ calcGiantSizes(cp);
+
+ /* basePrime or its reciprocal */
+ if(cp->primeType == FPT_General) {
+ /* FIXME this should be declared statically! */
+ cp->basePrimeRecip = newGiant(cp->maxDigits);
+ make_recip(cp->basePrime, cp->basePrimeRecip);
+ }
+ else {
+ /*
+ * FPT_FEE, FPT_Mersenne
+ */
+ cp->basePrime = newGiant(cp->maxDigits);
+ make_base_prim(cp);
+ }
+
+ /* y1Plus */
+ #if CRYPTKIT_ELL_PROJ_ENABLE
+ if(cp->curveType == FCT_Weierstrass) {
+ if(cp->y1Plus == NULL) {
+ /* ECDSA Curves already have this */
+ pointProj pt = newPointProj(cp->maxDigits);
+ findPointProj(pt, cp->x1Plus, cp);
+
+ /* initial point is supposed to be on curve! */
+ if(gcompg(pt->x, cp->x1Plus)) {
+ CKRaise("curveParamsInferFields failure");
+ }
+ cp->y1Plus = copyGiant(pt->y);
+ freePointProj(pt);
+ }
+ }
+ else {
+ cp->y1Plus = newGiant(1);
+ }
+ #else /* CRYPTKIT_ELL_PROJ_ENABLE */
+ cp->y1Plus = newGiant(1);
+ #endif
+
+ if((cp->x1OrderPlusRecip == NULL) || isZero(cp->x1OrderPlusRecip)) {
+ /*
+ * an easy way of figuring this one out, this should not
+ * normally run.
+ */
+ cp->x1OrderPlusRecip = newGiant(cp->maxDigits);
+ make_recip(cp->x1OrderPlus, cp->x1OrderPlusRecip);
+ if(cp->lesserX1OrderRecip != NULL) {
+ freeGiant(cp->lesserX1OrderRecip);
+ }
+ cp->lesserX1OrderRecip = cp->x1OrderPlusRecip;
+ }
+}
+
+/*
+ * Given key size in bits, obtain the asssociated depth.
+ * Returns FR_IllegalDepth if specify key size not found
+ * in current curve tables.
+ */
+#define LOG_DEPTH 0
+
+#if FEE_PROTOTYPE_CURVES
+feeReturn feeKeyBitsToDepth(unsigned keySize,
+ feePrimeType primeType, /* FPT_Fefault means "best one" */
+ feeCurveType curveType, /* FCT_Default means "best one" */
+ feeDepth *depth)
+{
+ feeReturn frtn = FR_Success;
+ switch(keySize) {
+ case 31:
+ switch(curveType) {
+ case FCT_Montgomery:
+ default:
+ *depth = FEE_DEPTH_31_1_M;
+ break;
+ case FCT_Weierstrass:
+ *depth = FEE_DEPTH_31_1_P;
+ break;
+ }
+ break;
+ case 40:
+ switch(curveType) {
+ case FCT_Weierstrass:
+ default:
+ *depth = FEE_DEPTH_40_213;
+ break;
+ case FCT_Montgomery:
+ return FR_IllegalDepth;
+ }
+ break;
+ case 127:
+ switch(curveType) {
+ case FCT_Montgomery:
+ if(primeType == FPT_General) {
+ *depth = FEE_DEPTH_127_GEN;
+ }
+ else{
+ *depth = FEE_DEPTH_127_1;
+ }
+ break;
+ case FCT_Weierstrass:
+ default:
+ *depth = FEE_DEPTH_127_1W;
+ break;
+ }
+ break;
+ case 160:
+ switch(curveType) {
+ case FCT_Montgomery:
+ return FR_IllegalDepth;
+ case FCT_Weierstrass:
+ default:
+ if(primeType == FPT_General) {
+ *depth = FEE_DEPTH_160_GEN;
+ }
+ else {
+ *depth = FEE_DEPTH_160_57;
+ }
+ break;
+ }
+ break;
+ case 192:
+ switch(curveType) {
+ case FCT_Montgomery:
+ *depth = FEE_DEPTH_192_M529891;
+ case FCT_Weierstrass:
+ default:
+ *depth = FEE_DEPTH_192_1425;
+ break;
+ }
+ break;
+ default:
+ frtn = FR_IllegalDepth;
+ break;
+ }
+ #if LOG_DEPTH
+ printf("feeKeyBitsToDepth: depth %d\n", *depth);
+ #endif
+ return frtn;
+}
+
+#else /* FEE_PROTOTYPE_CURVES */
+
+feeReturn feeKeyBitsToDepth(unsigned keySize,
+ feePrimeType primeType, /* FPT_Fefault means "best one" */
+ feeCurveType curveType, /* FCT_Default means "best one" */
+ feeDepth *depth)
+{
+ feeReturn frtn = FR_Success;
+ switch(keySize) {
+ case 31:
+ if(primeType == FPT_General) {
+ return FR_IllegalDepth;
+ }
+ /* note we cut a request for FPT_FEE some slack...this is actually
+ * FPT_Mersenne, but that is technically a subset of FEE. */
+ switch(curveType) {
+ case FCT_Montgomery:
+ *depth = FEE_DEPTH_31M;
+ break;
+ case FCT_Weierstrass:
+ case FCT_Default:
+ *depth = FEE_DEPTH_31W;
+ break;
+ default:
+ return FR_IllegalDepth;
+ }
+ break;
+ case 127:
+ /* Montgomery only */
+ if(primeType == FPT_General) {
+ return FR_IllegalDepth;
+ }
+ /* note we cut a request for FPT_FEE some slack...this is actually
+ * FPT_Mersenne, but that is technically a subset of FEE. */
+ switch(curveType) {
+ case FCT_Montgomery:
+ case FCT_Default:
+ *depth = FEE_DEPTH_127M;
+ break;
+ case FCT_Weierstrass:
+ default:
+ return FR_IllegalDepth;
+ }
+ break;
+ case 128:
+ /* Weierstrass/feemod only */
+ switch(primeType) {
+ case FPT_General:
+ case FPT_Mersenne:
+ return FR_IllegalDepth;
+ default:
+ /* FPT_Default, FPT_FEE */
+ break;
+ }
+ switch(curveType) {
+ case FCT_Weierstrass:
+ case FCT_Default:
+ *depth = FEE_DEPTH_128W;
+ break;
+ default:
+ return FR_IllegalDepth;
+ }
+ break;
+ case 161:
+ switch(curveType) {
+ case FCT_Weierstrass:
+ case FCT_Default:
+ switch(primeType) {
+ case FPT_General:
+ *depth = FEE_DEPTH_161G;
+ break;
+ case FPT_FEE:
+ case FPT_Default:
+ *depth = FEE_DEPTH_161W;
+ break;
+ default:
+ /* i.e., FPT_Mersenne */
+ return FR_IllegalDepth;
+ }
+ break;
+ default:
+ return FR_IllegalDepth;
+ }
+ break;
+ case 192:
+ switch(curveType) {
+ case FCT_Montgomery:
+ default:
+ return FR_IllegalDepth;
+ case FCT_Weierstrass:
+ case FCT_Default:
+ switch(primeType) {
+ case FPT_General:
+ case FPT_Default:
+ *depth = FEE_DEPTH_192G;
+ break;
+ default:
+ /* i.e., FPT_Mersenne, FPT_FEE */
+ return FR_IllegalDepth;
+ }
+ break;
+ case FCT_ANSI:
+ switch(primeType) {
+ case FPT_General:
+ case FPT_Default:
+ break;
+ default:
+ return FR_IllegalDepth;
+ }
+ *depth = FEE_DEPTH_secp192r1;
+ break;
+ }
+ break;
+ case 256:
+ switch(curveType) {
+ case FCT_ANSI:
+ case FCT_Default:
+ break;
+ default:
+ return FR_IllegalDepth;
+ }
+ switch(primeType) {
+ case FPT_General:
+ case FPT_Default:
+ break;
+ default:
+ return FR_IllegalDepth;
+ }
+ *depth = FEE_DEPTH_secp256r1;
+ break;
+ case 384:
+ switch(curveType) {
+ case FCT_ANSI:
+ case FCT_Default:
+ break;
+ default:
+ return FR_IllegalDepth;
+ }
+ switch(primeType) {
+ case FPT_General:
+ case FPT_Default:
+ break;
+ default:
+ return FR_IllegalDepth;
+ }
+ *depth = FEE_DEPTH_secp384r1;
+ break;
+ case 521:
+ switch(curveType) {
+ case FCT_ANSI:
+ case FCT_Default:
+ break;
+ default:
+ return FR_IllegalDepth;
+ }
+ switch(primeType) {
+ case FPT_General:
+ case FPT_Default:
+ break;
+ default:
+ return FR_IllegalDepth;
+ }
+ *depth = FEE_DEPTH_secp521r1;
+ break;
+
+ default:
+ frtn = FR_IllegalDepth;
+ break;
+ }
+ #if LOG_DEPTH
+ printf("feeKeyBitsToDepth: depth %d\n", *depth);
+ #endif
+ return frtn;
+}
+
+#endif /* FEE_PROTOTYPE_CURVES */
+
+/*
+ * Obtain depth for specified curveParams
+ */
+feeReturn curveParamsDepth(
+ curveParams *cp,
+ feeDepth *depth)
+{
+ if(cp == NULL) {
+ return FR_IllegalArg;
+ }
+
+ /* We do it this way to allow reconstructing depth from an encoded curveParams */
+ feeCurveType curveType = cp->curveType;
+ if((curveType == FCT_Weierstrass) && (cp->x1Minus == NULL)) {
+ /* actually an ANSI curve */
+ curveType = FCT_ANSI;
+ }
+ return feeKeyBitsToDepth(cp->q, cp->primeType, curveType, depth);
+}
+
+