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; }
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); }
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); }
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 iaddg(int i, giant g) /* Giant g becomes g + (int)i. */ { int w, j = 0, carry = 0, size = abs(g->sign); giant tmp; if (isZero(g)) { itog(i, g); } else if (g->sign < 0) { tmp = popg(); itog(i, tmp); addg(tmp, g); pushg(1); return; } else { w = g->n[0] + i; do { g->n[j] = (unsigned short)(w & 65535L); carry = w >> 16; w = g->n[++j] + carry; } while ((carry != 0) && (j < size)); } if (carry) { ++g->sign; g->n[size] = (unsigned short)carry; } }
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); } } }
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); }
/* input: receive edge and initialize graph */ void input(int n) { int i, v1, v2, pos1, pos2; for (i = numnode = 0; i < n; i++) { scanf("%d %d", &v1, &v2); pos1 = search(v1); if (pos1 == -1) pos1 = addg(v1); pos2 = search(v2); if (pos2 == -1) pos2 = addg(v2); if (pos1 != pos2) { update(pos1, pos2); update(pos2, pos1); } } }
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 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 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 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); }
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); }
int signature_compare(giant p0x, giant p1x, giant p2x, curveParams *par) /* Returns non-zero iff p0x cannot be the x-coordinate of the sum of two points whose respective x-coordinates are p1x, p2x. */ { int ret = 0; giant t1; giant t2; giant t3; giant t4; giant t5; PROF_START; t1 = borrowGiant(par->maxDigits); t2 = borrowGiant(par->maxDigits); t3 = borrowGiant(par->maxDigits); t4 = borrowGiant(par->maxDigits); t5 = borrowGiant(par->maxDigits); if(gcompg(p1x, p2x) == 0) { int_to_giant(1, t1); numer_double(p1x, t1, t2, par); denom_double(p1x, t1, t3, par); mulg(p0x, t3); subg(t3, t2); feemod(par, t2); } else { numer_plus(p1x, p2x, t1, par); gshiftleft(1, t1); feemod(par, t1); int_to_giant(1, t3); numer_times(p1x, t3, p2x, t3, t2, par); int_to_giant(1, t4); int_to_giant(1, t5); denom_times(p1x, t4 , p2x, t5, t3, par); /* Now we require t3 x0^2 - t1 x0 + t2 == 0. */ mulg(p0x, t3); feemod(par, t3); subg(t1, t3); mulg(p0x, t3); feemod(par, t3); addg(t3, t2); feemod(par, t2); } if(!isZero(t2)) ret = SIGNATURE_INVALID; returnGiant(t1); returnGiant(t2); returnGiant(t3); returnGiant(t4); returnGiant(t5); PROF_END(sigCompTime); return(ret); }
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; }
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; }
/* * Completely rewritten in CryptKit-18, 13 Jan 1997, for new IEEE-style * curveParameters. */ void elliptic_add(giant x1, giant x2, giant x3, curveParams *par, int s) { /* Addition algorithm for x3 = x1 + x2 on the curve, with sign ambiguity s. From theory, we know that if {x1,1} and {x2,1} are on a curve, then their elliptic sum (x1,1} + {x2,1} = {x3,1} must have x3 as one of two values: x3 = U/2 + s*Sqrt[U^2/4 - V] where sign s = +-1, and U,V are functions of x1,x2. Tho present function is called a maximum of twice, to settle which of +- is s. When a call is made, it is guaranteed already that x1, x2 both lie on the same curve (+- curve); i.e., which curve (+-) is not connected at all with sign s of the x3 relation. */ giant cur_n; giant t1; giant t2; giant t3; giant t4; giant t5; PROF_START; cur_n = borrowGiant(par->maxDigits); t1 = borrowGiant(par->maxDigits); t2 = borrowGiant(par->maxDigits); t3 = borrowGiant(par->maxDigits); t4 = borrowGiant(par->maxDigits); t5 = borrowGiant(par->maxDigits); if(gcompg(x1, x2)==0) { int_to_giant(1, t1); numer_double(x1, t1, x3, par); denom_double(x1, t1, t2, par); binvg_cp(par, t2); mulg(t2, x3); feemod(par, x3); goto out; } numer_plus(x1, x2, t1, par); int_to_giant(1, t3); numer_times(x1, t3, x2, t3, t2, par); int_to_giant(1, t4); int_to_giant(1, t5); denom_times(x1, t4, x2, t5, t3, par); binvg_cp(par, t3); mulg(t3, t1); feemod(par, t1); /* t1 := U/2. */ mulg(t3, t2); feemod(par, t2); /* t2 := V. */ /* Now x3 will be t1 +- Sqrt[t1^2 - t2]. */ gtog(t1, t4); gsquare(t4); feemod(par, t4); subg(t2, t4); make_base(par, cur_n); iaddg(1, cur_n); gshiftright(2, cur_n); /* cur_n := (p+1)/4. */ feepowermodg(par, t4, cur_n); /* t4 := t2^((p+1)/4) (mod p). */ gtog(t1, x3); if(s != SIGN_PLUS) negg(t4); addg(t4, x3); feemod(par, x3); out: returnGiant(cur_n); returnGiant(t1); returnGiant(t2); returnGiant(t3); returnGiant(t4); returnGiant(t5); PROF_END(ellAddTime); }
/* * Sign specified block of data (most likely a hash result) using * specified feePubKey. */ feeReturn feeSigSign(feeSig sig, const unsigned char *data, // data to be signed unsigned dataLen, // in bytes feePubKey pubKey) { sigInst *sinst = (sigInst*) sig; giant messageGiant = NULL; unsigned maxlen; giant privGiant; unsigned privGiantBytes; feeReturn frtn = FR_Success; unsigned randBytesLen; unsigned uDigits; // alloc'd digits in sinst->u curveParams *cp; if(pubKey == NULL) { return FR_BadPubKey; } cp = feePubKeyCurveParams(pubKey); if(cp == NULL) { return FR_BadPubKey; } privGiant = feePubKeyPrivData(pubKey); if(privGiant == NULL) { dbgLog(("Attempt to Sign without private data\n")); frtn = FR_IllegalArg; goto abort; } privGiantBytes = abs(privGiant->sign) * GIANT_BYTES_PER_DIGIT; /* * Note PmX = m 'o' P1. * Get message/digest as giant. May be significantly different * in size from pubKey's basePrime. */ messageGiant = giant_with_data(data, dataLen); // M(text) randBytesLen = feePubKeyBitsize(pubKey) / 8; maxlen = max(randBytesLen, dataLen); /* leave plenty of room.... */ uDigits = (3 * (privGiantBytes + maxlen)) / GIANT_BYTES_PER_DIGIT; sinst->u = newGiant(uDigits); gtog(privGiant, sinst->u); // u := ourPri mulg(messageGiant, sinst->u); // u *= M(text) addg(sinst->randGiant, sinst->u); // u += m /* * Paranoia: we're using the curveParams from the caller's pubKey; * this cp will have a valid x1OrderPlusRecip if pubKey is the same * as the one passed to feeSigNewWithKey() (since feeSigNewWithKey * called x1OrderPlusJustify()). But the caller could conceivably be * using a different instance of their pubKey, in which case * the key's cp->x1OrderPlusRecip may not be valid. */ calcX1OrderPlusRecip(cp); /* u := u mod x1OrderPlus */ #if SIG_DEBUG if(sigDebug) { printf("sigSign:\n"); printf("u pre-modg : "); printGiant(sinst->u); } #endif modg_via_recip(cp->x1OrderPlus, cp->x1OrderPlusRecip, sinst->u); #if SIG_DEBUG if(sigDebug) { printf("privGiant : "); printGiant(privGiant); printf("u : "); printGiant(sinst->u); printf("messageGiant: "); printGiant(messageGiant); printf("curveParams :\n"); printCurveParams(cp); } #endif // SIG_DEBUG abort: if(messageGiant) { freeGiant(messageGiant); } return frtn; }
static void ell_even(giant x1, giant z1, giant x2, giant z2, curveParams *par) { giant t1; giant t2; giant t3; EPROF_START; t1 = borrowGiant(par->maxDigits); t2 = borrowGiant(par->maxDigits); t3 = borrowGiant(par->maxDigits); if(par->curveType == FCT_Montgomery) { /* Begin Montgomery OPT: 10 Jan 98 REC. */ gtog(x1, t1); gsquare(t1); feemod(par, t1); /* t1 := x1^2. */ gtog(z1, t2); gsquare(t2); feemod(par, t2); /* t2 := z1^2. */ gtog(x1, t3); mulg(z1, t3); feemod(par, t3); gtog(t3, z2); mulg(par->c, z2); feemod(par, z2); addg(t1, z2); addg(t2, z2); mulg(t3, z2); gshiftleft(2, z2); feemod(par, z2); /* z2 := 4 x1 z1 (x1^2 + c x1 z1 + z1^2). */ gtog(t1, x2); subg(t2, x2); gsquare(x2); feemod(par, x2); /* x2 := (x1^2 - z1^2)^2. */ /* End OPT: 10 Jan 98 REC. */ } else if((par->curveType == FCT_Weierstrass) && isZero(par->a)) { /* Begin Atkin3 OPT: 9 Jan 98 REC. */ gtog(x1, t1); gsquare(t1); feemod(par, t1); mulg(x1, t1); feemod(par, t1); /* t1 := x^3. */ gtog(z1, t2); gsquare(t2); feemod(par, t2); mulg(z1, t2); feemod(par, t2); /* t2 := z1^3 */ mulg(par->b, t2); feemod(par, t2); /* t2 := b z1^3. */ gtog(t1, t3); addg(t2, t3); /* t3 := x^3 + b z1^3 */ mulg(z1, t3); feemod(par, t3); /* t3 *= z1 * = z1 ( x^3 + b z1^3 ) */ gshiftleft(2, t3); feemod(par, t3); /* t3 = 4 z1 (x1^3 + b z1^3) */ gshiftleft(3, t2); /* t2 = 8 b z1^3 */ subg(t2, t1); /* t1 = x^3 - 8 b z1^3 */ mulg(x1, t1); feemod(par, t1); /* t1 = x1 (x1^3 - 8 b z1^3) */ gtog(t3, z2); gtog(t1, x2); /* End OPT: 9 Jan 98 REC. */ } else { numer_double(x1, z1, t1, par); denom_double(x1, z1, t2, par); gtog(t1, x2); gtog(t2, z2); } returnGiant(t1); returnGiant(t2); returnGiant(t3); EPROF_END(ellEvenTime); EPROF_INCR(numEllEvens); /* printf("ell_even end\n"); printf(" x1 : "); printGiant(x1); printf(" z1 : "); printGiant(z1); printf(" x2 : "); printGiant(x2); printf(" z2 : "); printGiant(z2); */ }
static void ell_odd(giant x1, giant z1, giant x2, giant z2, giant xxor, giant zor, curveParams *par) { giant t1; giant t2; EPROF_START; t1 = borrowGiant(par->maxDigits); t2 = borrowGiant(par->maxDigits); if(par->curveType == FCT_Montgomery) { /* Begin Montgomery OPT: 10 Jan 98 REC. */ giant t3 = borrowGiant(par->maxDigits); giant t4 = borrowGiant(par->maxDigits); gtog(x1, t1); addg(z1, t1); /* t1 := x1 + z1. */ gtog(x2, t2); subg(z2, t2); /* t2 := x2 - z2. */ gtog(x1, t3); subg(z1, t3); /* t3 := x1 - z1. */ gtog(x2, t4); addg(z2, t4); /* t4 := x2 + z2. */ mulg(t2, t1); feemod(par, t1); /* t1 := (x1 + z1)(x2 - z2) */ mulg(t4, t3); feemod(par, t3); /* t4 := (x2 + z2)(x1 - z1) */ gtog(t1, z2); subg(t3, z2); /*???gshiftright(1, z2);*/ /* z2 := ((x1 + z1)(x2 - z2) - x2)/2 */ gsquare(z2); feemod(par, z2); mulg(xxor, z2); feemod(par, z2); gtog(t1, x2); addg(t3, x2); /*????gshiftright(1, x2);*/ gsquare(x2); feemod(par, x2); mulg(zor, x2); feemod(par, x2); returnGiant(t3); returnGiant(t4); } else if((par->curveType == FCT_Weierstrass) && isZero(par->a)) { /* Begin Atkin3 OPT: 9 Jan 98 REC. */ giant t3 = borrowGiant(par->maxDigits); giant t4 = borrowGiant(par->maxDigits); gtog(x1, t1); mulg(x2, t1); feemod(par, t1); /* t1 := x1 x2. */ gtog(z1, t2); mulg(z2, t2); feemod(par, t2); /* t2 := z1 z2. */ gtog(x1, t3); mulg(z2, t3); feemod(par, t3); /* t3 := x1 z2. */ gtog(z1, t4); mulg(x2, t4); feemod(par, t4); /* t4 := x2 z1. */ gtog(t3, z2); subg(t4, z2); gsquare(z2); feemod(par, z2); mulg(xxor, z2); feemod(par, z2); gtog(t1, x2); gsquare(x2); feemod(par, x2); addg(t4, t3); mulg(t2, t3); feemod(par, t3); mulg(par->b, t3); feemod(par, t3); addg(t3, t3); addg(t3, t3); subg(t3, x2); mulg(zor, x2); feemod(par, x2); returnGiant(t3); returnGiant(t4); /* End OPT: 9 Jan 98 REC. */ } else { numer_times(x1, z1, x2, z2, t1, par); mulg(zor, t1); feemod(par, t1); denom_times(x1, z1, x2, z2, t2, par); mulg(xxor, t2); feemod(par, t2); gtog(t1, x2); gtog(t2, z2); } returnGiant(t1); returnGiant(t2); EPROF_END(ellOddTime); EPROF_INCR(numEllOdds); /* printf("ell_odd end\n"); printf(" x2 : "); printGiant(x2); printf(" z2 : "); printGiant(z2); */ }
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 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); }
feeReturn feeECDSASign( feePubKey pubKey, feeSigFormat format, // Signature format DER 9.62 / RAW const unsigned char *data, // data to be signed unsigned dataLen, // in bytes feeRandFcn randFcn, // optional void *randRef, // optional unsigned char **sigData, // malloc'd and RETURNED unsigned *sigDataLen) // RETURNED { curveParams *cp; /* giant integers per IEEE P1363 notation */ giant c; // both 1363 'c' and 'i' // i.e., x-coord of u's pub key giant d; giant u; // random private key giant s; // private key as giant giant f; // data (message) as giant feeReturn frtn = FR_Success; feeRand frand; unsigned char *randBytes; unsigned randBytesLen; unsigned groupBytesLen; giant privGiant; #if ECDSA_SIGN_USE_PROJ pointProjStruct pt; // pt->x = c giant pty; // pt->y giant ptz; // pt->z #endif // ECDSA_SIGN_USE_PROJ if(pubKey == NULL) { return FR_BadPubKey; } cp = feePubKeyCurveParams(pubKey); if(cp == NULL) { return FR_BadPubKey; } if(cp->curveType != FCT_Weierstrass) { return FR_IllegalCurve; } CKASSERT(!isZero(cp->x1OrderPlus)); /* * Private key and message to be signed as giants */ privGiant = feePubKeyPrivData(pubKey); if(privGiant == NULL) { dbgLog(("Attempt to Sign without private data\n")); return FR_IllegalArg; } s = borrowGiant(cp->maxDigits); gtog(privGiant, s); if(dataLen > (cp->maxDigits * GIANT_BYTES_PER_DIGIT)) { f = borrowGiant(BYTES_TO_GIANT_DIGITS(dataLen)); } else { f = borrowGiant(cp->maxDigits); } deserializeGiant(data, f, dataLen); /* * Certicom SEC1 states that if the digest is larger than the modulus, * use the left q bits of the digest. */ unsigned hashBits = dataLen * 8; if(hashBits > cp->q) { gshiftright(hashBits - cp->q, f); } sigDbg(("ECDSA sign:\n")); sigLogGiant(" s : ", s); sigLogGiant(" f : ", f); c = borrowGiant(cp->maxDigits); d = borrowGiant(cp->maxDigits); u = borrowGiant(cp->maxDigits); if(randFcn == NULL) { frand = feeRandAlloc(); } else { frand = NULL; } /* * Random size is just larger than base prime */ groupBytesLen = ((feePubKeyBitsize(pubKey)+7) / 8); randBytesLen = groupBytesLen+8; // +8bytes (64bits) to reduce the biais when with reduction mod prime. Per FIPS186-4 - "Using Extra Random Bits" randBytes = (unsigned char*) fmalloc(randBytesLen); #if ECDSA_SIGN_USE_PROJ /* quick temp pointProj */ pty = borrowGiant(cp->maxDigits); ptz = borrowGiant(cp->maxDigits); pt.x = c; pt.y = pty; pt.z = ptz; #endif // ECDSA_SIGN_USE_PROJ while(1) { /* Repeat this loop until we have a non-zero c and d */ /* * 1) Obtain random u in [2, x1OrderPlus-2] */ SIGPROF_START; if(randFcn) { randFcn(randRef, randBytes, randBytesLen); } else { feeRandBytes(frand, randBytes, randBytesLen); } deserializeGiant(randBytes, u, randBytesLen); sigLogGiant(" raw u : ", u); sigLogGiant(" order : ", cp->x1OrderPlus); x1OrderPlusJustify(u, cp); SIGPROF_END(signStep1); sigLogGiant(" in range u : ", u); /* * note 'o' indicates elliptic multiply, * is integer mult. * * 2) Compute x coordinate, call it c, of u 'o' G * 3) Reduce: c := c mod x1OrderPlus; * 4) If c == 0, goto (1); */ SIGPROF_START; gtog(cp->x1Plus, c); #if ECDSA_SIGN_USE_PROJ /* projective coordinates */ gtog(cp->y1Plus, pty); int_to_giant(1, ptz); ellMulProjSimple(&pt, u, cp); #else /* ECDSA_SIGN_USE_PROJ */ /* the FEE way */ elliptic_simple(c, u, cp); #endif /* ECDSA_SIGN_USE_PROJ */ SIGPROF_END(signStep2); SIGPROF_START; x1OrderPlusMod(c, cp); SIGPROF_END(signStep34); if(isZero(c)) { dbgLog(("feeECDSASign: zero modulo (1)\n")); continue; } /* * 5) Compute u^(-1) mod x1OrderPlus; */ SIGPROF_START; gtog(u, d); binvg_x1OrderPlus(cp, d); SIGPROF_END(signStep5); sigLogGiant(" u^(-1) : ", d); /* * 6) Compute signature d as: * d = [u^(-1) (f + s*c)] (mod x1OrderPlus) */ SIGPROF_START; mulg(c, s); // s *= c x1OrderPlusMod(s, cp); addg(f, s); // s := f + (s * c) x1OrderPlusMod(s, cp); mulg(s, d); // d := u^(-1) (f + (s * c)) x1OrderPlusMod(d, cp); SIGPROF_END(signStep67); /* * 7) If d = 0, goto (1); */ if(isZero(d)) { dbgLog(("feeECDSASign: zero modulo (2)\n")); continue; } sigLogGiant(" c : ", c); sigLogGiant(" d : ", d); break; // normal successful exit } /* * 8) signature is now the integer pair (c, d). */ /* * Cook up raw data representing the signature. */ SIGPROF_START; ECDSA_encode(format,groupBytesLen, c, d, sigData, sigDataLen); SIGPROF_END(signStep8); if(frand != NULL) { feeRandFree(frand); } ffree(randBytes); returnGiant(u); returnGiant(d); returnGiant(c); returnGiant(f); returnGiant(s); #if ECDSA_SIGN_USE_PROJ returnGiant(pty); returnGiant(ptz); #endif /* ECDSA_SIGN_USE_PROJ */ return frtn; }
void main( void ) { giant x = newgiant(INFINITY), y = newgiant(INFINITY), p = newgiant(INFINITY), r = newgiant(100); int j; printf("Give two integers x, y on separate lines:\n"); gin(x); gin(y); gtog(y, p); /* p := y */ mulg(x, p); printf("y * x = "); gout(p); gtog(y, p); subg(x, p); printf("y - x = "); gout(p); gtog(y, p); addg(x, p); printf("y + x = "); gout(p); gtog(y, p); divg(x, p); printf("y div x = "); gout(p); gtog(y, p); modg(x, p); printf("y mod x = "); gout(p); gtog(y, p); gcdg(x, p); printf("GCD(x, y) = "); gout(p); /* Next, test which of x, y is greater. */ if (gcompg(x, y) < 0 ) printf("y is greater\n"); else if (gcompg(x,y) == 0) printf("x, y equal\n"); else printf("x is greater\n"); /* Next, we see how a giant struct is comprised. * We make a random, bipolar number of about 100 * digits in base 65536. */ for (j=0; j < 100; j++) { /* Fill 100 digits randomly. */ r->n[j] = (unsigned short)rand(); } r->sign = 100 * (1 - 2*(rand()%2)); /* Next, don't forget to check for leading zero digits, * even though such are unlikely. */ j = abs(r->sign) - 1; while ((r->n[j] == 0) && (j > 0)) { --j; } r->sign = (j+1) * ((r->sign > 0) ? 1: -1); printf("The random number: "); gout(r); /* Next, compare a large-FFT multiply with a standard, * grammar-school multiply. */ itog(1, x); gshiftleft(65536, x); iaddg(1, x); itog(5, y); gshiftleft(30000, y); itog(1, p); subg(p, y); /* Now we multiply (2^65536 + 1)*(5*(2^30000) - 1). */ gtog(y, p); mulg(x, p); /* Actually invokes FFT method because bit lengths of x, y are sufficiently large. */ printf("High digit of (2^65536 + 1)*(5*(2^30000) - 1) via FFT mul: %d\n", (int) p->n[abs(p->sign)-1]); fflush(stdout); gtog(y, p); grammarmulg(x, p); /* Grammar-school method. */ printf("High digit via grammar-school mul: %d\n", (int) p->n[abs(p->sign)-1]); fflush(stdout); /* Next, perform Fermat test for pseudoprimality. */ printf("Give prime candidate p:\n"); gin(p); gtog(p, y); itog(1, x); subg(x, y); itog(2, x); powermodg(x, y, p); if (isone(x)) printf("p is probably prime.\n"); else printf("p is composite.\n"); }
int expand(unsigned char *as, int rcnt) { int count; DIR *dirf; BOOL dir = 0; unsigned char *rescan = 0; unsigned char *slashsav = 0; register unsigned char *s, *cs; unsigned char *s2 = 0; struct argnod *schain = gchain; BOOL slash; int len; wchar_t wc; if (trapnote & SIGSET) return (0); s = cs = as; /* * check for meta chars */ { register BOOL open; slash = 0; open = 0; do { if ((len = nextc(&wc, (char *)cs)) <= 0) { len = 1; wc = (unsigned char)*cs; } cs += len; switch (wc) { case 0: if (rcnt && slash) break; else return (0); case '/': slash++; open = 0; continue; case '[': open++; continue; case ']': if (open == 0) continue; case '?': case '*': if (rcnt > slash) continue; else cs--; break; case '\\': cs++; default: continue; } break; } while (TRUE); } for (;;) { if (cs == s) { s = (unsigned char *)nullstr; break; } else if (*--cs == '/') { *cs = 0; if (s == cs) s = (unsigned char *)"/"; else { /* * push trimmed copy of directory prefix * onto stack */ s2 = cpystak(s); trim(s2); s = s2; } break; } } if ((dirf = opendir(*s ? (char *)s : (char *)".")) != 0) dir++; /* Let s point to original string because it will be trimmed later */ if (s2) s = as; count = 0; if (*cs == 0) slashsav = cs++; /* remember where first slash in as is */ /* check for rescan */ if (dir) { register unsigned char *rs; struct dirent *e; rs = cs; do /* find next / in as */ { if (*rs == '/') { rescan = rs; *rs = 0; gchain = 0; } } while (*rs++); while ((e = readdir(dirf)) && (trapnote & SIGSET) == 0) { if (e->d_name[0] == '.' && *cs != '.') continue; if (gmatch(e->d_name, cs)) { addg(s, e->d_name, rescan, slashsav); count++; } } closedir(dirf); if (rescan) { register struct argnod *rchain; rchain = gchain; gchain = schain; if (count) { count = 0; while (rchain) { count += expand(rchain->argval, slash + 1); rchain = rchain->argnxt; } } *rescan = '/'; } } if (slashsav) *slashsav = '/'; return (count); }