int eb_is_valid(const eb_t p) { eb_t t; fb_t lhs; int r = 0; eb_null(t); fb_null(lhs); TRY { eb_new(t); fb_new(lhs); eb_norm(t, p); fb_mul(lhs, t->x, t->y); eb_rhs(t->x, t); fb_sqr(t->y, t->y); fb_add(lhs, lhs, t->y); r = (fb_cmp(lhs, t->x) == CMP_EQ) || eb_is_infty(p); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { eb_free(t); fb_free(lhs); } return r; }
void eb_curve_set_ordin(const fb_t a, const fb_t b, const eb_t g, const bn_t r, const bn_t h) { ctx_t *ctx = core_get(); fb_copy(ctx->eb_a, a); fb_copy(ctx->eb_b, b); detect_opt(&(ctx->eb_opt_a), ctx->eb_a); detect_opt(&(ctx->eb_opt_b), ctx->eb_b); ctx->eb_is_super = 0; if (fb_cmp_dig(ctx->eb_b, 1) == CMP_EQ) { ctx->eb_is_kbltz = 1; } else { ctx->eb_is_kbltz = 0; } #if defined(EB_KBLTZ) && (EB_MUL == LWNAF || EB_FIX == LWNAF || EB_SIM == INTER || !defined(STRIP)) if (ctx->eb_is_kbltz) { compute_kbltz(); } #endif eb_norm(&(ctx->eb_g), g); bn_copy(&(ctx->eb_r), r); bn_copy(&(ctx->eb_h), h); #if defined(EB_PRECO) eb_mul_pre((eb_t *)eb_curve_get_tab(), &(ctx->eb_g)); #endif }
int eb_size_bin(const eb_t a, int pack) { eb_t t; int size = 0; eb_null(t); if (eb_is_infty(a)) { return 1; } TRY { eb_new(t); eb_norm(t, a); size = 1 + FB_BYTES; if (!pack) { size += FB_BYTES; } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { eb_free(t); } return size; }
void eb_curve_set_ordin(fb_t a, fb_t b, eb_t g, bn_t r, bn_t h) { fb_copy(curve_a, a); fb_copy(curve_b, b); detect_opt(&curve_opt_a, curve_a); detect_opt(&curve_opt_b, curve_b); curve_is_super = 0; if (fb_cmp_dig(curve_b, 1) == CMP_EQ) { curve_is_kbltz = 1; } else { curve_is_kbltz = 0; } #if defined(EB_KBLTZ) && (EB_MUL == LWNAF || EB_FIX == LWNAF || EB_SIM == INTER || !defined(STRIP)) if (curve_is_kbltz) { compute_kbltz(); } #endif eb_norm(g, g); eb_copy(&curve_g, g); bn_copy(&curve_r, r); bn_copy(&curve_h, h); #if defined(EB_PRECO) eb_mul_pre(eb_curve_get_tab(), &curve_g); #endif }
void eb_norm_sim(eb_t *r, const eb_t *t, int n) { int i; fb_t a[n]; if (n == 1) { eb_norm(r[0], t[0]); return; } for (i = 0; i < n; i++) { fb_null(a[i]); } TRY { for (i = 0; i < n; i++) { fb_new(a[i]); if (!eb_is_infty(t[i])) { fb_copy(a[i], t[i]->z); } else { fb_set_dig(a[i], 1); } } fb_inv_sim(a, (const fb_t *)a, n); for (i = 0; i < n; i++) { fb_copy(r[i]->x, t[i]->x); fb_copy(r[i]->y, t[i]->y); if (!eb_is_infty(t[i])) { fb_copy(r[i]->z, a[i]); } } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { for (i = 0; i < n; i++) { fb_free(a[i]); } } #if defined(EB_SUPER) if (eb_curve_is_super()) { for (i = 0; i < n; i++) { eb_norm_super(r[i], r[i], 1); } } #endif #if defined(EB_ORDIN) || defined(EB_KBLTZ) if (!eb_curve_is_super()) { for (i = 0; i < n; i++) { eb_norm_ordin(r[i], r[i], 1); } } #endif }
void eb_mul_fix_combd(eb_t r, eb_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); eb_curve_get_ord(n); d = bn_bits(n); d = ((d % EB_DEPTH) == 0 ? (d / EB_DEPTH) : (d / EB_DEPTH) + 1); e = (d % 2 == 0 ? (d / 2) : (d / 2) + 1); eb_set_infty(r); n0 = bn_bits(k); p1 = (e - 1) + (EB_DEPTH - 1) * d; for (i = e - 1; i >= 0; i--) { eb_dbl(r, r); w0 = 0; p0 = p1; for (j = EB_DEPTH - 1; j >= 0; j--, p0 -= d) { w0 = w0 << 1; if (p0 < n0 && bn_test_bit(k, p0)) { w0 = w0 | 1; } } w1 = 0; p0 = p1-- + e; for (j = EB_DEPTH - 1; j >= 0; j--, p0 -= d) { w1 = w1 << 1; if (i + e < d && p0 < n0 && bn_test_bit(k, p0)) { w1 = w1 | 1; } } eb_add(r, r, t[w0]); eb_add(r, r, t[(1 << EB_DEPTH) + w1]); } eb_norm(r, r); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(n); } }
void eb_mul_fix_combs(eb_t r, eb_t *t, bn_t k) { int i, j, l, w, n, p0, p1; bn_t ord; bn_null(ord); TRY { bn_new(ord); eb_curve_get_ord(ord); l = bn_bits(ord); l = ((l % EB_DEPTH) == 0 ? (l / EB_DEPTH) : (l / EB_DEPTH) + 1); n = bn_bits(k); p0 = (EB_DEPTH) * l - 1; w = 0; p1 = p0--; for (j = EB_DEPTH - 1; j >= 0; j--, p1 -= l) { w = w << 1; if (p1 < n && bn_test_bit(k, p1)) { w = w | 1; } } eb_copy(r, t[w]); for (i = l - 2; i >= 0; i--) { eb_dbl(r, r); w = 0; p1 = p0--; for (j = EB_DEPTH - 1; j >= 0; j--, p1 -= l) { w = w << 1; if (p1 < n && bn_test_bit(k, p1)) { w = w | 1; } } if (w > 0) { eb_add(r, r, t[w]); } } eb_norm(r, r); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(ord); } }
void eb_mul_sim_basic(eb_t r, const eb_t p, const bn_t k, const eb_t q, const bn_t m) { eb_t t; eb_null(t); TRY { eb_new(t); eb_mul(t, q, m); eb_mul(r, p, k); eb_add(t, t, r); eb_norm(r, t); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { eb_free(t); } }
void eb_write_bin(uint8_t *bin, int len, const eb_t a, int pack) { eb_t t; eb_null(t); if (eb_is_infty(a)) { if (len != 1) { THROW(ERR_NO_BUFFER); } else { bin[0] = 0; return; } } TRY { eb_new(t); eb_norm(t, a); if (pack) { if (len != FB_BYTES + 1) { THROW(ERR_NO_BUFFER); } else { eb_pck(t, t); bin[0] = 2 | fb_get_bit(t->y, 0); fb_write_bin(bin + 1, FB_BYTES, t->x); } } else { if (len != 2 * FB_BYTES + 1) { THROW(ERR_NO_BUFFER); } else { bin[0] = 4; fb_write_bin(bin + 1, FB_BYTES, t->x); fb_write_bin(bin + FB_BYTES + 1, FB_BYTES, t->y); } } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { eb_free(t); } }
void eb_curve_set_super(fb_t a, fb_t b, fb_t c, eb_t g, bn_t r, bn_t h) { curve_is_kbltz = 0; curve_is_super = 1; fb_copy(curve_a, a); fb_copy(curve_b, b); fb_copy(curve_c, c); detect_opt(&curve_opt_a, curve_a); detect_opt(&curve_opt_b, curve_b); detect_opt(&curve_opt_c, curve_c); eb_norm(g, g); eb_copy(&curve_g, g); bn_copy(&curve_r, r); bn_copy(&curve_h, h); #if defined(EB_PRECO) eb_mul_pre(eb_curve_get_tab(), &curve_g); #endif }
void eb_curve_set_kbltz(fb_t a, eb_t g, bn_t r, bn_t h) { curve_is_kbltz = 1; curve_is_super = 0; fb_copy(curve_a, a); fb_set_dig(curve_b, 1); detect_opt(&curve_opt_a, curve_a); detect_opt(&curve_opt_b, curve_b); #if EB_MUL == LWNAF || EB_FIX == LWNAF || EB_SIM == INTER || !defined(STRIP) compute_kbltz(); #endif eb_norm(g, g); eb_copy(&curve_g, g); bn_copy(&curve_r, r); bn_copy(&curve_h, h); #if defined(EB_PRECO) eb_mul_pre(eb_curve_get_tab(), &curve_g); #endif }
void eb_curve_set_kbltz(const fb_t a, const eb_t g, const bn_t r, const bn_t h) { ctx_t *ctx = core_get(); ctx->eb_is_kbltz = 1; ctx->eb_is_super = 0; fb_copy(ctx->eb_a, a); fb_set_dig(ctx->eb_b, 1); detect_opt(&(ctx->eb_opt_a), ctx->eb_a); detect_opt(&(ctx->eb_opt_b), ctx->eb_b); #if EB_MUL == LWNAF || EB_FIX == LWNAF || EB_SIM == INTER || !defined(STRIP) compute_kbltz(); #endif eb_norm(&(ctx->eb_g), g); bn_copy(&(ctx->eb_r), r); bn_copy(&(ctx->eb_h), h); #if defined(EB_PRECO) eb_mul_pre((eb_t *)eb_curve_get_tab(), &(ctx->eb_g)); #endif }
void eb_curve_set_super(const fb_t a, const fb_t b, const fb_t c, const eb_t g, const bn_t r, const bn_t h) { ctx_t *ctx = core_get(); ctx->eb_is_kbltz = 0; ctx->eb_is_super = 1; fb_copy(ctx->eb_a, a); fb_copy(ctx->eb_b, b); fb_copy(ctx->eb_c, c); detect_opt(&(ctx->eb_opt_a), ctx->eb_a); detect_opt(&(ctx->eb_opt_b), ctx->eb_b); detect_opt(&(ctx->eb_opt_c), ctx->eb_c); eb_norm(&(ctx->eb_g), g); bn_copy(&(ctx->eb_r), r); bn_copy(&(ctx->eb_h), h); #if defined(EB_PRECO) eb_mul_pre((eb_t *)eb_curve_get_tab(), &(ctx->eb_g)); #endif }
void eb_mul_sim_trick(eb_t r, const eb_t p, const bn_t k, const eb_t q, const bn_t m) { eb_t t0[1 << (EB_WIDTH / 2)], t1[1 << (EB_WIDTH / 2)], t[1 << EB_WIDTH]; bn_t n; int l0, l1, w = EB_WIDTH / 2; uint8_t w0[CEIL(FB_BITS, 2)], w1[CEIL(FB_BITS, w)]; bn_null(n); for (int i = 0; i < 1 << EB_WIDTH; i++) { eb_null(t[i]); } for (int i = 0; i < 1 << (EB_WIDTH / 2); i++) { eb_null(t0[i]); eb_null(t1[i]); } TRY { bn_new(n); eb_curve_get_ord(n); for (int i = 0; i < (1 << w); i++) { eb_new(t0[i]); eb_new(t1[i]); } for (int i = 0; i < (1 << EB_WIDTH); i++) { eb_new(t[i]); } eb_set_infty(t0[0]); for (int i = 1; i < (1 << w); i++) { eb_add(t0[i], t0[i - 1], p); } eb_set_infty(t1[0]); for (int i = 1; i < (1 << w); i++) { eb_add(t1[i], t1[i - 1], q); } for (int i = 0; i < (1 << w); i++) { for (int j = 0; j < (1 << w); j++) { eb_add(t[(i << w) + j], t0[i], t1[j]); } } #if EB_WIDTH > 2 && defined(EB_MIXED) eb_norm_sim(t + 1, (const eb_t *)(t + 1), (1 << EB_WIDTH) - 1); #endif l0 = l1 = CEIL(FB_BITS, w); bn_rec_win(w0, &l0, k, w); bn_rec_win(w1, &l1, m, w); for (int i = l0; i < l1; i++) { w0[i] = 0; } for (int i = l1; i < l0; i++) { w1[i] = 0; } eb_set_infty(r); for (int i = MAX(l0, l1) - 1; i >= 0; i--) { for (int j = 0; j < w; j++) { eb_dbl(r, r); } eb_add(r, r, t[(w0[i] << w) + w1[i]]); } eb_norm(r, r); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(n); for (int i = 0; i < (1 << w); i++) { eb_free(t0[i]); eb_free(t1[i]); } for (int i = 0; i < (1 << EB_WIDTH); i++) { eb_free(t[i]); } } }
/** * Multiplies and adds two binary elliptic curve points simultaneously, * optionally choosing the first point as the generator depending on an optional * table of precomputed points. * * @param[out] r - the result. * @param[in] p - the first point to multiply. * @param[in] k - the first integer. * @param[in] q - the second point to multiply. * @param[in] m - the second integer. * @param[in] t - the pointer to a precomputed table. */ static void eb_mul_sim_plain(eb_t r, const eb_t p, const bn_t k, const eb_t q, const bn_t m, const eb_t *t) { int l, l0, l1, i, n0, n1, w, g; int8_t naf0[FB_BITS + 1], naf1[FB_BITS + 1], *_k, *_m; eb_t t0[1 << (EB_WIDTH - 2)]; eb_t t1[1 << (EB_WIDTH - 2)]; for (i = 0; i < (1 << (EB_WIDTH - 2)); i++) { eb_null(t0[i]); eb_null(t1[i]); } TRY { g = (t == NULL ? 0 : 1); if (!g) { for (i = 0; i < (1 << (EB_WIDTH - 2)); i++) { eb_new(t0[i]); } eb_tab(t0, p, EB_WIDTH); t = (const eb_t *)t0; } /* Prepare the precomputation table. */ for (i = 0; i < (1 << (EB_WIDTH - 2)); i++) { eb_new(t1[i]); } /* Compute the precomputation table. */ eb_tab(t1, q, EB_WIDTH); /* Compute the w-NAF representation of k. */ if (g) { w = EB_DEPTH; } else { w = EB_WIDTH; } l0 = l1 = FB_BITS + 1; bn_rec_naf(naf0, &l0, k, w); bn_rec_naf(naf1, &l1, m, EB_WIDTH); l = MAX(l0, l1); _k = naf0 + l - 1; _m = naf1 + l - 1; for (i = l0; i < l; i++) { naf0[i] = 0; } for (i = l1; i < l; i++) { naf1[i] = 0; } eb_set_infty(r); for (i = l - 1; i >= 0; i--, _k--, _m--) { eb_dbl(r, r); n0 = *_k; n1 = *_m; if (n0 > 0) { eb_add(r, r, t[n0 / 2]); } if (n0 < 0) { eb_sub(r, r, t[-n0 / 2]); } if (n1 > 0) { eb_add(r, r, t1[n1 / 2]); } if (n1 < 0) { eb_sub(r, r, t1[-n1 / 2]); } } /* Convert r to affine coordinates. */ eb_norm(r, r); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { /* Free the precomputation tables. */ if (!g) { for (i = 0; i < 1 << (EB_WIDTH - 2); i++) { eb_free(t0[i]); } } for (i = 0; i < 1 << (EB_WIDTH - 2); i++) { eb_free(t1[i]); } } }
void eb_mul_sim_trick(eb_t r, const eb_t p, const bn_t k, const eb_t q, const bn_t m) { eb_t t0[1 << (EB_WIDTH / 2)], t1[1 << (EB_WIDTH / 2)], t[1 << EB_WIDTH]; int l0, l1, w = EB_WIDTH / 2; uint8_t *w0 = RLC_ALLOCA(uint8_t, RLC_CEIL(RLC_FB_BITS, w)); uint8_t *w1 = RLC_ALLOCA(uint8_t, RLC_CEIL(RLC_FB_BITS, w)); bn_t n; bn_null(n); if (bn_is_zero(k) || eb_is_infty(p)) { eb_mul(r, q, m); return; } if (bn_is_zero(m) || eb_is_infty(q)) { eb_mul(r, p, k); return; } TRY { bn_new(n); eb_curve_get_ord(n); for (int i = 0; i < (1 << w); i++) { eb_null(t0[i]); eb_null(t1[i]); eb_new(t0[i]); eb_new(t1[i]); } for (int i = 0; i < (1 << EB_WIDTH); i++) { eb_null(t[i]); eb_new(t[i]); } eb_set_infty(t0[0]); eb_copy(t0[1], p); if (bn_sign(k) == RLC_NEG) { eb_neg(t0[1], t0[1]); } for (int i = 2; i < (1 << w); i++) { eb_add(t0[i], t0[i - 1], t0[1]); } eb_set_infty(t1[0]); eb_copy(t1[1], q); if (bn_sign(m) == RLC_NEG) { eb_neg(t1[1], t1[1]); } for (int i = 2; i < (1 << w); i++) { eb_add(t1[i], t1[i - 1], t1[1]); } for (int i = 0; i < (1 << w); i++) { for (int j = 0; j < (1 << w); j++) { eb_add(t[(i << w) + j], t0[i], t1[j]); } } #if EB_WIDTH > 2 && defined(EB_MIXED) eb_norm_sim(t + 1, (const eb_t *)(t + 1), (1 << EB_WIDTH) - 1); #endif l0 = l1 = RLC_CEIL(RLC_FB_BITS + 1, w); bn_rec_win(w0, &l0, k, w); bn_rec_win(w1, &l1, m, w); for (int i = l0; i < l1; i++) { w0[i] = 0; } for (int i = l1; i < l0; i++) { w1[i] = 0; } eb_set_infty(r); for (int i = RLC_MAX(l0, l1) - 1; i >= 0; i--) { for (int j = 0; j < w; j++) { eb_dbl(r, r); } eb_add(r, r, t[(w0[i] << w) + w1[i]]); } eb_norm(r, r); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(n); for (int i = 0; i < (1 << w); i++) { eb_free(t0[i]); eb_free(t1[i]); } for (int i = 0; i < (1 << EB_WIDTH); i++) { eb_free(t[i]); } } }
void eb_mul_sim_joint(eb_t r, const eb_t p, const bn_t k, const eb_t q, const bn_t m) { eb_t t[5]; int u_i, len, offset; int8_t jsf[2 * (FB_BITS + 1)]; int i; eb_null(t[0]); eb_null(t[1]); eb_null(t[2]); eb_null(t[3]); eb_null(t[4]); TRY { for (i = 0; i < 5; i++) { eb_new(t[i]); } eb_set_infty(t[0]); eb_copy(t[1], q); eb_copy(t[2], p); eb_add(t[3], p, q); eb_sub(t[4], p, q); #if defined(EB_MIXED) eb_norm_sim(t + 3, (const eb_t*)(t + 3), 2); #endif len = 2 * (FB_BITS + 1); bn_rec_jsf(jsf, &len, k, m); eb_set_infty(r); offset = MAX(bn_bits(k), bn_bits(m)) + 1; for (i = len - 1; i >= 0; i--) { eb_dbl(r, r); if (jsf[i] != 0 && jsf[i] == -jsf[i + offset]) { u_i = jsf[i] * 2 + jsf[i + offset]; if (u_i < 0) { eb_sub(r, r, t[4]); } else { eb_add(r, r, t[4]); } } else { u_i = jsf[i] * 2 + jsf[i + offset]; if (u_i < 0) { eb_sub(r, r, t[-u_i]); } else { eb_add(r, r, t[u_i]); } } } eb_norm(r, r); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { for (i = 0; i < 5; i++) { eb_free(t[i]); } } }
/** * Multiplies and adds two binary elliptic curve points simultaneously, * optionally choosing the first point as the generator depending on an optional * table of precomputed points. * * @param[out] r - the result. * @param[in] p - the first point to multiply. * @param[in] k - the first integer. * @param[in] q - the second point to multiply. * @param[in] m - the second integer. * @param[in] t - the pointer to a precomputed table. */ static void eb_mul_sim_kbltz(eb_t r, const eb_t p, const bn_t k, const eb_t q, const bn_t m, const eb_t *t) { int l0, l1, l, i, n0, n1, w, g; int8_t u, tnaf0[FB_BITS + 8], tnaf1[FB_BITS + 8], *_k, *_m; eb_t t0[1 << (EB_WIDTH - 2)]; eb_t t1[1 << (EB_WIDTH - 2)]; bn_t vm, s0, s1; bn_null(vm); bn_null(s0); bn_null(s1); for (i = 0; i < (1 << (EB_WIDTH - 2)); i++) { eb_null(t0[i]); eb_null(t1[i]); } TRY { bn_new(vm); bn_new(s0); bn_new(s1); /* Compute the w-TNAF representation of k. */ if (eb_curve_opt_a() == OPT_ZERO) { u = -1; } else { u = 1; } g = (t == NULL ? 0 : 1); if (!g) { for (i = 0; i < (1 << (EB_WIDTH - 2)); i++) { eb_new(t0[i]); eb_set_infty(t0[i]); fb_set_bit(t0[i]->z, 0, 1); t0[i]->norm = 1; } eb_tab(t0, p, EB_WIDTH); t = (const eb_t *)t0; } /* Prepare the precomputation table. */ for (i = 0; i < (1 << (EB_WIDTH - 2)); i++) { eb_new(t1[i]); eb_set_infty(t1[i]); fb_set_bit(t1[i]->z, 0, 1); t1[i]->norm = 1; } /* Compute the precomputation table. */ eb_tab(t1, q, EB_WIDTH); /* Compute the w-TNAF representation of k. */ if (g) { w = EB_DEPTH; } else { w = EB_WIDTH; } eb_curve_get_vm(vm); eb_curve_get_s0(s0); eb_curve_get_s1(s1); l0 = l1 = FB_BITS + 8; bn_rec_tnaf(tnaf0, &l0, k, vm, s0, s1, u, FB_BITS, w); bn_rec_tnaf(tnaf1, &l1, m, vm, s0, s1, u, FB_BITS, EB_WIDTH); l = MAX(l0, l1); _k = tnaf0 + l - 1; _m = tnaf1 + l - 1; for (i = l0; i < l; i++) tnaf0[i] = 0; for (i = l1; i < l; i++) tnaf1[i] = 0; _k = tnaf0 + l - 1; _m = tnaf1 + l - 1; eb_set_infty(r); for (i = l - 1; i >= 0; i--, _k--, _m--) { eb_frb(r, r); n0 = *_k; n1 = *_m; if (n0 > 0) { eb_add(r, r, t[n0 / 2]); } if (n0 < 0) { eb_sub(r, r, t[-n0 / 2]); } if (n1 > 0) { eb_add(r, r, t1[n1 / 2]); } if (n1 < 0) { eb_sub(r, r, t1[-n1 / 2]); } } /* Convert r to affine coordinates. */ eb_norm(r, r); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { if (!g) { for (i = 0; i < (1 << (EB_WIDTH - 2)); i++) { eb_free(t0[i]); } } for (i = 0; i < (1 << (EB_WIDTH - 2)); i++) { eb_free(t1[i]); } bn_free(vm); bn_free(s0); bn_free(s1); } }
void eb_tab(eb_t *t, const eb_t p, int w) { int u; #if defined(EB_PLAIN) if (!eb_curve_is_kbltz()) { if (w > 2) { eb_dbl(t[0], p); #if defined(EB_MIXED) eb_norm(t[0], t[0]); #endif eb_add(t[1], t[0], p); for (int i = 2; i < (1 << (w - 2)); i++) { eb_add(t[i], t[i - 1], t[0]); } #if defined(EB_MIXED) eb_norm_sim(t + 1, (const eb_t *)t + 1, (1 << (w - 2)) - 1); #endif } eb_copy(t[0], p); } #endif /* EB_PLAIN */ #if defined(EB_KBLTZ) if (eb_curve_is_kbltz()) { u = (eb_curve_opt_a() == OPT_ZERO ? -1 : 1); /* Prepare the precomputation table. */ for (int i = 0; i < 1 << (w - 2); i++) { eb_set_infty(t[i]); fb_set_dig(t[i]->z, 1); t[i]->norm = 1; } #if defined(EB_MIXED) eb_norm(t[0], p); #else eb_copy(t[0], p); #endif switch (w) { #if EB_DEPTH == 3 || EB_WIDTH == 3 case 3: eb_frb(t[1], t[0]); if (u == 1) { eb_sub(t[1], t[0], t[1]); } else { eb_add(t[1], t[0], t[1]); } break; #endif #if EB_DEPTH == 4 || EB_WIDTH == 4 case 4: eb_frb(t[3], t[0]); eb_frb(t[3], t[3]); eb_sub(t[1], t[3], p); eb_add(t[2], t[3], p); eb_frb(t[3], t[3]); if (u == 1) { eb_neg(t[3], t[3]); } eb_sub(t[3], t[3], p); break; #endif #if EB_DEPTH == 5 || EB_WIDTH == 5 case 5: eb_frb(t[3], t[0]); eb_frb(t[3], t[3]); eb_sub(t[1], t[3], p); eb_add(t[2], t[3], p); eb_frb(t[3], t[3]); eb_frb(t[7], t[3]); eb_sub(t[7], t[7], p); if (u == 1) { eb_neg(t[3], t[3]); } eb_sub(t[3], t[3], p); eb_frb(t[4], t[2]); eb_frb(t[4], t[4]); eb_neg(t[4], t[4]); eb_sub(t[5], t[4], p); eb_add(t[6], t[4], p); eb_frb(t[4], t[4]); if (u == -1) { eb_neg(t[4], t[4]); } eb_add(t[4], t[4], p); break; #endif #if EB_DEPTH == 6 || EB_WIDTH == 6 case 6: eb_frb(t[0], t[0]); eb_frb(t[0], t[0]); eb_neg(t[14], t[0]); eb_sub(t[13], t[14], p); eb_add(t[14], t[14], p); eb_frb(t[0], t[0]); eb_frb(t[8], t[0]); if (u == -1) { eb_neg(t[0], t[0]); } eb_sub(t[11], t[0], p); eb_add(t[12], t[0], p); eb_frb(t[0], t[12]); eb_frb(t[0], t[0]); eb_sub(t[1], t[0], p); eb_add(t[2], t[0], p); eb_frb(t[15], t[8]); if (u == -1) { eb_neg(t[15], t[15]); } eb_sub(t[15], t[15], p); eb_frb(t[0], t[13]); eb_frb(t[0], t[0]); eb_sub(t[5], t[0], p); eb_add(t[6], t[0], p); eb_sub(t[7], t[8], p); eb_add(t[8], t[8], p); eb_frb(t[0], t[0]); if (u == -1) { eb_neg(t[0], t[0]); } eb_sub(t[3], t[0], p); eb_add(t[4], t[0], p); eb_frb(t[0], t[1]); eb_frb(t[0], t[0]); eb_neg(t[9], t[0]); eb_sub(t[9], t[9], p); eb_frb(t[0], t[14]); eb_frb(t[0], t[0]); eb_add(t[10], t[0], p); eb_copy(t[0], p); break; #endif #if EB_DEPTH == 7 || EB_WIDTH == 7 /** * Formulas from http://eprint.iacr.org/2012/519 */ case 7: eb_frb(t[0], t[0]); eb_frb(t[0], t[0]); eb_sub(t[17], t[0], p); eb_add(t[18], t[0], p); eb_frb(t[0], t[0]); if (u == 1) { eb_neg(t[0], t[0]); } eb_sub(t[19], t[0], p); eb_add(t[20], t[0], p); eb_frb(t[0], t[19]); eb_frb(t[0], t[0]); eb_frb(t[11], t[0]); if (u == 1) { eb_neg(t[11], t[11]); } eb_add(t[12], t[11], p); eb_sub(t[11], t[11], p); eb_neg(t[0], t[0]); eb_sub(t[1], t[0], p); eb_add(t[2], t[0], p); eb_frb(t[0], t[17]); eb_frb(t[0], t[0]); eb_frb(t[0], t[0]); if (u == -1) { eb_neg(t[0], t[0]); } eb_sub(t[3], t[0], p); eb_frb(t[0], t[1]); eb_frb(t[0], t[0]); eb_add(t[9], t[0], p); eb_neg(t[9], t[9]); eb_frb(t[0], t[0]); if (u == -1) { eb_neg(t[0], t[0]); } eb_add(t[4], t[0], p); eb_frb(t[0], t[18]); eb_frb(t[0], t[0]); eb_sub(t[7], t[0], t[18]); eb_sub(t[25], t[0], p); eb_add(t[26], t[0], p); eb_frb(t[0], t[0]); if (u == -1) { eb_neg(t[0], t[0]); } eb_sub(t[27], t[0], p); eb_add(t[28], t[0], p); eb_frb(t[0], t[17]); eb_frb(t[0], t[0]); eb_add(t[8], t[0], t[18]); eb_neg(t[0], t[0]); eb_add(t[10], t[0], p); eb_frb(t[0], t[7]); eb_frb(t[0], t[0]); eb_sub(t[13], t[0], p); eb_frb(t[0], t[8]); eb_frb(t[0], t[0]); eb_neg(t[0], t[0]); eb_add(t[14], t[0], p); eb_frb(t[0], t[19]); eb_frb(t[0], t[0]); eb_add(t[15], t[0], t[17]); eb_add(t[16], t[0], t[18]); eb_frb(t[0], t[26]); eb_frb(t[0], t[0]); eb_neg(t[0], t[0]); eb_sub(t[5], t[0], p); eb_add(t[6], t[0], p); eb_add(t[23], t[0], t[17]); eb_add(t[24], t[0], t[18]); eb_frb(t[0], t[25]); eb_frb(t[0], t[0]); eb_sub(t[21], t[0], p); eb_add(t[22], t[0], p); eb_frb(t[0], t[20]); eb_frb(t[0], t[0]); eb_add(t[29], t[0], p); eb_neg(t[29], t[29]); eb_frb(t[0], t[27]); eb_frb(t[0], t[0]); eb_add(t[30], t[0], p); eb_frb(t[0], t[7]); eb_frb(t[0], t[0]); eb_add(t[31], t[0], t[17]) eb_copy(t[0], p); break; #endif #if EB_DEPTH == 8 || EB_WIDTH == 8 /** * Formulas from http://eprint.iacr.org/2012/519 */ case 8: eb_frb(t[0], t[0]); eb_frb(t[0], t[0]); eb_neg(t[0], t[0]); eb_sub(t[45], t[0], p); eb_add(t[46], t[0], p); eb_frb(t[0], t[0]); if (u == 1) { eb_neg(t[0], t[0]); } eb_sub(t[43], t[0], p); eb_add(t[44], t[0], p); eb_frb(t[0], t[44]); eb_frb(t[0], t[0]); eb_sub(t[1], t[0], p); eb_add(t[2], t[0], p); eb_add(t[47], t[0], t[45]); eb_add(t[48], t[0], t[46]); eb_frb(t[0], t[46]); eb_frb(t[0], t[0]); eb_neg(t[0], t[0]); eb_sub(t[7], t[0], t[46]); eb_sub(t[8], t[0], t[45]); eb_frb(t[0], t[0]); if (u == -1) { eb_neg(t[0], t[0]); } eb_sub(t[3], t[0], p); eb_frb(t[0], t[1]); eb_frb(t[0], t[0]); eb_neg(t[0], t[0]); eb_add(t[55], t[0], t[45]); eb_add(t[56], t[0], t[46]); eb_sub(t[9], t[0], p); eb_add(t[10], t[0], p); eb_frb(t[0], t[0]); if (u == 1) { eb_neg(t[0], t[0]); } eb_add(t[4], t[0], p); eb_frb(t[0], t[47]); eb_frb(t[0], t[0]); eb_neg(t[0], t[0]); eb_sub(t[17], t[0], p); eb_add(t[18], t[0], p); eb_frb(t[0], t[8]); eb_frb(t[0], t[0]); eb_add(t[31], t[0], t[45]); eb_add(t[32], t[0], t[46]); eb_neg(t[0], t[0]); eb_sub(t[13], t[0], p); eb_add(t[14], t[0], p); eb_frb(t[0], t[0]); if (u == -1) { eb_neg(t[0], t[0]); } eb_sub(t[19], t[0], p); eb_frb(t[0], t[7]); eb_frb(t[0], t[0]); eb_frb(t[0], t[0]); if (u == -1) { eb_neg(t[0], t[0]); } eb_add(t[20], t[0], p); eb_frb(t[0], t[9]); eb_frb(t[0], t[0]); eb_sub(t[21], t[0], p); eb_add(t[22], t[0], p); eb_frb(t[0], t[2]); eb_frb(t[0], t[0]); eb_sub(t[25], t[0], p); eb_add(t[26], t[0], p); eb_frb(t[0], t[43]); eb_frb(t[0], t[0]); eb_neg(t[0], t[0]); eb_sub(t[33], t[0], p); eb_add(t[34], t[0], p); eb_frb(t[0], t[0]); if (u == -1) { eb_neg(t[0], t[0]); } eb_add(t[12], t[0], p); eb_frb(t[0], t[45]); eb_frb(t[0], t[0]); eb_sub(t[37], t[0], p); eb_add(t[38], t[0], p); eb_frb(t[0], t[0]); if (u == -1) { eb_neg(t[0], t[0]); } eb_sub(t[35], t[0], p); eb_add(t[36], t[0], p); eb_frb(t[0], t[38]); eb_frb(t[0], t[0]); eb_sub(t[41], t[0], p); eb_add(t[42], t[0], p); eb_neg(t[0], t[0]); eb_sub(t[39], t[0], t[46]); eb_sub(t[40], t[0], t[45]); eb_frb(t[0], t[37]); eb_frb(t[0], t[0]); eb_sub(t[5], t[0], p); eb_add(t[6], t[0], p); eb_frb(t[0], t[0]); if (u == -1) { eb_neg(t[0], t[0]); } eb_add(t[15], t[0], t[43]); eb_add(t[16], t[0], t[44]); eb_neg(t[0], t[0]); eb_sub(t[27], t[0], p); eb_add(t[28], t[0], p); eb_frb(t[0], t[36]); eb_frb(t[0], t[0]); eb_frb(t[0], t[0]); if (u == -1) { eb_neg(t[0], t[0]); } eb_sub(t[11], t[0], p); eb_frb(t[0], t[39]); eb_frb(t[0], t[0]); eb_add(t[0], t[0], p); eb_neg(t[49], t[0]); eb_frb(t[0], t[7]); eb_frb(t[0], t[0]); eb_neg(t[0], t[0]); eb_add(t[50], t[0], p); eb_frb(t[0], t[44]); eb_frb(t[0], t[0]); eb_frb(t[0], t[0]); if (u == 1) { eb_neg(t[0], t[0]); } eb_sub(t[51], t[0], p); eb_add(t[52], t[0], p); eb_frb(t[0], t[46]); eb_frb(t[0], t[0]); eb_neg(t[0], t[0]); eb_sub(t[53], t[0], p); eb_add(t[54], t[0], p); eb_frb(t[0], t[54]); eb_frb(t[0], t[0]); eb_add(t[23], t[0], t[45]); eb_add(t[24], t[0], t[46]); eb_frb(t[0], t[42]); eb_frb(t[0], t[0]); eb_sub(t[57], t[0], p); eb_frb(t[0], t[53]); eb_frb(t[0], t[0]); eb_neg(t[0], t[0]); eb_add(t[58], t[0], p); eb_frb(t[0], t[38]); eb_frb(t[0], t[0]); eb_frb(t[0], t[0]); if (u == -1) { eb_neg(t[0], t[0]); } eb_sub(t[59], t[0], p); eb_add(t[60], t[0], p); eb_frb(t[0], t[35]); eb_frb(t[0], t[0]); eb_sub(t[61], t[0], p); eb_add(t[62], t[0], p); eb_frb(t[0], t[47]); eb_frb(t[0], t[0]); eb_neg(t[0], t[0]); eb_add(t[63], t[0], t[45]); eb_frb(t[0], t[36]); eb_frb(t[0], t[0]); eb_neg(t[0], t[0]); eb_sub(t[29], t[0], p); eb_add(t[30], t[0], p); eb_copy(t[0], p); break; #endif } #if defined(EB_MIXED) if (w > 2) { eb_norm_sim(t + 1, (const eb_t *)t + 1, (1 << (w - 2)) - 1); } #endif } #endif /* EB_KBLTZ */ }