예제 #1
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);
}
예제 #2
0
파일: relic_fp_prime.c 프로젝트: ace0/relic
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);
	}
}
예제 #3
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);
}
예제 #4
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);
}
예제 #5
0
void bn_set_2b(bn_t a, int b) {
	int i, d;

	SPLIT(b, d, b, BN_DIG_LOG);

	bn_grow(a, d + 1);
	for (i = 0; i < d; i++)
		a->dp[i] = 0;
	a->used = d + 1;
	a->dp[d] = ((dig_t)1 << b);
	a->sign = BN_POS;
}
예제 #6
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);
}
예제 #7
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);
}
예제 #8
0
void bn_copy(bn_t c, const bn_t a) {
	int i;

	if (c->dp == a->dp)
		return;

	bn_grow(c, a->used);

	for (i = 0; i < a->used; i++) {
		c->dp[i] = a->dp[i];
	}

	c->used = a->used;
	c->sign = a->sign;
}
예제 #9
0
void bn_dbl(bn_t c, bn_t a) {
	dig_t carry;

	bn_grow(c, a->used + 1);

	c->used = a->used;
	carry = bn_lsh1_low(c->dp, a->dp, c->used);

	/* If there is an additional carry. */
	if (carry != 0) {
		c->dp[c->used] = carry;
		(c->used)++;
	}

	c->sign = a->sign;
}
예제 #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);
}