/** * Assigns the prime field modulus. * * @param[in] p - the new prime field modulus. */ static void fp_prime_set(const bn_t p) { dv_t s, q; bn_t t; ctx_t *ctx = core_get(); if (p->used != FP_DIGS) { THROW(ERR_NO_VALID); } dv_null(s); bn_null(t); dv_null(q); TRY { dv_new(s); bn_new(t); dv_new(q); bn_copy(&(ctx->prime), p); bn_mod_dig(&(ctx->mod8), &(ctx->prime), 8); switch (ctx->mod8) { case 3: case 7: ctx->qnr = -1; /* The current code for extensions of Fp^3 relies on qnr being * also a cubic non-residue. */ ctx->cnr = 0; break; case 1: case 5: ctx->qnr = ctx->cnr = -2; break; default: ctx->qnr = ctx->cnr = 0; THROW(ERR_NO_VALID); break; } #ifdef FP_QNRES if (ctx->mod8 != 3) { THROW(ERR_NO_VALID); } #endif #if FP_RDC == MONTY || !defined(STRIP) bn_mod_pre_monty(t, &(ctx->prime)); ctx->u = t->dp[0]; dv_zero(s, 2 * FP_DIGS); s[2 * FP_DIGS] = 1; dv_zero(q, 2 * FP_DIGS + 1); dv_copy(q, ctx->prime.dp, FP_DIGS); bn_divn_low(t->dp, ctx->conv.dp, s, 2 * FP_DIGS + 1, q, FP_DIGS); ctx->conv.used = FP_DIGS; bn_trim(&(ctx->conv)); bn_set_dig(&(ctx->one), 1); bn_lsh(&(ctx->one), &(ctx->one), ctx->prime.used * BN_DIGIT); bn_mod(&(ctx->one), &(ctx->one), &(ctx->prime)); #endif fp_prime_calc(); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(t); dv_free(s); dv_free(q); } }
/** * 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_sign(b)) { if (c != NULL) { bn_zero(c); } if (d != NULL) { bn_copy(d, a); } } else { if (c != NULL) { bn_set_dig(c, 1); bn_neg(c, c); } if (d != NULL) { bn_add(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_sign(b)) { bn_copy(c, q); } else { bn_sub_dig(c, q, 1); } } if (d != NULL) { r->used = b->used; r->sign = b->sign; bn_trim(r); if (bn_sign(a) == bn_sign(b)) { bn_copy(d, r); } else { bn_sub(d, b, r); } } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(r); bn_free(q); bn_free(x); bn_free(y); } }