/* computes x/R == x (mod N) via Montgomery Reduction */
int32 pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m,
		pstm_digit mp, pstm_digit *paD, uint32 paDlen)
{
	pstm_digit	*c, *_c, *tmpm, mu;
	int32		oldused, x, y;
	int16		pa;

	pa = m->used;

	if (paD && paDlen >= (uint32)2*pa+1) {
		c = paD;
		memset(c, 0x0, paDlen);
	} else {
		c = psMalloc(pool, 2*pa+1);
		if (c == NULL) {
			return PS_MEM_FAIL;
		} else {
			memset(c, 0x0, 2*pa+1);
		}
	}
	/* copy the input */
	oldused = a->used;
	for (x = 0; x < oldused; x++) {
		c[x] = a->dp[x];
	}

	MONT_START;

	for (x = 0; x < pa; x++) {
		pstm_digit cy = 0;
		/* get Mu for this round */
		LOOP_START;
		_c   = c + x;
		tmpm = m->dp;
		y = 0;
		for (; y < pa; y++) {
			INNERMUL;
			++_c;
		}
		LOOP_END;
		while (cy) {
			PROPCARRY;
			++_c;
		}
	}         

	/* now copy out */
	_c   = c + pa;
	tmpm = a->dp;
	for (x = 0; x < pa+1; x++) {
		*tmpm++ = *_c++;
	}

	for (; x < oldused; x++)   {
		*tmpm++ = 0;
	}

	MONT_FINI;

	a->used = pa+1;
	pstm_clamp(a);
  
	/* reuse x as return code */
	x = PSTM_OKAY;
	
	/* if A >= m then A = A - m */
	if (pstm_cmp_mag (a, m) != PSTM_LT) {
		if (s_pstm_sub (a, m, a) != PSTM_OKAY) {
			x = PS_MEM_FAIL;
		}
	}
	if (paDlen < (uint32)2*pa+1) {
		psFree(c);
	}
	return x;
}
Exemplo n.º 2
0
/**
	computes x/R == x (mod N) via Montgomery Reduction.
*/
int32_t pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, const pstm_int *m,
		pstm_digit mp, pstm_digit *paD, uint16_t paDlen)
{
	pstm_digit	*c, *_c, *tmpm, mu;
	int32		oldused, x, y;
	int16		pa;
	uint32		cSize;

	pa = m->used;
	if (pa > a->alloc) {
		/* Sanity test for bad numbers.  This will confirm no buffer overruns */
		return PS_LIMIT_FAIL;
	}

	cSize = (2 * pa + 1) * sizeof(pstm_digit);
	if (paD && paDlen >= cSize) {
		c = paD;
		memset(c, 0x0, paDlen);
	} else {
		c = psMalloc(pool, cSize);
		if (c == NULL) {
			return PS_MEM_FAIL;
		} else {
			memset(c, 0x0, cSize);
		}
	}
	/* copy the input */
	oldused = a->used;
	for (x = 0; x < oldused; x++) {
		c[x] = a->dp[x];
	}

	MONT_START;

	for (x = 0; x < pa; x++) {
		pstm_digit cy = 0;
		/* get Mu for this round */
		LOOP_START;
		_c   = c + x;
		tmpm = m->dp;
		y = 0;
#ifdef PSTM_X86_64
		for (; y < (pa & ~7); y += 8) {
			INNERMUL8;
			_c   += 8;
			tmpm += 8;
		}
#endif /* PSTM_X86_64 */
		for (; y < pa; y++) {
			INNERMUL;
			++_c;
		}
		LOOP_END;
		while (cy) {
			PROPCARRY;
			++_c;
		}
	}
	/* now copy out */
	_c   = c + pa;
	tmpm = a->dp;
	for (x = 0; x < pa+1; x++) {
		*tmpm++ = *_c++;
	}

	for (; x < oldused; x++)   {
		*tmpm++ = 0;
	}

	MONT_FINI;

	a->used = pa+1;
	pstm_clamp(a);

	/* reuse x as return code */
	x = PSTM_OKAY;

	/* if A >= m then A = A - m */
	if (pstm_cmp_mag (a, m) != PSTM_LT) {
		if (s_pstm_sub (a, m, a) != PSTM_OKAY) {
			x = PS_MEM_FAIL;
		}
	}
	if (paDlen < cSize) {
		psFree(c, pool);
	}
	return x;
}