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_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_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 ep2_sub_basic(ep2_t r, ep2_t p, ep2_t q) { ep2_t t; ep2_null(t); if (p == q) { ep2_set_infty(r); return; } TRY { ep2_new(t); ep2_neg_basic(t, q); ep2_add_basic(r, p, t); r->norm = 1; } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { ep2_free(t); } }
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_dbl_projc(ep2_t r, ep2_t p) { if (ep2_is_infty(p)) { ep2_set_infty(r); return; } ep2_dbl_projc_imp(r, p); }
void ep2_dbl_slp_basic(ep2_t r, fp2_t s, ep2_t p) { if (ep2_is_infty(p)) { ep2_set_infty(r); return; } ep2_dbl_basic_imp(r, s, p); }
void ep2_dbl_basic(ep2_t r, ep2_t p) { if (ep2_is_infty(p)) { ep2_set_infty(r); return; } ep2_dbl_basic_imp(r, NULL, p); }
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); } }
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; 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); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(n); } }
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_fix_basic(ep2_t r, ep2_t *t, bn_t k) { int i, l; l = bn_bits(k); ep2_set_infty(r); for (i = 0; i < l; i++) { if (bn_get_bit(k, i)) { ep2_add(r, r, t[i]); } } ep2_norm(r, r); }
void ep2_neg_projc(ep2_t r, ep2_t p) { if (ep2_is_infty(p)) { ep2_set_infty(r); return; } if (r != p) { fp2_copy(r->x, p->x); fp2_copy(r->z, p->z); } fp2_neg(r->y, p->y); r->norm = p->norm; }
void ep2_read_bin(ep2_t a, uint8_t *bin, int len) { if (len == 1) { if (bin[0] == 0) { ep2_set_infty(a); return; } else { THROW(ERR_NO_BUFFER); return; } } if (len != (2 * FP_BYTES + 1) && len != (4 * FP_BYTES + 1)) { THROW(ERR_NO_BUFFER); return; } a->norm = 1; fp_set_dig(a->z[0], 1); fp_zero(a->z[1]); fp2_read_bin(a->x, bin + 1, 2 * FP_BYTES); if (len == 2 * FP_BYTES + 1) { switch(bin[0]) { case 2: fp2_zero(a->y); break; case 3: fp2_zero(a->y); fp_set_bit(a->y[0], 0, 1); fp_zero(a->y[1]); break; default: THROW(ERR_NO_VALID); break; } ep2_upk(a, a); } if (len == 4 * FP_BYTES + 1) { if (bin[0] == 4) { fp2_read_bin(a->y, bin + 2 * FP_BYTES + 1, 2 * FP_BYTES); } else { THROW(ERR_NO_VALID); } } }
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_curve_init(void) { ctx_t *ctx = core_get(); #ifdef EP_PRECO for (int i = 0; i < EP_TABLE; i++) { ctx->ep2_ptr[i] = &(ctx->ep2_pre[i]); } #endif #if ALLOC == STATIC || ALLOC == DYNAMIC || ALLOC == STACK ctx->ep2_g.x[0] = ctx->ep2_gx[0]; ctx->ep2_g.x[1] = ctx->ep2_gx[1]; ctx->ep2_g.y[0] = ctx->ep2_gy[0]; ctx->ep2_g.y[1] = ctx->ep2_gy[1]; ctx->ep2_g.z[0] = ctx->ep2_gz[0]; ctx->ep2_g.z[1] = ctx->ep2_gz[1]; #endif #ifdef EP_PRECO #if ALLOC == STATIC || ALLOC == DYNAMIC for (int i = 0; i < EP_TABLE; i++) { fp2_new(ctx->ep2_pre[i].x); fp2_new(ctx->ep2_pre[i].y); fp2_new(ctx->ep2_pre[i].z); } #elif ALLOC == STACK for (int i = 0; i < EP_TABLE; i++) { ctx->ep2_pre[i].x[0] = ctx->_ep2_pre[3 * i][0]; ctx->ep2_pre[i].x[1] = ctx->_ep2_pre[3 * i][1]; ctx->ep2_pre[i].y[0] = ctx->_ep2_pre[3 * i + 1][0]; ctx->ep2_pre[i].y[1] = ctx->_ep2_pre[3 * i + 1][1]; ctx->ep2_pre[i].z[0] = ctx->_ep2_pre[3 * i + 2][0]; ctx->ep2_pre[i].z[1] = ctx->_ep2_pre[3 * i + 2][1]; } #endif #endif ep2_set_infty(&(ctx->ep2_g)); bn_init(&(ctx->ep2_r), FP_DIGS); bn_init(&(ctx->ep2_h), FP_DIGS); }
/** * 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 * FP_BITS + 1], *t; /* Compute the w-TNAF representation of k. */ len = 2 * 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); }
static void ep2_mul_sim_plain(ep2_t r, ep2_t p, bn_t k, ep2_t q, bn_t l, ep2_t *t) { int len, l0, l1, i, n0, n1, w, gen; int8_t naf0[2 * FP_BITS + 1], naf1[2 * FP_BITS + 1], *_k, *_m; ep2_t t0[1 << (EP_WIDTH - 2)]; ep2_t t1[1 << (EP_WIDTH - 2)]; for (i = 0; i < (1 << (EP_WIDTH - 2)); i++) { ep2_null(t0[i]); ep2_null(t1[i]); } TRY { gen = (t == NULL ? 0 : 1); if (!gen) { for (i = 0; i < (1 << (EP_WIDTH - 2)); i++) { ep2_new(t0[i]); } ep2_tab(t0, p, EP_WIDTH); t = (ep2_t *)t0; } /* Prepare the precomputation table. */ for (i = 0; i < (1 << (EP_WIDTH - 2)); i++) { ep2_new(t1[i]); } /* Compute the precomputation table. */ ep2_tab(t1, q, EP_WIDTH); /* Compute the w-TNAF representation of k. */ if (gen) { w = EP_DEPTH; } else { w = EP_WIDTH; } l0 = l1 = 2 * FP_BITS + 1; bn_rec_naf(naf0, &l0, k, w); bn_rec_naf(naf1, &l1, l, EP_WIDTH); len = MAX(l0, l1); _k = naf0 + len - 1; _m = naf1 + len - 1; for (i = l0; i < len; i++) naf0[i] = 0; for (i = l1; i < len; i++) naf1[i] = 0; ep2_set_infty(r); for (i = len - 1; i >= 0; i--, _k--, _m--) { ep2_dbl(r, r); n0 = *_k; n1 = *_m; if (n0 > 0) { ep2_add(r, r, t[n0 / 2]); } if (n0 < 0) { ep2_sub(r, r, t[-n0 / 2]); } if (n1 > 0) { ep2_add(r, r, t1[n1 / 2]); } if (n1 < 0) { ep2_sub(r, r, t1[-n1 / 2]); } } /* Convert r to affine coordinates. */ ep2_norm(r, r); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { /* Free the precomputation tables. */ if (!gen) { for (i = 0; i < (1 << (EP_WIDTH - 2)); i++) { ep2_free(t0[i]); } } for (i = 0; i < (1 << (EP_WIDTH - 2)); i++) { ep2_free(t1[i]); } } }
/** * Adds two points represented in affine coordinates on an ordinary prime * elliptic curve. * * @param r - the result. * @param s - the resulting slope. * @param p - the first point to add. * @param q - the second point to add. */ static void ep2_add_basic_imp(ep2_t r, fp2_t s, ep2_t p, ep2_t q) { fp2_t t0, t1, t2; fp2_null(t0); fp2_null(t1); fp2_null(t2); TRY { fp2_new(t0); fp2_new(t1); fp2_new(t2); /* t0 = x2 - x1. */ fp2_sub(t0, q->x, p->x); /* t1 = y2 - y1. */ fp2_sub(t1, q->y, p->y); /* If t0 is zero. */ if (fp2_is_zero(t0)) { if (fp2_is_zero(t1)) { /* If t1 is zero, q = p, should have doubled. */ ep2_dbl_basic(r, p); } else { /* If t1 is not zero and t0 is zero, q = -p and r = infty. */ ep2_set_infty(r); } } else { /* t2 = 1/(x2 - x1). */ fp2_inv(t2, t0); /* t2 = lambda = (y2 - y1)/(x2 - x1). */ fp2_mul(t2, t1, t2); /* x3 = lambda^2 - x2 - x1. */ fp2_sqr(t1, t2); fp2_sub(t0, t1, p->x); fp2_sub(t0, t0, q->x); /* y3 = lambda * (x1 - x3) - y1. */ fp2_sub(t1, p->x, t0); fp2_mul(t1, t2, t1); fp2_sub(r->y, t1, p->y); fp2_copy(r->x, t0); fp2_copy(r->z, p->z); if (s != NULL) { fp2_copy(s, t2); } r->norm = 1; } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { fp2_free(t0); fp2_free(t1); fp2_free(t2); } }
/** * Adds two points represented in projective coordinates on an ordinary prime * elliptic curve. * * @param r - the result. * @param p - the first point to add. * @param q - the second point to add. */ static void ep2_add_projc_imp(ep2_t r, ep2_t p, ep2_t q) { #if defined(EP_MIXED) && defined(STRIP) ep2_add_projc_mix(r, p, q); #else /* General addition. */ fp2_t t0, t1, t2, t3, t4, t5, t6; fp2_null(t0); fp2_null(t1); fp2_null(t2); fp2_null(t3); fp2_null(t4); fp2_null(t5); fp2_null(t6); TRY { fp2_new(t0); fp2_new(t1); fp2_new(t2); fp2_new(t3); fp2_new(t4); fp2_new(t5); fp2_new(t6); if (q->norm) { ep2_add_projc_mix(r, p, q); } else { /* t0 = z1^2. */ fp2_sqr(t0, p->z); /* t1 = z2^2. */ fp2_sqr(t1, q->z); /* t2 = U1 = x1 * z2^2. */ fp2_mul(t2, p->x, t1); /* t3 = U2 = x2 * z1^2. */ fp2_mul(t3, q->x, t0); /* t6 = z1^2 + z2^2. */ fp2_add(t6, t0, t1); /* t0 = S2 = y2 * z1^3. */ fp2_mul(t0, t0, p->z); fp2_mul(t0, t0, q->y); /* t1 = S1 = y1 * z2^3. */ fp2_mul(t1, t1, q->z); fp2_mul(t1, t1, p->y); /* t3 = H = U2 - U1. */ fp2_sub(t3, t3, t2); /* t0 = R = 2 * (S2 - S1). */ fp2_sub(t0, t0, t1); fp2_dbl(t0, t0); /* If E is zero. */ if (fp2_is_zero(t3)) { if (fp2_is_zero(t0)) { /* If I is zero, p = q, should have doubled. */ ep2_dbl_projc(r, p); } else { /* If I is not zero, q = -p, r = infinity. */ ep2_set_infty(r); } } else { /* t4 = I = (2*H)^2. */ fp2_dbl(t4, t3); fp2_sqr(t4, t4); /* t5 = J = H * I. */ fp2_mul(t5, t3, t4); /* t4 = V = U1 * I. */ fp2_mul(t4, t2, t4); /* x3 = R^2 - J - 2 * V. */ fp2_sqr(r->x, t0); fp2_sub(r->x, r->x, t5); fp2_dbl(t2, t4); fp2_sub(r->x, r->x, t2); /* y3 = R * (V - x3) - 2 * S1 * J. */ fp2_sub(t4, t4, r->x); fp2_mul(t4, t4, t0); fp2_mul(t1, t1, t5); fp2_dbl(t1, t1); fp2_sub(r->y, t4, t1); /* z3 = ((z1 + z2)^2 - z1^2 - z2^2) * H. */ fp2_add(r->z, p->z, q->z); fp2_sqr(r->z, r->z); fp2_sub(r->z, r->z, t6); fp2_mul(r->z, r->z, t3); } } r->norm = 0; } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { fp2_free(t0); fp2_free(t1); fp2_free(t2); fp2_free(t3); fp2_free(t4); fp2_free(t5); fp2_free(t6); } #endif }
/** * Adds a point represented in affine coordinates to a point represented in * projective coordinates. * * @param r - the result. * @param s - the slope. * @param p - the affine point. * @param q - the projective point. */ static void ep2_add_projc_mix(ep2_t r, ep2_t p, ep2_t q) { fp2_t t0, t1, t2, t3, t4, t5, t6; fp2_null(t0); fp2_null(t1); fp2_null(t2); fp2_null(t3); fp2_null(t4); fp2_null(t5); fp2_null(t6); TRY { fp2_new(t0); fp2_new(t1); fp2_new(t2); fp2_new(t3); fp2_new(t4); fp2_new(t5); fp2_new(t6); if (!p->norm) { /* t0 = z1^2. */ fp2_sqr(t0, p->z); /* t3 = U2 = x2 * z1^2. */ fp2_mul(t3, q->x, t0); /* t1 = S2 = y2 * z1^3. */ fp2_mul(t1, t0, p->z); fp2_mul(t1, t1, q->y); /* t3 = H = U2 - x1. */ fp2_sub(t3, t3, p->x); /* t1 = R = 2 * (S2 - y1). */ fp2_sub(t1, t1, p->y); } else { /* H = x2 - x1. */ fp2_sub(t3, q->x, p->x); /* t1 = R = 2 * (y2 - y1). */ fp2_sub(t1, q->y, p->y); } /* t2 = HH = H^2. */ fp2_sqr(t2, t3); /* If E is zero. */ if (fp2_is_zero(t3)) { if (fp2_is_zero(t1)) { /* If I is zero, p = q, should have doubled. */ ep2_dbl_projc(r, p); } else { /* If I is not zero, q = -p, r = infinity. */ ep2_set_infty(r); } } else { /* t5 = J = H * HH. */ fp2_mul(t5, t3, t2); /* t4 = V = x1 * HH. */ fp2_mul(t4, p->x, t2); /* x3 = R^2 - J - 2 * V. */ fp2_sqr(r->x, t1); fp2_sub(r->x, r->x, t5); fp2_dbl(t6, t4); fp2_sub(r->x, r->x, t6); /* y3 = R * (V - x3) - Y1 * J. */ fp2_sub(t4, t4, r->x); fp2_mul(t4, t4, t1); fp2_mul(t1, p->y, t5); fp2_sub(r->y, t4, t1); if (!p->norm) { /* z3 = z1 * H. */ fp2_mul(r->z, p->z, t3); } else { /* z3 = H. */ fp2_copy(r->z, t3); } } r->norm = 0; } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { fp2_free(t0); fp2_free(t1); fp2_free(t2); fp2_free(t3); fp2_free(t4); fp2_free(t5); fp2_free(t6); } }
static void ep2_mul_sim_ordin(ep2_t r, ep2_t p, bn_t k, ep2_t q, bn_t l, int gen) { int len, l0, l1, i, n0, n1, w; signed char naf0[FP_BITS + 1], naf1[FP_BITS + 1], *t0, *t1; ep2_t table0[1 << (EP_WIDTH - 2)]; ep2_t table1[1 << (EP_WIDTH - 2)]; ep2_t *t = NULL; for (i = 0; i < (1 << (EP_WIDTH - 2)); i++) { ep2_null(table0[i]); ep2_null(table1[i]); } if (gen) { #if defined(EP_PRECO) t = ep2_curve_get_tab(); #endif } else { for (i = 0; i < (1 << (EP_WIDTH - 2)); i++) { ep2_new(table0[i]); } ep2_tab(table0, p, EP_WIDTH); t = table0; } /* Prepare the precomputation table. */ for (i = 0; i < (1 << (EP_WIDTH - 2)); i++) { ep2_new(table1[i]); } /* Compute the precomputation table. */ ep2_tab(table1, q, EP_WIDTH); /* Compute the w-TNAF representation of k. */ if (gen) { w = EP_DEPTH; } else { w = EP_WIDTH; } l0 = l1 = FP_BITS + 1; bn_rec_naf(naf0, &l0, k, w); bn_rec_naf(naf1, &l1, l, EP_WIDTH); len = MAX(l0, l1); t0 = naf0 + len - 1; t1 = naf1 + len - 1; for (i = l0; i < len; i++) naf0[i] = 0; for (i = l1; i < len; i++) naf1[i] = 0; ep2_set_infty(r); for (i = len - 1; i >= 0; i--, t0--, t1--) { ep2_dbl(r, r); n0 = *t0; n1 = *t1; if (n0 > 0) { ep2_add(r, r, t[n0 / 2]); } if (n0 < 0) { ep2_sub(r, r, t[-n0 / 2]); } if (n1 > 0) { ep2_add(r, r, table1[n1 / 2]); } if (n1 < 0) { ep2_sub(r, r, table1[-n1 / 2]); } } /* Convert r to affine coordinates. */ ep2_norm(r, r); /* Free the precomputation table. */ for (i = 0; i < 1 << (EP_WIDTH - 2); i++) { ep2_free(table0[i]); ep2_free(table1[i]); } }
void ep2_mul_sim_trick(ep2_t r, ep2_t p, bn_t k, ep2_t q, bn_t l) { ep2_t t0[1 << (EP_WIDTH / 2)]; ep2_t t1[1 << (EP_WIDTH / 2)]; ep2_t t[1 << EP_WIDTH]; bn_t n; int l0, l1, w = EP_WIDTH / 2; uint8_t w0[CEIL(2 * FP_BITS, w)], w1[CEIL(2 * FP_BITS, w)]; bn_null(n); for (int i = 0; i < 1 << EP_WIDTH; i++) { ep2_null(t[i]); } for (int i = 0; i < 1 << (EP_WIDTH / 2); i++) { ep2_null(t0[i]); ep2_null(t1[i]); } TRY { bn_new(n); ep2_curve_get_ord(n); for (int i = 0; i < (1 << w); i++) { ep2_new(t0[i]); ep2_new(t1[i]); } for (int i = 0; i < (1 << EP_WIDTH); i++) { ep2_new(t[i]); } ep2_set_infty(t0[0]); for (int i = 1; i < (1 << w); i++) { ep2_add(t0[i], t0[i - 1], p); } ep2_set_infty(t1[0]); for (int i = 1; i < (1 << w); i++) { ep2_add(t1[i], t1[i - 1], q); } for (int i = 0; i < (1 << w); i++) { for (int j = 0; j < (1 << w); j++) { ep2_add(t[(i << w) + j], t0[i], t1[j]); } } l0 = l1 = CEIL(2 * FP_BITS, w); bn_rec_win(w0, &l0, k, w); bn_rec_win(w1, &l1, l, w); for (int i = l0; i < l1; i++) { w0[i] = 0; } for (int i = l1; i < l0; i++) { w1[i] = 0; } ep2_set_infty(r); for (int i = MAX(l0, l1) - 1; i >= 0; i--) { for (int j = 0; j < w; j++) { ep2_dbl(r, r); } ep2_add(r, r, t[(w0[i] << w) + w1[i]]); } ep2_norm(r, r); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(n); for (int i = 0; i < (1 << w); i++) { ep2_free(t0[i]); ep2_free(t1[i]); } for (int i = 0; i < (1 << EP_WIDTH); i++) { ep2_free(t[i]); } } }