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); }
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); } }
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); }
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); }
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; }
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); }
/** * 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); }
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; }
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; }
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); }
/** * 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); }