/* * mpbslide_w * precomputes the sliding window table for computing powers of x modulo b * needs workspace (4*size+2) */ void mpbslide_w(const mpbarrett* b, size_t xsize, const mpw* xdata, mpw* slide, mpw* wksp) { register size_t size = b->size; mpbsqrmod_w(b, xsize, xdata, slide , wksp); /* x^2 mod b, temp */ mpbmulmod_w(b, xsize, xdata, size, slide , slide+size , wksp); /* x^3 mod b */ mpbmulmod_w(b, size, slide, size, slide+size , slide+2*size, wksp); /* x^5 mod b */ mpbmulmod_w(b, size, slide, size, slide+2*size, slide+3*size, wksp); /* x^7 mod b */ mpbmulmod_w(b, size, slide, size, slide+3*size, slide+4*size, wksp); /* x^9 mod b */ mpbmulmod_w(b, size, slide, size, slide+4*size, slide+5*size, wksp); /* x^11 mod b */ mpbmulmod_w(b, size, slide, size, slide+5*size, slide+6*size, wksp); /* x^13 mod b */ mpbmulmod_w(b, size, slide, size, slide+6*size, slide+7*size, wksp); /* x^15 mod b */ mpsetx(size, slide, xsize, xdata); /* x^1 mod b */ }
/* * needs workspace of (5*size+2) words */ int mppmilraba_w(const mpbarrett* p, const mpw* adata, int s, const mpw* rdata, const mpw* ndata, mpw* wksp) { register size_t size = p->size; register int j = 0; mpbpowmod_w(p, size, adata, size, rdata, wksp, wksp+size); while (1) { if (mpisone(size, wksp)) return (j == 0); if (mpeq(size, wksp, ndata)) return 1; if (++j < s) mpbsqrmod_w(p, size, wksp, wksp, wksp+size); else return 0; } }
/* * mpbtwopowmod_w * needs workspace of (4*size+2) words */ void mpbtwopowmod_w(const mpbarrett* b, size_t psize, const mpw* pdata, mpw* result, mpw* wksp) { /* * Modular exponention, 2^p mod modulus, special optimization * * Uses left-to-right exponentiation; needs no extra storage * */ /* this routine calls mpbmod, which needs (size*2+2), this routine needs (size*2) for sdata */ register size_t size = b->size; register mpw temp = 0; mpsetw(size, result, 1); while (psize) { if ((temp = *(pdata++))) /* break when first non-zero word found */ break; psize--; } /* if temp is still zero, then we're trying to raise x to power zero, and result stays one */ if (temp) { register int count = MP_WBITS; /* first skip bits until we reach a one */ while (count) { if (temp & MP_MSBMASK) break; temp <<= 1; count--; } while (psize--) { while (count) { /* always square */ mpbsqrmod_w(b, size, result, result, wksp); /* multiply by two if bit is 1 */ if (temp & MP_MSBMASK) { if (mpadd(size, result, result) || mpge(size, result, b->modl)) { /* there was carry, or the result is greater than the modulus, so we need to adjust */ mpsub(size, result, b->modl); } } temp <<= 1; count--; } count = MP_WBITS; temp = *(pdata++); } } }
void mpbpowmodsld_w(const mpbarrett* b, const mpw* slide, size_t psize, const mpw* pdata, mpw* result, mpw* wksp) { /* * Modular exponentiation with precomputed sliding window table, so no x is required * */ size_t size = b->size; mpw temp; mpsetw(size, result, 1); while (psize) { if ((temp = *(pdata++))) /* break when first non-zero word found in power */ break; psize--; } /* if temp is still zero, then we're trying to raise x to power zero, and result stays one */ if (temp) { short l = 0, n = 0, count = MP_WBITS; /* first skip bits until we reach a one */ while (count) { if (temp & MP_MSBMASK) break; temp <<= 1; count--; } while (psize) { while (count) { byte bit = (temp & MP_MSBMASK) ? 1 : 0; n <<= 1; n += bit; if (n) { if (l) l++; else if (bit) l = 1; if (l == 4) { byte s = mpbslide_presq[n]; while (s--) mpbsqrmod_w(b, size, result, result, wksp); mpbmulmod_w(b, size, result, size, slide+mpbslide_mulg[n]*size, result, wksp); s = mpbslide_postsq[n]; while (s--) mpbsqrmod_w(b, size, result, result, wksp); l = n = 0; } } else mpbsqrmod_w(b, size, result, result, wksp); temp <<= 1; count--; } if (--psize) { count = MP_WBITS; temp = *(pdata++); } } if (n) { byte s = mpbslide_presq[n]; while (s--) mpbsqrmod_w(b, size, result, result, wksp); mpbmulmod_w(b, size, result, size, slide+mpbslide_mulg[n]*size, result, wksp); s = mpbslide_postsq[n]; while (s--) mpbsqrmod_w(b, size, result, result, wksp); } } }
int dldp_pgonGenerator_w(dldp_p* dp, randomGeneratorContext* rgc, mpw* wksp) { register size_t size = dp->p.size; mpnfree(&dp->g); mpnsize(&dp->g, size); while (1) { mpbrnd_w(&dp->p, rgc, dp->g.data, wksp); if (mpistwo(dp->r.size, dp->r.data)) { /* * A little math here: the only element in the group which has order 2 is (p-1); * the two group elements raised to power two which result in 1 (mod p) are thus (p-1) and 1 * * mpbrnd_w doesn't return 1 or (p-1), so the test where g^2 mod p = 1 can be safely skipped */ /* check g^q mod p*/ mpbpowmod_w(&dp->p, size, dp->g.data, dp->q.size, dp->q.modl, wksp, wksp+size); if (mpisone(size, wksp)) continue; } else { /* we can either compute g^r, g^2q and g^(qr/2) or * we first compute s = r/2, and then compute g^2s, g^2q and g^qs * * hence we first compute t = g^s * then compute t^2 mod p, and test if one * then compute t^q mod p, and test if one * then compute (g^q mod p)^2 mod p, and test if one */ /* compute s = r/2 */ mpsetx(size, wksp, dp->r.size, dp->r.data); mpdivtwo(size, wksp); /* compute t = g^s mod p */ mpbpowmod_w(&dp->p, size, dp->g.data, size, wksp, wksp+size, wksp+2*size); /* compute t^2 mod p = g^2s mod p = g^r mod p*/ mpbsqrmod_w(&dp->p, size, wksp+size, wksp+size, wksp+2*size); if (mpisone(size, wksp+size)) continue; /* compute t^q mod p = g^qs mod p */ mpbpowmod_w(&dp->p, size, wksp, dp->q.size, dp->q.modl, wksp+size, wksp+2*size); if (mpisone(size, wksp+size)) continue; /* compute g^2q mod p */ mpbpowmod_w(&dp->p, size, dp->g.data, dp->q.size, dp->q.modl, wksp, wksp+size); mpbsqrmod_w(&dp->p, size, wksp, wksp+size, wksp+2*size); if (mpisone(size, wksp+size)) continue; } return 0; } return -1; }