/** * Multiplies a point on a Barreto-Lynn-Soctt curve by the cofactor. * * @param[out] r - the result. * @param[in] p - the point to multiply. */ void ep2_mul_cof_b12(ep2_t r, ep2_t p) { bn_t x; ep2_t t0, t1, t2, t3; ep2_null(t0); ep2_null(t1); ep2_null(t2); ep2_null(t3); bn_null(x); TRY { ep2_new(t0); ep2_new(t1); ep2_new(t2); ep2_new(t3); bn_new(x); fp_param_get_var(x); /* Compute t0 = xP. */ ep2_mul(t0, p, x); if (bn_sign(x) == BN_NEG) { ep2_neg(t0, t0); } /* Compute t1 = [x^2]P. */ ep2_mul(t1, t0, x); if (bn_sign(x) == BN_NEG) { ep2_neg(t1, t1); } /* t2 = (x^2 - x - 1)P = x^2P - x*P - P. */ ep2_sub(t2, t1, t0); ep2_sub(t2, t2, p); /* t3 = \psi(x - 1)P. */ ep2_sub(t3, t0, p); ep2_norm(t3, t3); ep2_frb(t3, t3, 1); ep2_add(t2, t2, t3); /* t3 = \psi^2(2P). */ ep2_dbl(t3, p); ep2_norm(t3, t3); ep2_frb(t3, t3, 2); ep2_add(t2, t2, t3); ep2_norm(r, t2); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { ep2_free(t0); ep2_free(t1); ep2_free(t2); ep2_free(t3); bn_free(x); } }
/** * Multiplies a binary elliptic curve point by an integer using the w-NAF * method. * * @param[out] r - the result. * @param[in] p - the point to multiply. * @param[in] k - the integer. */ static void ep2_mul_fix_ordin(ep2_t r, ep2_t *table, bn_t k) { int len, i, n; int8_t naf[2 * RLC_FP_BITS + 1], *t; if (bn_is_zero(k)) { ep2_set_infty(r); return; } /* Compute the w-TNAF representation of k. */ len = 2 * RLC_FP_BITS + 1; bn_rec_naf(naf, &len, k, EP_DEPTH); t = naf + len - 1; ep2_set_infty(r); for (i = len - 1; i >= 0; i--, t--) { ep2_dbl(r, r); n = *t; if (n > 0) { ep2_add(r, r, table[n / 2]); } if (n < 0) { ep2_sub(r, r, table[-n / 2]); } } /* Convert r to affine coordinates. */ ep2_norm(r, r); if (bn_sign(k) == RLC_NEG) { ep2_neg(r, r); } }
/** * Compute the final lines for optimal ate pairings. * * @param[out] r - the result. * @param[out] t - the resulting point. * @param[in] q - the first point of the pairing, in G_2. * @param[in] p - the second point of the pairing, in G_1. * @param[in] a - the loop parameter. */ static void pp_fin_k12_oatep(fp12_t r, ep2_t t, ep2_t q, ep_t p) { ep2_t q1, q2; fp12_t tmp; fp12_null(tmp); ep2_null(q1); ep2_null(q2); TRY { ep2_new(q1); ep2_new(q2); fp12_new(tmp); fp12_zero(tmp); fp2_set_dig(q1->z, 1); fp2_set_dig(q2->z, 1); ep2_frb(q1, q, 1); ep2_frb(q2, q, 2); ep2_neg(q2, q2); pp_add_k12(tmp, t, q1, p); fp12_mul_dxs(r, r, tmp); pp_add_k12(tmp, t, q2, p); fp12_mul_dxs(r, r, tmp); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { fp12_free(tmp); ep2_free(q1); ep2_free(q2); } }
void ep2_mul_fix_combd(ep2_t r, ep2_t *t, bn_t k) { int i, j, d, e, w0, w1, 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); 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(r); n0 = bn_bits(k); p1 = (e - 1) + (EP_DEPTH - 1) * d; for (i = e - 1; i >= 0; i--) { ep2_dbl(r, r); w0 = 0; p0 = p1; for (j = EP_DEPTH - 1; j >= 0; j--, p0 -= d) { w0 = w0 << 1; if (p0 < n0 && bn_get_bit(k, p0)) { w0 = w0 | 1; } } w1 = 0; p0 = p1-- + e; for (j = EP_DEPTH - 1; j >= 0; j--, p0 -= d) { w1 = w1 << 1; if (i + e < d && p0 < n0 && bn_get_bit(k, p0)) { w1 = w1 | 1; } } ep2_add(r, r, t[w0]); ep2_add(r, r, t[(1 << EP_DEPTH) + w1]); } 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_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); } }
/** * Multiplies a point on a Barreto-Naehrig curve by the cofactor. * * @param[out] r - the result. * @param[in] p - the point to multiply. */ void ep2_mul_cof_bn(ep2_t r, ep2_t p) { bn_t x; ep2_t t0, t1, t2; ep2_null(t0); ep2_null(t1); ep2_null(t2); bn_null(x); TRY { ep2_new(t0); ep2_new(t1); ep2_new(t2); bn_new(x); fp_param_get_var(x); /* Compute t0 = xP. */ ep2_mul(t0, p, x); if (bn_sign(x) == BN_NEG) { ep2_neg(t0, t0); } /* Compute t1 = \psi(3xP). */ ep2_dbl(t1, t0); ep2_add(t1, t1, t0); ep2_norm(t1, t1); ep2_frb(t1, t1, 1); /* Compute t2 = \psi^3(P) + t0 + t1 + \psi^2(xP). */ ep2_frb(t2, p, 2); ep2_frb(t2, t2, 1); ep2_add(t2, t2, t0); ep2_add(t2, t2, t1); ep2_frb(t1, t0, 2); ep2_add(t2, t2, t1); ep2_norm(r, t2); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { ep2_free(t0); ep2_free(t1); ep2_free(t2); bn_free(x); } }
void ep2_mul_fix_basic(ep2_t r, ep2_t *t, bn_t k) { if (bn_is_zero(k)) { ep2_set_infty(r); return; } ep2_set_infty(r); for (int i = 0; i < bn_bits(k); i++) { if (bn_get_bit(k, i)) { ep2_add(r, r, t[i]); } } ep2_norm(r, r); if (bn_sign(k) == RLC_NEG) { ep2_neg(r, r); } }
/** * Compute the Miller loop for pairings of type G_1 x G_2 over the bits of a * given parameter. * * @param[out] r - the result. * @param[out] t - the resulting point. * @param[in] p - the first pairing argument in affine coordinates. * @param[in] q - 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_lit_k12(fp12_t r, ep_t *t, ep_t *p, ep2_t *q, int m, bn_t a) { fp12_t l; ep2_t _q[m]; int j; fp12_null(l); TRY { fp12_new(l); for (j = 0; j < m; j++) { ep2_null(_q[j]); ep2_new(_q[j]); ep_copy(t[j], p[j]); ep2_neg(_q[j], q[j]); } fp12_zero(l); for (int i = bn_bits(a) - 2; i >= 0; i--) { fp12_sqr(r, r); for (j = 0; j < m; j++) { pp_dbl_lit_k12(l, t[j], t[j], _q[j]); fp12_mul(r, r, l); if (bn_get_bit(a, i)) { pp_add_lit_k12(l, t[j], p[j], q[j]); fp12_mul(r, r, l); } } } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { fp12_free(l); for (j = 0; j < m; j++) { ep2_free(_q[j]); } } }
void pp_map_sim_oatep_k12(fp12_t r, ep_t *p, ep2_t *q, int m) { ep_t _p[m]; ep2_t t[m], _q[m]; bn_t a; int i, j, len = FP_BITS, s[FP_BITS]; TRY { bn_null(a); bn_new(a); for (i = 0; i < m; i++) { ep_null(_p[i]); ep2_null(_q[i]); ep2_null(t[i]); ep_new(_p[i]); ep2_new(_q[i]); ep2_new(t[i]); } j = 0; for (i = 0; i < m; i++) { if (!ep_is_infty(p[i]) && !ep2_is_infty(q[i])) { ep_norm(_p[j], p[i]); ep2_norm(_q[j++], q[i]); } } fp12_set_dig(r, 1); fp_param_get_var(a); bn_mul_dig(a, a, 6); bn_add_dig(a, a, 2); fp_param_get_map(s, &len); if (j > 0) { switch (ep_param_get()) { case BN_P158: case BN_P254: case BN_P256: case BN_P638: /* r = f_{|a|,Q}(P). */ pp_mil_sps_k12(r, t, _q, _p, j, s, len); if (bn_sign(a) == BN_NEG) { /* f_{-a,Q}(P) = 1/f_{a,Q}(P). */ fp12_inv_uni(r, r); } for (i = 0; i < j; i++) { if (bn_sign(a) == BN_NEG) { ep2_neg(t[i], t[i]); } pp_fin_k12_oatep(r, t[i], _q[i], _p[i]); } pp_exp_k12(r, r); break; case B12_P638: /* r = f_{|a|,Q}(P). */ pp_mil_sps_k12(r, t, _q, _p, j, s, len); if (bn_sign(a) == BN_NEG) { fp12_inv_uni(r, r); } pp_exp_k12(r, r); break; } } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(a); for (i = 0; i < m; i++) { ep_free(_p[i]); ep2_free(_q[i]); ep2_free(t[i]); } } }
void pp_map_oatep_k12(fp12_t r, ep_t p, ep2_t q) { ep_t _p[1]; ep2_t t[1], _q[1]; bn_t a; int len = FP_BITS, s[FP_BITS]; ep_null(_p[0]); ep2_null(_q[0]); ep2_null(t[0]); bn_null(a); TRY { ep_new(_p[0]); ep2_new(_q[0]); ep2_new(t[0]); bn_new(a); fp_param_get_var(a); bn_mul_dig(a, a, 6); bn_add_dig(a, a, 2); fp_param_get_map(s, &len); fp12_set_dig(r, 1); ep_norm(_p[0], p); ep2_norm(_q[0], q); if (!ep_is_infty(_p[0]) && !ep2_is_infty(_q[0])) { switch (ep_param_get()) { case BN_P158: case BN_P254: case BN_P256: case BN_P638: /* r = f_{|a|,Q}(P). */ pp_mil_sps_k12(r, t, _q, _p, 1, s, len); if (bn_sign(a) == BN_NEG) { /* f_{-a,Q}(P) = 1/f_{a,Q}(P). */ fp12_inv_uni(r, r); ep2_neg(t[0], t[0]); } pp_fin_k12_oatep(r, t[0], _q[0], _p[0]); pp_exp_k12(r, r); break; case B12_P638: /* r = f_{|a|,Q}(P). */ pp_mil_sps_k12(r, t, _q, _p, 1, s, len); if (bn_sign(a) == BN_NEG) { fp12_inv_uni(r, r); ep2_neg(t[0], t[0]); } pp_exp_k12(r, r); break; } } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { ep_free(_p[0]); ep2_free(_q[0]); ep2_free(t[0]); bn_free(a); } }
/** * 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]); } } }