/* * mpbrnd_w * generates a random number in the range 1 < r < b-1 * need workspace of (size) words */ void mpbrnd_w(const mpbarrett* b, randomGeneratorContext* rc, mpw* result, mpw* wksp) { size_t msz = mpmszcnt(b->size, b->modl); mpcopy(b->size, wksp, b->modl); mpsubw(b->size, wksp, 1); do { rc->rng->next(rc->param, (byte*) result, MP_WORDS_TO_BYTES(b->size)); result[0] &= (MP_ALLMASK >> msz); while (mpge(b->size, result, wksp)) mpsub(b->size, result, wksp); } while (mpleone(b->size, result)); }
/** * Computes the inverse (modulo b) of x, and returns 1 if x was invertible. * needs workspace of (6*size+6) words * @note xdata and result cannot point to the same area */ static int Xmpbinv_w(const mpbarrett* b, size_t xsize, const mpw* xdata, mpw* result, mpw* wksp) { /* * Fact: if a element of Zn, then a is invertible if and only if gcd(a,n) = 1 * Hence: if b->modl is even, then x must be odd, otherwise the gcd(x,n) >= 2 * * The calling routine must guarantee this condition. */ size_t ysize = b->size+1; mpw* u = wksp; mpw* v = u+ysize; mpw* A = v+ysize; mpw* B = A+ysize; mpw* C = B+ysize; mpw* D = C+ysize; mpsetx(ysize, u, b->size, b->modl); mpsetx(ysize, v, xsize, xdata); mpsetw(ysize, A, 1); mpzero(ysize, B); mpzero(ysize, C); mpsetw(ysize, D, 1); if (_debug < 0) fprintf(stderr, " u: "), mpfprintln(stderr, ysize, u); if (_debug < 0) fprintf(stderr, " v: "), mpfprintln(stderr, ysize, v); if (_debug < 0) fprintf(stderr, " A: "), mpfprintln(stderr, ysize, A); if (_debug < 0) fprintf(stderr, " B: "), mpfprintln(stderr, ysize, B); if (_debug < 0) fprintf(stderr, " C: "), mpfprintln(stderr, ysize, C); if (_debug < 0) fprintf(stderr, " D: "), mpfprintln(stderr, ysize, D); do { while (mpeven(ysize, u)) { mpdivtwo(ysize, u); if (mpodd(ysize, A) || mpodd(ysize, B)) { (void) mpaddx(ysize, A, xsize, xdata); (void) mpsubx(ysize, B, b->size, b->modl); } mpsdivtwo(ysize, A); mpsdivtwo(ysize, B); } while (mpeven(ysize, v)) { mpdivtwo(ysize, v); if (mpodd(ysize, C) || mpodd(ysize, D)) { (void) mpaddx(ysize, C, xsize, xdata); (void) mpsubx(ysize, D, b->size, b->modl); } mpsdivtwo(ysize, C); mpsdivtwo(ysize, D); } if (mpge(ysize, u, v)) { if (_debug < 0) fprintf(stderr, "--> 5 (u >= v)\n"); (void) mpsub(ysize, u, v); (void) mpsub(ysize, A, C); (void) mpsub(ysize, B, D); if (_debug < 0) fprintf(stderr, " u: "), mpfprintln(stderr, ysize, u); if (_debug < 0) fprintf(stderr, " A: "), mpfprintln(stderr, ysize, A); if (_debug < 0) fprintf(stderr, " B: "), mpfprintln(stderr, ysize, B); } else { if (_debug < 0) fprintf(stderr, "--> 5 (u < v)\n"); (void) mpsub(ysize, v, u); (void) mpsub(ysize, C, A); (void) mpsub(ysize, D, B); if (_debug < 0) fprintf(stderr, " v: "), mpfprintln(stderr, ysize, v); if (_debug < 0) fprintf(stderr, " C: "), mpfprintln(stderr, ysize, C); if (_debug < 0) fprintf(stderr, " D: "), mpfprintln(stderr, ysize, D); } } while (mpnz(ysize, u)); if (!mpisone(ysize, v)) return 0; if (result) { mpsetx(b->size, result, ysize, D); /*@-usedef@*/ if (*D & 0x80000000) (void) mpadd(b->size, result, b->modl); /*@=usedef@*/ } fprintf(stderr, "=== EXIT: "), mpfprintln(stderr, b->size, result); fprintf(stderr, " u: "), mpfprintln(stderr, ysize, u); fprintf(stderr, " v: "), mpfprintln(stderr, ysize, v); fprintf(stderr, " A: "), mpfprintln(stderr, ysize, A); fprintf(stderr, " B: "), mpfprintln(stderr, ysize, B); fprintf(stderr, " C: "), mpfprintln(stderr, ysize, C); fprintf(stderr, " D: "), mpfprintln(stderr, ysize, D); return 1; }
/* * 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++); } } }