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; }
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_sub_basic(eb_t r, const eb_t p, const eb_t q) { eb_t t; eb_null(t); if (p == q) { eb_set_infty(r); return; } TRY { eb_new(t); eb_neg_basic(t, q); eb_add_basic(r, p, t); r->norm = 1; } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { eb_free(t); } }
void eb_mul_sim_gen(eb_t r, const bn_t k, const eb_t q, const bn_t m) { eb_t g; eb_null(g); if (bn_is_zero(k)) { eb_mul(r, q, m); return; } if (bn_is_zero(m) || eb_is_infty(q)) { eb_mul_gen(r, k); return; } TRY { eb_new(g); eb_curve_get_gen(g); #if defined(EB_KBLTZ) #if EB_SIM == INTER && EB_FIX == LWNAF && defined(EB_PRECO) if (eb_curve_is_kbltz()) { eb_mul_sim_kbltz(r, g, k, q, m, eb_curve_get_tab()); } #else if (eb_curve_is_kbltz()) { eb_mul_sim(r, g, k, q, m); } #endif #endif #if defined(EB_PLAIN) #if EB_SIM == INTER && EB_FIX == LWNAF && defined(EB_PRECO) if (!eb_curve_is_kbltz()) { eb_mul_sim_plain(r, g, k, q, m, eb_curve_get_tab()); } #else if (!eb_curve_is_kbltz()) { eb_mul_sim(r, g, k, q, m); } #endif #endif } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { eb_free(g); } }
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); } }
/** * 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_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]); } } }
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_param_set(int param) { char str[2 * FB_BYTES + 1]; fb_t a, b; eb_t g; bn_t r; bn_t h; fb_null(a); fb_null(b); eb_null(g); bn_null(r); bn_null(h); TRY { fb_new(a); fb_new(b); eb_new(g); bn_new(r); bn_new(h); core_get()->eb_id = 0; switch (param) { #if defined(EB_PLAIN) && FB_POLYN == 163 case NIST_B163: ASSIGN(NIST_B163, NIST_163); break; #endif #if defined(EB_KBLTZ) && FB_POLYN == 163 case NIST_K163: ASSIGN(NIST_K163, NIST_163); break; #endif #if defined(EB_PLAIN) && FB_POLYN == 233 case NIST_B233: ASSIGN(NIST_B233, NIST_233); break; #endif #if defined(EB_KBLTZ) && FB_POLYN == 233 case NIST_K233: ASSIGN(NIST_K233, NIST_233); break; #endif #if defined(EB_KBLTZ) && FB_POLYN == 239 case SECG_K239: ASSIGN(SECG_K239, SECG_239); break; #endif #if defined(EB_PLAIN) && FB_POLYN == 251 case EBACS_B251: ASSIGN(EBACS_B251, PENTA_251); break; #endif #if defined(EB_PLAIN) && FB_POLYN == 257 case HALVE_B257: ASSIGN(HALVE_B257, TRINO_257); break; #endif #if defined(EB_PLAIN) && FB_POLYN == 283 case NIST_B283: ASSIGN(NIST_B283, NIST_283); break; #endif #if defined(EB_KBLTZ) && FB_POLYN == 283 case NIST_K283: ASSIGN(NIST_K283, NIST_283); break; #endif #if defined(EB_PLAIN) && FB_POLYN == 409 case NIST_B409: ASSIGN(NIST_B409, NIST_409); break; #endif #if defined(EB_KBLTZ) && FB_POLYN == 409 case NIST_K409: ASSIGN(NIST_K409, NIST_409); break; #endif #if defined(EB_PLAIN) && FB_POLYN == 571 case NIST_B571: ASSIGN(NIST_B571, NIST_571); break; #endif #if defined(EB_KBLTZ) && FB_POLYN == 571 case NIST_K571: ASSIGN(NIST_K571, NIST_571); break; #endif default: (void)str; THROW(ERR_NO_VALID); break; } fb_zero(g->z); fb_set_bit(g->z, 0, 1); g->norm = 1; eb_curve_set(a, b, g, r, h); core_get()->eb_id = param; } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { fb_free(a); fb_free(b); eb_free(g); bn_free(r); bn_free(h); } }
void eb_param_set(int param) { int super = 0; int ordin = 0; int kbltz = 0; char str[2 * FB_BYTES + 1]; fb_t a, b, c; eb_t g; bn_t r; bn_t h; fb_null(a); fb_null(b); fb_null(c); eb_null(g); bn_null(r); bn_null(h); TRY { fb_new(a); fb_new(b); fb_new(c); eb_new(g); bn_new(r); bn_new(h); core_get()->eb_id = 0; switch (param) { #if defined(EB_ORDIN) && FB_POLYN == 163 case NIST_B163: ASSIGN(NIST_B163, NIST_163); ordin = 1; break; #endif #if defined(EB_KBLTZ) && FB_POLYN == 163 case NIST_K163: ASSIGN(NIST_K163, NIST_163); kbltz = 1; break; #endif #if defined(EB_ORDIN) && FB_POLYN == 233 case NIST_B233: ASSIGN(NIST_B233, NIST_233); ordin = 1; break; #endif #if defined(EB_KBLTZ) && FB_POLYN == 233 case NIST_K233: ASSIGN(NIST_K233, NIST_233); kbltz = 1; break; #endif #if defined(EB_ORDIN) && FB_POLYN == 251 case EBACS_B251: ASSIGN(EBACS_B251, PENTA_251); ordin = 1; break; #endif #if defined(EB_ORDIN) && FB_POLYN == 257 case HALVE_B257: ASSIGN(HALVE_B257, TRINO_257); ordin = 1; break; #endif #if defined(EB_ORDIN) && FB_POLYN == 283 case NIST_B283: ASSIGN(NIST_B283, NIST_283); ordin = 1; break; #endif #if defined(EB_KBLTZ) && FB_POLYN == 283 case NIST_K283: ASSIGN(NIST_K283, NIST_283); kbltz = 1; break; #endif #if defined(EB_KBLTZ) && FB_POLYN == 239 case SECG_K239: ASSIGN(SECG_K239, SECG_239); kbltz = 1; break; #endif #if defined(EB_ORDIN) && FB_POLYN == 409 case NIST_B409: ASSIGN(NIST_B409, NIST_409); ordin = 1; break; #endif #if defined(EB_KBLTZ) && FB_POLYN == 409 case NIST_K409: ASSIGN(NIST_K409, NIST_409); kbltz = 1; break; #endif #if defined(EB_ORDIN) && FB_POLYN == 571 case NIST_B571: ASSIGN(NIST_B571, NIST_571); ordin = 1; break; #endif #if defined(EB_KBLTZ) && FB_POLYN == 571 case NIST_K571: ASSIGN(NIST_K571, NIST_571); kbltz = 1; break; #endif #if defined(EB_SUPER) && FB_POLYN == 271 case ETAT_P271: ASSIGNS(ETAT_P271, PENTA_271); super = 1; break; case ETAT_T271: ASSIGNS(ETAT_T271, TRINO_271); super = 1; break; #endif #if defined(EB_SUPER) && FB_POLYN == 353 case ETAT_S353: ASSIGNS(ETAT_S353, TRINO_353); super = 1; break; #endif #if defined(EB_SUPER) && FB_POLYN == 1223 case ETAT_S1223: ASSIGNS(ETAT_S1223, TRINO_1223); super = 1; break; #endif default: (void)str; THROW(ERR_NO_VALID); break; } /* Do not generate warnings. */ (void)kbltz; (void)ordin; (void)super; (void)c; fb_zero(g->z); fb_set_bit(g->z, 0, 1); g->norm = 1; #if defined(EB_ORDIN) if (ordin) { eb_curve_set_ordin(a, b, g, r, h); core_get()->eb_id = param; } #endif #if defined(EB_KBLTZ) if (kbltz) { eb_curve_set_kbltz(a, g, r, h); core_get()->eb_id = param; } #elif defined(EB_ORDIN) if (kbltz) { eb_curve_set_ordin(a, b, g, r, h); core_get()->eb_id = param; } #endif #if defined(EB_SUPER) if (super) { eb_curve_set_super(a, b, c, g, r, h); core_get()->eb_id = param; } #endif } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { fb_free(a); fb_free(b); fb_free(c); eb_free(g); bn_free(r); bn_free(h); } }