int cp_bdpe_gen(bdpe_t pub, bdpe_t prv, dig_t block, int bits) { bn_t t, r; int result = STS_OK; bn_null(t); bn_null(r); TRY { bn_new(t); bn_new(r); prv->t = pub->t = block; /* Make sure that block size is prime. */ bn_set_dig(t, block); if (bn_is_prime_basic(t) == 0) { THROW(ERR_NO_VALID); } /* Generate prime q such that gcd(block, (q - 1)) = 1. */ do { bn_gen_prime(prv->q, bits / 2); bn_sub_dig(prv->q, prv->q, 1); bn_gcd_dig(t, prv->q, block); bn_add_dig(prv->q, prv->q, 1); } while (bn_cmp_dig(t, 1) != CMP_EQ); /* Generate different primes p and q. */ do { /* Compute p = block * (x * block + b) + 1, 0 < b < block random. */ bn_rand(prv->p, BN_POS, bits / 2 - 2 * util_bits_dig(block)); bn_mul_dig(prv->p, prv->p, block); bn_rand(t, BN_POS, util_bits_dig(block)); bn_add_dig(prv->p, prv->p, t->dp[0]); /* We know that block divides (p-1). */ bn_gcd_dig(t, prv->p, block); bn_mul_dig(prv->p, prv->p, block); bn_add_dig(prv->p, prv->p, 1); } while (bn_cmp_dig(t, 1) != CMP_EQ || bn_is_prime(prv->p) == 0); /* Compute t = (p-1)*(q-1). */ bn_sub_dig(prv->q, prv->q, 1); bn_sub_dig(prv->p, prv->p, 1); bn_mul(t, prv->p, prv->q); bn_div_dig(t, t, block); /* Restore factors p and q and compute n = p * q. */ bn_add_dig(prv->p, prv->p, 1); bn_add_dig(prv->q, prv->q, 1); bn_mul(pub->n, prv->p, prv->q); bn_copy(prv->n, pub->n); /* Select random y such that y^{(p-1)(q-1)}/block \neq 1 mod N. */ do { bn_rand(pub->y, BN_POS, bits); bn_mxp(r, pub->y, t, pub->n); } while (bn_cmp_dig(r, 1) == CMP_EQ); bn_copy(prv->y, pub->y); } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(t); bn_free(r); } return result; }
int cp_rsa_gen_quick(rsa_t pub, rsa_t prv, int bits) { bn_t t, r; int result = STS_OK; if (pub == NULL || prv == NULL || bits == 0) { return STS_ERR; } bn_null(t); bn_null(r); TRY { bn_new(t); bn_new(r); /* Generate different primes p and q. */ do { bn_gen_prime(prv->p, bits / 2); bn_gen_prime(prv->q, bits / 2); } while (bn_cmp(prv->p, prv->q) == CMP_EQ); /* Swap p and q so that p is smaller. */ if (bn_cmp(prv->p, prv->q) == CMP_LT) { bn_copy(t, prv->p); bn_copy(prv->p, prv->q); bn_copy(prv->q, t); } /* n = pq. */ bn_mul(pub->n, prv->p, prv->q); bn_copy(prv->n, pub->n); bn_sub_dig(prv->p, prv->p, 1); bn_sub_dig(prv->q, prv->q, 1); /* phi(n) = (p - 1)(q - 1). */ bn_mul(t, prv->p, prv->q); bn_set_2b(pub->e, 16); bn_add_dig(pub->e, pub->e, 1); /* d = e^(-1) mod phi(n). */ bn_gcd_ext(r, prv->d, NULL, pub->e, t); if (bn_sign(prv->d) == BN_NEG) { bn_add(prv->d, prv->d, t); } if (bn_cmp_dig(r, 1) == CMP_EQ) { /* dP = d mod (p - 1). */ bn_mod(prv->dp, prv->d, prv->p); /* dQ = d mod (q - 1). */ bn_mod(prv->dq, prv->d, prv->q); bn_add_dig(prv->p, prv->p, 1); bn_add_dig(prv->q, prv->q, 1); /* qInv = q^(-1) mod p. */ bn_gcd_ext(r, prv->qi, NULL, prv->q, prv->p); if (bn_sign(prv->qi) == BN_NEG) { bn_add(prv->qi, prv->qi, prv->p); } result = STS_OK; } } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(t); bn_free(r); } return result; }
/** * 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); } }
/** * 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); } }
int bn_is_prime_solov(const bn_t a) { bn_t t0, t1, t2; int i, result; bn_null(t0); bn_null(t1); bn_null(t2); result = 1; TRY { bn_new(t0); bn_new(t1); bn_new(t2); for (i = 0; i < 100; i++) { /* Generate t0, 2 <= t0, <= a - 2. */ do { bn_rand(t0, BN_POS, bn_bits(a)); bn_mod(t0, t0, a); } while (bn_cmp_dig(t0, 2) == CMP_LT); /* t2 = a - 1. */ bn_copy(t2, a); bn_sub_dig(t2, t2, 1); /* t1 = (a - 1)/2. */ bn_rsh(t1, t2, 1); /* t1 = t0^(a - 1)/2 mod a. */ #if BN_MOD != PMERS bn_mxp(t1, t0, t1, a); #else bn_exp(t1, t0, t1, a); #endif /* If t1 != 1 and t1 != n - 1 return 0 */ if (bn_cmp_dig(t1, 1) != CMP_EQ && bn_cmp(t1, t2) != CMP_EQ) { result = 0; break; } /* t2 = (t0|a). */ bn_smb_jac(t2, t0, a); if (bn_sign(t2) == BN_NEG) { bn_add(t2, t2, a); } /* If t1 != t2 (mod a) return 0. */ bn_mod(t1, t1, a); bn_mod(t2, t2, a); if (bn_cmp(t1, t2) != CMP_EQ) { result = 0; break; } } } CATCH_ANY { result = 0; THROW(ERR_CAUGHT); } FINALLY { bn_free(t0); bn_free(t1); bn_free(t2); } return result; }
void bn_gen_prime_stron(bn_t a, int bits) { dig_t i, j; int found, k; bn_t r, s, t; bn_null(r); bn_null(s); bn_null(t); TRY { bn_new(r); bn_new(s); bn_new(t); do { do { /* Generate two large primes r and s. */ bn_rand(s, BN_POS, bits / 2 - BN_DIGIT / 2); bn_rand(t, BN_POS, bits / 2 - BN_DIGIT / 2); } while (!bn_is_prime(s) || !bn_is_prime(t)); found = 1; bn_rand(a, BN_POS, bits / 2 - bn_bits(t) - 1); i = a->dp[0]; bn_dbl(t, t); do { /* Find first prime r = 2 * i * t + 1. */ bn_mul_dig(r, t, i); bn_add_dig(r, r, 1); i++; if (bn_bits(r) > bits / 2 - 1) { found = 0; break; } } while (!bn_is_prime(r)); if (found == 0) { continue; } /* Compute t = 2 * (s^(r-2) mod r) * s - 1. */ bn_sub_dig(t, r, 2); #if BN_MOD != PMERS bn_mxp(t, s, t, r); #else bn_exp(t, s, t, r); #endif bn_mul(t, t, s); bn_dbl(t, t); bn_sub_dig(t, t, 1); k = bits - bn_bits(r); k -= bn_bits(s); bn_rand(a, BN_POS, k); j = a->dp[0]; do { /* Find first prime a = t + 2 * j * r * s. */ bn_mul(a, r, s); bn_mul_dig(a, a, j); bn_dbl(a, a); bn_add(a, a, t); j++; if (bn_bits(a) > bits) { found = 0; break; } } while (!bn_is_prime(a)); } while (found == 0 && bn_bits(a) != bits); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(r); bn_free(s); bn_free(t); } }
int bn_is_prime_rabin(const bn_t a) { bn_t t, n1, y, r; int i, s, j, result, b, tests = 0; tests = 0; result = 1; bn_null(t); bn_null(n1); bn_null(y); bn_null(r); if (bn_cmp_dig(a, 1) == CMP_EQ) { return 0; } TRY { /* * These values are taken from Table 4.4 inside Handbook of Applied * Cryptography. */ b = bn_bits(a); if (b >= 1300) { tests = 2; } else if (b >= 850) { tests = 3; } else if (b >= 650) { tests = 4; } else if (b >= 550) { tests = 5; } else if (b >= 450) { tests = 6; } else if (b >= 400) { tests = 7; } else if (b >= 350) { tests = 8; } else if (b >= 300) { tests = 9; } else if (b >= 250) { tests = 12; } else if (b >= 200) { tests = 15; } else if (b >= 150) { tests = 18; } else { tests = 27; } bn_new(t); bn_new(n1); bn_new(y); bn_new(r); /* r = (n - 1)/2^s. */ bn_sub_dig(n1, a, 1); s = 0; while (bn_is_even(n1)) { s++; bn_rsh(n1, n1, 1); } bn_lsh(r, n1, s); for (i = 0; i < tests; i++) { /* Fix the basis as the first few primes. */ bn_set_dig(t, primes[i]); /* y = b^r mod a. */ #if BN_MOD != PMERS bn_mxp(y, t, r, a); #else bn_exp(y, t, r, a); #endif if (bn_cmp_dig(y, 1) != CMP_EQ && bn_cmp(y, n1) != CMP_EQ) { j = 1; while ((j <= (s - 1)) && bn_cmp(y, n1) != CMP_EQ) { bn_sqr(y, y); bn_mod(y, y, a); /* If y == 1 then composite. */ if (bn_cmp_dig(y, 1) == CMP_EQ) { result = 0; break; } ++j; } /* If y != n1 then composite. */ if (bn_cmp(y, n1) != CMP_EQ) { result = 0; break; } } } } CATCH_ANY { result = 0; THROW(ERR_CAUGHT); } FINALLY { bn_free(r); bn_free(y); bn_free(n1); bn_free(t); } return result; }
/** * Computes the constants required for evaluating Frobenius maps. */ static void fp3_calc() { bn_t e; fp3_t t0, t1, t2; ctx_t *ctx = core_get(); bn_null(e); fp3_null(t0); fp3_null(t1); fp3_null(t2); TRY { bn_new(e); fp3_new(t0); fp3_new(t1); fp3_new(t2); fp_set_dig(ctx->fp3_base[0], -fp_prime_get_cnr()); fp_neg(ctx->fp3_base[0], ctx->fp3_base[0]); e->used = FP_DIGS; dv_copy(e->dp, fp_prime_get(), FP_DIGS); bn_sub_dig(e, e, 1); bn_div_dig(e, e, 3); fp_exp(ctx->fp3_base[0], ctx->fp3_base[0], e); fp_sqr(ctx->fp3_base[1], ctx->fp3_base[0]); fp3_zero(t0); fp_set_dig(t0[1], 1); dv_copy(e->dp, fp_prime_get(), FP_DIGS); bn_sub_dig(e, e, 1); bn_div_dig(e, e, 6); /* t0 = u^((p-1)/6). */ fp3_exp(t0, t0, e); fp_copy(ctx->fp3_p[0], t0[2]); fp3_sqr(t1, t0); fp_copy(ctx->fp3_p[1], t1[1]); fp3_mul(t2, t1, t0); fp_copy(ctx->fp3_p[2], t2[0]); fp3_sqr(t2, t1); fp_copy(ctx->fp3_p[3], t2[2]); fp3_mul(t2, t2, t0); fp_copy(ctx->fp3_p[4], t2[1]); fp_mul(ctx->fp3_p2[0], ctx->fp3_p[0], ctx->fp3_base[1]); fp_mul(t0[0], ctx->fp3_p2[0], ctx->fp3_p[0]); fp_neg(ctx->fp3_p2[0], t0[0]); for (int i = -1; i > fp_prime_get_cnr(); i--) { fp_sub(ctx->fp3_p2[0], ctx->fp3_p2[0], t0[0]); } fp_mul(ctx->fp3_p2[1], ctx->fp3_p[1], ctx->fp3_base[0]); fp_mul(ctx->fp3_p2[1], ctx->fp3_p2[1], ctx->fp3_p[1]); fp_sqr(ctx->fp3_p2[2], ctx->fp3_p[2]); fp_mul(ctx->fp3_p2[3], ctx->fp3_p[3], ctx->fp3_base[1]); fp_mul(t0[0], ctx->fp3_p2[3], ctx->fp3_p[3]); fp_neg(ctx->fp3_p2[3], t0[0]); for (int i = -1; i > fp_prime_get_cnr(); i--) { fp_sub(ctx->fp3_p2[3], ctx->fp3_p2[3], t0[0]); } fp_mul(ctx->fp3_p2[4], ctx->fp3_p[4], ctx->fp3_base[0]); fp_mul(ctx->fp3_p2[4], ctx->fp3_p2[4], ctx->fp3_p[4]); fp_mul(ctx->fp3_p3[0], ctx->fp3_p[0], ctx->fp3_base[0]); fp_mul(t0[0], ctx->fp3_p3[0], ctx->fp3_p2[0]); fp_neg(ctx->fp3_p3[0], t0[0]); for (int i = -1; i > fp_prime_get_cnr(); i--) { fp_sub(ctx->fp3_p3[0], ctx->fp3_p3[0], t0[0]); } fp_mul(ctx->fp3_p3[1], ctx->fp3_p[1], ctx->fp3_base[1]); fp_mul(t0[0], ctx->fp3_p3[1], ctx->fp3_p2[1]); fp_neg(ctx->fp3_p3[1], t0[0]); for (int i = -1; i > fp_prime_get_cnr(); i--) { fp_sub(ctx->fp3_p3[1], ctx->fp3_p3[1], t0[0]); } fp_mul(ctx->fp3_p3[2], ctx->fp3_p[2], ctx->fp3_p2[2]); fp_mul(ctx->fp3_p3[3], ctx->fp3_p[3], ctx->fp3_base[0]); fp_mul(t0[0], ctx->fp3_p3[3], ctx->fp3_p2[3]); fp_neg(ctx->fp3_p3[3], t0[0]); for (int i = -1; i > fp_prime_get_cnr(); i--) { fp_sub(ctx->fp3_p3[3], ctx->fp3_p3[3], t0[0]); } fp_mul(ctx->fp3_p3[4], ctx->fp3_p[4], ctx->fp3_base[1]); fp_mul(t0[0], ctx->fp3_p3[4], ctx->fp3_p2[4]); fp_neg(ctx->fp3_p3[4], t0[0]); for (int i = -1; i > fp_prime_get_cnr(); i--) { fp_sub(ctx->fp3_p3[4], ctx->fp3_p3[4], t0[0]); } for (int i = 0; i < 5; i++) { fp_mul(ctx->fp3_p4[i], ctx->fp3_p[i], ctx->fp3_p3[i]); fp_mul(ctx->fp3_p5[i], ctx->fp3_p2[i], ctx->fp3_p3[i]); } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(e); fp3_free(t0); fp3_free(t1); fp3_free(t2); } }
/** * Computes the constantes required for evaluating Frobenius maps. */ static void fp2_calc() { bn_t e; fp2_t t0; fp2_t t1; ctx_t *ctx = core_get(); bn_null(e); fp2_null(t0); fp2_null(t1); TRY { bn_new(e); fp2_new(t0); fp2_new(t1); fp2_zero(t0); fp_set_dig(t0[0], 1); fp2_mul_nor(t0, t0); e->used = FP_DIGS; dv_copy(e->dp, fp_prime_get(), FP_DIGS); bn_sub_dig(e, e, 1); bn_div_dig(e, e, 6); fp2_exp(t0, t0, e); #if ALLOC == AUTO fp2_copy(ctx->fp2_p[0], t0); fp2_sqr(ctx->fp2_p[1], ctx->fp2_p[0]); fp2_mul(ctx->fp2_p[2], ctx->fp2_p[1], ctx->fp2_p[0]); fp2_sqr(ctx->fp2_p[3], ctx->fp2_p[1]); fp2_mul(ctx->fp2_p[4], ctx->fp2_p[3], ctx->fp2_p[0]); #else fp_copy(ctx->fp2_p[0][0], t0[0]); fp_copy(ctx->fp2_p[0][1], t0[1]); fp2_sqr(t1, t0); fp_copy(ctx->fp2_p[1][0], t1[0]); fp_copy(ctx->fp2_p[1][1], t1[1]); fp2_mul(t1, t1, t0); fp_copy(ctx->fp2_p[2][0], t1[0]); fp_copy(ctx->fp2_p[2][1], t1[1]); fp2_sqr(t1, t0); fp2_sqr(t1, t1); fp_copy(ctx->fp2_p[3][0], t1[0]); fp_copy(ctx->fp2_p[3][1], t1[1]); fp2_mul(t1, t1, t0); fp_copy(ctx->fp2_p[4][0], t1[0]); fp_copy(ctx->fp2_p[4][1], t1[1]); #endif fp2_frb(t1, t0, 1); fp2_mul(t0, t1, t0); fp_copy(ctx->fp2_p2[0], t0[0]); fp_sqr(ctx->fp2_p2[1], ctx->fp2_p2[0]); fp_mul(ctx->fp2_p2[2], ctx->fp2_p2[1], ctx->fp2_p2[0]); fp_sqr(ctx->fp2_p2[3], ctx->fp2_p2[1]); for (int i = 0; i < 5; i++) { fp_mul(ctx->fp2_p3[i][0], ctx->fp2_p2[i % 3], ctx->fp2_p[i][0]); fp_mul(ctx->fp2_p3[i][1], ctx->fp2_p2[i % 3], ctx->fp2_p[i][1]); } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(e); fp2_free(t0); fp2_free(t1); } }
void pp_map_sim_weilp_k12(fp12_t r, ep_t *p, ep2_t *q, int m) { ep_t _p[m], t0[m]; ep2_t _q[m], t1[m]; fp12_t r0, r1; bn_t n; int i, j; fp12_null(r0); fp12_null(r1); bn_null(r); TRY { fp12_new(r0); fp12_new(r1); bn_new(n); for (i = 0; i < m; i++) { ep_null(_p[i]); ep_null(t0[i]); ep2_null(_q[i]); ep2_null(t1[i]); ep_new(_p[i]); ep_new(t0[i]); ep2_new(_q[i]); ep2_new(t1[i]); } j = 0; for (i = 0; i < m; i++) { if (!ep_is_infty(p[i]) && !ep2_is_infty(q[i])) { ep_norm(_p[j], p[i]); ep2_norm(_q[j++], q[i]); } } ep_curve_get_ord(n); bn_sub_dig(n, n, 1); fp12_set_dig(r0, 1); fp12_set_dig(r1, 1); if (j > 0) { pp_mil_lit_k12(r0, t0, _p, _q, j, n); pp_mil_k12(r1, t1, _q, _p, j, n); fp12_inv(r1, r1); fp12_mul(r0, r0, r1); fp12_inv(r1, r0); fp12_inv_uni(r0, r0); } fp12_mul(r, r0, r1); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { fp12_free(r0); fp12_free(r1); bn_free(n); for (i = 0; i < m; i++) { ep_free(_p[i]); ep_free(t0[i]); ep2_free(_q[i]); ep2_free(t1[i]); } } }
void fp_param_set(int param) { bn_t t0, t1, t2, p; int f[10] = { 0 }; bn_null(t0); bn_null(t1); bn_null(t2); bn_null(p); /* Suppress possible unused parameter warning. */ (void) f; TRY { bn_new(t0); bn_new(t1); bn_new(t2); bn_new(p); core_get()->fp_id = param; switch (param) { #if FP_PRIME == 158 case BN_158: /* x = 4000000031. */ fp_param_get_var(t0); /* p = 36 * x^4 + 36 * x^3 + 24 * x^2 + 6 * x + 1. */ bn_set_dig(p, 1); bn_mul_dig(t1, t0, 6); bn_add(p, p, t1); bn_mul(t1, t0, t0); bn_mul_dig(t1, t1, 24); bn_add(p, p, t1); bn_mul(t1, t0, t0); bn_mul(t1, t1, t0); bn_mul_dig(t1, t1, 36); bn_add(p, p, t1); bn_mul(t0, t0, t0); bn_mul(t1, t0, t0); bn_mul_dig(t1, t1, 36); bn_add(p, p, t1); fp_prime_set_dense(p); break; #elif FP_PRIME == 160 case SECG_160: /* p = 2^160 - 2^31 + 1. */ f[0] = -1; f[1] = -31; f[2] = 160; fp_prime_set_pmers(f, 3); break; case SECG_160D: /* p = 2^160 - 2^32 - 2^14 - 2^12 - 2^9 - 2^8 - 2^7 - 2^3 - 2^2 - 1.*/ f[0] = -1; f[1] = -2; f[2] = -3; f[3] = -7; f[4] = -8; f[5] = -9; f[6] = -12; f[7] = -14; f[8] = -32; f[9] = 160; fp_prime_set_pmers(f, 10); break; #elif FP_PRIME == 192 case NIST_192: /* p = 2^192 - 2^64 - 1. */ f[0] = -1; f[1] = -64; f[2] = 192; fp_prime_set_pmers(f, 3); break; case SECG_192: /* p = 2^192 - 2^32 - 2^12 - 2^8 - 2^7 - 2^6 - 2^3 - 1.*/ f[0] = -1; f[1] = -3; f[2] = -6; f[3] = -7; f[4] = -8; f[5] = -12; f[6] = -32; f[7] = 192; fp_prime_set_pmers(f, 8); break; #elif FP_PRIME == 224 case NIST_224: /* p = 2^224 - 2^96 + 1. */ f[0] = 1; f[1] = -96; f[2] = 224; fp_prime_set_pmers(f, 3); break; case SECG_224: /* p = 2^224 - 2^32 - 2^12 - 2^11 - 2^9 - 2^7 - 2^4 - 2 - 1.*/ f[0] = -1; f[1] = -1; f[2] = -4; f[3] = -7; f[4] = -9; f[5] = -11; f[6] = -12; f[7] = -32; f[8] = 224; fp_prime_set_pmers(f, 9); break; #elif FP_PRIME == 254 case BN_254: /* x = -4080000000000001. */ fp_param_get_var(t0); /* p = 36 * x^4 + 36 * x^3 + 24 * x^2 + 6 * x + 1. */ bn_set_dig(p, 1); bn_mul_dig(t1, t0, 6); bn_add(p, p, t1); bn_mul(t1, t0, t0); bn_mul_dig(t1, t1, 24); bn_add(p, p, t1); bn_mul(t1, t0, t0); bn_mul(t1, t1, t0); bn_mul_dig(t1, t1, 36); bn_add(p, p, t1); bn_mul(t0, t0, t0); bn_mul(t1, t0, t0); bn_mul_dig(t1, t1, 36); bn_add(p, p, t1); fp_prime_set_dense(p); break; #elif FP_PRIME == 256 case NIST_256: /* p = 2^256 - 2^224 + 2^192 + 2^96 - 1. */ f[0] = -1; f[1] = 96; f[2] = 192; f[3] = -224; f[4] = 256; fp_prime_set_pmers(f, 5); break; case SECG_256: /* p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1. */ f[0] = -1; f[1] = -4; f[2] = -6; f[3] = -7; f[4] = -8; f[5] = -9; f[6] = -32; f[7] = 256; fp_prime_set_pmers(f, 8); break; case BN_256: /* x = 6000000000001F2D. */ fp_param_get_var(t0); /* p = 36 * x^4 + 36 * x^3 + 24 * x^2 + 6 * x + 1. */ bn_set_dig(p, 1); bn_mul_dig(t1, t0, 6); bn_add(p, p, t1); bn_mul(t1, t0, t0); bn_mul_dig(t1, t1, 24); bn_add(p, p, t1); bn_mul(t1, t0, t0); bn_mul(t1, t1, t0); bn_mul_dig(t1, t1, 36); bn_add(p, p, t1); bn_mul(t0, t0, t0); bn_mul(t1, t0, t0); bn_mul_dig(t1, t1, 36); bn_add(p, p, t1); fp_prime_set_dense(p); break; #elif FP_PRIME == 384 case NIST_384: /* p = 2^384 - 2^128 - 2^96 + 2^32 - 1. */ f[0] = -1; f[1] = 32; f[2] = -96; f[3] = -128; f[4] = 384; fp_prime_set_pmers(f, 5); break; #elif FP_PRIME == 477 case B24_477: fp_param_get_var(t0); /* p = (u - 1)^2 * (u^8 - u^4 + 1) div 3 + u. */ bn_sub_dig(p, t0, 1); bn_sqr(p, p); bn_sqr(t1, t0); bn_sqr(t1, t1); bn_sqr(t2, t1); bn_sub(t2, t2, t1); bn_add_dig(t2, t2, 1); bn_mul(p, p, t2); bn_div_dig(p, p, 3); bn_add(p, p, t0); fp_prime_set_dense(p); break; #elif FP_PRIME == 508 case KSS_508: fp_param_get_var(t0); /* h = (49*u^2 + 245 * u + 343)/3 */ bn_mul_dig(p, t0, 245); bn_add_dig(p, p, 200); bn_add_dig(p, p, 143); bn_sqr(t1, t0); bn_mul_dig(t2, t1, 49); bn_add(p, p, t2); bn_div_dig(p, p, 3); /* n = (u^6 + 37 * u^3 + 343)/343. */ bn_mul(t1, t1, t0); bn_mul_dig(t2, t1, 37); bn_sqr(t1, t1); bn_add(t2, t2, t1); bn_add_dig(t2, t2, 200); bn_add_dig(t2, t2, 143); bn_div_dig(t2, t2, 49); bn_div_dig(t2, t2, 7); bn_mul(p, p, t2); /* t = (u^4 + 16 * u + 7)/7. */ bn_mul_dig(t1, t0, 16); bn_add_dig(t1, t1, 7); bn_sqr(t2, t0); bn_sqr(t2, t2); bn_add(t2, t2, t1); bn_div_dig(t2, t2, 7); bn_add(p, p, t2); bn_sub_dig(p, p, 1); fp_prime_set_dense(p); break; #elif FP_PRIME == 521 case NIST_521: /* p = 2^521 - 1. */ f[0] = -1; f[1] = 521; fp_prime_set_pmers(f, 2); break; #elif FP_PRIME == 638 case BN_638: fp_param_get_var(t0); /* p = 36 * x^4 + 36 * x^3 + 24 * x^2 + 6 * x + 1. */ bn_set_dig(p, 1); bn_mul_dig(t1, t0, 6); bn_add(p, p, t1); bn_mul(t1, t0, t0); bn_mul_dig(t1, t1, 24); bn_add(p, p, t1); bn_mul(t1, t0, t0); bn_mul(t1, t1, t0); bn_mul_dig(t1, t1, 36); bn_add(p, p, t1); bn_mul(t0, t0, t0); bn_mul(t1, t0, t0); bn_mul_dig(t1, t1, 36); bn_add(p, p, t1); fp_prime_set_dense(p); break; case B12_638: fp_param_get_var(t0); /* p = (x^2 - 2x + 1) * (x^4 - x^2 + 1)/3 + x. */ bn_sqr(t1, t0); bn_sqr(p, t1); bn_sub(p, p, t1); bn_add_dig(p, p, 1); bn_sub(t1, t1, t0); bn_sub(t1, t1, t0); bn_add_dig(t1, t1, 1); bn_mul(p, p, t1); bn_div_dig(p, p, 3); bn_add(p, p, t0); fp_prime_set_dense(p); break; #elif FP_PRIME == 1536 case SS_1536: fp_param_get_var(t0); bn_read_str(p, SS_P1536, strlen(SS_P1536), 16); bn_mul(p, p, t0); bn_dbl(p, p); bn_sub_dig(p, p, 1); fp_prime_set_dense(p); break; #else default: bn_gen_prime(p, FP_BITS); fp_prime_set_dense(p); core_get()->fp_id = 0; break; #endif } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(t0); bn_free(t1); bn_free(t2); bn_free(p); } }