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 i, u_i, len, offset; int8_t jsf[2 * (RLC_FB_BITS + 1)]; 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 { for (i = 0; i < 5; i++) { eb_null(t[i]); eb_new(t[i]); } eb_set_infty(t[0]); eb_copy(t[1], q); if (bn_sign(m) == RLC_NEG) { eb_neg(t[1], t[1]); } eb_copy(t[2], p); if (bn_sign(k) == RLC_NEG) { eb_neg(t[2], t[2]); } eb_add(t[3], t[2], t[1]); eb_sub(t[4], t[2], t[1]); #if defined(EB_MIXED) eb_norm_sim(t + 3, (const eb_t*)(t + 3), 2); #endif len = 2 * (RLC_FB_BITS + 1); bn_rec_jsf(jsf, &len, k, m); eb_set_infty(r); offset = RLC_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_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 */ }