int fp_bits(const fp_t a) { int i = RLC_FP_DIGS - 1; while (i >= 0 && a[i] == 0) { i--; } if (i > 0) { return (i << RLC_DIG_LOG) + util_bits_dig(a[i]); } else { return util_bits_dig(a[0]); } }
void ep2_mul_dig(ep2_t r, ep2_t p, dig_t k) { int i, l; ep2_t t; ep2_null(t); if (k == 0) { ep2_set_infty(r); return; } TRY { ep2_new(t); l = util_bits_dig(k); ep2_copy(t, p); for (i = l - 2; i >= 0; i--) { ep2_dbl(t, t); if (k & ((dig_t)1 << i)) { ep2_add(t, t, p); } } ep2_norm(r, t); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { ep2_free(t); } }
void bn_mxp_dig(bn_t c, const bn_t a, dig_t b, const bn_t m) { int i, l; bn_t t, u, r; if (b == 0) { bn_set_dig(c, 1); return; } bn_null(t); bn_null(u); bn_null(r); TRY { bn_new(t); bn_new(u); bn_new(r); bn_mod_pre(u, m); l = util_bits_dig(b); #if BN_MOD == MONTY bn_mod_monty_conv(t, a, m); #else bn_copy(t, a); #endif bn_copy(r, t); for (i = l - 2; i >= 0; i--) { bn_sqr(r, r); bn_mod(r, r, m, u); if (b & ((dig_t)1 << i)) { bn_mul(r, r, t); bn_mod(r, r, m, u); } } #if BN_MOD == MONTY bn_mod_monty_back(c, r, m); #else bn_copy(c, r); #endif } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(t); bn_free(u); bn_free(r); } }
int bn_bits(const bn_t a) { int bits; if (a->used == 0) { return 0; } /* Bits in lower digits. */ bits = (a->used - 1) * BN_DIGIT; return bits + util_bits_dig(a->dp[a->used - 1]); }
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); } }
int cp_bdpe_gen(bdpe_t pub, bdpe_t prv, dig_t block, int bits) { bn_t t, r; int result = STS_OK; bn_null(t); bn_null(r); TRY { bn_new(t); bn_new(r); prv->t = pub->t = block; /* Make sure that block size is prime. */ bn_set_dig(t, block); if (bn_is_prime_basic(t) == 0) { THROW(ERR_NO_VALID); } /* Generate prime q such that gcd(block, (q - 1)) = 1. */ do { bn_gen_prime(prv->q, bits / 2); bn_sub_dig(prv->q, prv->q, 1); bn_gcd_dig(t, prv->q, block); bn_add_dig(prv->q, prv->q, 1); } while (bn_cmp_dig(t, 1) != CMP_EQ); /* Generate different primes p and q. */ do { /* Compute p = block * (x * block + b) + 1, 0 < b < block random. */ bn_rand(prv->p, BN_POS, bits / 2 - 2 * util_bits_dig(block)); bn_mul_dig(prv->p, prv->p, block); bn_rand(t, BN_POS, util_bits_dig(block)); bn_add_dig(prv->p, prv->p, t->dp[0]); /* We know that block divides (p-1). */ bn_gcd_dig(t, prv->p, block); bn_mul_dig(prv->p, prv->p, block); bn_add_dig(prv->p, prv->p, 1); } while (bn_cmp_dig(t, 1) != CMP_EQ || bn_is_prime(prv->p) == 0); /* Compute t = (p-1)*(q-1). */ bn_sub_dig(prv->q, prv->q, 1); bn_sub_dig(prv->p, prv->p, 1); bn_mul(t, prv->p, prv->q); bn_div_dig(t, t, block); /* Restore factors p and q and compute n = p * q. */ bn_add_dig(prv->p, prv->p, 1); bn_add_dig(prv->q, prv->q, 1); bn_mul(pub->n, prv->p, prv->q); bn_copy(prv->n, pub->n); /* Select random y such that y^{(p-1)(q-1)}/block \neq 1 mod N. */ do { bn_rand(pub->y, BN_POS, bits); bn_mxp(r, pub->y, t, pub->n); } while (bn_cmp_dig(r, 1) == CMP_EQ); bn_copy(prv->y, pub->y); } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(t); bn_free(r); } return result; }
void fb_invn_low(dig_t *c, const dig_t *a) { int j, d, lu, lv, lt, l1, l2, bu, bv; align dig_t _u[2 * FB_DIGS], _v[2 * FB_DIGS]; align dig_t _g1[2 * FB_DIGS], _g2[2 * FB_DIGS]; dig_t *t = NULL, *u = NULL, *v = NULL, *g1 = NULL, *g2 = NULL, carry; dv_zero(_g1, FB_DIGS + 1); dv_zero(_g2, FB_DIGS + 1); u = _u; v = _v; g1 = _g1; g2 = _g2; /* u = a, v = f, g1 = 1, g2 = 0. */ dv_copy(u, a, FB_DIGS); dv_copy(v, fb_poly_get(), FB_DIGS); g1[0] = 1; lu = lv = FB_DIGS; l1 = l2 = 1; bu = fb_bits(u); bv = FB_BITS + 1; j = bu - bv; /* While (u != 1). */ while (1) { /* If j < 0 then swap(u, v), swap(g1, g2), j = -j. */ if (j < 0) { t = u; u = v; v = t; lt = lu; lu = lv; lv = lt; t = g1; g1 = g2; g2 = t; lt = l1; l1 = l2; l2 = lt; j = -j; } SPLIT(j, d, j, FB_DIG_LOG); /* u = u + v * z^j. */ if (j > 0) { carry = fb_lsha_low(u + d, v, j, lv); u[d + lv] ^= carry; } else { fb_addd_low(u + d, u + d, v, lv); } /* g1 = g1 + g2 * z^j. */ if (j > 0) { carry = fb_lsha_low(g1 + d, g2, j, l2); l1 = (l2 + d >= l1 ? l2 + d : l1); if (carry) { g1[d + l2] ^= carry; l1 = (l2 + d >= l1 ? l1 + 1 : l1); } } else { fb_addd_low(g1 + d, g1 + d, g2, l2); l1 = (l2 + d > l1 ? l2 + d : l1); } while (u[lu - 1] == 0) lu--; while (v[lv - 1] == 0) lv--; if (lu == 1 && u[0] == 1) break; /* j = deg(u) - deg(v). */ lt = util_bits_dig(u[lu - 1]) - util_bits_dig(v[lv - 1]); j = ((lu - lv) << FB_DIG_LOG) + lt; } /* Return g1. */ fb_copy(c, g1); }
void ed_mul_slide(ed_t r, const ed_t p, const bn_t k) { ed_t t[1 << (EP_WIDTH - 1)], q; int i, j, l; uint8_t win[RLC_FP_BITS + 1]; ed_null(q); if (bn_is_zero(k) || ed_is_infty(p)) { ed_set_infty(r); return; } TRY { for (i = 0; i < (1 << (EP_WIDTH - 1)); i ++) { ed_null(t[i]); ed_new(t[i]); } ed_new(q); ed_copy(t[0], p); ed_dbl(q, p); #if defined(EP_MIXED) ed_norm(q, q); #endif /* Create table. */ for (i = 1; i < (1 << (EP_WIDTH - 1)); i++) { ed_add(t[i], t[i - 1], q); } #if defined(EP_MIXED) ed_norm_sim(t + 1, (const ed_t *)t + 1, (1 << (EP_WIDTH - 1)) - 1); #endif ed_set_infty(q); l = RLC_FP_BITS + 1; bn_rec_slw(win, &l, k, EP_WIDTH); for (i = 0; i < l; i++) { if (win[i] == 0) { ed_dbl(q, q); } else { for (j = 0; j < util_bits_dig(win[i]); j++) { ed_dbl(q, q); } ed_add(q, q, t[win[i] >> 1]); } } ed_norm(r, q); if (bn_sign(k) == RLC_NEG) { ed_neg(r, r); } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { for (i = 0; i < (1 << (EP_WIDTH - 1)); i++) { ed_free(t[i]); } ed_free(q); } }
void fp_exp_slide(fp_t c, const fp_t a, const bn_t b) { fp_t t[1 << (FP_WIDTH - 1)], r; int i, j, l; uint8_t win[FP_BITS + 1]; fp_null(r); if (bn_is_zero(b)) { fp_set_dig(c, 1); return; } /* Initialize table. */ for (i = 0; i < (1 << (FP_WIDTH - 1)); i++) { fp_null(t[i]); } TRY { for (i = 0; i < (1 << (FP_WIDTH - 1)); i ++) { fp_new(t[i]); } fp_new(r); fp_copy(t[0], a); fp_sqr(r, a); /* Create table. */ for (i = 1; i < 1 << (FP_WIDTH - 1); i++) { fp_mul(t[i], t[i - 1], r); } fp_set_dig(r, 1); l = FP_BITS + 1; bn_rec_slw(win, &l, b, FP_WIDTH); for (i = 0; i < l; i++) { if (win[i] == 0) { fp_sqr(r, r); } else { for (j = 0; j < util_bits_dig(win[i]); j++) { fp_sqr(r, r); } fp_mul(r, r, t[win[i] >> 1]); } } if (bn_sign(b) == BN_NEG) { fp_inv(c, r); } else { fp_copy(c, r); } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { for (i = 0; i < (1 << (FP_WIDTH - 1)); i++) { fp_free(t[i]); } fp_free(r); } }
void bn_divn_low(dig_t *c, dig_t *d, dig_t *a, int sa, dig_t *b, int sb) { int norm, i, n, t, sd; dig_t carry, t1[3], t2[3]; /* Normalize x and y so that the leading digit of y is bigger than * 2^(BN_DIGIT-1). */ norm = util_bits_dig(b[sb - 1]) % BN_DIGIT; if (norm < (int)(BN_DIGIT - 1)) { norm = (BN_DIGIT - 1) - norm; carry = bn_lshb_low(a, a, sa, norm); if (carry) { a[sa++] = carry; } carry = bn_lshb_low(b, b, sb, norm); if (carry) { b[sb++] = carry; } } else { norm = 0; } n = sa - 1; t = sb - 1; /* Shift y so that the most significant digit of y is aligned with the * most significant digit of x. */ bn_lshd_low(b, b, sb, (n - t)); /* Find the most significant digit of the quotient. */ while (bn_cmpn_low(a, b, sa) != CMP_LT) { c[n - t]++; bn_subn_low(a, a, b, sa); } /* Shift y back. */ bn_rshd_low(b, b, sb + (n - t), (n - t)); /* Find the remaining digits. */ for (i = n; i >= (t + 1); i--) { if (i > sa) { continue; } if (a[i] == b[t]) { c[i - t - 1] = ((((dbl_t)1) << BN_DIGIT) - 1); } else { dbl_t tmp; tmp = ((dbl_t)a[i]) << ((dbl_t)BN_DIGIT); tmp |= (dbl_t)(a[i - 1]); tmp /= (dbl_t)(b[t]); c[i - t - 1] = (dig_t)tmp; } c[i - t - 1]++; do { c[i - t - 1]--; t1[0] = (t - 1 < 0) ? 0 : b[t - 1]; t1[1] = b[t]; carry = bn_mul1_low(t1, t1, c[i - t - 1], 2); t1[2] = carry; t2[0] = (i - 2 < 0) ? 0 : a[i - 2]; t2[1] = (i - 1 < 0) ? 0 : a[i - 1]; t2[2] = a[i]; } while (bn_cmpn_low(t1, t2, 3) == CMP_GT); carry = bn_mul1_low(d, b, c[i - t - 1], sb); sd = sb; if (carry) { d[sd++] = carry; } carry = bn_subn_low(a + (i - t - 1), a + (i - t - 1), d, sd); sd += (i - t - 1); if (sa - sd > 0) { carry = bn_sub1_low(a + sd, a + sd, carry, sa - sd); } if (carry) { sd = sb + (i - t - 1); carry = bn_addn_low(a + (i - t - 1), a + (i - t - 1), b, sb); carry = bn_add1_low(a + sd, a + sd, carry, sa - sd); c[i - t - 1]--; } } /* Remainder should be not be longer than the divisor. */ bn_rshb_low(d, a, sb, norm); }