int fp3_srt(fp3_t c, fp3_t a) { int r = 0; fp3_t t0, t1, t2, t3; bn_t e; fp3_null(t0); fp3_null(t1); fp3_null(t2); fp3_null(t3); bn_null(e); TRY { fp3_new(t0); fp3_new(t1); fp3_new(t2); fp3_new(t3); bn_new(e); fp3_dbl(t3, a); fp3_frb(t0, t3, 1); fp3_sqr(t1, t0); fp3_mul(t2, t1, t0); fp3_mul(t1, t1, t2); fp3_frb(t0, t0, 1); fp3_mul(t3, t3, t1); fp3_mul(t0, t0, t3); e->used = FP_DIGS; dv_copy(e->dp, fp_prime_get(), FP_DIGS); bn_sub_dig(e, e, 5); bn_div_dig(e, e, 8); fp3_exp(t0, t0, e); fp3_mul(t0, t0, t2); fp3_sqr(t1, t0); fp3_mul(t1, t1, a); fp3_dbl(t1, t1); fp3_mul(t0, t0, a); fp_sub_dig(t1[0], t1[0], 1); fp3_mul(c, t0, t1); fp3_sqr(t0, c); if (fp3_cmp(t0, a) == CMP_EQ) { r = 1; } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { fp3_free(t0); fp3_free(t1); fp3_free(t2); fp3_free(t3); bn_free(e); } return r; }
int cp_bdpe_dec(dig_t *out, uint8_t *in, int in_len, bdpe_t prv) { bn_t m, t, z; unsigned i; int size, result = STS_OK; size = bn_size_bin(prv->n); if (in_len < 0 || in_len != size) { return STS_ERR; } bn_null(m); bn_null(t); bn_null(z); TRY { bn_new(m); bn_new(t); bn_new(z); /* Compute t = (p-1)(q-1)/block. */ bn_mul(t, prv->p, prv->q); bn_sub(t, t, prv->p); bn_sub(t, t, prv->q); bn_add_dig(t, t, 1); bn_div_dig(t, t, prv->t); bn_read_bin(m, in, in_len); bn_mxp(m, m, t, prv->n); bn_mxp(t, prv->y, t, prv->n); for (i = 0; i < prv->t; i++) { bn_mxp_dig(z, t, i, prv->n); if (bn_cmp(z, m) == CMP_EQ) { *out = i; break; } } if (i == prv->t) { result = STS_ERR; } } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(m); bn_free(t); bn_free(z); } return result; }
int bn_size_str(const bn_t a, int radix) { int digits = 0; bn_t t; bn_null(t); /* Binary case requires the bits, a sign and the null terminator. */ if (radix == 2) { return bn_bits(a) + (a->sign == BN_NEG ? 1 : 0) + 1; } /* Check the radix. */ if (radix < 2 || radix > 64) { THROW(ERR_NO_VALID); } if (bn_is_zero(a)) { return 2; } if (a->sign == BN_NEG) { digits++; } TRY { bn_new(t); bn_copy(t, a); t->sign = BN_POS; while (!bn_is_zero(t)) { bn_div_dig(t, t, (dig_t)radix); digits++; } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(t); } return digits + 1; }
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; }
/** * 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 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); } }