Crypt-MatrixSSL

 view release on metacpan or  search on metacpan

matrixssl-1-8-6-open/src/crypto/peersec/mpi.c  view on Meta::CPAN

 */
	if (X->sign == MP_NEG) {
		mp_int tmpG, tmpX;
		int32 err;

/*
		first compute 1/G mod P
 */
		if ((err = mp_init(pool, &tmpG)) != MP_OKAY) {
			return err;
		}
		if ((err = mp_invmod(pool, G, P, &tmpG)) != MP_OKAY) {
			mp_clear(&tmpG);
			return err;
		}

/*
		now get |X|
 */
		if ((err = mp_init(pool, &tmpX)) != MP_OKAY) {
			mp_clear(&tmpG);
			return err;
		}
		if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
			mp_clear(&tmpG);
			mp_clear(&tmpX);
			return err;
		}

/*
		and now compute (1/G)**|X| instead of G**X [X < 0]
 */
		err = mp_exptmod(pool, &tmpG, &tmpX, P, Y);
		mp_clear(&tmpG);
		mp_clear(&tmpX);
		return err;
	}

/*
	if the modulus is odd or dr != 0 use the fast method
 */
	if (mp_isodd (P) == 1) {
		return mp_exptmod_fast (pool, G, X, P, Y, 0);
	} else {
/*
		no exptmod for evens
 */
		return MP_VAL;
	}
}

/******************************************************************************/
/*
	Call only from mp_exptmod to make sure this fast version qualifies
*/
static int32 mp_exptmod_fast(psPool_t *pool, mp_int * G, mp_int * X,
				mp_int * P, mp_int * Y, int32 redmode)
{
	mp_int		M[TAB_SIZE], res;
	mp_digit	buf, mp;
	int32		err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;


/*
	use a pointer to the reduction algorithm.  This allows us to use
	one of many reduction algorithms without modding the guts of
	the code with if statements everywhere.
 */
	int32	(*redux)(mp_int*,mp_int*,mp_digit);

/*
	find window size
 */
	x = mp_count_bits (X);
	if (x <= 7) {
		winsize = 2;
	} else if (x <= 36) {
		winsize = 3;
	} else if (x <= 140) {
		winsize = 4;
	} else if (x <= 450) {
		winsize = 5;
	} else if (x <= 1303) {
		winsize = 6;
	} else if (x <= 3529) {
		winsize = 7;
	} else {
		winsize = 8;
	}

#ifdef MP_LOW_MEM
	if (winsize > 5) {
		winsize = 5;
	}
#endif

/*
	init M array
	init first cell
 */
	if ((err = mp_init(pool, &M[1])) != MP_OKAY) {
		return err;
	}

/*
	now init the second half of the array
 */
	for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
		if ((err = mp_init(pool, &M[x])) != MP_OKAY) {
			for (y = 1<<(winsize-1); y < x; y++) {
				mp_clear(&M[y]);
			}
			mp_clear(&M[1]);
			return err;
		}
	}


/*
	now setup montgomery
 */

matrixssl-1-8-6-open/src/crypto/peersec/mpi.c  view on Meta::CPAN

 */
	if ((err = mp_init(pool, &res)) != MP_OKAY) {
		goto LBL_M;
	}

/*
	create M table. The first half of the table is not computed
	though accept for M[0] and M[1]
*/

/*
	now we need R mod m
 */
	if ((err = mp_montgomery_calc_normalization(&res, P)) != MP_OKAY) {
		goto LBL_RES;
	}

/*
	now set M[1] to G * R mod m
 */
	if ((err = mp_mulmod(pool, G, &res, P, &M[1])) != MP_OKAY) {
		goto LBL_RES;
	}

/*
	compute the value at M[1<<(winsize-1)] by squaring
	M[1] (winsize-1) times
*/
	if ((err = mp_copy(&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
		goto LBL_RES;
	}

	for (x = 0; x < (winsize - 1); x++) {
		if ((err = mp_sqr(pool, &M[1 << (winsize - 1)],
				&M[1 << (winsize - 1)])) != MP_OKAY) {
			goto LBL_RES;
		}
		if ((err = redux(&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) {
			goto LBL_RES;
		}
	}

/*
	create upper table
 */
	for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
		if ((err = mp_mul(pool, &M[x - 1], &M[1], &M[x])) != MP_OKAY) {
			goto LBL_RES;
		}
		if ((err = redux(&M[x], P, mp)) != MP_OKAY) {
			goto LBL_RES;
		}
	}

/*
	set initial mode and bit cnt
 */
	mode   = 0;
	bitcnt = 1;
	buf    = 0;
	digidx = X->used - 1;
	bitcpy = 0;
	bitbuf = 0;

	for (;;) {
/*
		grab next digit as required
 */
		if (--bitcnt == 0) {
			/* if digidx == -1 we are out of digits so break */
			if (digidx == -1) {
				break;
			}
			/* read next digit and reset bitcnt */
			buf    = X->dp[digidx--];
			bitcnt = (int)DIGIT_BIT;
		}

		/* grab the next msb from the exponent */
		y     = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
		buf <<= (mp_digit)1;

/*
		if the bit is zero and mode == 0 then we ignore it
		These represent the leading zero bits before the first 1 bit
		in the exponent.  Technically this opt is not required but it
		does lower the # of trivial squaring/reductions used
*/
		if (mode == 0 && y == 0) {
			continue;
		}

/*
		if the bit is zero and mode == 1 then we square
 */
		if (mode == 1 && y == 0) {
			if ((err = mp_sqr (pool, &res, &res)) != MP_OKAY) {
				goto LBL_RES;
			}
			if ((err = redux (&res, P, mp)) != MP_OKAY) {
				goto LBL_RES;
			}
			continue;
		}

/*
		else we add it to the window
 */
		bitbuf |= (y << (winsize - ++bitcpy));
		mode    = 2;

		if (bitcpy == winsize) {
/*
			ok window is filled so square as required and multiply
			square first
 */
			for (x = 0; x < winsize; x++) {
				if ((err = mp_sqr(pool, &res, &res)) != MP_OKAY) {
					goto LBL_RES;
				}
				if ((err = redux(&res, P, mp)) != MP_OKAY) {
					goto LBL_RES;
				}
			}

			/* then multiply */
			if ((err = mp_mul(pool, &res, &M[bitbuf], &res)) != MP_OKAY) {
				goto LBL_RES;
			}
			if ((err = redux(&res, P, mp)) != MP_OKAY) {
				goto LBL_RES;
			}

/*
			empty window and reset



( run in 0.548 second using v1.01-cache-2.11-cpan-acf6aa7dc9e )