void ep_curve_set_endom(const fp_t b, const ep_t g, const bn_t r, const bn_t h, const fp_t beta, const bn_t l) { int bits = bn_bits(r); ctx_t *ctx = core_get(); ctx->ep_is_endom = 1; ctx->ep_is_super = 0; fp_zero(ctx->ep_a); fp_copy(ctx->ep_b, b); detect_opt(&(ctx->ep_opt_a), ctx->ep_a); detect_opt(&(ctx->ep_opt_b), ctx->ep_b); #if EP_MUL == LWNAF || EP_FIX == COMBS || EP_FIX == LWNAF || EP_SIM == INTER || !defined(STRIP) fp_copy(ctx->beta, beta); bn_gcd_ext_mid(&(ctx->ep_v1[1]), &(ctx->ep_v1[2]), &(ctx->ep_v2[1]), &(ctx->ep_v2[2]), l, r); /* l = v1[1] * v2[2] - v1[2] * v2[1], r = l / 2. */ bn_mul(&(ctx->ep_v1[0]), &(ctx->ep_v1[1]), &(ctx->ep_v2[2])); bn_mul(&(ctx->ep_v2[0]), &(ctx->ep_v1[2]), &(ctx->ep_v2[1])); bn_sub(&(ctx->ep_r), &(ctx->ep_v1[0]), &(ctx->ep_v2[0])); bn_hlv(&(ctx->ep_r), &(ctx->ep_r)); /* v1[0] = round(v2[2] * 2^|n| / l). */ bn_lsh(&(ctx->ep_v1[0]), &(ctx->ep_v2[2]), bits + 1); if (bn_sign(&(ctx->ep_v1[0])) == BN_POS) { bn_add(&(ctx->ep_v1[0]), &(ctx->ep_v1[0]), &(ctx->ep_r)); } else { bn_sub(&(ctx->ep_v1[0]), &(ctx->ep_v1[0]), &(ctx->ep_r)); } bn_dbl(&(ctx->ep_r), &(ctx->ep_r)); bn_div(&(ctx->ep_v1[0]), &(ctx->ep_v1[0]), &(ctx->ep_r)); if (bn_sign(&ctx->ep_v1[0]) == BN_NEG) { bn_add_dig(&(ctx->ep_v1[0]), &(ctx->ep_v1[0]), 1); } /* v2[0] = round(v1[2] * 2^|n| / l). */ bn_lsh(&(ctx->ep_v2[0]), &(ctx->ep_v1[2]), bits + 1); if (bn_sign(&(ctx->ep_v2[0])) == BN_POS) { bn_add(&(ctx->ep_v2[0]), &(ctx->ep_v2[0]), &(ctx->ep_r)); } else { bn_sub(&(ctx->ep_v2[0]), &(ctx->ep_v2[0]), &(ctx->ep_r)); } bn_div(&(ctx->ep_v2[0]), &(ctx->ep_v2[0]), &(ctx->ep_r)); if (bn_sign(&ctx->ep_v2[0]) == BN_NEG) { bn_add_dig(&(ctx->ep_v2[0]), &(ctx->ep_v2[0]), 1); } bn_neg(&(ctx->ep_v2[0]), &(ctx->ep_v2[0])); #endif ep_norm(&(ctx->ep_g), g); bn_copy(&(ctx->ep_r), r); bn_copy(&(ctx->ep_h), h); #if defined(EP_PRECO) ep_mul_pre((ep_t *)ep_curve_get_tab(), &(ctx->ep_g)); #endif }
void ep2_curve_get_vs(bn_t *v) { bn_t x, t; bn_null(x); bn_null(t); TRY { bn_new(x); bn_new(t); fp_param_get_var(x); bn_mul_dig(v[0], x, 3); bn_add_dig(v[0], v[0], 1); bn_copy(v[1], x); bn_copy(v[2], x); bn_copy(v[3], x); bn_sqr(x, x); bn_lsh(t, x, 1); bn_add(v[0], v[0], t); bn_add(v[3], v[3], t); bn_lsh(t, t, 1); bn_add(v[2], v[2], t); bn_lsh(t, t, 1); bn_add(v[1], v[1], t); fp_param_get_var(t); bn_mul(x, x, t); bn_mul_dig(t, x, 6); bn_add(v[2], v[2], t); bn_lsh(t, t, 1); bn_add(v[1], v[1], t); bn_neg(v[3], v[3]); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(x); bn_free(t); } }
status_t element_neg(element_t c, element_t a) { GroupType type = a->type; EXIT_IF_NOT_SAME(a, c); if(type == ZR) { bn_neg(c->bn, a->bn); } else if(type == G1) { g1_neg(c->g1, a->g1); } else if(type == G2) { g2_neg(c->g2, a->g2); } else if(type == GT) { gt_inv(c->gt, a->gt); } else { return ELEMENT_INVALID_TYPES; } return ELEMENT_OK; }
/** * Precomputes additional parameters for Koblitz curves used by the w-TNAF * multiplication algorithm. */ static void compute_kbltz(void) { int u, i; bn_t a, b, c; bn_null(a); bn_null(b); bn_null(c); TRY { bn_new(a); bn_new(b); bn_new(c); if (curve_opt_a == OPT_ZERO) { u = -1; } else { u = 1; } bn_set_dig(a, 2); bn_set_dig(b, 1); if (u == -1) { bn_neg(b, b); } for (i = 2; i <= FB_BITS; i++) { bn_copy(c, b); if (u == -1) { bn_neg(b, b); } bn_dbl(a, a); bn_sub(b, b, a); bn_copy(a, c); } bn_copy(&curve_vm, b); bn_zero(a); bn_set_dig(b, 1); for (i = 2; i <= FB_BITS; i++) { bn_copy(c, b); if (u == -1) { bn_neg(b, b); } bn_dbl(a, a); bn_sub(b, b, a); bn_add_dig(b, b, 1); bn_copy(a, c); } bn_copy(&curve_s0, b); bn_zero(a); bn_zero(b); for (i = 2; i <= FB_BITS; i++) { bn_copy(c, b); if (u == -1) { bn_neg(b, b); } bn_dbl(a, a); bn_sub(b, b, a); bn_sub_dig(b, b, 1); bn_copy(a, c); } bn_copy(&curve_s1, b); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(a); bn_free(b); bn_free(c); } }
/** * Divides two multiple precision integers, computing the quotient and the * remainder. * * @param[out] c - the quotient. * @param[out] d - the remainder. * @param[in] a - the dividend. * @param[in] b - the the divisor. */ static void bn_div_imp(bn_t c, bn_t d, const bn_t a, const bn_t b) { bn_t q, x, y, r; int sign; bn_null(q); bn_null(x); bn_null(y); bn_null(r); /* If a < b, we're done. */ if (bn_cmp_abs(a, b) == CMP_LT) { if (bn_sign(a) == BN_POS) { if (c != NULL) { bn_zero(c); } if (d != NULL) { bn_copy(d, a); } } else { if (c != NULL) { bn_set_dig(c, 1); if (bn_sign(b) == BN_POS) { bn_neg(c, c); } } if (d != NULL) { if (bn_sign(b) == BN_POS) { bn_add(d, a, b); } else { bn_sub(d, a, b); } } } return; } TRY { bn_new(x); bn_new(y); bn_new_size(q, a->used + 1); bn_new(r); bn_zero(q); bn_zero(r); bn_abs(x, a); bn_abs(y, b); /* Find the sign. */ sign = (a->sign == b->sign ? BN_POS : BN_NEG); bn_divn_low(q->dp, r->dp, x->dp, a->used, y->dp, b->used); /* We have the quotient in q and the remainder in r. */ if (c != NULL) { q->used = a->used - b->used + 1; q->sign = sign; bn_trim(q); if (bn_sign(a) == BN_NEG) { bn_sub_dig(c, q, 1); } else { bn_copy(c, q); } } if (d != NULL) { r->used = b->used; r->sign = a->sign; bn_trim(r); if (bn_sign(a) == BN_NEG) { bn_add(d, r, b); } else { bn_copy(d, r); } } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(r); bn_free(q); bn_free(x); bn_free(y); } }
void fp_param_get_var(bn_t x) { bn_t a; bn_null(a); TRY { bn_new(a); switch (fp_param_get()) { case BN_158: /* x = 4000000031. */ bn_set_2b(x, 38); bn_add_dig(x, x, 0x31); break; case BN_254: /* x = -4080000000000001. */ bn_set_2b(x, 62); bn_set_2b(a, 55); bn_add(x, x, a); bn_add_dig(x, x, 1); bn_neg(x, x); break; case BN_256: /* x = -600000000000219B. */ bn_set_2b(x, 62); bn_set_2b(a, 61); bn_add(x, x, a); bn_set_dig(a, 0x21); bn_lsh(a, a, 8); bn_add(x, x, a); bn_add_dig(x, x, 0x9B); bn_neg(x, x); break; case B24_477: /* x = -2^48 + 2^45 + 2^31 - 2^7. */ bn_set_2b(x, 48); bn_set_2b(a, 45); bn_sub(x, x, a); bn_set_2b(a, 31); bn_sub(x, x, a); bn_set_2b(a, 7); bn_add(x, x, a); bn_neg(x, x); break; case KSS_508: /* x = -(2^64 + 2^51 - 2^46 - 2^12). */ bn_set_2b(x, 64); bn_set_2b(a, 51); bn_add(x, x, a); bn_set_2b(a, 46); bn_sub(x, x, a); bn_set_2b(a, 12); bn_sub(x, x, a); bn_neg(x, x); break; case BN_638: /* x = 2^158 - 2^128 - 2^68 + 1. */ bn_set_2b(x, 158); bn_set_2b(a, 128); bn_sub(x, x, a); bn_set_2b(a, 68); bn_sub(x, x, a); bn_add_dig(x, x, 1); break; case B12_638: /* x = -2^107 + 2^105 + 2^93 + 2^5. */ bn_set_2b(x, 107); bn_set_2b(a, 105); bn_sub(x, x, a); bn_set_2b(a, 93); bn_sub(x, x, a); bn_set_2b(a, 5); bn_sub(x, x, a); bn_neg(x, x); break; case SS_1536: /* x = 2^255 + 2^41 + 1. */ bn_set_2b(x, 255); bn_set_2b(a, 41); bn_add(x, x, a); bn_add_dig(x, x, 1); break; default: THROW(ERR_NO_VALID); break; } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(a); } }
void fp_param_get_sps(int *s, int *len) { bn_t a; bn_null(a); if (*len < MAX_TERMS) { THROW(ERR_NO_BUFFER); } TRY { bn_new(a); *len = 0; switch (fp_param_get()) { case BN_158: case BN_254: case BN_256: fp_param_get_var(a); if (bn_sign(a) == BN_NEG) { bn_neg(a, a); } *len = bn_ham(a); for (int i = 0, j = 0; j < bn_bits(a); j++) { if (bn_test_bit(a, j)) { s[i++] = j; } } break; case B24_477: s[0] = 7; s[1] = -31; s[2] = -45; s[3] = 48; *len = 4; break; case KSS_508: s[0] = -12; s[1] = -46; s[2] = 51; s[3] = 64; *len = 4; break; case BN_638: s[0] = 0; s[1] = -68; s[2] = -128; s[3] = 158; *len = 4; break; case B12_638: s[0] = -5; s[1] = -93; s[2] = -105; s[3] = 107; *len = 4; break; case SS_1536: s[0] = 0; s[1] = 41; s[2] = 255; *len = 3; break; default: THROW(ERR_NO_VALID); break; } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(a); } }