static void numer_plus(giant x1, giant x2, giant res, curveParams *par) /* Numerator algebra. res = (x1 x2 + a)(x1 + x2) + 2(c x1 x2 + b). */ { giant t1; giant t2; PROF_START; t1 = borrowGiant(par->maxDigits); t2 = borrowGiant(par->maxDigits); gtog(x1, t1); mulg(x2, t1); feemod(par, t1); gtog(x2, t2); addg(x1, t2); feemod(par, t2); gtog(t1, res); if(!isZero(par->a)) addg(par->a, res); mulg(t2, res); feemod(par, res); if(par->curveType == FCT_Weierstrass) { // i.e., isZero(par->c) int_to_giant(0, t1); } else { mulg(par->c, t1); feemod(par, t1); } if(!isZero(par->b)) addg(par->b, t1); gshiftleft(1, t1); addg(t1, res); feemod(par, res); returnGiant(t1); returnGiant(t2); PROF_END(numerPlusTime); }
/* * Completely rewritten in CryptKit-18, 13 Jan 1997, for new IEEE-style * curveParameters. */ int which_curve(giant x, curveParams *par) /* Returns (+-1) depending on whether x is on curve (+-)y^2 = x^3 + c x^2 + a x + b. */ { giant t1; giant t2; giant t3; int result; PROF_START; t1 = borrowGiant(par->maxDigits); t2 = borrowGiant(par->maxDigits); t3 = borrowGiant(par->maxDigits); /* First, set t2:= x^3 + c x^2 + a x + b. */ gtog(x, t2); addg(par->c, t2); mulg(x, t2); addg(par->a, t2); /* t2 := x^2 + c x + a. */ feemod(par, t2); mulg(x, t2); addg(par->b, t2); feemod(par, t2); /* Next, test whether t2 is a square. */ gtog(t2, t1); make_base(par, t3); iaddg(1, t3); gshiftright(1, t3); /* t3 = (p+1)/2. */ feepowermodg(par, t1, t3); /* t1 := t2^((p+1)/2) (mod p). */ if(gcompg(t1, t2) == 0) result = CURVE_PLUS; else result = CURVE_MINUS; returnGiant(t1); returnGiant(t2); returnGiant(t3); PROF_END(whichCurveTime); return result; }
key new_public_with_key(key old_key, curveParams *cp) { key result; result = new_public(cp, old_key->twist); CKASSERT((old_key->x != NULL) && (old_key->y != NULL)); CKASSERT((result->x != NULL) && (result->y != NULL)); gtog(old_key->x, result->x); gtog(old_key->y, result->y); return result; }
int binvaux(giant p, giant x) /* Binary inverse method. Returns zero if no inverse exists, in which case x becomes GCD(x,p). */ { giant scratch7; giant u0; giant u1; giant v0; giant v1; int result = 1; int giantSize; PROF_START; if(isone(x)) return(result); giantSize = 4 * abs(p->sign); scratch7 = borrowGiant(giantSize); u0 = borrowGiant(giantSize); u1 = borrowGiant(giantSize); v0 = borrowGiant(giantSize); v1 = borrowGiant(giantSize); int_to_giant(1, v0); gtog(x, v1); int_to_giant(0,x); gtog(p, u1); while(!isZero(v1)) { gtog(u1, u0); bdivg(v1, u0); gtog(x, scratch7); gtog(v0, x); mulg(u0, v0); subg(v0,scratch7); gtog(scratch7, v0); gtog(u1, scratch7); gtog(v1, u1); mulg(u0, v1); subg(v1,scratch7); gtog(scratch7, v1); } if (!isone(u1)) { gtog(u1,x); if(x->sign<0) addg(p, x); result = 0; goto done; } if (x->sign<0) addg(p, x); done: returnGiant(scratch7); returnGiant(u0); returnGiant(u1); returnGiant(v0); returnGiant(v1); PROF_END(binvauxTime); return(result); }
void modg(giant d, giant n) /* n becomes n%d. n is arbitrary, but the denominator d must be positive! */ { if (cur_recip == NULL) { cur_recip = newgiant(current_max_size); cur_den = newgiant(current_max_size); gtog(d, cur_den); make_recip(d, cur_recip); } else if (gcompg(d, cur_den)) { gtog(d, cur_den); make_recip(d, cur_recip); } modg_via_recip(d, cur_recip, n); }
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); }
void gmersennemod( int n, giant g ) /* g := g (mod 2^n - 1) */ { int the_sign; giant scratch3 = borrowGiant(g->capacity); giant scratch4 = borrowGiant(1); if ((the_sign = gsign(g)) < 0) absg(g); while (bitlen(g) > n) { gtog(g,scratch3); gshiftright(n,scratch3); addg(scratch3,g); gshiftleft(n,scratch3); subg(scratch3,g); } if(isZero(g)) goto out; int_to_giant(1,scratch3); gshiftleft(n,scratch3); int_to_giant(1,scratch4); subg(scratch4,scratch3); if(gcompg(g,scratch3) >= 0) subg(scratch3,g); if (the_sign < 0) { g->sign = -g->sign; addg(scratch3,g); } out: returnGiant(scratch3); returnGiant(scratch4); }
/* * New, 13 Jan 1997. */ static void feepowermodg(curveParams *par, giant x, giant n) /* Power ladder. x := x^n (mod 2^q-k) */ { int len, pos; giant t1; PROF_START; t1 = borrowGiant(par->maxDigits); gtog(x, t1); int_to_giant(1, x); len = bitlen(n); pos = 0; while(1) { if(bitval(n, pos++)) { mulg(t1, x); feemod(par, x); } if(pos>=len) break; gsquare(t1); feemod(par, t1); } returnGiant(t1); PROF_END(powerModTime); }
/* * Key exchange atom. */ giant make_pad(giant privGiant, key publicKey) { curveParams *par = publicKey->cp; giant result = newGiant(par->maxDigits); gtog(publicKey->x, result); elliptic_simple(result, privGiant, par); return result; }
static void numer_double(giant x, giant z, giant res, curveParams *par) /* Numerator algebra. res := (x^2 - a z^2)^2 - 4 b (2 x + c z) z^3. */ { giant t1; giant t2; PROF_START; t1 = borrowGiant(par->maxDigits); t2 = borrowGiant(par->maxDigits); gtog(x, t1); gsquare(t1); feemod(par, t1); gtog(z, res); gsquare(res); feemod(par, res); gtog(res, t2); if(!isZero(par->a) ) { if(!isone(par->a)) { /* Speedup - REC 17 Jan 1997. */ mulg(par->a, res); feemod(par, res); } subg(res, t1); feemod(par, t1); } gsquare(t1); feemod(par, t1); /* t1 := (x^2 - a z^2)^2. */ if(isZero(par->b)) { /* Speedup - REC 17 Jan 1997. */ gtog(t1, res); goto done; } if(par->curveType != FCT_Weierstrass) { // i.e., !isZero(par->c) // Speedup - REC 17 Jan 1997. gtog(z, res); mulg(par->c, res); feemod(par, res); } else { int_to_giant(0, res); } addg(x, res); addg(x, res); mulg(par->b, res); feemod(par, res); gshiftleft(2, res); mulg(z, res); feemod(par, res); mulg(t2, res); feemod(par, res); negg(res); addg(t1, res); feemod(par, res); done: returnGiant(t1); returnGiant(t2); PROF_END(numerDoubleTime); }
void make_recip(giant d, giant r) /* r becomes the steady-state reciprocal * 2^(2b)/d, where b = bit-length of d-1. */ { int b; giant tmp, tmp2; if (isZero(d) || (d->sign < 0)) { exit(SIGN); } tmp = popg(); tmp2 = popg(); itog(1, r); subg(r, d); b = bitlen(d); addg(r, d); gshiftleft(b, r); gtog(r, tmp2); while (1) { gtog(r, tmp); squareg(tmp); gshiftright(b, tmp); mulg(d, tmp); gshiftright(b, tmp); addg(r, r); subg(tmp, r); if (gcompg(r, tmp2) <= 0) break; gtog(r, tmp2); } itog(1, tmp); gshiftleft(2 * b, tmp); gtog(r, tmp2); mulg(d, tmp2); subg(tmp2, tmp); itog(1, tmp2); while (tmp->sign < 0) { subg(tmp2, r); addg(d, tmp); } pushg(2); }
static void denom_times(giant x1, giant z1, giant x2, giant z2, giant res, curveParams *par) /* Denominator algebra. res := (x1 z2 - x2 z1)^2 */ { giant t1; PROF_START; t1 = borrowGiant(par->maxDigits); gtog(x1, res); mulg(z2, res); feemod(par, res); gtog(z1, t1); mulg(x2, t1); feemod(par, t1); subg(t1, res); gsquare(res); feemod(par, res); returnGiant(t1); PROF_END(denomTimesTime); }
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; }
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 subg(giant a, giant b) /* b := b - a, any signs, any result. */ { int asgn = a->sign, bsgn = b->sign; if (asgn == 0) return; if (bsgn == 0) { gtog(a, b); negg(b); return; } if ((asgn < 0) != (bsgn < 0)) { if (bsgn > 0) { negg(a); normal_addg(a, b); negg(a); return; } negg(b); normal_addg(a, b); negg(b); return; } if (bsgn > 0) { if (gcompg(b, a) >= 0) { normal_subg(a, b); return; } reverse_subg(a, b); negg(b); return; } negg(a); negg(b); if (gcompg(b, a) >= 0) { normal_subg(a, b); negg(a); negg(b); return; } reverse_subg(a, b); negg(a); return; }
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); }
/* * Specify private data for key created by new_public(). * Generates k->x. */ void set_priv_key_giant(key k, giant privGiant) { curveParams *cp = k->cp; /* elliptiy multiply of initial public point times private key */ #if CRYPTKIT_ELL_PROJ_ENABLE if((k->twist == CURVE_PLUS) && (cp->curveType == FCT_Weierstrass)) { /* projective */ pointProj pt1 = newPointProj(cp->maxDigits); CKASSERT((cp->y1Plus != NULL) && (!isZero(cp->y1Plus))); CKASSERT(k->y != NULL); /* pt1 := {x1Plus, y1Plus, 1} */ gtog(cp->x1Plus, pt1->x); gtog(cp->y1Plus, pt1->y); int_to_giant(1, pt1->z); /* pt1 := pt1 * privateKey */ ellMulProjSimple(pt1, privGiant, cp); /* result back to {k->x, k->y} */ gtog(pt1->x, k->x); gtog(pt1->y, k->y); freePointProj(pt1); // FIXME - clear the giants } else { #else { #endif /* CRYPTKIT_ELL_PROJ_ENABLE */ /* FEE */ if(k->twist == CURVE_PLUS) { gtog(cp->x1Plus, k->x); } else { gtog(cp->x1Minus, k->x); } elliptic_simple(k->x, privGiant, k->cp); } } int key_equal(key one, key two) { if (keys_inconsistent(one, two)) return 0; return !gcompg(one->x, two->x); } static void make_base(curveParams *par, giant result) /* Jams result with 2^q-k. */ { gtog(par->basePrime, result); }
/* * General elliptic multiply. * * {xx, zz} := k * {xx, zz} */ void elliptic(giant xx, giant zz, giant k, curveParams *par) { int len = bitlen(k); int pos = len - 2; giant xs; giant zs; giant xorg; giant zorg; PROF_START; if(sequalg(1,k)) return; if(sequalg(2,k)) { ell_even(xx, zz, xx, zz, par); goto out; } zs = borrowGiant(par->maxDigits); xs = borrowGiant(par->maxDigits); zorg = borrowGiant(par->maxDigits); xorg = borrowGiant(par->maxDigits); gtog(xx, xorg); gtog(zz, zorg); ell_even(xx, zz, xs, zs, par); do { if(bitval(k, pos--)) { ell_odd(xs, zs, xx, zz, xorg, zorg, par); ell_even(xs, zs, xs, zs, par); } else { ell_odd(xx, zz, xs, zs, xorg, zorg, par); ell_even(xx, zz, xx, zz, par); } } while (pos >= 0); // REC fix 9/23/94 returnGiant(xs); returnGiant(zs); returnGiant(xorg); returnGiant(zorg); out: PROF_END(ellipticTime); }
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 denom_double(giant x, giant z, giant res, curveParams *par) /* Denominator algebra. res = 4 z (x^3 + c x^2 z + a x z^2 + b z^3). */ { giant t1; giant t2; PROF_START; t1 = borrowGiant(par->maxDigits); t2 = borrowGiant(par->maxDigits); gtog(x, res); gtog(z, t1); if(par->curveType != FCT_Weierstrass) { // i.e., !isZero(par->c) gtog(par->c, t2); mulg(t1, t2); feemod(par, t2); addg(t2, res); } mulg(x, res); feemod(par, res); gsquare(t1); feemod(par, t1); if(!isZero(par->a)) { gtog(t1, t2); mulg(par->a, t2); feemod(par, t2); addg(t2, res); } mulg(x, res); feemod(par, res); if(!isZero(par->b)) { mulg(z, t1); feemod(par, t1); mulg(par->b, t1); feemod(par, t1); addg(t1, res); } mulg(z, res); gshiftleft(2, res); feemod(par, res); returnGiant(t1); returnGiant(t2); PROF_END(denomDoubleTime); }
void gmersennemod(int n, giant g) { /* g becomes g mod ((2^n)-1) 31 Jul 96 modified REC. 17 Jan 97 modified REC. */ unsigned bits = n & (GIANT_BITS_PER_DIGIT - 1); unsigned digits = 1 + ((n-1) >> GIANT_LOG2_BITS_PER_DIGIT); int isPositive = (g->sign > 0); int j; int b; int size; int foundzero; giantDigit mask = (bits == 0) ? GIANT_DIGIT_MASK : (giantDigit)((1<<bits)-1); giant scratch1; b = bitlen(g); if(b < n) { unsigned numDigits = (n + GIANT_BITS_PER_DIGIT - 1) >> GIANT_LOG2_BITS_PER_DIGIT; giantDigit lastWord = 0; giantDigit bits = 1; if(g->sign >= 0) return; /* * Cons up ((2**n)-1), add to g. */ scratch1 = borrowGiant(numDigits + 1); scratch1->sign = numDigits; for(j=0; j<(int)(numDigits-1); j++) { scratch1->n[j] = GIANT_DIGIT_MASK; } /* * Last word has lower (n & (GIANT_BITS_PER_DIGIT-1)) bits set. */ for(j=0; j < (int)(n & (GIANT_BITS_PER_DIGIT-1)); j++) { lastWord |= bits; bits <<= 1; } scratch1->n[numDigits-1] = lastWord; addg(g, scratch1); /* One version. */ gtog(scratch1, g); returnGiant(scratch1); return; }
static void numer_times(giant x1, giant z1, giant x2, giant z2, giant res, curveParams *par) /* Numerator algebra. res := (x1 x2 - a z1 z2)^2 - 4 b(x1 z2 + x2 z1 + c z1 z2) z1 z2 */ { giant t1; giant t2; giant t3; giant t4; PROF_START; t1 = borrowGiant(par->maxDigits); t2 = borrowGiant(par->maxDigits); t3 = borrowGiant(par->maxDigits); t4 = borrowGiant(par->maxDigits); gtog(x1, t1); mulg(x2, t1); feemod(par, t1); gtog(z1, t2); mulg(z2, t2); feemod(par, t2); gtog(t1, res); if(!isZero(par->a)) { gtog(par->a, t3); mulg(t2, t3); feemod(par, t3); subg(t3, res); } gsquare(res); feemod(par, res); if(isZero(par->b)) goto done; if(par->curveType != FCT_Weierstrass) { // i.e., !isZero(par->c) gtog(par->c, t3); mulg(t2, t3); feemod(par, t3); } else int_to_giant(0, t3); gtog(z1, t4); mulg(x2, t4); feemod(par, t4); addg(t4, t3); gtog(x1, t4); mulg(z2, t4); feemod(par, t4); addg(t4, t3); mulg(par->b, t3); feemod(par, t3); mulg(t2, t3); gshiftleft(2, t3); feemod(par, t3); subg(t3, res); feemod(par, res); done: returnGiant(t1); returnGiant(t2); returnGiant(t3); returnGiant(t4); PROF_END(numerTimesTime); }
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); }
static void reverse_subg(giant a, giant b) /* b := a - b; requires b, a non-negative and a >= b. */ { int j; int size = a->sign; giantDigit tmp; giantDigit borrow1 = 0; giantDigit borrow2 = 0; giantDigit *an = a->n; giantDigit *bn = b->n; if(b->sign == 0) { gtog(a, b); return; } for (j=0; j<b->sign; ++j) { if(borrow1 || borrow2) { tmp = giantSubDigits(an[j], (giantDigit)1, &borrow1); } else { tmp = an[j]; borrow1 = 0; } bn[j] = giantSubDigits(tmp, bn[j], &borrow2); } if(borrow1 || borrow2) { /* propagate borrow thru remainder of bn[] */ borrow1 = 1; } for (j=b->sign; j<size; ++j) { if(borrow1) { bn[j] = giantSubDigits(an[j], (giantDigit)1, &borrow1); } else { bn[j] = an[j]; borrow1 = 0; } } b->sign = size; /* REC, 21 Apr 1996. */ while(!b->n[--size]); b->sign = size+1; }
void grammarmulg(giant a, giant b) /* b becomes a*b. */ { int i, j; unsigned int prod, carry = 0; int asize = abs(a->sign), bsize = abs(b->sign); unsigned short *aptr, *bptr, *destptr; unsigned short mult; giant scratch = popg(); for (i = 0; i < asize + bsize; ++i) { scratch->n[i] = 0; } bptr = &(b->n[0]); for (i = 0; i < bsize; ++i) { mult = *(bptr++); if (mult) { carry = 0; aptr = &(a->n[0]); destptr = &(scratch->n[i]); for (j = 0; j < asize; ++j) { prod = *(aptr++) * mult + *destptr + carry; *(destptr++) = (unsigned short)(prod & 0xffff); carry = prod >> 16; } *destptr = (unsigned short)carry; } } bsize += asize; if (!carry) --bsize; scratch->sign = gsign(a)*gsign(b)*bsize; gtog(scratch, b); pushg(1); }
main(int argc, char **argv) { giant p = newgiant(CM_SHORTS); giant u = newgiant(CM_SHORTS); giant v = newgiant(CM_SHORTS); giant g[6]; giant plus_order = newgiant(CM_SHORTS); giant minus_order = newgiant(CM_SHORTS); giant a = newgiant(CM_SHORTS); giant b = newgiant(CM_SHORTS); int d, dc, olen, k; init_tools(CM_SHORTS); /* Basic algorithms. */ printf("Give base prime p:\n"); fflush(stdout); gin(p); for(dc=0; dc < 6; dc++) g[dc] = newgiant(CM_SHORTS); for(dc = 0; dc < DCOUNT; dc++) { d = disc12[dc]; /* Next, seek representation 4N = u^2 + |d| v^2. */ if(cornacchia4(p, d, u, v) == 0) continue; /* Here, (u,v) give the quadratic representation of 4p. */ printf("D: %d\n", d); fflush(stdout); gtog(u, g[0]); switch(d) { case -3: olen = 3; /* Six orders: p + 1 +- g[0,1,2]. */ gtog(u, g[1]); gtog(v, g[2]); addg(g[2], g[2]); addg(v, g[2]); /* g[2] := 3v. */ addg(g[2], g[1]); gshiftright(1, g[1]); /* g[1] = (u + 3v)/2. */ subg(u, g[2]); gshiftright(1, g[2]); absg(g[2]); /* g[2] = |u-3v|/2. */ break; case -4: olen = 2; /* Four orders: p + 1 +- g[0,1]. */ gtog(v, g[1]); addg(g[1], g[1]); /* g[1] = 2v. */ break; default: olen = 1; /* Two orders: p + 1 +- g[0]. */ } for(k=0; k < olen; k++) { gtog(p, plus_order); iaddg(1, plus_order); gtog(p, minus_order); iaddg(1, minus_order); addg(g[k], plus_order); subg(g[k], minus_order); printf("curve orders: \n"); printf("(%d) ", prime_probable(plus_order)); gout(plus_order); printf("(%d) ", prime_probable(minus_order)); gout(minus_order); } } }
void modg_via_recip(giant d, giant r, giant n) /* This is the fastest mod of the present collection. * n := n % d, where r is the precalculated * steady-state reciprocal of d. */ { int s = (bitlen(r) - 1), sign = n->sign; giant tmp, tmp2; if (isZero(d) || (d->sign < 0)) { exit(SIGN); } tmp = popg(); tmp2 = popg(); n->sign = abs(n->sign); while (1) { gtog(n, tmp); gshiftright(s - 1, tmp); mulg(r, tmp); gshiftright(s + 1, tmp); mulg(d, tmp); subg(tmp, n); if (gcompg(n, d) >= 0) subg(d, n); if (gcompg(n, d) < 0) break; } if (sign >= 0) goto done; if (isZero(n)) goto done; negg(n); addg(d, n); done: pushg(2); return; }
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); }
/* * New optimzation of curveOrderJustify using known reciprocal, 11 June 1997. * g is set to be within [2, curveOrder-2]. */ static void curveOrderJustifyWithRecip(giant g, giant curveOrder, giant recip) { giant tmp; CKASSERT(!isZero(curveOrder)); modg_via_recip(curveOrder, recip, g); // g now in [0, curveOrder-1] if(isZero(g)) { /* * First degenerate case - (g == 0) : set g := 2 */ dbgLog(("curveOrderJustify: case 1\n")); int_to_giant(2, g); return; } if(isone(g)) { /* * Second case - (g == 1) : set g := 2 */ dbgLog(("curveOrderJustify: case 2\n")); int_to_giant(2, g); return; } tmp = borrowGiant(g->capacity); gtog(g, tmp); iaddg(1, tmp); if(gcompg(tmp, curveOrder) == 0) { /* * Third degenerate case - (g == (curveOrder-1)) : set g -= 1 */ dbgLog(("curveOrderJustify: case 3\n")); int_to_giant(1, tmp); subg(tmp, g); } returnGiant(tmp); return; }
static void bdivg(giant v, giant u) /* u becomes greatest power of two not exceeding u/v. */ { int diff = bitlen(u) - bitlen(v); giant scratch7; if (diff<0) { int_to_giant(0,u); return; } scratch7 = borrowGiant(u->capacity); gtog(v, scratch7); gshiftleft(diff,scratch7); if(gcompg(u,scratch7) < 0) diff--; if(diff<0) { int_to_giant(0,u); returnGiant(scratch7); return; } int_to_giant(1,u); gshiftleft(diff,u); returnGiant(scratch7); }