void eb_pck(eb_t r, const eb_t p) { if (eb_curve_is_super()) { /* z3 = y1/c. */ fb_inv(r->z, eb_curve_get_c()); fb_mul(r->z, r->z, p->y); /* x3 = x1. */ fb_copy(r->x, p->x); /* y3 = b(y1/c). */ fb_set_dig(r->y, fb_get_bit(r->z, 0)); /* z3 = 1. */ fb_set_dig(r->z, 1); } else { /* z3 = y1/x1. */ fb_inv(r->z, p->x); fb_mul(r->z, r->z, p->y); /* x3 = x1. */ fb_copy(r->x, p->x); /* y3 = b(y1/x1). */ fb_set_dig(r->y, fb_get_bit(r->z, 0)); /* z3 = 1. */ fb_set_dig(r->z, 1); } r->norm = 1; }
int eb_upk(eb_t r, const eb_t p) { fb_t t0, t1; int res = 0; fb_null(t0); fb_null(t1); TRY { fb_new(t0); fb_new(t1); eb_rhs(t1, p); if (eb_curve_is_super()) { /* t0 = c^2. */ fb_sqr(t0, eb_curve_get_c()); /* t0 = 1/c^2. */ fb_inv(t0, t0); /* t0 = t1/c^2. */ fb_mul(t0, t0, t1); res = (fb_trc(t0) == 0); /* Solve t1^2 + t1 = t0. */ fb_slv(t1, t0); /* If this is not the correct solution, try the other. */ if (fb_get_bit(t1, 0) != fb_get_bit(p->y, 0)) { fb_add_dig(t1, t1, 1); } /* x3 = x1, y3 = t1 * c, z3 = 1. */ fb_mul(r->y, t1, eb_curve_get_c()); } else { fb_sqr(t0, p->x); /* t0 = 1/x1^2. */ fb_inv(t0, t0); /* t0 = t1/x1^2. */ fb_mul(t0, t0, t1); res = (fb_trc(t0) == 0); /* Solve t1^2 + t1 = t0. */ fb_slv(t1, t0); /* If this is not the correct solution, try the other. */ if (fb_get_bit(t1, 0) != fb_get_bit(p->y, 0)) { fb_add_dig(t1, t1, 1); } /* x3 = x1, y3 = t1 * x1, z3 = 1. */ fb_mul(r->y, t1, p->x); } fb_copy(r->x, p->x); fb_set_dig(r->z, 1); r->norm = 1; } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { fb_free(t0); fb_free(t1); } return res; }
/** * Multiplies two binary field elements using shift-and-add multiplication. * * @param c - the result. * @param a - the first binary field element. * @param b - the second binary field element. * @param size - the number of digits to multiply. */ static void fb_mul_basic_imp(dig_t *c, const dig_t *a, const dig_t *b, int size) { int i; dv_t s; dv_null(s); TRY { /* We need a temporary variable so that c can be a or b. */ dv_new(s); dv_zero(s, 2 * FB_DIGS); dv_copy(s, b, size); dv_zero(c, 2 * size); if (a[0] & 1) { dv_copy(c, b, size); } for (i = 1; i <= (FB_DIGIT * size) - 1; i++) { fb_lsh1_low(s, s); fb_rdc(s, s); if (fb_get_bit(a, i)) { fb_add(c, c, s); } } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { dv_free(s); } }
void fb_rdc_basic(fb_t c, dv_t a) { int j, k; dig_t *tmpa; dv_t r; dv_null(r); TRY { dv_new(r); tmpa = a + FB_DIGS; /* First reduce the high part. */ for (int i = fb_bits(tmpa) - 1; i >= 0; i--) { if (fb_get_bit(tmpa, i)) { SPLIT(k, j, i - FB_BITS, FB_DIG_LOG); if (k <= 0) { fb_addd_low(tmpa + j, tmpa + j, fb_poly_get(), FB_DIGS); } else { r[FB_DIGS] = fb_lshb_low(r, fb_poly_get(), k); fb_addd_low(tmpa + j, tmpa + j, r, FB_DIGS + 1); } } } for (int i = fb_bits(a) - 1; i >= FB_BITS; i--) { if (fb_get_bit(a, i)) { SPLIT(k, j, i - FB_BITS, FB_DIG_LOG); if (k == 0) { fb_addd_low(a + j, a + j, fb_poly_get(), FB_DIGS); } else { r[FB_DIGS] = fb_lshb_low(r, fb_poly_get(), k); fb_addd_low(a + j, a + j, r, FB_DIGS + 1); } } } fb_copy(c, a); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { fb_free(r); } }
dig_t fb_trcn_low(const dig_t *a) { int ta, tb, tc; dig_t r; fb_poly_get_trc(&ta, &tb, &tc); #if ALLOC == AUTO r = fb_get_bit(a, ta); if (tb != -1) { r ^= fb_get_bit(a, tb); } if (tc != -1) { r ^= fb_get_bit(a, tc); } #else r = fb_get_bit((const fb_t)a, ta); if (tb != -1) { r ^= fb_get_bit((const fb_t)a, tb); } if (tc != -1) { r ^= fb_get_bit((const fb_t)a, tc); } #endif return r; }
void eb_pck(eb_t r, const eb_t p) { /* z3 = y1/x1. */ fb_inv(r->z, p->x); fb_mul(r->z, r->z, p->y); /* x3 = x1. */ fb_copy(r->x, p->x); /* y3 = b(y1/x1). */ fb_set_dig(r->y, fb_get_bit(r->z, 0)); /* z3 = 1. */ fb_set_dig(r->z, 1); r->norm = 1; }
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 fb_mul_basic(fb_t c, const fb_t a, const fb_t b) { int i; dv_t s; fb_t t; dv_null(s); fb_null(t); TRY { /* We need a temporary variable so that c can be a or b. */ fb_new(t); dv_new(s); fb_zero(t); dv_zero(s + FB_DIGS, FB_DIGS); fb_copy(s, b); if (a[0] & 1) { fb_copy(t, b); } for (i = 1; i < FB_BITS; i++) { /* We are already shifting a temporary value, so this is more efficient * than calling fb_lsh(). */ s[FB_DIGS] = fb_lsh1_low(s, s); fb_rdc(s, s); if (fb_get_bit(a, i)) { fb_add(t, t, s); } } if (fb_bits(t) > FB_BITS) { fb_poly_add(c, t); } else { fb_copy(c, t); } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { fb_free(t); fb_free(s); } }