/** * Multiplies a binary elliptic curve point by an integer using the w-NAF mixed coordinate * method. * * @param[out] r - the result. * @param[in] t - the precomputed table. * @param[in] k - the integer. */ static void ed_mul_fix_plain_mixed(ed_t r, const ed_t *t, const bn_t k) { int l, i, n; int8_t naf[FP_BITS + 1], *_k; /* Compute the w-TNAF representation of k. */ l = FP_BITS + 1; bn_rec_naf(naf, &l, k, ED_DEPTH); _k = naf + l - 1; ed_set_infty(r); for (i = l - 1; i >= 0; i--, _k--) { n = *_k; if (n == 0) { /* doubling is followed by another doubling */ if (i > 0) { ed_dbl_short(r, r); } else { /* use full extended coordinate doubling for last step */ ed_dbl(r, r); } } else { ed_dbl(r, r); if (n > 0) { ed_add(r, r, t[n / 2]); } else if (n < 0) { ed_sub(r, r, t[-n / 2]); } } } /* Convert r to affine coordinates. */ ed_norm(r, r); }
/** * 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); } }
void ep2_mul_fix_nafwi(ep2_t r, ep2_t *t, bn_t k) { int i, j, l, d, m; ep2_t a; int8_t naf[2 * FP_BITS + 1]; char w; ep2_null(a); TRY { ep2_new(a); ep2_set_infty(r); ep2_set_infty(a); l = 2 * FP_BITS + 1; bn_rec_naf(naf, &l, k, 2); d = ((l % EP_DEPTH) == 0 ? (l / EP_DEPTH) : (l / EP_DEPTH) + 1); for (i = 0; i < d; i++) { w = 0; for (j = EP_DEPTH - 1; j >= 0; j--) { if (i * EP_DEPTH + j < l) { w = (char)(w << 1); w = (char)(w + naf[i * EP_DEPTH + j]); } } naf[i] = w; } if (EP_DEPTH % 2 == 0) { m = ((1 << (EP_DEPTH + 1)) - 2) / 3; } else { m = ((1 << (EP_DEPTH + 1)) - 1) / 3; } for (j = m; j >= 1; j--) { for (i = 0; i < d; i++) { if (naf[i] == j) { ep2_add(a, a, t[i]); } if (naf[i] == -j) { ep2_sub(a, a, t[i]); } } ep2_add(r, r, a); } ep2_norm(r, r); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { ep2_free(a); } }
/** * Multiplies a binary elliptic curve point by an integer using the w-NAF * method. * * @param[out] r - the result. * @param[in] t - the precomputed table. * @param[in] k - the integer. */ static void ed_mul_fix_plain(ed_t r, const ed_t *t, const bn_t k) { int l, i, n; int8_t naf[FP_BITS + 1], *_k; /* Compute the w-TNAF representation of k. */ l = FP_BITS + 1; bn_rec_naf(naf, &l, k, ED_DEPTH); _k = naf + l - 1; ed_set_infty(r); for (i = l - 1; i >= 0; i--, _k--) { ed_dbl(r, r); n = *_k; if (n > 0) { ed_add(r, r, t[n / 2]); } if (n < 0) { ed_sub(r, r, t[-n / 2]); } } /* Convert r to affine coordinates. */ ed_norm(r, r); }
/** * 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]); } } }
/** * Multiplies and adds two prime 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 the precomputed table. */ void ep_mul_sim_endom(ep_t r, const ep_t p, const bn_t k, const ep_t q, const bn_t m, const ep_t *t) { int len, len0, len1, len2, len3, i, n, sk0, sk1, sl0, sl1, w, g = 0; int8_t naf0[FP_BITS + 1], naf1[FP_BITS + 1], *t0, *t1; int8_t naf2[FP_BITS + 1], naf3[FP_BITS + 1], *t2, *t3; bn_t k0, k1, l0, l1; bn_t ord, v1[3], v2[3]; ep_t u; ep_t tab0[1 << (EP_WIDTH - 2)]; ep_t tab1[1 << (EP_WIDTH - 2)]; bn_null(ord); bn_null(k0); bn_null(k1); bn_null(l0); bn_null(l1); ep_null(u); for (i = 0; i < (1 << (EP_WIDTH - 2)); i++) { ep_null(tab0[i]); ep_null(tab1[i]); } bn_new(ord); bn_new(k0); bn_new(k1); bn_new(l0); bn_new(l1); ep_new(u); TRY { for (i = 0; i < 3; i++) { bn_null(v1[i]); bn_null(v2[i]); bn_new(v1[i]); bn_new(v2[i]); } ep_curve_get_ord(ord); ep_curve_get_v1(v1); ep_curve_get_v2(v2); bn_rec_glv(k0, k1, k, ord, (const bn_t *)v1, (const bn_t *)v2); sk0 = bn_sign(k0); sk1 = bn_sign(k1); bn_abs(k0, k0); bn_abs(k1, k1); bn_rec_glv(l0, l1, m, ord, (const bn_t *)v1, (const bn_t *)v2); sl0 = bn_sign(l0); sl1 = bn_sign(l1); bn_abs(l0, l0); bn_abs(l1, l1); g = (t == NULL ? 0 : 1); if (!g) { for (i = 0; i < (1 << (EP_WIDTH - 2)); i++) { ep_new(tab0[i]); } ep_tab(tab0, p, EP_WIDTH); t = (const ep_t *)tab0; } /* Prepare the precomputation table. */ for (i = 0; i < (1 << (EP_WIDTH - 2)); i++) { ep_new(tab1[i]); } /* Compute the precomputation table. */ ep_tab(tab1, q, EP_WIDTH); /* Compute the w-TNAF representation of k and l */ if (g) { w = EP_DEPTH; } else { w = EP_WIDTH; } len0 = len1 = len2 = len3 = FP_BITS + 1; bn_rec_naf(naf0, &len0, k0, w); bn_rec_naf(naf1, &len1, k1, w); bn_rec_naf(naf2, &len2, l0, EP_WIDTH); bn_rec_naf(naf3, &len3, l1, EP_WIDTH); len = MAX(MAX(len0, len1), MAX(len2, len3)); t0 = naf0 + len - 1; t1 = naf1 + len - 1; t2 = naf2 + len - 1; t3 = naf3 + len - 1; for (i = len0; i < len; i++) { naf0[i] = 0; } for (i = len1; i < len; i++) { naf1[i] = 0; } for (i = len2; i < len; i++) { naf2[i] = 0; } for (i = len3; i < len; i++) { naf3[i] = 0; } ep_set_infty(r); for (i = len - 1; i >= 0; i--, t0--, t1--, t2--, t3--) { ep_dbl(r, r); n = *t0; if (n > 0) { if (sk0 == BN_POS) { ep_add(r, r, t[n / 2]); } else { ep_sub(r, r, t[n / 2]); } } if (n < 0) { if (sk0 == BN_POS) { ep_sub(r, r, t[-n / 2]); } else { ep_add(r, r, t[-n / 2]); } } n = *t1; if (n > 0) { ep_copy(u, t[n / 2]); fp_mul(u->x, u->x, ep_curve_get_beta()); if (sk1 == BN_NEG) { ep_neg(u, u); } ep_add(r, r, u); } if (n < 0) { ep_copy(u, t[-n / 2]); fp_mul(u->x, u->x, ep_curve_get_beta()); if (sk1 == BN_NEG) { ep_neg(u, u); } ep_sub(r, r, u); } n = *t2; if (n > 0) { if (sl0 == BN_POS) { ep_add(r, r, tab1[n / 2]); } else { ep_sub(r, r, tab1[n / 2]); } } if (n < 0) { if (sl0 == BN_POS) { ep_sub(r, r, tab1[-n / 2]); } else { ep_add(r, r, tab1[-n / 2]); } } n = *t3; if (n > 0) { ep_copy(u, tab1[n / 2]); fp_mul(u->x, u->x, ep_curve_get_beta()); if (sl1 == BN_NEG) { ep_neg(u, u); } ep_add(r, r, u); } if (n < 0) { ep_copy(u, tab1[-n / 2]); fp_mul(u->x, u->x, ep_curve_get_beta()); if (sl1 == BN_NEG) { ep_neg(u, u); } ep_sub(r, r, u); } } /* Convert r to affine coordinates. */ ep_norm(r, r); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(ord); bn_free(k0); bn_free(k1); bn_free(l0); bn_free(l1); ep_free(u); if (!g) { for (i = 0; i < 1 << (EP_WIDTH - 2); i++) { ep_free(tab0[i]); } } /* Free the precomputation tables. */ for (i = 0; i < 1 << (EP_WIDTH - 2); i++) { ep_free(tab1[i]); } for (i = 0; i < 3; i++) { bn_free(v1[i]); bn_free(v2[i]); } } }
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]); } } }
static void ed_mul_naf_imp(ed_t r, const ed_t p, const bn_t k) { int l, i, n; int8_t naf[RLC_FP_BITS + 1]; ed_t t[1 << (ED_WIDTH - 2)]; if (bn_is_zero(k)) { ed_set_infty(r); return; } TRY { /* Prepare the precomputation table. */ for (i = 0; i < (1 << (ED_WIDTH - 2)); i++) { ed_null(t[i]); ed_new(t[i]); } /* Compute the precomputation table. */ ed_tab(t, p, ED_WIDTH); /* Compute the w-NAF representation of k. */ l = sizeof(naf); bn_rec_naf(naf, &l, k, EP_WIDTH); ed_set_infty(r); for (i = l - 1; i > 0; i--) { n = naf[i]; if (n == 0) { /* This point will be doubled in the previous iteration. */ r->norm = 2; ed_dbl(r, r); } else { ed_dbl(r, r); if (n > 0) { ed_add(r, r, t[n / 2]); } else if (n < 0) { ed_sub(r, r, t[-n / 2]); } } } /* Last iteration. */ n = naf[0]; ed_dbl(r, r); if (n > 0) { ed_add(r, r, t[n / 2]); } else if (n < 0) { ed_sub(r, r, t[-n / 2]); } /* Convert r to affine coordinates. */ ed_norm(r, r); if (bn_sign(k) == RLC_NEG) { ed_neg(r, r); } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { /* Free the precomputation table. */ for (i = 0; i < (1 << (ED_WIDTH - 2)); i++) { ed_free(t[i]); } } }
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]); } }