Пример #1
0
void fp_prime_back(bn_t c, const fp_t a) {
	dv_t t;
	int i;

	dv_null(t);

	TRY {
		dv_new(t);

		bn_grow(c, FP_DIGS);
		for (i = 0; i < FP_DIGS; i++) {
			c->dp[i] = a[i];
		}
#if FP_RDC == MONTY
		dv_zero(t, 2 * FP_DIGS + 1);
		dv_copy(t, a, FP_DIGS);
		fp_rdc(c->dp, t);
#endif
		c->used = FP_DIGS;
		c->sign = BN_POS;
		bn_trim(c);
	}
	CATCH_ANY {
		THROW(ERR_CAUGHT);
	}
	FINALLY {
		dv_free(t);
	}
}
Пример #2
0
void bn_sqr_comba(bn_t c, const bn_t a) {
	int digits;
	bn_t t;

	bn_null(t);

	digits = 2 * a->used;

	TRY {
		/* We need a temporary variable so that c can be a or b. */
		bn_new_size(t, digits);
		t->used = digits;

		bn_sqrn_low(t->dp, a->dp, a->used);

		t->sign = BN_POS;
		bn_trim(t);
		bn_copy(c, t);
	} CATCH_ANY {
		THROW(ERR_CAUGHT);
	}
	FINALLY {
		bn_free(t);
	}
}
Пример #3
0
void bn_rsh(bn_t c, bn_t a, int bits) {
	int digits = 0;

	if (bits <= 0) {
		bn_copy(c, a);
		return;
	}

	SPLIT(bits, digits, bits, BN_DIG_LOG);

	if (digits > 0) {
		bn_rshd_low(c->dp, a->dp, a->used, digits);
	}
	c->used = a->used - digits;
	c->sign = a->sign;

	if (c->used > 0 && bits > 0) {
		if (digits == 0 && c != a) {
			bn_rshb_low(c->dp, a->dp + digits, a->used - digits, bits);
		} else {
			bn_rshb_low(c->dp, c->dp, c->used, bits);
		}
	}
	bn_trim(c);
}
Пример #4
0
void bn_sqr_basic(bn_t c, const bn_t a) {
	int i, digits;
	bn_t t;

	bn_null(t);

	digits = 2 * a->used;

	TRY {
		bn_new_size(t, digits);
		bn_zero(t);
		t->used = digits;

		for (i = 0; i < a->used; i++) {
			bn_sqra_low(t->dp + (2 * i), a->dp + i, a->used - i);
		}

		t->sign = BN_POS;
		bn_trim(t);
		bn_copy(c, t);
	}
	CATCH_ANY {
		THROW(ERR_CAUGHT);
	}
	FINALLY {
		bn_free(t);
	}
}
Пример #5
0
void bn_read_bin(bn_t a, const uint8_t *bin, int len) {
	int i, j;
	dig_t d = (BN_DIGIT / 8);
	int digs = (len % d == 0 ? len / d : len / d + 1);

	bn_grow(a, digs);
	bn_zero(a);
	a->used = digs;

	for (i = 0; i < digs - 1; i++) {
		d = 0;
		for (j = (BN_DIGIT / 8) - 1; j >= 0; j--) {
			d = d << 8;
			d |= bin[len - 1 - (i * (BN_DIGIT / 8) + j)];
		}
		a->dp[i] = d;
	}
	d = 0;
	for (j = (BN_DIGIT / 8) - 1; j >= 0; j--) {
		if ((int)(i * (BN_DIGIT / 8) + j) < len) {
			d = d << 8;
			d |= bin[len - 1 - (i * (BN_DIGIT / 8) + j)];
		}
	}
	a->dp[i] = d;

	a->sign = BN_POS;
	bn_trim(a);
}
Пример #6
0
void bn_sub_dig(bn_t c, bn_t a, dig_t b) {
	dig_t carry;

	bn_grow(c, a->used);

	/* If a < 0, compute c = -(|a| + b). */
	if (a->sign == BN_NEG) {
		carry = bn_add1_low(c->dp, a->dp, b, a->used);
		if (carry) {
			bn_grow(c, a->used + 1);
			c->dp[a->used] = carry;
		}
		c->used = a->used + carry;
		c->sign = BN_NEG;
	} else {
		/* If a > 0 && |a| >= b, compute c = (|a| - b). */
		if (a->used > 1 || a->dp[0] >= b) {
			carry = bn_sub1_low(c->dp, a->dp, b, a->used);
			c->used = a->used;
			c->sign = BN_POS;
		} else {
			/* If a > 0 && a < b. */
			if (a->used == 1) {
				c->dp[0] = b - a->dp[0];
			} else {
				c->dp[0] = b;
			}
			c->used = 1;
			c->sign = BN_NEG;
		}
	}
	bn_trim(c);
}
Пример #7
0
void bn_hlv(bn_t c, bn_t a) {
	bn_grow(c, a->used);

	c->used = a->used;
	bn_rsh1_low(c->dp, a->dp, c->used);

	c->sign = a->sign;
	bn_trim(c);
}
Пример #8
0
void bn_set_bit(bn_t a, int bit, int value) {
	int d;

	SPLIT(bit, d, bit, BN_DIG_LOG);

	if (value == 1) {
		a->dp[d] |= ((dig_t)1 << bit);
		if ((d + 1) > a->used) {
			a->used = d + 1;
		}
	} else {
		a->dp[d] &= ~((dig_t)1 << bit);
		bn_trim(a);
	}
}
Пример #9
0
void bn_div_rem_dig(bn_t c, dig_t *d, const bn_t a, dig_t b) {
	bn_t q;
	dig_t r;

	bn_null(q);

	if (b == 0) {
		THROW(ERR_NO_VALID);
	}

	if (b == 1 || bn_is_zero(a) == 1) {
		if (d != NULL) {
			*d = 0;
		}
		if (c != NULL) {
			bn_copy(c, a);
		}
		return;
	}

	TRY {
		bn_new(q);
		int size = a->used;
		const dig_t *ap = a->dp;

		bn_div1_low(q->dp, &r, ap, size, b);

		if (c != NULL) {
			q->used = a->used;
			q->sign = a->sign;
			bn_trim(q);
			bn_copy(c, q);
		}

		if (d != NULL) {
			*d = r;
		}
	}
	CATCH_ANY {
		THROW(ERR_CAUGHT);
	}
	FINALLY {
		bn_free(q);
	}
}
Пример #10
0
void bn_rand(bn_t a, int sign, int bits) {
	int digits;

	SPLIT(bits, digits, bits, BN_DIG_LOG);
	digits += (bits > 0 ? 1 : 0);

	bn_grow(a, digits);

	rand_bytes((uint8_t *)a->dp, digits * sizeof(dig_t));

	a->used = digits;
	a->sign = sign;
	if (bits > 0) {
		dig_t mask = ((dig_t)1 << (dig_t)bits) - 1;
		a->dp[a->used - 1] &= mask;
	}
	bn_trim(a);
}
Пример #11
0
/**
 * Subtracts two multiple precision integers, where a >= b.
 *
 * @param[out] c        - the destination.
 * @param[in] a         - the first multiple precision integer to subtract.
 * @param[in] b         - the second multiple precision integer to subtract.
 */
static void bn_sub_imp(bn_t c, bn_t a, bn_t b) {
	int max, min;
	dig_t carry;

	max = a->used;
	min = b->used;

	/* Grow the destination to accomodate the result. */
	bn_grow(c, max);

	if (a->used == b->used) {
		carry = bn_subn_low(c->dp, a->dp, b->dp, min);
	} else {
		carry = bn_subn_low(c->dp, a->dp, b->dp, min);
		carry = bn_sub1_low(c->dp + min, a->dp + min, carry, max - min);
	}
	c->used = max;
	bn_trim(c);
}
Пример #12
0
void bn_lsh(bn_t c, bn_t a, int bits) {
	int digits;
	dig_t carry;

	bn_copy(c, a);
	if (bits <= 0) {
		return;
	}

	SPLIT(bits, digits, bits, BN_DIG_LOG);

	if (bits > 0) {
		if (bn_bits(c) + bits > c->used * (int)BN_DIGIT) {
			bn_grow(c, c->used + digits + 1);
		}
	} else {
		bn_grow(c, c->used + digits);
	}

	if (digits > 0) {
		bn_lshd_low(c->dp, a->dp, a->used, digits);
	}
	c->used = a->used + digits;
	c->sign = a->sign;

	if (bits > 0) {
		if (c != a) {
			carry = bn_lshb_low(c->dp + digits, a->dp, a->used, bits);
		} else {
			carry = bn_lshb_low(c->dp + digits, c->dp + digits, c->used, bits);
		}
		if (carry != 0) {
			c->dp[c->used] = carry;
			(c->used)++;
		}
	}
	bn_trim(c);
}
Пример #13
0
/**
 * Adds two multiple precision integers, where a >= b.
 *
 * @param[out] c        - the result.
 * @param[in] a         - the first multiple precision integer to add.
 * @param[in] b         - the second multiple precision integer to add.
 */
static void bn_add_imp(bn_t c, bn_t a, bn_t b) {
	int max, min;
	dig_t carry;

	max = a->used;
	min = b->used;

	/* Grow the result. */
	bn_grow(c, max);

	if (a->used == b->used) {
		carry = bn_addn_low(c->dp, a->dp, b->dp, max);
	} else {
		carry = bn_addn_low(c->dp, a->dp, b->dp, min);
		carry = bn_add1_low(c->dp + min, a->dp + min, carry, max - min);
	}
	if (carry) {
		bn_grow(c, max + 1);
		c->dp[max] = carry;
	}
	c->used = max + carry;
	bn_trim(c);
}
Пример #14
0
/**
 * Computes the square of a multiple precision integer using recursive Karatsuba
 * squaring.
 *
 * @param[out] c			- the result.
 * @param[in] a				- the multiple precision integer to square.
 * @param[in] level			- the number of Karatsuba steps to apply.
 */
static void bn_sqr_karat_imp(bn_t c, const bn_t a, int level) {
	int h;
	bn_t a0, a1, a0a0, a1a1, t;
	const dig_t *tmpa;
	dig_t *t0;

	bn_null(a0);
	bn_null(a1);
	bn_null(a0a0);
	bn_null(a1a1);
	bn_null(t);

	/* Compute half the digits of a or b. */
	h = a->used >> 1;

	TRY {
		/* Allocate the temp variables. */
		bn_new(a0);
		bn_new(a1);
		bn_new(a0a0);
		bn_new(a1a1);
		bn_new(t);

		a0->used = h;
		a1->used = a->used - h;

		tmpa = a->dp;

		/* a = a1 || a0 */
		t0 = a0->dp;
		for (int i = 0; i < h; i++, t0++, tmpa++)
			*t0 = *tmpa;
		t0 = a1->dp;
		for (int i = 0; i < a1->used; i++, t0++, tmpa++)
			*t0 = *tmpa;

		bn_trim(a0);

		if (level <= 1) {
			/* a0a0 = a0 * a0 and a1a1 = a1 * a1 */
#if BN_SQR == BASIC
			bn_sqr_basic(a0a0, a0);
			bn_sqr_basic(a1a1, a1);
#elif BN_SQR == COMBA
			bn_sqr_comba(a0a0, a0);
			bn_sqr_comba(a1a1, a1);
#elif BN_SQR == MULTP
			bn_mul_comba(a0a0, a0, a0);
			bn_mul_comba(a1a1, a1, a1);
#endif
		} else {
			bn_sqr_karat_imp(a0a0, a0, level - 1);
			bn_sqr_karat_imp(a1a1, a1, level - 1);
		}

		/* t = (a1 + a0) */
		bn_add(t, a1, a0);

		if (level <= 1) {
			/* t = (a1 + a0)*(a1 + a0) */
#if BN_SQR == BASIC
			bn_sqr_basic(t, t);
#elif BN_SQR == COMBA
			bn_sqr_comba(t, t);
#elif BN_SQR == MULTP
			bn_mul_comba(t, t, t);
#endif
		} else {
			bn_sqr_karat_imp(t, t, level - 1);
		}

		/* t2 = (a0*a0 + a1*a1) */
		bn_add(a0, a0a0, a1a1);
		/* t = (a1 + a0)*(b1 + b0) - (a0*a0 + a1*a1) */
		bn_sub(t, t, a0);

		/* t = (a1 + a0)*(a1 + a0) - (a0*a0 + a1*a1) << h digits */
		bn_lsh(t, t, h * BN_DIGIT);

		/* t2 = a1 * b1 << 2*h digits */
		bn_lsh(a1a1, a1a1, 2 * h * BN_DIGIT);

		/* t = t + a0*a0 */
		bn_add(t, t, a0a0);
		/* c = t + a1*a1 */
		bn_add(t, t, a1a1);

		t->sign = BN_POS;
		bn_copy(c, t);
	}
	CATCH_ANY {
		THROW(ERR_CAUGHT);
	}
	FINALLY {
		bn_free(a0);
		bn_free(a1);
		bn_free(a0a0);
		bn_free(a1a1);
		bn_free(t);
	}
}
Пример #15
0
/**
 * Assigns the prime field modulus.
 *
 * @param[in] p			- the new prime field modulus.
 */
static void fp_prime_set(const bn_t p) {
	dv_t s, q;
	bn_t t;
	ctx_t *ctx = core_get();

	if (p->used != FP_DIGS) {
		THROW(ERR_NO_VALID);
	}

	dv_null(s);
	bn_null(t);
	dv_null(q);

	TRY {
		dv_new(s);
		bn_new(t);
		dv_new(q);

		bn_copy(&(ctx->prime), p);

		bn_mod_dig(&(ctx->mod8), &(ctx->prime), 8);

		switch (ctx->mod8) {
			case 3:
			case 7:
				ctx->qnr = -1;
				/* The current code for extensions of Fp^3 relies on qnr being
				 * also a cubic non-residue. */
				ctx->cnr = 0;
				break;
			case 1:
			case 5:
				ctx->qnr = ctx->cnr = -2;
				break;
			default:
				ctx->qnr = ctx->cnr = 0;
				THROW(ERR_NO_VALID);
				break;
		}
#ifdef FP_QNRES
		if (ctx->mod8 != 3) {
			THROW(ERR_NO_VALID);
		}
#endif

#if FP_RDC == MONTY || !defined(STRIP)
		bn_mod_pre_monty(t, &(ctx->prime));
		ctx->u = t->dp[0];
		dv_zero(s, 2 * FP_DIGS);
		s[2 * FP_DIGS] = 1;
		dv_zero(q, 2 * FP_DIGS + 1);
		dv_copy(q, ctx->prime.dp, FP_DIGS);
		bn_divn_low(t->dp, ctx->conv.dp, s, 2 * FP_DIGS + 1, q, FP_DIGS);
		ctx->conv.used = FP_DIGS;
		bn_trim(&(ctx->conv));
		bn_set_dig(&(ctx->one), 1);
		bn_lsh(&(ctx->one), &(ctx->one), ctx->prime.used * BN_DIGIT);
		bn_mod(&(ctx->one), &(ctx->one), &(ctx->prime));
#endif
		fp_prime_calc();
	}
	CATCH_ANY {
		THROW(ERR_CAUGHT);
	}
	FINALLY {
		bn_free(t);
		dv_free(s);
		dv_free(q);
	}
}
Пример #16
0
void bn_mxp_slide(bn_t c, const bn_t a, const bn_t b, const bn_t m) {
	bn_t tab[TABLE_SIZE], t, u, r;
	int i, j, l, w = 1;
	uint8_t win[BN_BITS];

	bn_null(t);
	bn_null(u);
	bn_null(r);
	/* Initialize table. */
	for (i = 0; i < TABLE_SIZE; i++) {
		bn_null(tab[i]);
	}

	TRY {

		/* Find window size. */
		i = bn_bits(b);
		if (i <= 21) {
			w = 2;
		} else if (i <= 32) {
			w = 3;
		} else if (i <= 128) {
			w = 4;
		} else if (i <= 256) {
			w = 5;
		} else {
			w = 6;
		}

		for (i = 1; i < (1 << w); i += 2) {
			bn_new(tab[i]);
		}

		bn_new(t);
		bn_new(u);
		bn_new(r);
		bn_mod_pre(u, m);

#if BN_MOD == MONTY
		bn_set_dig(r, 1);
		bn_mod_monty_conv(r, r, m);
		bn_mod_monty_conv(t, a, m);
#else /* BN_MOD == BARRT || BN_MOD == RADIX */
		bn_set_dig(r, 1);
		bn_copy(t, a);
#endif

		bn_copy(tab[1], t);
		bn_sqr(t, tab[1]);
		bn_mod(t, t, m, u);
		/* Create table. */
		for (i = 1; i < 1 << (w - 1); i++) {
			bn_mul(tab[2 * i + 1], tab[2 * i - 1], t);
			bn_mod(tab[2 * i + 1], tab[2 * i + 1], m, u);
		}

		l = BN_BITS + 1;
		bn_rec_slw(win, &l, b, w);
		for (i = 0; i < l; i++) {
			if (win[i] == 0) {
				bn_sqr(r, r);
				bn_mod(r, r, m, u);
			} else {
				for (j = 0; j < util_bits_dig(win[i]); j++) {
					bn_sqr(r, r);
					bn_mod(r, r, m, u);
				}
				bn_mul(r, r, tab[win[i]]);
				bn_mod(r, r, m, u);
			}
		}
		bn_trim(r);
#if BN_MOD == MONTY
		bn_mod_monty_back(c, r, m);
#else
		bn_copy(c, r);
#endif
	}
	CATCH_ANY {
		THROW(ERR_CAUGHT);
	}
	FINALLY {
		for (i = 1; i < (1 << w); i++) {
			bn_free(tab[i]);
		}
		bn_free(u);
		bn_free(t);
		bn_free(r);
	}
}
Пример #17
0
/**
 * Divides two multiple precision integers, computing the quotient and the
 * remainder.
 *
 * @param[out] c		- the quotient.
 * @param[out] d		- the remainder.
 * @param[in] a			- the dividend.
 * @param[in] b			- the the divisor.
 */
static void bn_div_imp(bn_t c, bn_t d, const bn_t a, const bn_t b) {
	bn_t q, x, y, r;
	int sign;

	bn_null(q);
	bn_null(x);
	bn_null(y);
	bn_null(r);

	/* If a < b, we're done. */
	if (bn_cmp_abs(a, b) == CMP_LT) {
		if (bn_sign(a) == BN_POS) {
			if (c != NULL) {
				bn_zero(c);
			}
			if (d != NULL) {
				bn_copy(d, a);
			}
		} else {
			if (c != NULL) {
				bn_set_dig(c, 1);
				if (bn_sign(b) == BN_POS) {
					bn_neg(c, c);
				}
			}
			if (d != NULL) {
				if (bn_sign(b) == BN_POS) {
					bn_add(d, a, b);	
				} else {
					bn_sub(d, a, b);
				}
			}
		}
		return;
	}

	TRY {
		bn_new(x);
		bn_new(y);
		bn_new_size(q, a->used + 1);
		bn_new(r);
		bn_zero(q);
		bn_zero(r);
		bn_abs(x, a);
		bn_abs(y, b);

		/* Find the sign. */
		sign = (a->sign == b->sign ? BN_POS : BN_NEG);

		bn_divn_low(q->dp, r->dp, x->dp, a->used, y->dp, b->used);

		/* We have the quotient in q and the remainder in r. */
		if (c != NULL) {
			q->used = a->used - b->used + 1;
			q->sign = sign;
			bn_trim(q);
			if (bn_sign(a) == BN_NEG) {
				bn_sub_dig(c, q, 1);
			} else {
				bn_copy(c, q);
			}
		}

		if (d != NULL) {
			r->used = b->used;
			r->sign = a->sign;
			bn_trim(r);
			if (bn_sign(a) == BN_NEG) {
				bn_add(d, r, b);
			} else {
				bn_copy(d, r);
			}
		}
	}
	CATCH_ANY {
		THROW(ERR_CAUGHT);
	}
	FINALLY {
		bn_free(r);
		bn_free(q);
		bn_free(x);
		bn_free(y);
	}
}