X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/Security/libsecurity_cryptkit/lib/ellipticProj.c diff --git a/Security/libsecurity_cryptkit/lib/ellipticProj.c b/Security/libsecurity_cryptkit/lib/ellipticProj.c deleted file mode 100644 index bdb24316..00000000 --- a/Security/libsecurity_cryptkit/lib/ellipticProj.c +++ /dev/null @@ -1,565 +0,0 @@ -/* 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. - *************************************************************************** - * - * ellipticProj.c - elliptic projective algebra routines. - * - * Revision History - * ---------------- - * 1 Sep 1998 at Apple - * Created. - * - ************************************************************** - - PROJECTIVE FORMAT - - Functions are supplied herein for projective format - of points. Alternative formats differ in their - range of applicability, efficiency, and so on. - Primary advantages of the projective format herein are: - -- No explicit inversions (until perhaps one such at the end of - an elliptic multiply operation) - -- Fairly low operation count (~11 muls for point doubling, - ~16 muls for point addition) - - The elliptic curve is over F_p, with p > 3 prime, and Weierstrass - parameterization: - - y^2 = x^3 + a x + b - - The projective-format coordinates are actually stored in - the form {X, Y, Z}, with true x,y - coordinates on the curve given by {x,y} = {X/Z^2, Y/Z^3}. - The function normalizeProj() performs the - transformation from projective->true. - (The other direction is trivial, i.e. {x,y} -> {x,y,1} will do.) - The basic point multiplication function is - - ellMulProj() - - which obtains the result k * P for given point P and integer - multiplier k. If true {x,y} are required for a multiple, one - passes a point P = {X, Y, 1} to ellMulProj(), then afterwards - calls normalizeProj(), - - Projective format is an answer to the typical sluggishness of - standard elliptic arithmetic, whose explicit inversion in the - field is, depending of course on the machinery and programmer, - costly. Projective format is thus especially interesting for - cryptography. - - REFERENCES - - perspective," Springer-Verlag, manuscript - - Solinas J 1998, IEEE P1363 Annex A (draft standard) - -***********************************************************/ - -#include "ckconfig.h" -#if CRYPTKIT_ELL_PROJ_ENABLE - -#include "ellipticProj.h" -#include "falloc.h" -#include "curveParams.h" -#include "elliptic.h" -#include "feeDebug.h" - -/* - * convert REC-style smulg to generic imulg - */ -#define smulg(s, g) imulg((unsigned)s, g) - -pointProj newPointProj(unsigned numDigits) -{ - pointProj pt; - - pt = (pointProj) fmalloc(sizeof(pointProjStruct)); - pt->x = newGiant(numDigits); - pt->y = newGiant(numDigits); - pt->z = newGiant(numDigits); - return(pt); -} - -void freePointProj(pointProj pt) -{ - clearGiant(pt->x); freeGiant(pt->x); - clearGiant(pt->y); freeGiant(pt->y); - clearGiant(pt->z); freeGiant(pt->z); - ffree(pt); -} - -void ptopProj(pointProj pt1, pointProj pt2) -{ - gtog(pt1->x, pt2->x); - gtog(pt1->y, pt2->y); - gtog(pt1->z, pt2->z); -} - -/************************************************************** - * - * Elliptic curve operations - * - **************************************************************/ - -/* Begin projective-format functions for - - y^2 = x^3 + a x + b. - - These are useful in elliptic curve cryptography (ECC). - A point is kept as a triple {X,Y,Z}, with the true (x,y) - coordinates given by - - {x,y} = {X/Z^2, Y/Z^3} - - The function normalizeProj() performs the inverse conversion to get - the true (x,y) pair. - */ - -void ellDoubleProj(pointProj pt, curveParams *cp) -/* pt := 2 pt on the curve. */ -{ - giant x = pt->x, y = pt->y, z = pt->z; - giant t1; - giant t2; - giant t3; - - if(isZero(y) || isZero(z)) { - int_to_giant(1,x); int_to_giant(1,y); int_to_giant(0,z); - return; - } - t1 = borrowGiant(cp->maxDigits); - t2 = borrowGiant(cp->maxDigits); - t3 = borrowGiant(cp->maxDigits); - - if((cp->a->sign >= 0) || (cp->a->n[0] != 3)) { /* Path prior to Apr2001. */ - gtog(z,t1); gsquare(t1); feemod(cp, t1); - gsquare(t1); feemod(cp, t1); - mulg(cp->a, t1); feemod(cp, t1); /* t1 := a z^4. */ - gtog(x, t2); gsquare(t2); feemod(cp, t2); - smulg(3, t2); /* t2 := 3x^2. */ - addg(t2, t1); feemod(cp, t1); /* t1 := slope m. */ - } else { /* New optimization for a = -3 (post Apr 2001). */ - gtog(z, t1); gsquare(t1); feemod(cp, t1); /* t1 := z^2. */ - gtog(x, t2); subg(t1, t2); /* t2 := x-z^2. */ - addg(x, t1); smulg(3, t1); /* t1 := 3(x+z^2). */ - mulg(t2, t1); feemod(cp, t1); /* t1 := slope m. */ - } - mulg(y, z); addg(z,z); feemod(cp, z); /* z := 2 y z. */ - gtog(y, t2); gsquare(t2); feemod(cp, t2); /* t2 := y^2. */ - gtog(t2, t3); gsquare(t3); feemod(cp, t3); /* t3 := y^4. */ - gshiftleft(3, t3); /* t3 := 8 y^4. */ - mulg(x, t2); gshiftleft(2, t2); feemod(cp, t2); /* t2 := 4xy^2. */ - gtog(t1, x); gsquare(x); feemod(cp, x); - subg(t2, x); subg(t2, x); feemod(cp, x); /* x done. */ - gtog(t1, y); subg(x, t2); mulg(t2, y); subg(t3, y); - feemod(cp, y); - returnGiant(t1); - returnGiant(t2); - returnGiant(t3); -} - -void ellAddProj(pointProj pt0, pointProj pt1, curveParams *cp) -/* pt0 := pt0 + pt1 on the curve. */ -{ - giant x0 = pt0->x, y0 = pt0->y, z0 = pt0->z, - x1 = pt1->x, y1 = pt1->y, z1 = pt1->z; - giant t1; - giant t2; - giant t3; - giant t4; - giant t5; - giant t6; - giant t7; - - if(isZero(z0)) { - gtog(x1,x0); gtog(y1,y0); gtog(z1,z0); - return; - } - if(isZero(z1)) return; - - t1 = borrowGiant(cp->maxDigits); - t2 = borrowGiant(cp->maxDigits); - t3 = borrowGiant(cp->maxDigits); - t4 = borrowGiant(cp->maxDigits); - t5 = borrowGiant(cp->maxDigits); - t6 = borrowGiant(cp->maxDigits); - t7 = borrowGiant(cp->maxDigits); - - gtog(x0, t1); gtog(y0,t2); gtog(z0, t3); - gtog(x1, t4); gtog(y1, t5); - if(!isone(z1)) { - gtog(z1, t6); - gtog(t6, t7); gsquare(t7); feemod(cp, t7); - mulg(t7, t1); feemod(cp, t1); - mulg(t6, t7); feemod(cp, t7); - mulg(t7, t2); feemod(cp, t2); - } - gtog(t3, t7); gsquare(t7); feemod(cp, t7); - mulg(t7, t4); feemod(cp, t4); - mulg(t3, t7); feemod(cp, t7); - mulg(t7, t5); feemod(cp, t5); - negg(t4); addg(t1, t4); feemod(cp, t4); - negg(t5); addg(t2, t5); feemod(cp, t5); - if(isZero(t4)) { - if(isZero(t5)) { - ellDoubleProj(pt0, cp); - } else { - int_to_giant(1, x0); int_to_giant(1, y0); - int_to_giant(0, z0); - } - goto out; - } - addg(t1, t1); subg(t4, t1); feemod(cp, t1); - addg(t2, t2); subg(t5, t2); feemod(cp, t2); - if(!isone(z1)) { - mulg(t6, t3); feemod(cp, t3); - } - mulg(t4, t3); feemod(cp, t3); - gtog(t4, t7); gsquare(t7); feemod(cp, t7); - mulg(t7, t4); feemod(cp, t4); - mulg(t1, t7); feemod(cp, t7); - gtog(t5, t1); gsquare(t1); feemod(cp, t1); - subg(t7, t1); feemod(cp, t1); - subg(t1, t7); subg(t1, t7); feemod(cp, t7); - mulg(t7, t5); feemod(cp, t5); - mulg(t2, t4); feemod(cp, t4); - gtog(t5, t2); subg(t4,t2); feemod(cp, t2); - if(t2->n[0] & 1) { /* Test if t2 is odd. */ - addg(cp->basePrime, t2); - } - gshiftright(1, t2); - gtog(t1, x0); gtog(t2, y0); gtog(t3, z0); -out: - returnGiant(t1); - returnGiant(t2); - returnGiant(t3); - returnGiant(t4); - returnGiant(t5); - returnGiant(t6); - returnGiant(t7); -} - - -void ellNegProj(pointProj pt, curveParams *cp) -/* pt := -pt on the curve. */ -{ - negg(pt->y); feemod(cp, pt->y); -} - -void ellSubProj(pointProj pt0, pointProj pt1, curveParams *cp) -/* pt0 := pt0 - pt1 on the curve. */ -{ - ellNegProj(pt1, cp); - ellAddProj(pt0, pt1,cp); - ellNegProj(pt1, cp); -} - -/* - * Simple projective multiply. - * - * pt := pt * k, result normalized. - */ -void ellMulProjSimple(pointProj pt0, giant k, curveParams *cp) -{ - pointProjStruct pt1; // local, giants borrowed - - CKASSERT(isone(pt0->z)); - CKASSERT(cp->curveType == FCT_Weierstrass); - - /* ellMulProj assumes constant pt0, can't pass as src and dst */ - pt1.x = borrowGiant(cp->maxDigits); - pt1.y = borrowGiant(cp->maxDigits); - pt1.z = borrowGiant(cp->maxDigits); - ellMulProj(pt0, &pt1, k, cp); - normalizeProj(&pt1, cp); - CKASSERT(isone(pt1.z)); - - ptopProj(&pt1, pt0); - returnGiant(pt1.x); - returnGiant(pt1.y); - returnGiant(pt1.z); -} - -void ellMulProj(pointProj pt0, pointProj pt1, giant k, curveParams *cp) -/* General elliptic multiplication; - pt1 := k*pt0 on the curve, - with k an arbitrary integer. - */ -{ - giant x = pt0->x, y = pt0->y, z = pt0->z, - xx = pt1->x, yy = pt1->y, zz = pt1->z; - int ksign, hlen, klen, b, hb, kb; - giant t0; - - CKASSERT(cp->curveType == FCT_Weierstrass); - if(isZero(k)) { - int_to_giant(1, xx); - int_to_giant(1, yy); - int_to_giant(0, zz); - return; - } - t0 = borrowGiant(cp->maxDigits); - ksign = k->sign; - if(ksign < 0) negg(k); - gtog(x,xx); gtog(y,yy); gtog(z,zz); - gtog(k, t0); addg(t0, t0); addg(k, t0); /* t0 := 3k. */ - hlen = bitlen(t0); - klen = bitlen(k); - for(b = hlen-2; b > 0; b--) { - ellDoubleProj(pt1,cp); - hb = bitval(t0, b); - if(b < klen) kb = bitval(k, b); else kb = 0; - if((hb != 0) && (kb == 0)) - ellAddProj(pt1, pt0, cp); - else if((hb == 0) && (kb !=0)) - ellSubProj(pt1, pt0, cp); - } - if(ksign < 0) { - ellNegProj(pt1, cp); - k->sign = -k->sign; - } - returnGiant(t0); -} - -void normalizeProj(pointProj pt, curveParams *cp) -/* Obtain actual x,y coords via normalization: - {x,y,z} := {x/z^2, y/z^3, 1}. - */ - -{ giant x = pt->x, y = pt->y, z = pt->z; - giant t1; - - CKASSERT(cp->curveType == FCT_Weierstrass); - if(isZero(z)) { - int_to_giant(1,x); int_to_giant(1,y); - return; - } - t1 = borrowGiant(cp->maxDigits); - binvg_cp(cp, z); // was binvaux(p, z); - gtog(z, t1); - gsquare(z); feemod(cp, z); - mulg(z, x); feemod(cp, x); - mulg(t1, z); mulg(z, y); feemod(cp, y); - int_to_giant(1, z); - returnGiant(t1); -} - -static int -jacobi_symbol(giant a, curveParams *cp) -/* Standard Jacobi symbol (a/cp->basePrime). - basePrime must be odd, positive. */ -{ - int t = 1, u; - giant t5 = borrowGiant(cp->maxDigits); - giant t6 = borrowGiant(cp->maxDigits); - giant t7 = borrowGiant(cp->maxDigits); - int rtn; - - gtog(a, t5); feemod(cp, t5); - gtog(cp->basePrime, t6); - while(!isZero(t5)) { - u = (t6->n[0]) & 7; - while((t5->n[0] & 1) == 0) { - gshiftright(1, t5); - if((u==3) || (u==5)) t = -t; - } - gtog(t5, t7); gtog(t6, t5); gtog(t7, t6); - u = (t6->n[0]) & 3; - if(((t5->n[0] & 3) == 3) && ((u & 3) == 3)) t = -t; - modg(t6, t5); - } - if(isone(t6)) { - rtn = t; - } - else { - rtn = 0; - } - returnGiant(t5); - returnGiant(t6); - returnGiant(t7); - - return rtn; -} - -static void -powFp2(giant a, giant b, giant w2, giant n, curveParams *cp) -/* Perform powering in the field F_p^2: - a + b w := (a + b w)^n (mod p), where parameter w2 is a quadratic - nonresidue (formally equal to w^2). - */ -{ - int j; - giant t6; - giant t7; - giant t8; - giant t9; - - if(isZero(n)) { - int_to_giant(1,a); - int_to_giant(0,b); - return; - } - t6 = borrowGiant(cp->maxDigits); - t7 = borrowGiant(cp->maxDigits); - t8 = borrowGiant(cp->maxDigits); - t9 = borrowGiant(cp->maxDigits); - gtog(a, t8); gtog(b, t9); - for(j = bitlen(n)-2; j >= 0; j--) { - gtog(b, t6); - mulg(a, b); addg(b,b); feemod(cp, b); /* b := 2 a b. */ - gsquare(t6); feemod(cp, t6); - mulg(w2, t6); feemod(cp, t6); - gsquare(a); addg(t6, a); feemod(cp, a); - /* a := a^2 + b^2 w2. */ - if(bitval(n, j)) { - gtog(b, t6); mulg(t8, b); feemod(cp, b); - gtog(a, t7); mulg(t9, a); addg(a, b); feemod(cp, b); - mulg(t9, t6); feemod(cp, t6); - mulg(w2, t6); feemod(cp, t6); - mulg(t8, a); addg(t6, a); feemod(cp, a); - } - } - returnGiant(t6); - returnGiant(t7); - returnGiant(t8); - returnGiant(t9); - return; -} - -static void -powermodg( - giant x, - giant n, - curveParams *cp -) -/* x becomes x^n (mod basePrime). */ -{ - int len, pos; - giant scratch2 = borrowGiant(cp->maxDigits); - - gtog(x, scratch2); - int_to_giant(1, x); - len = bitlen(n); - pos = 0; - while (1) - { - if (bitval(n, pos++)) - { - mulg(scratch2, x); - feemod(cp, x); - } - if (pos>=len) - break; - gsquare(scratch2); - feemod(cp, scratch2); - } - returnGiant(scratch2); -} - -static int sqrtmod(giant x, curveParams *cp) -/* If Sqrt[x] (mod p) exists, function returns 1, else 0. - In either case x is modified, but if 1 is returned, - x:= Sqrt[x] (mod p). - */ -{ - int rtn; - giant t0 = borrowGiant(cp->maxDigits); - giant t1 = borrowGiant(cp->maxDigits); - giant t2 = borrowGiant(cp->maxDigits); - giant t3 = borrowGiant(cp->maxDigits); - giant t4 = borrowGiant(cp->maxDigits); - - giant p = cp->basePrime; - - feemod(cp, x); /* Justify the argument. */ - gtog(x, t0); /* Store x for eventual validity check on square root. */ - if((p->n[0] & 3) == 3) { /* The case p = 3 (mod 4). */ - gtog(p, t1); - iaddg(1, t1); gshiftright(2, t1); - powermodg(x, t1, cp); - goto resolve; - } - /* Next, handle case p = 5 (mod 8). */ - if((p->n[0] & 7) == 5) { - gtog(p, t1); int_to_giant(1, t2); - subg(t2, t1); gshiftright(2, t1); - gtog(x, t2); - powermodg(t2, t1, cp); /* t2 := x^((p-1)/4) % p. */ - iaddg(1, t1); - gshiftright(1, t1); /* t1 := (p+3)/8. */ - if(isone(t2)) { - powermodg(x, t1, cp); /* x^((p+3)/8) is root. */ - goto resolve; - } else { - int_to_giant(1, t2); subg(t2, t1); - /* t1 := (p-5)/8. */ - gshiftleft(2,x); - powermodg(x, t1, cp); - mulg(t0, x); addg(x, x); feemod(cp, x); - /* 2x (4x)^((p-5)/8. */ - goto resolve; - } - } - - /* Next, handle tougher case: p = 1 (mod 8). */ - int_to_giant(2, t1); - while(1) { /* Find appropriate nonresidue. */ - gtog(t1, t2); - gsquare(t2); subg(x, t2); feemod(cp, t2); - if(jacobi_symbol(t2, cp) == -1) break; - iaddg(1, t1); - } /* t2 is now w^2 in F_p^2. */ - int_to_giant(1, t3); - gtog(p, t4); iaddg(1, t4); gshiftright(1, t4); - powFp2(t1, t3, t2, t4, cp); - gtog(t1, x); - -resolve: - gtog(x,t1); gsquare(t1); feemod(cp, t1); - if(gcompg(t0, t1) == 0) { - rtn = 1; /* Success. */ - } - else { - rtn = 0; /* no square root */ - } - returnGiant(t0); - returnGiant(t1); - returnGiant(t2); - returnGiant(t3); - returnGiant(t4); - return rtn; -} - - -void findPointProj(pointProj pt, giant seed, curveParams *cp) -/* Starting with seed, finds a random (projective) point {x,y,1} on curve. - */ -{ - giant x = pt->x, y = pt->y, z = pt->z; - - CKASSERT(cp->curveType == FCT_Weierstrass); - feemod(cp, seed); - while(1) { - gtog(seed, x); - gsquare(x); feemod(cp, x); // x := seed^2 - addg(cp->a, x); // x := seed^2 + a - mulg(seed,x); // x := seed^3 + a*seed - addg(cp->b, x); - feemod(cp, x); // x := seed^3 + a seed + b. - /* test cubic form for having root. */ - if(sqrtmod(x, cp)) break; - iaddg(1, seed); - } - gtog(x, y); - gtog(seed,x); - int_to_giant(1, z); -} - -#endif /* CRYPTKIT_ELL_PROJ_ENABLE */