void ep2_mul(ep2_t r, ep2_t p, bn_t k) { int i, l; ep2_t t; ep2_null(t); TRY { ep2_new(t); l = bn_bits(k); if (bn_get_bit(k, l - 1)) { ep2_copy(t, p); } else { ep2_set_infty(t); } for (i = l - 2; i >= 0; i--) { ep2_dbl(t, t); if (bn_get_bit(k, i)) { ep2_add(t, t, p); } } ep2_copy(r, t); ep2_norm(r, r); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { ep2_free(t); } }
void ep2_mul_sim_joint(ep2_t r, ep2_t p, bn_t k, ep2_t q, bn_t l) { ep2_t t[5]; int u_i, len, offset; int8_t jsf[4 * (FP_BITS + 1)]; int i; ep2_null(t[0]); ep2_null(t[1]); ep2_null(t[2]); ep2_null(t[3]); ep2_null(t[4]); TRY { for (i = 0; i < 5; i++) { ep2_new(t[i]); } ep2_set_infty(t[0]); ep2_copy(t[1], q); ep2_copy(t[2], p); ep2_add(t[3], p, q); ep2_sub(t[4], p, q); len = 4 * (FP_BITS + 1); bn_rec_jsf(jsf, &len, k, l); ep2_set_infty(r); i = bn_bits(k); offset = MAX(i, bn_bits(l)) + 1; for (i = len - 1; i >= 0; i--) { ep2_dbl(r, r); if (jsf[i] != 0 && jsf[i] == -jsf[i + offset]) { u_i = jsf[i] * 2 + jsf[i + offset]; if (u_i < 0) { ep2_sub(r, r, t[4]); } else { ep2_add(r, r, t[4]); } } else { u_i = jsf[i] * 2 + jsf[i + offset]; if (u_i < 0) { ep2_sub(r, r, t[-u_i]); } else { ep2_add(r, r, t[u_i]); } } } ep2_norm(r, r); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { for (i = 0; i < 5; i++) { ep2_free(t[i]); } } }
void ep2_add_slp_basic(ep2_t r, fp2_t s, ep2_t p, ep2_t q) { if (ep2_is_infty(p)) { ep2_copy(r, q); return; } if (ep2_is_infty(q)) { ep2_copy(r, p); return; } ep2_add_basic_imp(r, s, p, q); }
void pp_dbl_k12_basic(fp12_t l, ep2_t r, ep2_t q, ep_t p) { fp2_t s; ep2_t t; int one = 1, zero = 0; fp2_null(s); ep2_null(t); TRY { fp2_new(s); ep2_new(t); ep2_copy(t, q); ep2_dbl_slp_basic(r, s, q); fp12_zero(l); if (ep2_curve_is_twist() == EP_MTYPE) { one ^= 1; zero ^= 1; } fp_mul(l[one][zero][0], s[0], p->x); fp_mul(l[one][zero][1], s[1], p->x); fp2_mul(l[one][one], s, t->x); fp2_sub(l[one][one], t->y, l[one][one]); fp_copy(l[zero][zero][0], p->y); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { fp2_free(s); ep2_free(t); } }
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); } }
/** * Compute the Miller loop for pairings of type G_2 x G_1 over the bits of a * given parameter. * * @param[out] r - the result. * @param[out] t - the resulting point. * @param[in] q - the first pairing argument in affine coordinates. * @param[in] p - the second pairing argument in affine coordinates. * @param[in] n - the number of pairings to evaluate. * @param[in] a - the loop parameter. */ static void pp_mil_k12(fp12_t r, ep2_t *t, ep2_t *q, ep_t *p, int m, bn_t a) { fp12_t l; ep_t _p[m]; int i, j; if (m == 0) { return; } fp12_null(l); TRY { fp12_new(l); for (j = 0; j < m; j++) { ep_null(_p[j]); ep_new(_p[j]); #if EP_ADD == BASIC ep_neg(_p[j], p[i]); #else fp_add(_p[j]->x, p[j]->x, p[j]->x); fp_add(_p[j]->x, _p[j]->x, p[j]->x); fp_neg(_p[j]->y, p[j]->y); #endif ep2_copy(t[j], q[j]); } fp12_zero(l); /* Precomputing. */ pp_dbl_k12(r, t[0], t[0], _p[0]); if (bn_get_bit(a, bn_bits(a) - 2)) { for (j = 0; j < m; j++) { pp_add_k12(l, t[j], q[j], p[j]); fp12_mul_dxs(r, r, l); } } for (i = bn_bits(a) - 3; i >= 0; i--) { fp12_sqr(r, r); for (j = 0; j < m; j++) { pp_dbl_k12(l, t[j], t[j], _p[j]); fp12_mul_dxs(r, r, l); if (bn_get_bit(a, i)) { pp_add_k12(l, t[j], q[j], p[j]); fp12_mul_dxs(r, r, l); } } } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { fp12_free(l); for (j = 0; j < m; j++) { ep_free(_p[j]); } } }
void ep2_mul_pre_nafwi(ep2_t *t, ep2_t p) { int l; bn_t n; bn_null(n); TRY { bn_new(n); ep2_curve_get_ord(n); l = bn_bits(n) + 1; l = ((l % EP_DEPTH) == 0 ? (l / EP_DEPTH) : (l / EP_DEPTH) + 1); ep2_copy(t[0], p); for (int i = 1; i < l; i++) { ep2_dbl(t[i], t[i - 1]); for (int j = 1; j < EP_DEPTH; j++) { ep2_dbl(t[i], t[i]); } } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(n); } }
void ep2_mul_fix_combs(ep2_t r, ep2_t *t, bn_t k) { int i, j, l, w, n0, p0, p1; bn_t n; if (bn_is_zero(k)) { ep2_set_infty(r); return; } bn_null(n); TRY { bn_new(n); ep2_curve_get_ord(n); l = bn_bits(n); l = ((l % EP_DEPTH) == 0 ? (l / EP_DEPTH) : (l / EP_DEPTH) + 1); n0 = bn_bits(k); p0 = (EP_DEPTH) * l - 1; w = 0; p1 = p0--; for (j = EP_DEPTH - 1; j >= 0; j--, p1 -= l) { w = w << 1; if (p1 < n0 && bn_get_bit(k, p1)) { w = w | 1; } } ep2_copy(r, t[w]); for (i = l - 2; i >= 0; i--) { ep2_dbl(r, r); w = 0; p1 = p0--; for (j = EP_DEPTH - 1; j >= 0; j--, p1 -= l) { w = w << 1; if (p1 < n0 && bn_get_bit(k, p1)) { w = w | 1; } } if (w > 0) { ep2_add(r, r, t[w]); } } ep2_norm(r, r); if (bn_sign(k) == RLC_NEG) { ep2_neg(r, r); } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(n); } }
void ep2_add_projc(ep2_t r, ep2_t p, ep2_t q) { if (ep2_is_infty(p)) { ep2_copy(r, q); return; } if (ep2_is_infty(q)) { ep2_copy(r, p); return; } if (p == q) { /* TODO: This is a quick hack. Should we fix this? */ ep2_dbl(r, p); return; } ep2_add_projc_imp(r, p, q); }
void pp_norm_k12(ep2_t r, ep2_t p) { if (ep2_is_infty(p)) { ep2_set_infty(r); return; } if (p->norm) { /* If the point is represented in affine coordinates, we just copy it. */ ep2_copy(r, p); } #if EP_ADD == PROJC || !defined(STRIP) pp_norm_imp(r, p); #endif }
void ep2_mul_pre_combd(ep2_t *t, ep2_t p) { int i, j, d, e; bn_t n; bn_null(n); TRY { bn_new(n); ep2_curve_get_ord(n); d = bn_bits(n); d = ((d % EP_DEPTH) == 0 ? (d / EP_DEPTH) : (d / EP_DEPTH) + 1); e = (d % 2 == 0 ? (d / 2) : (d / 2) + 1); ep2_set_infty(t[0]); ep2_copy(t[1], p); for (j = 1; j < EP_DEPTH; j++) { ep2_dbl(t[1 << j], t[1 << (j - 1)]); for (i = 1; i < d; i++) { ep2_dbl(t[1 << j], t[1 << j]); } #if defined(EP_MIXED) ep2_norm(t[1 << j], t[1 << j]); #endif for (i = 1; i < (1 << j); i++) { ep2_add(t[(1 << j) + i], t[i], t[1 << j]); } } ep2_set_infty(t[1 << EP_DEPTH]); for (j = 1; j < (1 << EP_DEPTH); j++) { ep2_dbl(t[(1 << EP_DEPTH) + j], t[j]); for (i = 1; i < e; i++) { ep2_dbl(t[(1 << EP_DEPTH) + j], t[(1 << EP_DEPTH) + j]); } } #if defined(EP_MIXED) for (i = 1; i < RELIC_EP_TABLE_COMBD; i++) { ep2_norm(t[i], t[i]); } #endif } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(n); } }
void ep2_frb(ep2_t r, ep2_t p, int i) { switch (i) { case 0: ep2_copy(r, p); break; case 1: fp2_frb(r->x, p->x, 1); fp2_frb(r->y, p->y, 1); if (ep2_curve_is_twist() == EP_MTYPE) { fp2_mul_frb(r->x, r->x, 1, 4); fp2_mul_art(r->x, r->x); fp2_mul_art(r->y, r->y); } else { fp2_mul_frb(r->x, r->x, 1, 2); } fp2_mul_frb(r->y, r->y, 1, 3); break; case 2: if (ep2_curve_is_twist() == EP_MTYPE) { fp2_mul_frb(r->x, p->x, 2, 4); } else { fp2_mul_frb(r->x, p->x, 2, 2); } fp2_neg(r->y, p->y); break; case 3: if (ep2_curve_is_twist() == EP_MTYPE) { fp2_frb(r->x, p->x, 1); fp2_frb(r->y, p->y, 1); fp2_mul_frb(r->x, r->x, 1, 4); fp2_mul_frb(r->x, r->x, 2, 4); fp2_mul_art(r->x, r->x); fp2_mul_frb(r->y, r->y, 1, 3); fp2_mul_art(r->y, r->y); fp2_neg(r->y, r->y); } else { fp2_frb(r->x, p->x, 1); fp2_mul_frb(r->x, r->x, 3, 2); fp_neg(r->y[0], p->y[0]); fp_copy(r->y[1], p->y[1]); fp2_mul_frb(r->y, r->y, 1, 3); } break; } r->norm = 1; fp_set_dig(r->z[0], 1); fp_zero(r->z[1]); }
void ep2_frb(ep2_t r, ep2_t p, int i) { ep2_copy(r, p); switch (i) { case 1: fp2_frb(r->x, r->x, 1); fp2_frb(r->y, r->y, 1); fp2_frb(r->z, r->z, 1); if (ep2_curve_is_twist() == EP_MTYPE) { fp2_mul_frb(r->x, r->x, 1, 4); fp2_mul_art(r->x, r->x); fp2_mul_art(r->y, r->y); } else { fp2_mul_frb(r->x, r->x, 1, 2); } fp2_mul_frb(r->y, r->y, 1, 3); break; case 2: if (ep2_curve_is_twist() == EP_MTYPE) { fp2_mul_frb(r->x, r->x, 2, 4); } else { fp2_mul_frb(r->x, r->x, 2, 2); } fp2_neg(r->y, r->y); break; case 3: if (ep2_curve_is_twist() == EP_MTYPE) { fp2_frb(r->x, r->x, 1); fp2_frb(r->y, r->y, 1); fp2_frb(r->z, r->z, 1); fp2_mul_frb(r->x, r->x, 1, 4); fp2_mul_frb(r->x, r->x, 2, 4); fp2_mul_art(r->x, r->x); fp2_mul_frb(r->y, r->y, 1, 3); fp2_mul_art(r->y, r->y); fp2_neg(r->y, r->y); } else { fp2_frb(r->x, r->x, 1); fp2_mul_frb(r->x, r->x, 3, 2); fp_neg(r->y[0], r->y[0]); fp_copy(r->y[1], r->y[1]); fp2_mul_frb(r->y, r->y, 1, 3); } break; } }
void ep2_tab(ep2_t * t, ep2_t p, int w) { if (w > 2) { ep2_dbl(t[0], p); #if defined(EP_MIXED) ep2_norm(t[0], t[0]); #endif ep2_add(t[1], t[0], p); for (int i = 2; i < (1 << (w - 2)); i++) { ep2_add(t[i], t[i - 1], t[0]); } #if defined(EP_MIXED) for (int i = 1; i < (1 << (EP_WIDTH - 2)); i++) { ep2_norm(t[i], t[i]); } #endif } ep2_copy(t[0], p); }
void ep2_mul_pre_combs(ep2_t *t, ep2_t p) { int i, j, l; bn_t n; bn_null(n); TRY { bn_new(n); ep2_curve_get_ord(n); l = bn_bits(n); l = ((l % EP_DEPTH) == 0 ? (l / EP_DEPTH) : (l / EP_DEPTH) + 1); ep2_set_infty(t[0]); ep2_copy(t[1], p); for (j = 1; j < EP_DEPTH; j++) { ep2_dbl(t[1 << j], t[1 << (j - 1)]); for (i = 1; i < l; i++) { ep2_dbl(t[1 << j], t[1 << j]); } #if defined(EP_MIXED) ep2_norm(t[1 << j], t[1 << j]); #endif for (i = 1; i < (1 << j); i++) { ep2_add(t[(1 << j) + i], t[i], t[1 << j]); } } #if defined(EP_MIXED) for (i = 1; i < RLC_EP_TABLE_COMBS; i++) { ep2_norm(t[i], t[i]); } #endif } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(n); } }
void ep2_mul_pre_basic(ep2_t *t, ep2_t p) { bn_t n; bn_null(n); TRY { bn_new(n); ep2_curve_get_ord(n); ep2_copy(t[0], p); for (int i = 1; i < bn_bits(n); i++) { ep2_dbl(t[i], t[i - 1]); } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(n); } }
/** * Precomputes a table for a point multiplication on an ordinary curve. * * @param[out] t - the destination table. * @param[in] p - the point to multiply. */ static void ep2_mul_pre_ordin(ep2_t *t, ep2_t p) { int i; ep2_dbl(t[0], p); #if defined(EP_MIXED) ep2_norm(t[0], t[0]); #endif #if EP_DEPTH > 2 ep2_add(t[1], t[0], p); for (i = 2; i < (1 << (EP_DEPTH - 2)); i++) { ep2_add(t[i], t[i - 1], t[0]); } #if defined(EP_MIXED) for (i = 1; i < (1 << (EP_DEPTH - 2)); i++) { ep2_norm(t[i], t[i]); } #endif #endif ep2_copy(t[0], p); }
/** * Compute the Miller loop for pairings of type G_2 x G_1 over the bits of a * given parameter represented in sparse form. * * @param[out] r - the result. * @param[out] t - the resulting point. * @param[in] q - the vector of first arguments in affine coordinates. * @param[in] p - the vector of second arguments in affine coordinates. * @param[in] n - the number of pairings to evaluate. * @param[in] s - the loop parameter in sparse form. * @paramin] len - the length of the loop parameter. */ static void pp_mil_sps_k12(fp12_t r, ep2_t *t, ep2_t *q, ep_t *p, int m, int *s, int len) { fp12_t l; ep_t _p[m]; ep2_t _q[m]; int i, j; if (m == 0) { return; } fp12_null(l); TRY { fp12_new(l); fp12_zero(l); for (j = 0; j < m; j++) { ep_null(_p[j]); ep2_null(_q[j]); ep_new(_p[j]); ep2_new(_q[j]); ep2_copy(t[j], q[j]); ep2_neg(_q[j], q[j]); #if EP_ADD == BASIC ep_neg(_p[j], p[j]); #else fp_add(_p[j]->x, p[j]->x, p[j]->x); fp_add(_p[j]->x, _p[j]->x, p[j]->x); fp_neg(_p[j]->y, p[j]->y); #endif } pp_dbl_k12(r, t[0], t[0], _p[0]); for (j = 1; j < m; j++) { pp_dbl_k12(l, t[j], t[j], _p[j]); fp12_mul_dxs(r, r, l); } if (s[len - 2] > 0) { for (j = 0; j < m; j++) { pp_add_k12(l, t[j], q[j], p[j]); fp12_mul_dxs(r, r, l); } } if (s[len - 2] < 0) { for (j = 0; j < m; j++) { pp_add_k12(l, t[j], _q[j], p[j]); fp12_mul_dxs(r, r, l); } } for (i = len - 3; i >= 0; i--) { fp12_sqr(r, r); for (j = 0; j < m; j++) { pp_dbl_k12(l, t[j], t[j], _p[j]); fp12_mul_dxs(r, r, l); if (s[i] > 0) { pp_add_k12(l, t[j], q[j], p[j]); fp12_mul_dxs(r, r, l); } if (s[i] < 0) { pp_add_k12(l, t[j], _q[j], p[j]); fp12_mul_dxs(r, r, l); } } } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { fp12_free(l); for (j = 0; j < m; j++) { ep_free(_p[j]); ep2_free(_q[j]); } } }
void ep2_curve_get_gen(ep2_t g) { ep2_copy(g, &(core_get()->ep2_g)); }
void ep2_curve_set_twist(int type) { char str[2 * FP_BYTES + 1]; ctx_t *ctx = core_get(); ep2_t g; fp2_t a; fp2_t b; bn_t r; ep2_null(g); fp2_null(a); fp2_null(b); bn_null(r); ctx->ep2_is_twist = 0; if (type == EP_MTYPE || type == EP_DTYPE) { ctx->ep2_is_twist = type; } else { return; } TRY { ep2_new(g); fp2_new(a); fp2_new(b); bn_new(r); switch (ep_param_get()) { #if FP_PRIME == 158 case BN_P158: ASSIGN(BN_P158); break; #elif FP_PRIME == 254 case BN_P254: ASSIGN(BN_P254); break; #elif FP_PRIME == 256 case BN_P256: ASSIGN(BN_P256); break; #elif FP_PRIME == 638 case BN_P638: ASSIGN(BN_P638); break; case B12_P638: ASSIGN(B12_P638); break; #endif default: (void)str; THROW(ERR_NO_VALID); break; } fp2_zero(g->z); fp_set_dig(g->z[0], 1); g->norm = 1; ep2_copy(&(ctx->ep2_g), g); fp_copy(ctx->ep2_a[0], a[0]); fp_copy(ctx->ep2_a[1], a[1]); fp_copy(ctx->ep2_b[0], b[0]); fp_copy(ctx->ep2_b[1], b[1]); bn_copy(&(ctx->ep2_r), r); /* I don't have a better place for this. */ fp_prime_calc(); #if defined(EP_PRECO) ep2_mul_pre((ep2_t *)ep2_curve_get_tab(), &(ctx->ep2_g)); #endif } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { ep2_free(g); fp2_free(a); fp2_free(b); bn_free(r); } }