/** * Multiplies a point on a Barreto-Lynn-Soctt curve by the cofactor. * * @param[out] r - the result. * @param[in] p - the point to multiply. */ void ep2_mul_cof_b12(ep2_t r, ep2_t p) { bn_t x; ep2_t t0, t1, t2, t3; ep2_null(t0); ep2_null(t1); ep2_null(t2); ep2_null(t3); bn_null(x); TRY { ep2_new(t0); ep2_new(t1); ep2_new(t2); ep2_new(t3); bn_new(x); fp_param_get_var(x); /* Compute t0 = xP. */ ep2_mul(t0, p, x); if (bn_sign(x) == BN_NEG) { ep2_neg(t0, t0); } /* Compute t1 = [x^2]P. */ ep2_mul(t1, t0, x); if (bn_sign(x) == BN_NEG) { ep2_neg(t1, t1); } /* t2 = (x^2 - x - 1)P = x^2P - x*P - P. */ ep2_sub(t2, t1, t0); ep2_sub(t2, t2, p); /* t3 = \psi(x - 1)P. */ ep2_sub(t3, t0, p); ep2_norm(t3, t3); ep2_frb(t3, t3, 1); ep2_add(t2, t2, t3); /* t3 = \psi^2(2P). */ ep2_dbl(t3, p); ep2_norm(t3, t3); ep2_frb(t3, t3, 2); ep2_add(t2, t2, t3); ep2_norm(r, t2); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { ep2_free(t0); ep2_free(t1); ep2_free(t2); ep2_free(t3); bn_free(x); } }
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); } }
/** * Multiplies a point on a Barreto-Naehrig curve by the cofactor. * * @param[out] r - the result. * @param[in] p - the point to multiply. */ void ep2_mul_cof_bn(ep2_t r, ep2_t p) { bn_t x; ep2_t t0, t1, t2; ep2_null(t0); ep2_null(t1); ep2_null(t2); bn_null(x); TRY { ep2_new(t0); ep2_new(t1); ep2_new(t2); bn_new(x); fp_param_get_var(x); /* Compute t0 = xP. */ ep2_mul(t0, p, x); if (bn_sign(x) == BN_NEG) { ep2_neg(t0, t0); } /* Compute t1 = \psi(3xP). */ ep2_dbl(t1, t0); ep2_add(t1, t1, t0); ep2_norm(t1, t1); ep2_frb(t1, t1, 1); /* Compute t2 = \psi^3(P) + t0 + t1 + \psi^2(xP). */ ep2_frb(t2, p, 2); ep2_frb(t2, t2, 1); ep2_add(t2, t2, t0); ep2_add(t2, t2, t1); ep2_frb(t1, t0, 2); ep2_add(t2, t2, t1); ep2_norm(r, t2); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { ep2_free(t0); ep2_free(t1); ep2_free(t2); bn_free(x); } }
void pp_map_sim_oatep_k12(fp12_t r, ep_t *p, ep2_t *q, int m) { ep_t _p[m]; ep2_t t[m], _q[m]; bn_t a; int i, j, len = FP_BITS, s[FP_BITS]; TRY { bn_null(a); bn_new(a); for (i = 0; i < m; i++) { ep_null(_p[i]); ep2_null(_q[i]); ep2_null(t[i]); ep_new(_p[i]); ep2_new(_q[i]); ep2_new(t[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]); } } fp12_set_dig(r, 1); fp_param_get_var(a); bn_mul_dig(a, a, 6); bn_add_dig(a, a, 2); fp_param_get_map(s, &len); if (j > 0) { switch (ep_param_get()) { case BN_P158: case BN_P254: case BN_P256: case BN_P638: /* r = f_{|a|,Q}(P). */ pp_mil_sps_k12(r, t, _q, _p, j, s, len); if (bn_sign(a) == BN_NEG) { /* f_{-a,Q}(P) = 1/f_{a,Q}(P). */ fp12_inv_uni(r, r); } for (i = 0; i < j; i++) { if (bn_sign(a) == BN_NEG) { ep2_neg(t[i], t[i]); } pp_fin_k12_oatep(r, t[i], _q[i], _p[i]); } pp_exp_k12(r, r); break; case B12_P638: /* r = f_{|a|,Q}(P). */ pp_mil_sps_k12(r, t, _q, _p, j, s, len); if (bn_sign(a) == BN_NEG) { fp12_inv_uni(r, r); } pp_exp_k12(r, r); break; } } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(a); for (i = 0; i < m; i++) { ep_free(_p[i]); ep2_free(_q[i]); ep2_free(t[i]); } } }
void pp_map_oatep_k12(fp12_t r, ep_t p, ep2_t q) { ep_t _p[1]; ep2_t t[1], _q[1]; bn_t a; int len = FP_BITS, s[FP_BITS]; ep_null(_p[0]); ep2_null(_q[0]); ep2_null(t[0]); bn_null(a); TRY { ep_new(_p[0]); ep2_new(_q[0]); ep2_new(t[0]); bn_new(a); fp_param_get_var(a); bn_mul_dig(a, a, 6); bn_add_dig(a, a, 2); fp_param_get_map(s, &len); fp12_set_dig(r, 1); ep_norm(_p[0], p); ep2_norm(_q[0], q); if (!ep_is_infty(_p[0]) && !ep2_is_infty(_q[0])) { switch (ep_param_get()) { case BN_P158: case BN_P254: case BN_P256: case BN_P638: /* r = f_{|a|,Q}(P). */ pp_mil_sps_k12(r, t, _q, _p, 1, s, len); if (bn_sign(a) == BN_NEG) { /* f_{-a,Q}(P) = 1/f_{a,Q}(P). */ fp12_inv_uni(r, r); ep2_neg(t[0], t[0]); } pp_fin_k12_oatep(r, t[0], _q[0], _p[0]); pp_exp_k12(r, r); break; case B12_P638: /* r = f_{|a|,Q}(P). */ pp_mil_sps_k12(r, t, _q, _p, 1, s, len); if (bn_sign(a) == BN_NEG) { fp12_inv_uni(r, r); ep2_neg(t[0], t[0]); } pp_exp_k12(r, r); break; } } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { ep_free(_p[0]); ep2_free(_q[0]); ep2_free(t[0]); bn_free(a); } }
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); } }
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); } }
/** * Computes the final exponentiation of a pairing defined over a Barreto-Naehrig * curve. * * @param[out] c - the result. * @param[in] a - the extension field element to exponentiate. */ static void pp_exp_bn(fp12_t c, fp12_t a) { fp12_t t0, t1, t2, t3; int l = MAX_TERMS + 1, b[MAX_TERMS + 1]; bn_t x; fp12_null(t0); fp12_null(t1); fp12_null(t2); fp12_null(t3); bn_null(x); TRY { fp12_new(t0); fp12_new(t1); fp12_new(t2); fp12_new(t3); bn_new(x); /* * New final exponentiation following Fuentes-Castañeda, Knapp and * Rodríguez-Henríquez: Fast Hashing to G_2. */ fp_param_get_var(x); fp_param_get_sps(b, &l); /* First, compute m = f^(p^6 - 1)(p^2 + 1). */ fp12_conv_cyc(c, a); /* Now compute m^((p^4 - p^2 + 1) / r). */ /* t0 = m^2x. */ fp12_exp_cyc_sps(t0, c, b, l); fp12_sqr_cyc(t0, t0); /* t1 = m^6x. */ fp12_sqr_cyc(t1, t0); fp12_mul(t1, t1, t0); /* t2 = m^6x^2. */ fp12_exp_cyc_sps(t2, t1, b, l); /* t3 = m^12x^3. */ fp12_sqr_cyc(t3, t2); fp12_exp_cyc_sps(t3, t3, b, l); if (bn_sign(x) == BN_NEG) { fp12_inv_uni(t0, t0); fp12_inv_uni(t1, t1); fp12_inv_uni(t3, t3); } /* t3 = a = m^12x^3 * m^6x^2 * m^6x. */ fp12_mul(t3, t3, t2); fp12_mul(t3, t3, t1); /* t0 = b = 1/(m^2x) * t3. */ fp12_inv_uni(t0, t0); fp12_mul(t0, t0, t3); /* Compute t2 * t3 * m * b^p * a^p^2 * [b * 1/m]^p^3. */ fp12_mul(t2, t2, t3); fp12_mul(t2, t2, c); fp12_inv_uni(c, c); fp12_mul(c, c, t0); fp12_frb(c, c, 3); fp12_mul(c, c, t2); fp12_frb(t0, t0, 1); fp12_mul(c, c, t0); fp12_frb(t3, t3, 2); fp12_mul(c, c, t3); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { fp12_free(t0); fp12_free(t1); fp12_free(t2); fp12_free(t3); bn_free(x); } }
/** * Computes the final exponentiation of a pairing defined over a * Barreto-Lynn-Scott curve. * * @param[out] c - the result. * @param[in] a - the extension field element to exponentiate. */ static void pp_exp_b12(fp12_t c, fp12_t a) { fp12_t t[10]; bn_t x; int l = MAX_TERMS + 1, b[MAX_TERMS + 1]; bn_null(x); TRY { for (int i = 0; i < 10; i++) { fp12_null(t[i]); fp12_new(t[i]); } bn_new(x); fp_param_get_var(x); fp_param_get_sps(b, &l); /* First, compute m^(p^6 - 1)(p^2 + 1). */ fp12_conv_cyc(c, a); /* v0 = f^-1. */ fp12_inv_uni(t[0], c); /* v1 = f^-2. */ fp12_sqr_cyc(t[1], t[0]); /* v2 = f^x. */ fp12_exp_cyc_sps(t[2], c, b, l); if (bn_sign(x) == BN_NEG) { fp12_inv_uni(t[2], t[2]); } /* v3 = f^2x. */ fp12_sqr_cyc(t[3], t[2]); /* v4 = f^(x - 2). */ fp12_mul(t[4], t[2], t[1]); /* v5 = f^(x^2 - 2x). */ fp12_exp_cyc_sps(t[5], t[4], b, l); if (bn_sign(x) == BN_NEG) { fp12_inv_uni(t[5], t[5]); } /* v6 = f^(x^3 - 2x^2). */ fp12_exp_cyc_sps(t[6], t[5], b, l); if (bn_sign(x) == BN_NEG) { fp12_inv_uni(t[6], t[6]); } /* v7 = f^(x^4 - 2x^3 + 2x). */ fp12_exp_cyc_sps(t[7], t[6], b, l); if (bn_sign(x) == BN_NEG) { fp12_inv_uni(t[7], t[7]); } fp12_mul(t[7], t[7], t[3]); /* v8 = f^(x^5 - 2x^4 + 2x^2). */ fp12_exp_cyc_sps(t[8], t[7], b, l); if (bn_sign(x) == BN_NEG) { fp12_inv_uni(t[8], t[8]); } /* v7 = f^(x^4 - 2x^3 + 2x - 1)^p. */ fp12_mul(t[7], t[7], t[0]); fp12_frb(t[7], t[7], 1); /* v6 = f^(x^3 - 2x^2 + x)^p^2. */ fp12_mul(t[6], t[6], t[2]); fp12_frb(t[6], t[6], 2); /* v5 = f^(x^2 - 2x + 1)^p^3. */ fp12_mul(t[5], t[5], c); fp12_frb(t[5], t[5], 1); fp12_frb(t[5], t[5], 2); /* v4 = f^(2 - x). */ fp12_inv_uni(t[4], t[4]); /* Now compute f * v4 * v5 * v6 * v7 * v8. */ fp12_mul(c, c, t[4]); fp12_mul(c, c, t[5]); fp12_mul(c, c, t[6]); fp12_mul(c, c, t[7]); fp12_mul(c, c, t[8]); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { for (int i = 0; i < 9; i++) { fp12_free(t[i]); } bn_free(x); } }