diff --git a/.github/workflows/gmp-sec.yml b/.github/workflows/gmp-sec.yml
index 61fd18203..5a2ad6c1a 100644
--- a/.github/workflows/gmp-sec.yml
+++ b/.github/workflows/gmp-sec.yml
@@ -61,6 +61,7 @@ jobs:
gcc
cmake
gmp
+ gmp-devel
update: true
- name: Run CMake (MingW)
diff --git a/.github/workflows/gmp.yml b/.github/workflows/gmp.yml
index 03cbf8d5a..40d036ecf 100644
--- a/.github/workflows/gmp.yml
+++ b/.github/workflows/gmp.yml
@@ -61,6 +61,7 @@ jobs:
gcc
cmake
gmp
+ gmp-devel
update: true
- name: Run CMake (MingW)
diff --git a/bench/bench_dv.c b/bench/bench_dv.c
index 7f1584619..62670d21c 100644
--- a/bench/bench_dv.c
+++ b/bench/bench_dv.c
@@ -67,16 +67,16 @@ static void copy(void) {
BENCH_ADD(dv_copy(a, b, RLC_DV_DIGS));
} BENCH_END;
- BENCH_RUN("dv_copy_cond") {
+ BENCH_RUN("dv_copy_sec") {
rand_bytes((uint8_t *)a, RLC_DV_DIGS * sizeof(dig_t));
rand_bytes((uint8_t *)b, RLC_DV_DIGS * sizeof(dig_t));
- BENCH_ADD(dv_copy_cond(a, b, RLC_DV_DIGS, 1));
+ BENCH_ADD(dv_copy_sec(a, b, RLC_DV_DIGS, 1));
} BENCH_END;
- BENCH_RUN("dv_swap_cond") {
+ BENCH_RUN("dv_swap_sec") {
rand_bytes((uint8_t *)a, RLC_DV_DIGS * sizeof(dig_t));
rand_bytes((uint8_t *)b, RLC_DV_DIGS * sizeof(dig_t));
- BENCH_ADD(dv_swap_cond(a, b, RLC_DV_DIGS, 1));
+ BENCH_ADD(dv_swap_sec(a, b, RLC_DV_DIGS, 1));
} BENCH_END;
BENCH_RUN("dv_cmp") {
@@ -85,10 +85,10 @@ static void copy(void) {
BENCH_ADD(dv_cmp(a, b, RLC_DV_DIGS));
} BENCH_END;
- BENCH_RUN("dv_cmp_const") {
+ BENCH_RUN("dv_cmp_sec") {
rand_bytes((uint8_t *)a, RLC_DV_DIGS * sizeof(dig_t));
rand_bytes((uint8_t *)b, RLC_DV_DIGS * sizeof(dig_t));
- BENCH_ADD(dv_cmp_const(a, b, RLC_DV_DIGS));
+ BENCH_ADD(dv_cmp_sec(a, b, RLC_DV_DIGS));
} BENCH_END;
dv_free(a);
diff --git a/bench/bench_eb.c b/bench/bench_eb.c
index 1bd9d94d3..c6b4b945f 100644
--- a/bench/bench_eb.c
+++ b/bench/bench_eb.c
@@ -116,7 +116,7 @@ static void util(void) {
BENCH_RUN("eb_rhs") {
eb_rand(p);
- BENCH_ADD(eb_rhs(q->x, p));
+ BENCH_ADD(eb_rhs(q->x, p->x));
} BENCH_END;
BENCH_RUN("eb_tab (4)") {
diff --git a/bench/bench_ed.c b/bench/bench_ed.c
index f2db37565..8f1f5f939 100644
--- a/bench/bench_ed.c
+++ b/bench/bench_ed.c
@@ -116,7 +116,7 @@ static void util(void) {
BENCH_RUN("ed_rhs") {
ed_rand(p);
- BENCH_ADD(ed_rhs(q->x, p));
+ BENCH_ADD(ed_rhs(q->x, p->x));
} BENCH_END;
BENCH_RUN("ed_tab (4)") {
diff --git a/bench/bench_ep.c b/bench/bench_ep.c
index 54b36f890..26aee2cba 100644
--- a/bench/bench_ep.c
+++ b/bench/bench_ep.c
@@ -130,7 +130,7 @@ static void util(void) {
BENCH_RUN("ep_rhs") {
ep_rand(p);
- BENCH_ADD(ep_rhs(q->x, p));
+ BENCH_ADD(ep_rhs(q->x, p->x));
} BENCH_END;
BENCH_RUN("ep_tab (4)") {
diff --git a/bench/bench_epx.c b/bench/bench_epx.c
index 3380f9801..27e96484c 100644
--- a/bench/bench_epx.c
+++ b/bench/bench_epx.c
@@ -240,8 +240,7 @@ static void arith2(void) {
ep2_rand(p);
ep2_add_projc(q, q, p);
BENCH_ADD(ep2_add_projc(r, p, q));
- }
- BENCH_END;
+ } BENCH_END;
BENCH_RUN("ep2_add_projc (z2 = 1)") {
ep2_rand(p);
@@ -250,8 +249,7 @@ static void arith2(void) {
ep2_rand(q);
ep2_norm(q, q);
BENCH_ADD(ep2_add_projc(r, p, q));
- }
- BENCH_END;
+ } BENCH_END;
BENCH_RUN("ep2_add_projc (z1,z2 = 1)") {
ep2_rand(p);
@@ -259,8 +257,36 @@ static void arith2(void) {
ep2_rand(q);
ep2_norm(q, q);
BENCH_ADD(ep2_add_projc(r, p, q));
- }
- BENCH_END;
+ } BENCH_END;
+#endif
+
+#if EP_ADD == JACOB || !defined(STRIP)
+ BENCH_RUN("ep2_add_jacob") {
+ ep2_rand(p);
+ ep2_rand(q);
+ ep2_add_jacob(p, p, q);
+ ep2_rand(q);
+ ep2_rand(p);
+ ep2_add_jacob(q, q, p);
+ BENCH_ADD(ep2_add_jacob(r, p, q));
+ } BENCH_END;
+
+ BENCH_RUN("ep2_add_jacob (z2 = 1)") {
+ ep2_rand(p);
+ ep2_rand(q);
+ ep2_add_jacob(p, p, q);
+ ep2_rand(q);
+ ep2_norm(q, q);
+ BENCH_ADD(ep2_add_jacob(r, p, q));
+ } BENCH_END;
+
+ BENCH_RUN("ep2_add_jacob (z1,z2 = 1)") {
+ ep2_rand(p);
+ ep2_norm(p, p);
+ ep2_rand(q);
+ ep2_norm(q, q);
+ BENCH_ADD(ep2_add_jacob(r, p, q));
+ } BENCH_END;
#endif
BENCH_RUN("ep2_sub") {
@@ -302,15 +328,28 @@ static void arith2(void) {
ep2_rand(q);
ep2_add_projc(p, p, q);
BENCH_ADD(ep2_dbl_projc(r, p));
- }
- BENCH_END;
+ } BENCH_END;
BENCH_RUN("ep2_dbl_projc (z1 = 1)") {
ep2_rand(p);
ep2_norm(p, p);
BENCH_ADD(ep2_dbl_projc(r, p));
- }
- BENCH_END;
+ } BENCH_END;
+#endif
+
+#if EP_ADD == JACOB || !defined(STRIP)
+ BENCH_RUN("ep2_dbl_jacob") {
+ ep2_rand(p);
+ ep2_rand(q);
+ ep2_add_jacob(p, p, q);
+ BENCH_ADD(ep2_dbl_jacob(r, p));
+ } BENCH_END;
+
+ BENCH_RUN("ep2_dbl_jacob (z1 = 1)") {
+ ep2_rand(p);
+ ep2_norm(p, p);
+ BENCH_ADD(ep2_dbl_jacob(r, p));
+ } BENCH_END;
#endif
BENCH_RUN("ep2_neg") {
@@ -357,6 +396,14 @@ static void arith2(void) {
} BENCH_END;
#endif
+#if EP_MUL == LWREG || !defined(STRIP)
+ BENCH_RUN("ep2_mul_lwreg") {
+ bn_rand_mod(k, n);
+ ep2_rand(p);
+ BENCH_ADD(ep2_mul_lwreg(q, p, k));
+ } BENCH_END;
+#endif
+
BENCH_RUN("ep2_mul_gen") {
bn_rand_mod(k, n);
BENCH_ADD(ep2_mul_gen(q, k));
@@ -902,6 +949,14 @@ static void arith3(void) {
} BENCH_END;
#endif
+#if EP_MUL == LWREG || !defined(STRIP)
+ BENCH_RUN("ep3_mul_lwreg") {
+ bn_rand_mod(k, n);
+ ep3_rand(p);
+ BENCH_ADD(ep3_mul_lwreg(q, p, k));
+ } BENCH_END;
+#endif
+
BENCH_RUN("ep3_mul_gen") {
bn_rand_mod(k, n);
BENCH_ADD(ep3_mul_gen(q, k));
@@ -1396,6 +1451,14 @@ static void arith4(void) {
} BENCH_END;
#endif
+#if EP_MUL == LWREG || !defined(STRIP)
+ BENCH_RUN("ep4_mul_lwreg") {
+ bn_rand_mod(k, n);
+ ep4_rand(p);
+ BENCH_ADD(ep4_mul_lwreg(q, p, k));
+ } BENCH_END;
+#endif
+
BENCH_RUN("ep4_mul_gen") {
bn_rand_mod(k, n);
BENCH_ADD(ep4_mul_gen(q, k));
@@ -1890,6 +1953,14 @@ static void arith8(void) {
} BENCH_END;
#endif
+#if EP_MUL == LWREG || !defined(STRIP)
+ BENCH_RUN("ep8_mul_lwreg") {
+ bn_rand_mod(k, n);
+ ep8_rand(p);
+ BENCH_ADD(ep8_mul_lwreg(q, p, k));
+ } BENCH_END;
+#endif
+
BENCH_RUN("ep8_mul_gen") {
bn_rand_mod(k, n);
BENCH_ADD(ep8_mul_gen(q, k));
diff --git a/bench/bench_fp.c b/bench/bench_fp.c
index ea3f576c2..0d8ae5254 100644
--- a/bench/bench_fp.c
+++ b/bench/bench_fp.c
@@ -69,6 +69,18 @@ static void util(void) {
}
BENCH_END;
+ BENCH_RUN("fp_copy_sec (0)") {
+ fp_rand(a);
+ BENCH_ADD(fp_copy_sec(b, a, 0));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp_copy_sec (1)") {
+ fp_rand(a);
+ BENCH_ADD(fp_copy_sec(b, a, 1));
+ }
+ BENCH_END;
+
BENCH_RUN("fp_zero") {
fp_rand(a);
BENCH_ADD(fp_zero(a));
diff --git a/bench/bench_fpx.c b/bench/bench_fpx.c
index 818aa8b14..1a89a6333 100644
--- a/bench/bench_fpx.c
+++ b/bench/bench_fpx.c
@@ -66,6 +66,18 @@ static void util2(void) {
}
BENCH_END;
+ BENCH_RUN("fp2_copy_sec (0)") {
+ fp2_rand(a);
+ BENCH_ADD(fp2_copy_sec(b, a, 0));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp2_copy_sec (1)") {
+ fp2_rand(a);
+ BENCH_ADD(fp2_copy_sec(b, a, 1));
+ }
+ BENCH_END;
+
BENCH_RUN("fp2_neg") {
fp2_rand(a);
BENCH_ADD(fp2_neg(b, a));
@@ -453,6 +465,18 @@ static void util3(void) {
}
BENCH_END;
+ BENCH_RUN("fp3_copy_sec (0)") {
+ fp3_rand(a);
+ BENCH_ADD(fp3_copy_sec(b, a, 0));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp3_copy_sec (1)") {
+ fp3_rand(a);
+ BENCH_ADD(fp3_copy_sec(b, a, 1));
+ }
+ BENCH_END;
+
BENCH_RUN("fp3_neg") {
fp3_rand(a);
BENCH_ADD(fp3_neg(b, a));
@@ -753,6 +777,18 @@ static void util4(void) {
}
BENCH_END;
+ BENCH_RUN("fp4_copy_sec (0)") {
+ fp4_rand(a);
+ BENCH_ADD(fp4_copy_sec(b, a, 0));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp4_copy_sec (1)") {
+ fp4_rand(a);
+ BENCH_ADD(fp4_copy_sec(b, a, 1));
+ }
+ BENCH_END;
+
BENCH_RUN("fp4_neg") {
fp4_rand(a);
BENCH_ADD(fp4_neg(b, a));
@@ -979,6 +1015,18 @@ static void util6(void) {
}
BENCH_END;
+ BENCH_RUN("fp6_copy_sec (0)") {
+ fp6_rand(a);
+ BENCH_ADD(fp6_copy_sec(b, a, 0));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp6_copy_sec (1)") {
+ fp6_rand(a);
+ BENCH_ADD(fp6_copy_sec(b, a, 1));
+ }
+ BENCH_END;
+
BENCH_RUN("fp6_neg") {
fp6_rand(a);
BENCH_ADD(fp6_neg(b, a));
@@ -1191,6 +1239,18 @@ static void util8(void) {
}
BENCH_END;
+ BENCH_RUN("fp8_copy_sec (0)") {
+ fp8_rand(a);
+ BENCH_ADD(fp8_copy_sec(b, a, 0));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp8_copy_sec (1)") {
+ fp8_rand(a);
+ BENCH_ADD(fp8_copy_sec(b, a, 1));
+ }
+ BENCH_END;
+
BENCH_RUN("fp8_neg") {
fp8_rand(a);
BENCH_ADD(fp8_neg(b, a));
@@ -1241,13 +1301,13 @@ static void util8(void) {
BENCH_RUN("fp8_write_bin") {
fp8_rand(a);
- BENCH_ADD(fp8_write_bin(bin, sizeof(bin), a));
+ BENCH_ADD(fp8_write_bin(bin, sizeof(bin), a, 0));
}
BENCH_END;
BENCH_RUN("fp8_read_bin") {
fp8_rand(a);
- fp8_write_bin(bin, sizeof(bin), a);
+ fp8_write_bin(bin, sizeof(bin), a, 0);
BENCH_ADD(fp8_read_bin(a, bin, sizeof(bin)));
}
BENCH_END;
@@ -1483,6 +1543,18 @@ static void util9(void) {
}
BENCH_END;
+ BENCH_RUN("fp9_copy_sec (0)") {
+ fp9_rand(a);
+ BENCH_ADD(fp9_copy_sec(b, a, 0));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp9_copy_sec (1)") {
+ fp9_rand(a);
+ BENCH_ADD(fp9_copy_sec(b, a, 1));
+ }
+ BENCH_END;
+
BENCH_RUN("fp9_neg") {
fp9_rand(a);
BENCH_ADD(fp9_neg(b, a));
@@ -1695,6 +1767,18 @@ static void util12(void) {
}
BENCH_END;
+ BENCH_RUN("fp12_copy_sec (0)") {
+ fp12_rand(a);
+ BENCH_ADD(fp12_copy_sec(b, a, 0));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp12_copy_sec (1)") {
+ fp12_rand(a);
+ BENCH_ADD(fp12_copy_sec(b, a, 1));
+ }
+ BENCH_END;
+
BENCH_RUN("fp12_neg") {
fp12_rand(a);
BENCH_ADD(fp12_neg(b, a));
@@ -1976,16 +2060,6 @@ static void arith12(void) {
}
BENCH_END;
- if (ep_curve_is_pairf() && ep_param_embed() == 12) {
- BENCH_RUN("fp12_exp_cyc (gls)") {
- fp12_rand(a);
- fp12_conv_cyc(a, a);
- bn_rand(e, RLC_POS, RLC_FP_BITS);
- BENCH_ADD(fp12_exp_cyc_gls(c, a, e));
- }
- BENCH_END;
- }
-
BENCH_RUN("fp12_exp_cyc (param or sparse)") {
fp12_rand(a);
fp12_conv_cyc(a, a);
@@ -2093,6 +2167,18 @@ static void util16(void) {
}
BENCH_END;
+ BENCH_RUN("fp16_copy_sec (0)") {
+ fp16_rand(a);
+ BENCH_ADD(fp16_copy_sec(b, a, 0));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp16_copy_sec (1)") {
+ fp16_rand(a);
+ BENCH_ADD(fp16_copy_sec(b, a, 1));
+ }
+ BENCH_END;
+
BENCH_RUN("fp16_neg") {
fp16_rand(a);
BENCH_ADD(fp16_neg(b, a));
@@ -2251,16 +2337,6 @@ static void arith16(void) {
}
BENCH_END;
- if (ep_curve_is_pairf() && ep_param_embed() == 16) {
- BENCH_RUN("fp16_exp_cyc (gls)") {
- fp16_rand(a);
- fp16_conv_cyc(a, a);
- bn_rand(e, RLC_POS, RLC_FP_BITS);
- BENCH_ADD(fp16_exp_cyc_gls(c, a, e));
- }
- BENCH_END;
- }
-
BENCH_RUN("fp16_exp_cyc (param or sparse)") {
fp16_rand(a);
fp16_conv_cyc(a, a);
@@ -2328,6 +2404,18 @@ static void util18(void) {
}
BENCH_END;
+ BENCH_RUN("fp18_copy_sec (0)") {
+ fp18_rand(a);
+ BENCH_ADD(fp18_copy_sec(b, a, 0));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp18_copy_sec (1)") {
+ fp18_rand(a);
+ BENCH_ADD(fp18_copy_sec(b, a, 1));
+ }
+ BENCH_END;
+
BENCH_RUN("fp18_neg") {
fp18_rand(a);
BENCH_ADD(fp18_neg(b, a));
@@ -2609,16 +2697,6 @@ static void arith18(void) {
}
BENCH_END;
- if (ep_curve_is_pairf() && ep_param_embed() == 18) {
- BENCH_RUN("fp18_exp_cyc (gls)") {
- fp18_rand(a);
- fp18_conv_cyc(a, a);
- bn_rand(e, RLC_POS, RLC_FP_BITS);
- BENCH_ADD(fp18_exp_cyc_gls(c, a, e));
- }
- BENCH_END;
- }
-
BENCH_RUN("fp18_exp_cyc (param or sparse)") {
fp18_rand(a);
fp18_conv_cyc(a, a);
@@ -2712,6 +2790,18 @@ static void util24(void) {
}
BENCH_END;
+ BENCH_RUN("fp24_copy_sec (0)") {
+ fp24_rand(a);
+ BENCH_ADD(fp24_copy_sec(b, a, 0));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp24_copy_sec (1)") {
+ fp24_rand(a);
+ BENCH_ADD(fp24_copy_sec(b, a, 1));
+ }
+ BENCH_END;
+
BENCH_RUN("fp24_neg") {
fp24_rand(a);
BENCH_ADD(fp24_neg(b, a));
@@ -2930,16 +3020,6 @@ static void arith24(void) {
}
BENCH_END;
- if (ep_curve_is_pairf() && ep_param_embed() == 24) {
- BENCH_RUN("fp24_exp_cyc (gls)") {
- fp24_rand(a);
- fp24_conv_cyc(a, a);
- bn_rand(e, RLC_POS, RLC_FP_BITS);
- BENCH_ADD(fp24_exp_cyc_gls(c, a, e));
- }
- BENCH_END;
- }
-
BENCH_RUN("fp24_exp_cyc (param or sparse)") {
fp24_rand(a);
fp24_conv_cyc(a, a);
@@ -3033,6 +3113,18 @@ static void util48(void) {
}
BENCH_END;
+ BENCH_RUN("fp48_copy_sec (0)") {
+ fp48_rand(a);
+ BENCH_ADD(fp48_copy_sec(b, a, 0));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp48_copy_sec (1)") {
+ fp48_rand(a);
+ BENCH_ADD(fp48_copy_sec(b, a, 1));
+ }
+ BENCH_END;
+
BENCH_RUN("fp48_neg") {
fp48_rand(a);
BENCH_ADD(fp48_neg(b, a));
@@ -3296,16 +3388,6 @@ static void arith48(void) {
}
BENCH_END;
- if (ep_curve_is_pairf() && ep_param_embed() == 48) {
- BENCH_RUN("fp48_exp_cyc (gls)") {
- fp48_rand(a);
- fp48_conv_cyc(a, a);
- bn_rand(e, RLC_POS, RLC_FP_BITS);
- BENCH_ADD(fp48_exp_cyc_gls(c, a, e));
- }
- BENCH_END;
- }
-
BENCH_RUN("fp48_exp_cyc (param or sparse)") {
fp48_rand(a);
fp48_conv_cyc(a, a);
@@ -3399,6 +3481,18 @@ static void util54(void) {
}
BENCH_END;
+ BENCH_RUN("fp54_copy_sec (0)") {
+ fp54_rand(a);
+ BENCH_ADD(fp54_copy_sec(b, a, 0));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp54_copy_sec (1)") {
+ fp54_rand(a);
+ BENCH_ADD(fp54_copy_sec(b, a, 1));
+ }
+ BENCH_END;
+
BENCH_RUN("fp54_neg") {
fp54_rand(a);
BENCH_ADD(fp54_neg(b, a));
@@ -3778,7 +3872,7 @@ int main(void) {
arith6();
}
- if (fp_prime_get_qnr() && (ep_param_embed() >= 8)) {
+ if (fp_prime_get_qnr() && (ep_curve_embed() >= 8)) {
util_banner("Octic extension:", 0);
util_banner("Utilities:", 1);
memory8();
@@ -3787,7 +3881,7 @@ int main(void) {
arith8();
}
- if (fp_prime_get_cnr() && (ep_param_embed() >= 9)) {
+ if (fp_prime_get_cnr() && (ep_curve_embed() >= 9)) {
util_banner("Nonic extension:", 0);
util_banner("Utilities:", 1);
memory9();
@@ -3796,7 +3890,7 @@ int main(void) {
arith9();
}
- if (fp_prime_get_qnr() && fp_prime_get_cnr() && (ep_param_embed() >= 12)) {
+ if (fp_prime_get_qnr() && fp_prime_get_cnr() && (ep_curve_embed() >= 12)) {
util_banner("Dodecic extension:", 0);
util_banner("Utilities:", 1);
memory12();
@@ -3805,7 +3899,7 @@ int main(void) {
arith12();
}
- if (fp_prime_get_qnr() && (ep_param_embed() >= 16)) {
+ if (fp_prime_get_qnr() && (ep_curve_embed() >= 16)) {
util_banner("Sextadecic extension:", 0);
util_banner("Utilities:", 1);
memory16();
@@ -3815,7 +3909,7 @@ int main(void) {
arith16();
}
- if (fp_prime_get_cnr() && (ep_param_embed() >= 18)) {
+ if (fp_prime_get_cnr() && (ep_curve_embed() >= 18)) {
util_banner("Octdecic extension:", 0);
util_banner("Utilities:", 1);
memory18();
@@ -3825,7 +3919,7 @@ int main(void) {
arith18();
}
- if (fp_prime_get_qnr() && (ep_param_embed() >= 24)) {
+ if (fp_prime_get_qnr() && (ep_curve_embed() >= 24)) {
util_banner("Extension of degree 24:", 0);
util_banner("Utilities:", 1);
memory24();
@@ -3834,7 +3928,7 @@ int main(void) {
arith24();
}
- if (fp_prime_get_qnr() && (ep_param_embed() >= 48)) {
+ if (fp_prime_get_qnr() && (ep_curve_embed() >= 48)) {
util_banner("Extension of degree 48:", 0);
util_banner("Utilities:", 1);
memory48();
@@ -3843,7 +3937,7 @@ int main(void) {
arith48();
}
- if (fp_prime_get_cnr() && (ep_param_embed() >= 54)) {
+ if (fp_prime_get_cnr() && (ep_curve_embed() >= 54)) {
util_banner("Extension of degree 54:", 0);
util_banner("Utilities:", 1);
memory54();
diff --git a/bench/bench_pc.c b/bench/bench_pc.c
index b161cb91a..bb040c6f4 100755
--- a/bench/bench_pc.c
+++ b/bench/bench_pc.c
@@ -216,6 +216,14 @@ static void arith1(void) {
}
BENCH_END;
+ BENCH_RUN("g1_mul_sec") {
+ bn_rand(k, RLC_POS, bn_bits(n));
+ bn_rand_mod(k, n);
+ g1_rand(p);
+ BENCH_ADD(g1_mul_sec(q, p, k));
+ }
+ BENCH_END;
+
BENCH_RUN("g1_mul_gen") {
bn_rand(k, RLC_POS, bn_bits(n));
bn_rand_mod(k, n);
@@ -468,6 +476,14 @@ static void arith2(void) {
}
BENCH_END;
+ BENCH_RUN("g2_mul_sec") {
+ bn_rand(k, RLC_POS, bn_bits(n));
+ bn_rand_mod(k, n);
+ g2_rand(p);
+ BENCH_ADD(g2_mul_sec(q, p, k));
+ }
+ BENCH_END;
+
BENCH_RUN("g2_mul_gen") {
bn_rand(k, RLC_POS, bn_bits(n));
bn_rand_mod(k, n);
@@ -613,7 +629,7 @@ static void util(void) {
BENCH_ADD(gt_read_bin(a, bin, l));
} BENCH_END;
- if (ep_param_embed() == 12) {
+ if (ep_curve_embed() == 12) {
BENCH_RUN("gt_write_bin (1)") {
gt_rand(a);
l = gt_size_bin(a, 1);
@@ -676,6 +692,14 @@ static void arith(void) {
}
BENCH_END;
+ BENCH_RUN("gt_exp_sec") {
+ gt_rand(a);
+ pc_get_ord(d);
+ bn_rand_mod(e, d);
+ BENCH_ADD(gt_exp_sec(c, a, e));
+ }
+ BENCH_END;
+
BENCH_RUN("gt_exp_gen") {
pc_get_ord(d);
bn_rand_mod(e, d);
diff --git a/bench/bench_pp.c b/bench/bench_pp.c
index a90c4e329..12407a134 100644
--- a/bench/bench_pp.c
+++ b/bench/bench_pp.c
@@ -1345,35 +1345,35 @@ int main(void) {
ep_param_print();
util_banner("Arithmetic:", 1);
- if (ep_param_embed() == 2) {
+ if (ep_curve_embed() == 2) {
pairing2();
}
- if (ep_param_embed() == 8) {
+ if (ep_curve_embed() == 8) {
pairing8();
}
- if (ep_param_embed() == 12) {
+ if (ep_curve_embed() == 12) {
pairing12();
}
- if (ep_param_embed() == 16) {
+ if (ep_curve_embed() == 16) {
pairing16();
}
- if (ep_param_embed() == 18) {
+ if (ep_curve_embed() == 18) {
pairing18();
}
- if (ep_param_embed() == 48) {
+ if (ep_curve_embed() == 48) {
pairing24();
}
- if (ep_param_embed() == 48) {
+ if (ep_curve_embed() == 48) {
pairing48();
}
- if (ep_param_embed() == 54) {
+ if (ep_curve_embed() == 54) {
pairing54();
}
diff --git a/cmake/gmp.cmake b/cmake/gmp.cmake
index abb00c44c..f71f64e65 100644
--- a/cmake/gmp.cmake
+++ b/cmake/gmp.cmake
@@ -36,7 +36,18 @@ if (GMP_INCLUDE_DIR AND GMP_LIBRARIES)
unset(GMP_LIBRARIES CACHE)
endif (GMP_INCLUDE_DIR AND GMP_LIBRARIES)
-find_path(GMP_INCLUDE_DIR NAMES gmp.h)
+find_path(GMP_INCLUDE_DIR gmp.h
+ PATHS
+ ENV GMP_ROOT
+ ENV GMP_INCLUDE_DIR
+ ${GMP_ROOT}
+ /usr
+ /usr/local
+ $ENV{HOME}/.local
+ PATH_SUFFIXES
+ include
+)
+
if(STBIN)
find_library(GMP_LIBRARIES NAMES libgmp.a gmp.lib libgmp-10 libgmp gmp)
else(STBIN)
diff --git a/demo/ers-etrs/test-bench b/demo/ers-etrs/test-bench
new file mode 100755
index 000000000..f412aa9ed
Binary files /dev/null and b/demo/ers-etrs/test-bench differ
diff --git a/include/relic_core.h b/include/relic_core.h
index 02e08741c..13805aeb5 100644
--- a/include/relic_core.h
+++ b/include/relic_core.h
@@ -267,8 +267,6 @@ typedef struct _ctx_t {
fp_st ep_a;
/** The b-coefficient of the elliptic curve. */
fp_st ep_b;
- /** The value 3b used in elliptic curve arithmetic. */
- fp_st ep_b3;
/** The generator of the elliptic curve. */
ep_st ep_g;
/** The order of the group of points in the elliptic curve. */
@@ -292,8 +290,6 @@ typedef struct _ctx_t {
int ep_opt_a;
/** Optimization identifier for the b-coefficient. */
int ep_opt_b;
- /** Optimization identifier for the b3 value. */
- int ep_opt_b3;
/** Flag that stores if the prime curve has efficient endomorphisms. */
int ep_is_endom;
/** Flag that stores if the prime curve is supersingular. */
diff --git a/include/relic_dv.h b/include/relic_dv.h
index cb7244cf7..6909c89a2 100644
--- a/include/relic_dv.h
+++ b/include/relic_dv.h
@@ -166,9 +166,9 @@ void dv_copy(dig_t *c, const dig_t *a, size_t digits);
* @param[out] c - the destination.
* @paraim[in] a - the source.
* @param[in] digits - the number of digits to copy.
- * @param[in] cond - the condition to evaluate.
+ * @param[in] bit - the condition bit to evaluate.
*/
-void dv_copy_cond(dig_t *c, const dig_t *a, size_t digits, dig_t cond);
+void dv_copy_sec(dig_t *c, const dig_t *a, size_t digits, dig_t bit);
/**
* Conditionally swap two digit vectors.
@@ -176,9 +176,9 @@ void dv_copy_cond(dig_t *c, const dig_t *a, size_t digits, dig_t cond);
* @param[in,out] c - the destination.
* @paraim[in,out] a - the source.
* @param[in] digits - the number of digits to copy.
- * @param[in] cond - the condition to evaluate.
+ * @param[in] bit - the condition bit to evaluate.
*/
-void dv_swap_cond(dig_t *c, dig_t *a, size_t digits, dig_t cond);
+void dv_swap_sec(dig_t *c, dig_t *a, size_t digits, dig_t bit);
/**
* Returns the result of a comparison between two digit vectors.
@@ -198,7 +198,7 @@ int dv_cmp(const dig_t *a, const dig_t *b, size_t size);
* @param[in] size - the length in digits of the vectors.
* @return RLC_EQ if they are equal and RLC_NE otherwise.
*/
-int dv_cmp_const(const dig_t *a, const dig_t *b, size_t size);
+int dv_cmp_sec(const dig_t *a, const dig_t *b, size_t size);
/**
* Allocates and initializes a temporary double-precision digit vector.
diff --git a/include/relic_eb.h b/include/relic_eb.h
index 8fbd928b0..1a5da9899 100644
--- a/include/relic_eb.h
+++ b/include/relic_eb.h
@@ -511,13 +511,13 @@ void eb_rand(eb_t p);
void eb_blind(eb_t r, const eb_t p);
/**
- * Computes the right-hand side of the elliptic curve equation at a certain
- * elliptic curve point.
+ * Computes the right-hand side of the elliptic curve equation at the
+ * x-coordinate of a certain binary elliptic curve point.
*
* @param[out] rhs - the result.
- * @param[in] p - the point.
+ * @param[in] x - the x-coordinate of the point.
*/
-void eb_rhs(fb_t rhs, const eb_t p);
+void eb_rhs(fb_t rhs, const fb_t p);
/** Tests if a point is in the curve.
*
diff --git a/include/relic_ed.h b/include/relic_ed.h
index abc888f3f..b30d196fe 100644
--- a/include/relic_ed.h
+++ b/include/relic_ed.h
@@ -321,13 +321,13 @@ void ed_rand(ed_t p);
void ed_blind(ed_t r, const ed_t p);
/**
- * Computes the right-hand side of the elliptic curve equation at a certain
- * Edwards elliptic curve point.
+ * Computes the right-hand side of the elliptic curve equation at the
+ * x-coordinate of a certain Edwards elliptic curve point.
*
* @param[out] rhs - the result.
- * @param[in] p - the point.
+ * @param[in] x - the x-coordinate of the point.
*/
-void ed_rhs(fp_t rhs, const ed_t p);
+void ed_rhs(fp_t rhs, const fp_t p);
/**
* Copies the second argument to the first argument.
diff --git a/include/relic_ep.h b/include/relic_ep.h
index 4279ce9b3..6daa5b96d 100644
--- a/include/relic_ep.h
+++ b/include/relic_ep.h
@@ -175,8 +175,6 @@ enum {
K18_P638,
/** Scott-Guillevic curve with embedding degree 18. */
SG18_P638,
- /** New family with embeeding degree 16. */
- N16_P765,
/* Fotiadis-Moartindale with embedding degree 16. */
FM16_P765,
/** Kachisa-Schaefer-Scott with embedding degree 16. */
@@ -185,6 +183,8 @@ enum {
N16_P766,
/* Fotiadis-Moartindale with embedding degree 18. */
FM18_P768,
+ /** Barreto-Lynn-Scott curve with embedding degree 12. */
+ B12_P1150,
/** 1536-bit supersingular curve. */
SS_P1536,
/** 3072-bit supersingular curve. */
@@ -221,7 +221,7 @@ enum {
#define RLC_EP_TABLE_COMBD (1 << (RLC_DEPTH + 1))
/**
- * Size of a precomputation table using the w-(T)NAF method.
+ * Size of a precomputation table using the w-NAF method.
*/
#define RLC_EP_TABLE_LWNAF (1 << (RLC_DEPTH - 2))
@@ -467,6 +467,16 @@ typedef iso_st *iso_t;
#define ep_mul_sim(R, P, K, Q, M) ep_mul_sim_joint(R, P, K, Q, M)
#endif
+/**
+ * Multiplies a point in an elliptic curve over by an unrestricted scalar.
+ * Computes R = [k]P.
+ *
+ * @param[out] R - the result.
+ * @param[in] P - the point to multiply.
+ * @param[in] K - the integer.
+ */
+#define ep_mul_big(R, P, K) ep_mul_basic(R, P, K)
+
/**
* Hashes a byte string to a prime elliptic point or the right order.
* Computes R = H(s).
@@ -547,13 +557,6 @@ int ep_curve_opt_a(void);
*/
int ep_curve_opt_b(void);
-/**
- * Returns a optimization identifier based on the b-coefficient of the curve.
- *
- * @return the optimization identifier.
- */
-int ep_curve_opt_b3(void);
-
/**
* Multiplies a field element by the a-coefficient of the curve.
*
@@ -570,13 +573,6 @@ void ep_curve_mul_a(fp_t c, const fp_t a);
*/
void ep_curve_mul_b(fp_t c, const fp_t a);
-/**
- * Multiplies a field element by the b3 value of the curve.
- *
- * @param[out] c - the result.
- * @param[in] a - the field element to multiply.
- */
-void ep_curve_mul_b3(fp_t c, const fp_t a);
/**
* Tests if the configured prime elliptic curve is a Koblitz curve.
*
@@ -683,6 +679,17 @@ void ep_curve_set_super(const fp_t a, const fp_t b, const ep_t g, const bn_t r,
void ep_curve_set_endom(const fp_t a, 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 ctmap);
+/**
+ * Returns the embedding degree of the currently configured elliptic curve.
+ */
+int ep_curve_embed(void);
+
+/**
+ * Returns the dimension of Frobenius expansions of the currently configured
+ * elliptic curve.
+ */
+int ep_curve_frdim(void);
+
/**
* Configures a prime elliptic curve by its parameter identifier.
*
@@ -745,11 +752,6 @@ void ep_param_print(void);
*/
int ep_param_level(void);
-/**
- * Returns the embedding degree of the currently configured elliptic curve.
- */
-int ep_param_embed(void);
-
/**
* Tests if a point on a prime elliptic curve is at the infinity.
*
@@ -798,13 +800,13 @@ void ep_rand(ep_t p);
void ep_blind(ep_t r, const ep_t p);
/**
- * Computes the right-hand side of the elliptic curve equation at a certain
- * prime elliptic curve point.
+ * Computes the right-hand side of the elliptic curve equation at the
+ * x-coordinate of a certain prime elliptic curve point.
*
* @param[out] rhs - the result.
- * @param[in] p - the point.
+ * @param[in] x - the x-coordinate of the point.
*/
-void ep_rhs(fp_t rhs, const ep_t p);
+void ep_rhs(fp_t rhs, const fp_t x);
/**
* Tests if a point is in the curve.
diff --git a/include/relic_epx.h b/include/relic_epx.h
index 9cb652243..ffd06f2ee 100644
--- a/include/relic_epx.h
+++ b/include/relic_epx.h
@@ -33,7 +33,7 @@
* The scalar multiplication functions are only guaranteed to work
* in the prime order subgroup used by pairings. If you need a generic scalar
- * multiplication function, use \sa ep2_mul_big().
+ * multiplication function, use epx_mul_big().
*
* @ingroup epx
*/
@@ -150,7 +150,7 @@ typedef ep3_st *ep3_t;
#endif
/**
- * Represents an elliptic curve point over a octic extension over a prime
+ * Represents an elliptic curve point over an octic extension over a prime
* field.
*/
typedef struct {
@@ -165,7 +165,7 @@ typedef struct {
} ep4_st;
/**
- * Pointer to an elliptic curve point over a octic extension field.
+ * Pointer to an elliptic curve point over an octic extension field.
*/
#if ALLOC == AUTO
typedef ep4_st ep4_t[1];
@@ -441,9 +441,11 @@ typedef iso2_st *iso2_t;
* @param[in] Q - the second point to add.
*/
#if EP_ADD == BASIC
-#define ep2_add(R, P, Q) ep2_add_basic(R, P, Q);
-#elif EP_ADD == PROJC || EP_ADD == JACOB
-#define ep2_add(R, P, Q) ep2_add_projc(R, P, Q);
+#define ep2_add(R, P, Q) ep2_add_basic(R, P, Q)
+#elif EP_ADD == PROJC
+#define ep2_add(R, P, Q) ep2_add_projc(R, P, Q)
+#elif EP_ADD == JACOB
+#define ep2_add(R, P, Q) ep2_add_jacob(R, P, Q)
#endif
/**
@@ -454,9 +456,11 @@ typedef iso2_st *iso2_t;
* @param[in] P - the point to double.
*/
#if EP_ADD == BASIC
-#define ep2_dbl(R, P) ep2_dbl_basic(R, P);
-#elif EP_ADD == PROJC || EP_ADD == JACOB
-#define ep2_dbl(R, P) ep2_dbl_projc(R, P);
+#define ep2_dbl(R, P) ep2_dbl_basic(R, P)
+#elif EP_ADD == PROJC
+#define ep2_dbl(R, P) ep2_dbl_projc(R, P)
+#elif EP_ADD == JACOB
+#define ep2_dbl(R, P) ep2_dbl_jacob(R, P)
#endif
/**
@@ -473,8 +477,10 @@ typedef iso2_st *iso2_t;
#define ep2_mul(R, P, K) ep2_mul_slide(R, P, K)
#elif EP_MUL == MONTY
#define ep2_mul(R, P, K) ep2_mul_monty(R, P, K)
-#elif EP_MUL == LWNAF || EP_MUL == LWREG
+#elif EP_MUL == LWNAF
#define ep2_mul(R, P, K) ep2_mul_lwnaf(R, P, K)
+#elif EP_MUL == LWREG
+#define ep2_mul(R, P, K) ep2_mul_lwreg(R, P, K)
#endif
/**
@@ -534,6 +540,16 @@ typedef iso2_st *iso2_t;
#define ep2_mul_sim(R, P, K, Q, M) ep2_mul_sim_joint(R, P, K, Q, M)
#endif
+/**
+ * Multiplies a point in an elliptic curve over a quadratic extension field by
+ * an unrestricted integer scalar. Computes R = [k]P.
+ *
+ * @param[out] R - the result.
+ * @param[in] P - the point to multiply.
+ * @param[in] K - the integer.
+ */
+#define ep2_mul_big(R, P, K) ep2_mul_basic(R, P, K)
+
/**
* Hashes a byte string to a prime elliptic point or the right order.
* Computes R = H(s).
@@ -559,9 +575,11 @@ typedef iso2_st *iso2_t;
* @param[in] Q - the second point to add.
*/
#if EP_ADD == BASIC
-#define ep3_add(R, P, Q) ep3_add_basic(R, P, Q);
-#elif EP_ADD == PROJC || EP_ADD == JACOB
-#define ep3_add(R, P, Q) ep3_add_projc(R, P, Q);
+#define ep3_add(R, P, Q) ep3_add_basic(R, P, Q)
+#elif EP_ADD == PROJC
+#define ep3_add(R, P, Q) ep3_add_projc(R, P, Q)
+#elif EP_ADD == JACOB
+#define ep3_add(R, P, Q) ep3_add_jacob(R, P, Q)
#endif
/**
@@ -572,9 +590,11 @@ typedef iso2_st *iso2_t;
* @param[in] P - the point to double.
*/
#if EP_ADD == BASIC
-#define ep3_dbl(R, P) ep3_dbl_basic(R, P);
-#elif EP_ADD == PROJC || EP_ADD == JACOB
-#define ep3_dbl(R, P) ep3_dbl_projc(R, P);
+#define ep3_dbl(R, P) ep3_dbl_basic(R, P)
+#elif EP_ADD == PROJC
+#define ep3_dbl(R, P) ep3_dbl_projc(R, P)
+#elif EP_ADD == JACOB
+#define ep3_dbl(R, P) ep3_dbl_jacob(R, P)
#endif
/**
@@ -591,8 +611,10 @@ typedef iso2_st *iso2_t;
#define ep3_mul(R, P, K) ep3_mul_slide(R, P, K)
#elif EP_MUL == MONTY
#define ep3_mul(R, P, K) ep3_mul_monty(R, P, K)
-#elif EP_MUL == LWNAF || EP_MUL == LWREG
+#elif EP_MUL == LWNAF
#define ep3_mul(R, P, K) ep3_mul_lwnaf(R, P, K)
+#elif EP_MUL == LWREG
+#define ep3_mul(R, P, K) ep3_mul_lwreg(R, P, K)
#endif
/**
@@ -653,7 +675,17 @@ typedef iso2_st *iso2_t;
#endif
/**
- * Adds two points in an elliptic curve over a octic extension field.
+ * Multiplies a point in an elliptic curve over a cubic extension field by
+ * an unrestricted integer scalar. Computes R = [k]P.
+ *
+ * @param[out] R - the result.
+ * @param[in] P - the point to multiply.
+ * @param[in] K - the integer.
+ */
+#define ep3_mul_big(R, P, K) ep3_mul_basic(R, P, K)
+
+/**
+ * Adds two points in an elliptic curve over a quartic extension field.
* Computes R = P + Q.
*
* @param[out] R - the result.
@@ -661,36 +693,30 @@ typedef iso2_st *iso2_t;
* @param[in] Q - the second point to add.
*/
#if EP_ADD == BASIC
-#define ep4_add(R, P, Q) ep4_add_basic(R, P, Q);
-#elif EP_ADD == PROJC || EP_ADD == JACOB
-#define ep4_add(R, P, Q) ep4_add_projc(R, P, Q);
+#define ep4_add(R, P, Q) ep4_add_basic(R, P, Q)
+#elif EP_ADD == PROJC
+#define ep4_add(R, P, Q) ep4_add_projc(R, P, Q)
+#elif EP_ADD == JACOB
+#define ep4_add(R, P, Q) ep4_add_jacob(R, P, Q)
#endif
/**
- * Doubles a point in an elliptic curve over a octic extension field.
+ * Doubles a point in an elliptic curve over a quartic extension field.
* Computes R = 2P.
*
* @param[out] R - the result.
* @param[in] P - the point to double.
*/
#if EP_ADD == BASIC
-#define ep4_dbl(R, P) ep4_dbl_basic(R, P);
-#elif EP_ADD == PROJC || EP_ADD == JACOB
-#define ep4_dbl(R, P) ep4_dbl_projc(R, P);
+#define ep4_dbl(R, P) ep4_dbl_basic(R, P)
+#elif EP_ADD == PROJC
+#define ep4_dbl(R, P) ep4_dbl_projc(R, P)
+#elif EP_ADD == JACOB
+#define ep4_dbl(R, P) ep4_dbl_jacob(R, P)
#endif
/**
- * Multiplies a point in an elliptic curve over a octic extension field by
- * an unrestricted integer scalar. Computes R = [k]P.
- *
- * @param[out] R - the result.
- * @param[in] P - the point to multiply.
- * @param[in] K - the integer.
- */
-#define ep4_mul_big(R, P, K) ep4_mul_basic(R, P, K)
-
-/**
- * Multiplies a point in an elliptic curve over a octic extension field.
+ * Multiplies a point in an elliptic curve over a quartic extension field.
* Computes R = [k]P.
*
* @param[out] R - the result.
@@ -703,13 +729,15 @@ typedef iso2_st *iso2_t;
#define ep4_mul(R, P, K) ep4_mul_slide(R, P, K)
#elif EP_MUL == MONTY
#define ep4_mul(R, P, K) ep4_mul_monty(R, P, K)
-#elif EP_MUL == LWNAF || EP_MUL == LWREG
+#elif EP_MUL == LWNAF
#define ep4_mul(R, P, K) ep4_mul_lwnaf(R, P, K)
+#elif EP_MUL == LWREG
+#define ep4_mul(R, P, K) ep4_mul_lwreg(R, P, K)
#endif
/**
* Builds a precomputation table for multiplying a fixed prime elliptic point
- * over a octic extension.
+ * over a quartic extension.
*
* @param[out] T - the precomputation table.
* @param[in] P - the point to multiply.
@@ -726,7 +754,7 @@ typedef iso2_st *iso2_t;
#endif
/**
- * Multiplies a fixed prime elliptic point over a octic extension using a
+ * Multiplies a fixed prime elliptic point over a quartic extension using a
* precomputation table. Computes R = [k]P.
*
* @param[out] R - the result.
@@ -765,7 +793,17 @@ typedef iso2_st *iso2_t;
#endif
/**
- * Adds two points in an elliptic curve over a octic extension field.
+ * Multiplies a point in an elliptic curve over a quartic extension field by
+ * an unrestricted integer scalar. Computes R = [k]P.
+ *
+ * @param[out] R - the result.
+ * @param[in] P - the point to multiply.
+ * @param[in] K - the integer.
+ */
+#define ep4_mul_big(R, P, K) ep4_mul_basic(R, P, K)
+
+/**
+ * Adds two points in an elliptic curve over an octic extension field.
* Computes R = P + Q.
*
* @param[out] R - the result.
@@ -773,36 +811,30 @@ typedef iso2_st *iso2_t;
* @param[in] Q - the second point to add.
*/
#if EP_ADD == BASIC
-#define ep8_add(R, P, Q) ep8_add_basic(R, P, Q);
-#elif EP_ADD == PROJC || EP_ADD == JACOB
-#define ep8_add(R, P, Q) ep8_add_projc(R, P, Q);
+#define ep8_add(R, P, Q) ep8_add_basic(R, P, Q)
+#elif EP_ADD == PROJC
+#define ep8_add(R, P, Q) ep8_add_projc(R, P, Q)
+#elif EP_ADD == JACOB
+#define ep8_add(R, P, Q) ep8_add_jacob(R, P, Q)
#endif
/**
- * Doubles a point in an elliptic curve over a octic extension field.
+ * Doubles a point in an elliptic curve over an octic extension field.
* Computes R = 2P.
*
* @param[out] R - the result.
* @param[in] P - the point to double.
*/
#if EP_ADD == BASIC
-#define ep8_dbl(R, P) ep8_dbl_basic(R, P);
-#elif EP_ADD == PROJC || EP_ADD == JACOB
-#define ep8_dbl(R, P) ep8_dbl_projc(R, P);
+#define ep8_dbl(R, P) ep8_dbl_basic(R, P)
+#elif EP_ADD == PROJC
+#define ep8_dbl(R, P) ep8_dbl_projc(R, P)
+#elif EP_ADD == JACOB
+#define ep8_dbl(R, P) ep8_dbl_jacob(R, P)
#endif
/**
- * Multiplies a point in an elliptic curve over a octic extension field by
- * an unrestricted integer scalar. Computes R = [k]P.
- *
- * @param[out] R - the result.
- * @param[in] P - the point to multiply.
- * @param[in] K - the integer.
- */
-#define ep8_mul_big(R, P, K) ep8_mul_basic(R, P, K)
-
-/**
- * Multiplies a point in an elliptic curve over a octic extension field.
+ * Multiplies a point in an elliptic curve over an octic extension field.
* Computes R = [k]P.
*
* @param[out] R - the result.
@@ -815,13 +847,15 @@ typedef iso2_st *iso2_t;
#define ep8_mul(R, P, K) ep8_mul_slide(R, P, K)
#elif EP_MUL == MONTY
#define ep8_mul(R, P, K) ep8_mul_monty(R, P, K)
-#elif EP_MUL == LWNAF || EP_MUL == LWREG
+#elif EP_MUL == LWNAF
#define ep8_mul(R, P, K) ep8_mul_lwnaf(R, P, K)
+#elif EP_MUL == LWREG
+#define ep8_mul(R, P, K) ep8_mul_lwreg(R, P, K)
#endif
/**
* Builds a precomputation table for multiplying a fixed prime elliptic point
- * over a octic extension.
+ * over an octic extension.
*
* @param[out] T - the precomputation table.
* @param[in] P - the point to multiply.
@@ -838,7 +872,7 @@ typedef iso2_st *iso2_t;
#endif
/**
- * Multiplies a fixed prime elliptic point over a octic extension using a
+ * Multiplies a fixed prime elliptic point over an octic extension using a
* precomputation table. Computes R = [k]P.
*
* @param[out] R - the result.
@@ -876,6 +910,16 @@ typedef iso2_st *iso2_t;
#define ep8_mul_sim(R, P, K, Q, M) ep8_mul_sim_joint(R, P, K, Q, M)
#endif
+/**
+ * Multiplies a point in an elliptic curve over an octic extension field by
+ * an unrestricted integer scalar. Computes R = [k]P.
+ *
+ * @param[out] R - the result.
+ * @param[in] P - the point to multiply.
+ * @param[in] K - the integer.
+ */
+#define ep8_mul_big(R, P, K) ep8_mul_basic(R, P, K)
+
/*============================================================================*/
/* Function prototypes */
/*============================================================================*/
@@ -918,6 +962,22 @@ int ep2_curve_opt_a(void);
*/
int ep2_curve_opt_b(void);
+/**
+ * Multiplies a field element by the a-coefficient of the curve.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the field element to multiply.
+ */
+void ep2_curve_mul_a(fp2_t c, const fp2_t a);
+
+/**
+ * Multiplies a field element by the b-coefficient of the curve.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the field element to multiply.
+ */
+void ep2_curve_mul_b(fp2_t c, const fp2_t a);
+
/**
* Tests if the configured elliptic curve is a twist.
*
@@ -1032,13 +1092,13 @@ void ep2_rand(ep2_t p);
void ep2_blind(ep2_t r, const ep2_t p);
/**
- * Computes the right-hand side of the elliptic curve equation at a certain
- * elliptic curve point.
+ * Computes the right-hand side of the elliptic curve equation at the
+ * x-coordinate of a certain prime elliptic curve point.
*
* @param[out] rhs - the result.
- * @param[in] p - the point.
+ * @param[in] x - the x-coordinate of the point.
*/
-void ep2_rhs(fp2_t rhs, const ep2_t p);
+void ep2_rhs(fp2_t rhs, const fp2_t x);
/**
* Tests if a point is in the curve.
@@ -1137,6 +1197,16 @@ void ep2_add_slp_basic(ep2_t r, fp2_t s, const ep2_t p, const ep2_t q);
*/
void ep2_add_projc(ep2_t r, const ep2_t p, const ep2_t q);
+/**
+ * Adds two points represented in Jacobian coordinates in an elliptic curve
+ * over a quadratic extension.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the first point to add.
+ * @param[in] q - the second point to add.
+ */
+void ep2_add_jacob(ep2_t r, const ep2_t p, const ep2_t q);
+
/**
* Subtracts a point in an elliptic curve over a quadratic extension from
* another.
@@ -1148,7 +1218,7 @@ void ep2_add_projc(ep2_t r, const ep2_t p, const ep2_t q);
void ep2_sub(ep2_t r, const ep2_t p, const ep2_t q);
/**
- * Doubles a points represented in affine coordinates in an elliptic curve over
+ * Doubles a point represented in affine coordinates in an elliptic curve over
* a quadratic extension.
*
* @param[out] r - the result.
@@ -1157,7 +1227,7 @@ void ep2_sub(ep2_t r, const ep2_t p, const ep2_t q);
void ep2_dbl_basic(ep2_t r, const ep2_t p);
/**
- * Doubles a points represented in affine coordinates in an elliptic curve over
+ * Doubles a point represented in affine coordinates in an elliptic curve over
* a quadratic extension and returns the computed slope.
*
* @param[out] r - the result.
@@ -1167,7 +1237,7 @@ void ep2_dbl_basic(ep2_t r, const ep2_t p);
void ep2_dbl_slp_basic(ep2_t r, fp2_t s, const ep2_t p);
/**
- * Doubles a points represented in projective coordinates in an elliptic curve
+ * Doubles a point represented in projective coordinates in an elliptic curve
* over a quadratic extension.
*
* @param[out] r - the result.
@@ -1175,6 +1245,15 @@ void ep2_dbl_slp_basic(ep2_t r, fp2_t s, const ep2_t p);
*/
void ep2_dbl_projc(ep2_t r, const ep2_t p);
+/**
+ * Doubles a point represented in Jacobian coordinates in an elliptic curve
+ * over a quadratic extension.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the point to double.
+ */
+void ep2_dbl_jacob(ep2_t r, const ep2_t p);
+
/**
* Multiplies a prime elliptic point by an integer using the binary method.
*
@@ -1525,12 +1604,12 @@ void ep2_pck(ep2_t r, const ep2_t p);
int ep2_upk(ep2_t r, const ep2_t p);
/**
- * Initializes the elliptic curve over octic extension.
+ * Initializes the elliptic curve over cubic extension.
*/
void ep3_curve_init(void);
/**
- * Finalizes the elliptic curve over octic extension.
+ * Finalizes the elliptic curve over cubic extension.
*/
void ep3_curve_clean(void);
@@ -1539,14 +1618,14 @@ void ep3_curve_clean(void);
*
* @return the 'a' coefficient of the elliptic curve.
*/
-void ep3_curve_get_a(fp3_t a);
+fp_t *ep3_curve_get_a(void);
/**
* Returns the 'b' coefficient of the currently configured elliptic curve.
*
* @param[out] b - the 'b' coefficient of the elliptic curve.
*/
-void ep3_curve_get_b(fp3_t b);
+fp_t *ep3_curve_get_b(void);
/**
* Returns a optimization identifier based on the 'a' coefficient of the curve.
@@ -1562,6 +1641,22 @@ int ep3_curve_opt_a(void);
*/
int ep3_curve_opt_b(void);
+/**
+ * Multiplies a field element by the a-coefficient of the curve.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the field element to multiply.
+ */
+void ep3_curve_mul_a(fp3_t c, const fp3_t a);
+
+/**
+ * Multiplies a field element by the b-coefficient of the curve.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the field element to multiply.
+ */
+void ep3_curve_mul_b(fp3_t c, const fp3_t a);
+
/**
* Tests if the configured elliptic curve is a twist.
*
@@ -1598,7 +1693,7 @@ void ep3_curve_get_ord(bn_t n);
void ep3_curve_get_cof(bn_t h);
/**
- * Configures an elliptic curve over a octic extension by its coefficients.
+ * Configures an elliptic curve over a cubic extension by its coefficients.
*
* @param[in] a - the 'a' coefficient of the curve.
* @param[in] b - the 'b' coefficient of the curve.
@@ -1664,13 +1759,13 @@ void ep3_rand(ep3_t p);
void ep3_blind(ep3_t r, const ep3_t p);
/**
- * Computes the right-hand side of the elliptic curve equation at a certain
- * elliptic curve point.
+ * Computes the right-hand side of the elliptic curve equation at the
+ * x-coordinate of a certain prime elliptic curve point.
*
* @param[out] rhs - the result.
- * @param[in] p - the point.
+ * @param[in] x - the x-coordinate of the point.
*/
-void ep3_rhs(fp3_t rhs, const ep3_t p);
+void ep3_rhs(fp3_t rhs, const fp3_t x);
/**
* Tests if a point is in the curve.
@@ -1697,7 +1792,7 @@ void ep3_print(const ep3_t p);
/**
* Returns the number of bytes necessary to store a prime elliptic curve point
- * over a octic extension with optional point compression.
+ * over a cubic extension with optional point compression.
*
* @param[in] a - the prime field element.
* @param[in] pack - the flag to indicate compression.
@@ -1706,7 +1801,7 @@ void ep3_print(const ep3_t p);
int ep3_size_bin(const ep3_t a, int pack);
/**
- * Reads a prime elliptic curve point over a octic extension from a byte
+ * Reads a prime elliptic curve point over a cubic extension from a byte
* vector in big-endian format.
*
* @param[out] a - the result.
@@ -1718,7 +1813,7 @@ int ep3_size_bin(const ep3_t a, int pack);
void ep3_read_bin(ep3_t a, const uint8_t *bin, size_t len);
/**
- * Writes a prime elliptic curve pointer over a octic extension to a byte
+ * Writes a prime elliptic curve pointer over a cubic extension to a byte
* vector in big-endian format with optional point compression.
*
* @param[out] bin - the byte vector.
@@ -1731,7 +1826,7 @@ void ep3_write_bin(uint8_t *bin, size_t len, const ep3_t a, int pack);
/**
* Negates a point represented in affine coordinates in an elliptic curve over
- * a octic extension.
+ * a cubic extension.
*
* @param[out] r - the result.
* @param[out] p - the point to negate.
@@ -1740,7 +1835,7 @@ void ep3_neg(ep3_t r, const ep3_t p);
/**
* Adds to points represented in affine coordinates in an elliptic curve over a
- * octic extension.
+ * cubic extension.
*
* @param[out] r - the result.
* @param[in] p - the first point to add.
@@ -1750,7 +1845,7 @@ void ep3_add_basic(ep3_t r, const ep3_t p, const ep3_t q);
/**
* Adds to points represented in affine coordinates in an elliptic curve over a
- * octic extension and returns the computed slope.
+ * cubic extension and returns the computed slope.
*
* @param[out] r - the result.
* @param[out] s - the slope.
@@ -1761,7 +1856,7 @@ void ep3_add_slp_basic(ep3_t r, fp3_t s, const ep3_t p, const ep3_t q);
/**
* Adds two points represented in projective coordinates in an elliptic curve
- * over a octic extension.
+ * over a cubic extension.
*
* @param[out] r - the result.
* @param[in] p - the first point to add.
@@ -1769,8 +1864,18 @@ void ep3_add_slp_basic(ep3_t r, fp3_t s, const ep3_t p, const ep3_t q);
*/
void ep3_add_projc(ep3_t r, const ep3_t p, const ep3_t q);
+/**
+ * Adds two points represented in Jacobian coordinates in an elliptic curve
+ * over a cubic extension.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the first point to add.
+ * @param[in] q - the second point to add.
+ */
+void ep3_add_jacob(ep3_t r, const ep3_t p, const ep3_t q);
+
/**
- * Subtracts a point in an elliptic curve over a octic extension from
+ * Subtracts a point in an elliptic curve over a cubic extension from
* another.
*
* @param[out] r - the result.
@@ -1780,8 +1885,8 @@ void ep3_add_projc(ep3_t r, const ep3_t p, const ep3_t q);
void ep3_sub(ep3_t r, const ep3_t p, const ep3_t q);
/**
- * Doubles a points represented in affine coordinates in an elliptic curve over
- * a octic extension.
+ * Doubles a point represented in affine coordinates in an elliptic curve over
+ * a cubic extension.
*
* @param[out] r - the result.
* @param[int] p - the point to double.
@@ -1789,8 +1894,8 @@ void ep3_sub(ep3_t r, const ep3_t p, const ep3_t q);
void ep3_dbl_basic(ep3_t r, const ep3_t p);
/**
- * Doubles a points represented in affine coordinates in an elliptic curve over
- * a octic extension and returns the computed slope.
+ * Doubles a point represented in affine coordinates in an elliptic curve over
+ * a cubic extension and returns the computed slope.
*
* @param[out] r - the result.
* @param[out] s - the slope.
@@ -1799,14 +1904,23 @@ void ep3_dbl_basic(ep3_t r, const ep3_t p);
void ep3_dbl_slp_basic(ep3_t r, fp3_t s, const ep3_t p);
/**
- * Doubles a points represented in projective coordinates in an elliptic curve
- * over a octic extension.
+ * Doubles a point represented in projective coordinates in an elliptic curve
+ * over a cubic extension.
*
* @param[out] r - the result.
* @param[in] p - the point to double.
*/
void ep3_dbl_projc(ep3_t r, const ep3_t p);
+/**
+ * Doubles a point represented in Jacobian coordinates in an elliptic curve
+ * over a cubic extension.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the point to double.
+ */
+void ep3_dbl_jacob(ep3_t r, const ep3_t p);
+
/**
* Multiplies a prime elliptic point by an integer using the binary method.
*
@@ -1872,7 +1986,7 @@ void ep3_mul_gen(ep3_t r, const bn_t k);
void ep3_mul_dig(ep3_t r, const ep3_t p, const dig_t k);
/**
- * Multiplies a point in an elliptic curve over a octic extension field by
+ * Multiplies a point in an elliptic curve over a cubic extension field by
* the curve cofactor or a small multiple for which a short vector exists.
* In short, it takes a point in the curve to the large prime-order subgroup.
*
@@ -2105,10 +2219,10 @@ void ep3_map(ep3_t p, const uint8_t *msg, size_t len);
/**
* Computes a power of the Gailbraith-Lin-Scott homomorphism of a point
* represented in affine coordinates on a twisted elliptic curve over a
- * octic exension. That is, Psi^i(P) = Twist(P)(Frob^i(unTwist(P)).
- * On the trace-zero group of a octic twist, consists of a power of the
+ * cubic exension. That is, Psi^i(P) = Twist(P)(Frob^i(unTwist(P)).
+ * On the trace-zero group of a cubic twist, consists of a power of the
* Frobenius map of a point represented in affine coordinates in an elliptic
- * curve over a octic exension. Computes Frob^i(P) = (p^i)P.
+ * curve over a cubic exension. Computes Frob^i(P) = (p^i)P.
*
* @param[out] r - the result in affine coordinates.
* @param[in] p - a point in affine coordinates.
@@ -2117,7 +2231,7 @@ void ep3_map(ep3_t p, const uint8_t *msg, size_t len);
void ep3_frb(ep3_t r, const ep3_t p, int i);
/**
- * Compresses a point in an elliptic curve over a octic extension.
+ * Compresses a point in an elliptic curve over a cubic extension.
*
* @param[out] r - the result.
* @param[in] p - the point to compress.
@@ -2125,7 +2239,7 @@ void ep3_frb(ep3_t r, const ep3_t p, int i);
void ep3_pck(ep3_t r, const ep3_t p);
/**
- * Decompresses a point in an elliptic curve over a octic extension.
+ * Decompresses a point in an elliptic curve over a cubic extension.
*
* @param[out] r - the result.
* @param[in] p - the point to decompress.
@@ -2134,12 +2248,12 @@ void ep3_pck(ep3_t r, const ep3_t p);
int ep3_upk(ep3_t r, const ep3_t p);
/**
- * Initializes the elliptic curve over octic extension.
+ * Initializes the elliptic curve over quartic extension.
*/
void ep4_curve_init(void);
/**
- * Finalizes the elliptic curve over octic extension.
+ * Finalizes the elliptic curve over quartic extension.
*/
void ep4_curve_clean(void);
@@ -2148,14 +2262,14 @@ void ep4_curve_clean(void);
*
* @return the 'a' coefficient of the elliptic curve.
*/
-void ep4_curve_get_a(fp4_t a);
+fp2_t *ep4_curve_get_a(void);
/**
* Returns the 'b' coefficient of the currently configured elliptic curve.
*
* @param[out] b - the 'b' coefficient of the elliptic curve.
*/
-void ep4_curve_get_b(fp4_t b);
+fp2_t *ep4_curve_get_b(void);
/**
* Returns a optimization identifier based on the 'a' coefficient of the curve.
@@ -2171,6 +2285,22 @@ int ep4_curve_opt_a(void);
*/
int ep4_curve_opt_b(void);
+/**
+ * Multiplies a field element by the a-coefficient of the curve.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the field element to multiply.
+ */
+void ep4_curve_mul_a(fp4_t c, const fp4_t a);
+
+/**
+ * Multiplies a field element by the b-coefficient of the curve.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the field element to multiply.
+ */
+void ep4_curve_mul_b(fp4_t c, const fp4_t a);
+
/**
* Tests if the configured elliptic curve is a twist.
*
@@ -2207,7 +2337,7 @@ void ep4_curve_get_ord(bn_t n);
void ep4_curve_get_cof(bn_t h);
/**
- * Configures an elliptic curve over a octic extension by its coefficients.
+ * Configures an elliptic curve over a quartic extension by its coefficients.
*
* @param[in] a - the 'a' coefficient of the curve.
* @param[in] b - the 'b' coefficient of the curve.
@@ -2273,13 +2403,13 @@ void ep4_rand(ep4_t p);
void ep4_blind(ep4_t r, const ep4_t p);
/**
- * Computes the right-hand side of the elliptic curve equation at a certain
- * elliptic curve point.
+ * Computes the right-hand side of the elliptic curve equation at the
+ * x-coordinate of a certain prime elliptic curve point.
*
* @param[out] rhs - the result.
- * @param[in] p - the point.
+ * @param[in] x - the x-coordinate of the point.
*/
-void ep4_rhs(fp4_t rhs, const ep4_t p);
+void ep4_rhs(fp4_t rhs, const fp4_t x);
/**
* Tests if a point is in the curve.
@@ -2306,7 +2436,7 @@ void ep4_print(const ep4_t p);
/**
* Returns the number of bytes necessary to store a prime elliptic curve point
- * over a octic extension with optional point compression.
+ * over a quartic extension with optional point compression.
*
* @param[in] a - the prime field element.
* @param[in] pack - the flag to indicate compression.
@@ -2315,7 +2445,7 @@ void ep4_print(const ep4_t p);
int ep4_size_bin(const ep4_t a, int pack);
/**
- * Reads a prime elliptic curve point over a octic extension from a byte
+ * Reads a prime elliptic curve point over a quartic extension from a byte
* vector in big-endian format.
*
* @param[out] a - the result.
@@ -2327,7 +2457,7 @@ int ep4_size_bin(const ep4_t a, int pack);
void ep4_read_bin(ep4_t a, const uint8_t *bin, size_t len);
/**
- * Writes a prime elliptic curve pointer over a octic extension to a byte
+ * Writes a prime elliptic curve pointer over a quartic extension to a byte
* vector in big-endian format with optional point compression.
*
* @param[out] bin - the byte vector.
@@ -2340,7 +2470,7 @@ void ep4_write_bin(uint8_t *bin, size_t len, const ep4_t a, int pack);
/**
* Negates a point represented in affine coordinates in an elliptic curve over
- * a octic extension.
+ * a quartic extension.
*
* @param[out] r - the result.
* @param[out] p - the point to negate.
@@ -2349,7 +2479,7 @@ void ep4_neg(ep4_t r, const ep4_t p);
/**
* Adds to points represented in affine coordinates in an elliptic curve over a
- * octic extension.
+ * quartic extension.
*
* @param[out] r - the result.
* @param[in] p - the first point to add.
@@ -2359,7 +2489,7 @@ void ep4_add_basic(ep4_t r, const ep4_t p, const ep4_t q);
/**
* Adds to points represented in affine coordinates in an elliptic curve over a
- * octic extension and returns the computed slope.
+ * quartic extension and returns the computed slope.
*
* @param[out] r - the result.
* @param[out] s - the slope.
@@ -2370,7 +2500,7 @@ void ep4_add_slp_basic(ep4_t r, fp4_t s, const ep4_t p, const ep4_t q);
/**
* Adds two points represented in projective coordinates in an elliptic curve
- * over a octic extension.
+ * over a quartic extension.
*
* @param[out] r - the result.
* @param[in] p - the first point to add.
@@ -2378,8 +2508,18 @@ void ep4_add_slp_basic(ep4_t r, fp4_t s, const ep4_t p, const ep4_t q);
*/
void ep4_add_projc(ep4_t r, const ep4_t p, const ep4_t q);
+/**
+ * Adds two points represented in Jacobian coordinates in an elliptic curve
+ * over a quartic extension.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the first point to add.
+ * @param[in] q - the second point to add.
+ */
+void ep4_add_jacob(ep4_t r, const ep4_t p, const ep4_t q);
+
/**
- * Subtracts a point in an elliptic curve over a octic extension from
+ * Subtracts a point in an elliptic curve over a quartic extension from
* another.
*
* @param[out] r - the result.
@@ -2389,8 +2529,8 @@ void ep4_add_projc(ep4_t r, const ep4_t p, const ep4_t q);
void ep4_sub(ep4_t r, const ep4_t p, const ep4_t q);
/**
- * Doubles a points represented in affine coordinates in an elliptic curve over
- * a octic extension.
+ * Doubles a point represented in affine coordinates in an elliptic curve over
+ * a quartic extension.
*
* @param[out] r - the result.
* @param[int] p - the point to double.
@@ -2398,8 +2538,8 @@ void ep4_sub(ep4_t r, const ep4_t p, const ep4_t q);
void ep4_dbl_basic(ep4_t r, const ep4_t p);
/**
- * Doubles a points represented in affine coordinates in an elliptic curve over
- * a octic extension and returns the computed slope.
+ * Doubles a point represented in affine coordinates in an elliptic curve over
+ * a quartic extension and returns the computed slope.
*
* @param[out] r - the result.
* @param[out] s - the slope.
@@ -2408,14 +2548,23 @@ void ep4_dbl_basic(ep4_t r, const ep4_t p);
void ep4_dbl_slp_basic(ep4_t r, fp4_t s, const ep4_t p);
/**
- * Doubles a points represented in projective coordinates in an elliptic curve
- * over a octic extension.
+ * Doubles a point represented in projective coordinates in an elliptic curve
+ * over a quartic extension.
*
* @param[out] r - the result.
* @param[in] p - the point to double.
*/
void ep4_dbl_projc(ep4_t r, const ep4_t p);
+/**
+ * Doubles a point represented in Jacobian coordinates in an elliptic curve
+ * over a quartic extension.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the point to double.
+ */
+void ep4_dbl_jacob(ep4_t r, const ep4_t p);
+
/**
* Multiplies a prime elliptic point by an integer using the binary method.
*
@@ -2482,7 +2631,7 @@ void ep4_mul_dig(ep4_t r, const ep4_t p, const dig_t k);
/**
- * Multiplies a point in an elliptic curve over a octic extension field by
+ * Multiplies a point in an elliptic curve over a quartic extension field by
* the curve cofactor or a small multiple for which a short vector exists.
* In short, it takes a point in the curve to the large prime-order subgroup.
*
@@ -2704,7 +2853,7 @@ void ep4_norm(ep4_t r, const ep4_t p);
void ep4_norm_sim(ep4_t *r, const ep4_t *t, int n);
/**
- * Maps a byte array to a point in an elliptic curve over a octic extension.
+ * Maps a byte array to a point in an elliptic curve over a quartic extension.
*
* @param[out] p - the result.
* @param[in] msg - the byte array to map.
@@ -2715,10 +2864,10 @@ void ep4_map(ep4_t p, const uint8_t *msg, size_t len);
/**
* Computes a power of the Gailbraith-Lin-Scott homomorphism of a point
* represented in affine coordinates on a twisted elliptic curve over a
- * octic exension. That is, Psi^i(P) = Twist(P)(Frob^i(unTwist(P)).
- * On the trace-zero group of a octic twist, consists of a power of the
+ * quartic exension. That is, Psi^i(P) = Twist(P)(Frob^i(unTwist(P)).
+ * On the trace-zero group of a quartic twist, consists of a power of the
* Frobenius map of a point represented in affine coordinates in an elliptic
- * curve over a octic exension. Computes Frob^i(P) = (p^i)P.
+ * curve over a quartic exension. Computes Frob^i(P) = (p^i)P.
*
* @param[out] r - the result in affine coordinates.
* @param[in] p - a point in affine coordinates.
@@ -2727,7 +2876,7 @@ void ep4_map(ep4_t p, const uint8_t *msg, size_t len);
void ep4_frb(ep4_t r, const ep4_t p, int i);
/**
- * Compresses a point in an elliptic curve over a octic extension.
+ * Compresses a point in an elliptic curve over a quartic extension.
*
* @param[out] r - the result.
* @param[in] p - the point to compress.
@@ -2735,7 +2884,7 @@ void ep4_frb(ep4_t r, const ep4_t p, int i);
void ep4_pck(ep4_t r, const ep4_t p);
/**
- * Decompresses a point in an elliptic curve over a octic extension.
+ * Decompresses a point in an elliptic curve over a quartic extension.
*
* @param[out] r - the result.
* @param[in] p - the point to decompress.
@@ -2758,14 +2907,14 @@ void ep8_curve_clean(void);
*
* @return the 'a' coefficient of the elliptic curve.
*/
-void ep8_curve_get_a(fp8_t a);
+fp4_t *ep8_curve_get_a(void);
/**
* Returns the 'b' coefficient of the currently configured elliptic curve.
*
* @param[out] b - the 'b' coefficient of the elliptic curve.
*/
-void ep8_curve_get_b(fp8_t b);
+fp4_t *ep8_curve_get_b(void);
/**
* Returns a optimization identifier based on the 'a' coefficient of the curve.
@@ -2781,6 +2930,22 @@ int ep8_curve_opt_a(void);
*/
int ep8_curve_opt_b(void);
+/**
+ * Multiplies a field element by the a-coefficient of the curve.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the field element to multiply.
+ */
+void ep8_curve_mul_a(fp8_t c, const fp8_t a);
+
+/**
+ * Multiplies a field element by the b-coefficient of the curve.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the field element to multiply.
+ */
+void ep8_curve_mul_b(fp8_t c, const fp8_t a);
+
/**
* Tests if the configured elliptic curve is a twist.
*
@@ -2817,7 +2982,7 @@ void ep8_curve_get_ord(bn_t n);
void ep8_curve_get_cof(bn_t h);
/**
- * Configures an elliptic curve over a octic extension by its coefficients.
+ * Configures an elliptic curve over an octic extension by its coefficients.
*
* @param[in] a - the 'a' coefficient of the curve.
* @param[in] b - the 'b' coefficient of the curve.
@@ -2883,13 +3048,13 @@ void ep8_rand(ep8_t p);
void ep8_blind(ep8_t r, const ep8_t p);
/**
- * Computes the right-hand side of the elliptic curve equation at a certain
- * elliptic curve point.
+ * Computes the right-hand side of the elliptic curve equation at the
+ * x-coordinate of a certain prime elliptic curve point.
*
* @param[out] rhs - the result.
- * @param[in] p - the point.
+ * @param[in] x - the x-coordinate of the point.
*/
-void ep8_rhs(fp8_t rhs, const ep8_t p);
+void ep8_rhs(fp8_t rhs, const fp8_t x);
/**
* Tests if a point is in the curve.
@@ -2916,7 +3081,7 @@ void ep8_print(const ep8_t p);
/**
* Returns the number of bytes necessary to store a prime elliptic curve point
- * over a octic extension with optional point compression.
+ * over an octic extension with optional point compression.
*
* @param[in] a - the prime field element.
* @param[in] pack - the flag to indicate compression.
@@ -2925,7 +3090,7 @@ void ep8_print(const ep8_t p);
int ep8_size_bin(const ep8_t a, int pack);
/**
- * Reads a prime elliptic curve point over a octic extension from a byte
+ * Reads a prime elliptic curve point over an octic extension from a byte
* vector in big-endian format.
*
* @param[out] a - the result.
@@ -2937,7 +3102,7 @@ int ep8_size_bin(const ep8_t a, int pack);
void ep8_read_bin(ep8_t a, const uint8_t *bin, size_t len);
/**
- * Writes a prime elliptic curve pointer over a octic extension to a byte
+ * Writes a prime elliptic curve pointer over an octic extension to a byte
* vector in big-endian format with optional point compression.
*
* @param[out] bin - the byte vector.
@@ -2950,7 +3115,7 @@ void ep8_write_bin(uint8_t *bin, size_t len, const ep8_t a, int pack);
/**
* Negates a point represented in affine coordinates in an elliptic curve over
- * a octic extension.
+ * an octic extension.
*
* @param[out] r - the result.
* @param[out] p - the point to negate.
@@ -2980,7 +3145,7 @@ void ep8_add_slp_basic(ep8_t r, fp8_t s, const ep8_t p, const ep8_t q);
/**
* Adds two points represented in projective coordinates in an elliptic curve
- * over a octic extension.
+ * over an octic extension.
*
* @param[out] r - the result.
* @param[in] p - the first point to add.
@@ -2988,8 +3153,18 @@ void ep8_add_slp_basic(ep8_t r, fp8_t s, const ep8_t p, const ep8_t q);
*/
void ep8_add_projc(ep8_t r, const ep8_t p, const ep8_t q);
+/**
+ * Adds two points represented in Jacobian coordinates in an elliptic curve
+ * over an octic extension.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the first point to add.
+ * @param[in] q - the second point to add.
+ */
+void ep8_add_jacob(ep8_t r, const ep8_t p, const ep8_t q);
+
/**
- * Subtracts a point in an elliptic curve over a octic extension from
+ * Subtracts a point in an elliptic curve over an octic extension from
* another.
*
* @param[out] r - the result.
@@ -2999,8 +3174,8 @@ void ep8_add_projc(ep8_t r, const ep8_t p, const ep8_t q);
void ep8_sub(ep8_t r, const ep8_t p, const ep8_t q);
/**
- * Doubles a points represented in affine coordinates in an elliptic curve over
- * a octic extension.
+ * Doubles a point represented in affine coordinates in an elliptic curve over
+ * an octic extension.
*
* @param[out] r - the result.
* @param[int] p - the point to double.
@@ -3008,8 +3183,8 @@ void ep8_sub(ep8_t r, const ep8_t p, const ep8_t q);
void ep8_dbl_basic(ep8_t r, const ep8_t p);
/**
- * Doubles a points represented in affine coordinates in an elliptic curve over
- * a octic extension and returns the computed slope.
+ * Doubles a point represented in affine coordinates in an elliptic curve over
+ * an octic extension and returns the computed slope.
*
* @param[out] r - the result.
* @param[out] s - the slope.
@@ -3018,14 +3193,23 @@ void ep8_dbl_basic(ep8_t r, const ep8_t p);
void ep8_dbl_slp_basic(ep8_t r, fp8_t s, const ep8_t p);
/**
- * Doubles a points represented in projective coordinates in an elliptic curve
- * over a octic extension.
+ * Doubles a point represented in projective coordinates in an elliptic curve
+ * over an octic extension.
*
* @param[out] r - the result.
* @param[in] p - the point to double.
*/
void ep8_dbl_projc(ep8_t r, const ep8_t p);
+/**
+ * Doubles a point represented in Jacobian coordinates in an elliptic curve
+ * over an octic extension.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the point to double.
+ */
+void ep8_dbl_jacob(ep8_t r, const ep8_t p);
+
/**
* Multiplies a prime elliptic point by an integer using the binary method.
*
@@ -3092,7 +3276,7 @@ void ep8_mul_dig(ep8_t r, const ep8_t p, const dig_t k);
/**
- * Multiplies a point in an elliptic curve over a octic extension field by
+ * Multiplies a point in an elliptic curve over an octic extension field by
* the curve cofactor or a small multiple for which a short vector exists.
* In short, it takes a point in the curve to the large prime-order subgroup.
*
@@ -3314,7 +3498,7 @@ void ep8_norm(ep8_t r, const ep8_t p);
void ep8_norm_sim(ep8_t *r, const ep8_t *t, int n);
/**
- * Maps a byte array to a point in an elliptic curve over a octic extension.
+ * Maps a byte array to a point in an elliptic curve over an octic extension.
*
* @param[out] p - the result.
* @param[in] msg - the byte array to map.
@@ -3326,9 +3510,9 @@ void ep8_map(ep8_t p, const uint8_t *msg, size_t len);
* Computes a power of the Gailbraith-Lin-Scott homomorphism of a point
* represented in affine coordinates on a twisted elliptic curve over a
* octic exension. That is, Psi^i(P) = Twist(P)(Frob^i(unTwist(P)).
- * On the trace-zero group of a octic twist, consists of a power of the
+ * On the trace-zero group of an octic twist, consists of a power of the
* Frobenius map of a point represented in affine coordinates in an elliptic
- * curve over a octic exension. Computes Frob^i(P) = (p^i)P.
+ * curve over an octic exension. Computes Frob^i(P) = (p^i)P.
*
* @param[out] r - the result in affine coordinates.
* @param[in] p - a point in affine coordinates.
@@ -3337,7 +3521,7 @@ void ep8_map(ep8_t p, const uint8_t *msg, size_t len);
void ep8_frb(ep8_t r, const ep8_t p, int i);
/**
- * Compresses a point in an elliptic curve over a octic extension.
+ * Compresses a point in an elliptic curve over an octic extension.
*
* @param[out] r - the result.
* @param[in] p - the point to compress.
@@ -3345,7 +3529,7 @@ void ep8_frb(ep8_t r, const ep8_t p, int i);
void ep8_pck(ep8_t r, const ep8_t p);
/**
- * Decompresses a point in an elliptic curve over a octic extension.
+ * Decompresses a point in an elliptic curve over an octic extension.
*
* @param[out] r - the result.
* @param[in] p - the point to decompress.
diff --git a/include/relic_fp.h b/include/relic_fp.h
index 8dabbf887..2ae5474af 100644
--- a/include/relic_fp.h
+++ b/include/relic_fp.h
@@ -156,8 +156,6 @@ enum {
K18_638,
/** 638-bit prime for SG curve with embedding degree 18. */
SG18_638,
- /** 765-bit prime for new family with embedding degree 16. */
- N16_765,
/** 765-bit prime for FM curve with embedding degree 16. */
FM16_765,
/** 766-bit prime for KSS curve with embedding degree 16. */
@@ -168,6 +166,8 @@ enum {
FM18_768,
/** 1024-bit prime for CTIDH. */
CTIDH_1024,
+ /** 1150-bit prime for BLS curve with embedding degree 12. */
+ B12_1150,
/** 1536-bit prime for supersingular curve with embedding degree k = 2. */
SS_1536,
/** 2048-bit prime for CTDIH. */
@@ -668,6 +668,15 @@ void fp_param_get_sps(int *s, int *len);
*/
void fp_copy(fp_t c, const fp_t a);
+/**
+ * Conditionally copies a field element to another field element.
+ *
+ * @param[out] c - the destination.
+ * @paraim[in] a - the source.
+ * @param[in] bit - the condition bit to evaluate.
+ */
+void fp_copy_sec(fp_t c, const fp_t a, dig_t bit);
+
/**
* Assigns zero to a prime field element.
*
diff --git a/include/relic_fpx.h b/include/relic_fpx.h
index c0f5f9c62..f06eb56fe 100644
--- a/include/relic_fpx.h
+++ b/include/relic_fpx.h
@@ -338,7 +338,7 @@ typedef fp18_t fp54_t[3];
/**
* Multiplies a quadratic extension field by the quadratic/cubic non-residue.
* Computes C = A * E, where E is a non-square/non-cube in the quadratic
- * extension.
+ * extension field.
*
* @param[out] C - the result.
* @param[in] A - the quadratic extension field element to multiply.
@@ -1398,6 +1398,15 @@ int fp2_field_get_qnr(void);
*/
void fp2_copy(fp2_t c, const fp2_t a);
+/**
+ * Conditionally copies the second argument to the first argument.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the quadratic extension field element to copy.
+ * @param[in] bit - the condition bit to evaluate.
+ */
+void fp2_copy_sec(fp2_t c, const fp2_t a, dig_t bit);
+
/**
* Assigns zero to a quadratic extension field element.
*
@@ -1800,6 +1809,15 @@ int fp3_field_get_cnr(void);
*/
void fp3_copy(fp3_t c, const fp3_t a);
+/**
+ * Conditionally copies the second argument to the first argument.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the cubic extension field element to copy.
+ * @param[in] bit - the condition bit to evaluate.
+ */
+void fp3_copy_sec(fp3_t c, const fp3_t a, dig_t bit);
+
/**
* Assigns zero to a cubic extension field element.
*
@@ -2107,10 +2125,19 @@ void fp4_field_init(void);
* Copies the second argument to the first argument.
*
* @param[out] c - the result.
- * @param[in] a - the sextic extension field element to copy.
+ * @param[in] a - the quartic extension field element to copy.
*/
void fp4_copy(fp4_t c, const fp4_t a);
+/**
+ * Conditionally copies the second argument to the first argument.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the quartic extension field element to copy.
+ * @param[in] bit - the condition bit to evaluate.
+ */
+void fp4_copy_sec(fp4_t c, const fp4_t a, dig_t bit);
+
/**
* Assigns zero to a quartic extension field element.
*
@@ -2417,6 +2444,16 @@ int fp4_srt(fp4_t c, const fp4_t a);
*/
void fp6_copy(fp6_t c, const fp6_t a);
+
+/**
+ * Conditionally copies the second argument to the first argument.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the sextic extension field element to copy.
+ * @param[in] bit - the condition bit to evaluate.
+ */
+void fp6_copy_sec(fp6_t c, const fp6_t a, dig_t bit);
+
/**
* Assigns zero to a sextic extension field element.
*
@@ -2651,6 +2688,15 @@ void fp8_field_init(void);
*/
void fp8_copy(fp8_t c, const fp8_t a);
+/**
+ * Conditionally copies the second argument to the first argument.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the octic extension field element to copy.
+ * @param[in] bit - the condition bit to evaluate.
+ */
+void fp8_copy_sec(fp8_t c, const fp8_t a, dig_t bit);
+
/**
* Assigns zero to an octic extension field element.
*
@@ -2708,9 +2754,10 @@ void fp8_read_bin(fp8_t a, const uint8_t *bin, size_t len);
* @param[out] bin - the byte vector.
* @param[in] len - the buffer capacity.
* @param[in] a - the extension field element to write.
+ * @param[in] pack - the flag to indicate compression.
* @throw ERR_NO_BUFFER - if the buffer capacity is not correct.
*/
-void fp8_write_bin(uint8_t *bin, size_t len, const fp8_t a);
+void fp8_write_bin(uint8_t *bin, size_t len, const fp8_t a, int pack);
/**
* Returns the result of a comparison between two octic extension field
@@ -2937,6 +2984,18 @@ void fp8_exp_dig(fp8_t c, const fp8_t a, dig_t b);
*/
void fp8_exp_cyc(fp8_t c, const fp8_t a, const bn_t b);
+/**
+ * Computes a power of two cyclotomic octic extension field elements.
+ *
+ * @param[out] e - the result.
+ * @param[in] a - the first element to exponentiate.
+ * @param[in] b - the first exponent.
+ * @param[in] c - the second element to exponentiate.
+ * @param[in] d - the second exponent.
+ */
+void fp8_exp_cyc_sim(fp8_t e, const fp8_t a, const bn_t b, const fp8_t c,
+ const bn_t d);
+
/**
* Computes a power of the Frobenius endomorphism of an octic extension field
* element. Computes c = a^p^i.
@@ -2973,6 +3032,15 @@ int fp8_srt(fp8_t c, const fp8_t a);
*/
void fp9_copy(fp9_t c, const fp9_t a);
+/**
+ * Conditionally copies the second argument to the first argument.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the nonic extension field element to copy.
+ * @param[in] bit - the condition bit to evaluate.
+ */
+void fp9_copy_sec(fp9_t c, const fp9_t a, dig_t bit);
+
/**
* Assigns zero to a nonic extension field element.
*
@@ -3211,6 +3279,15 @@ void fp9_frb(fp9_t c, const fp9_t a, int i);
*/
void fp12_copy(fp12_t c, const fp12_t a);
+/**
+ * Conditionally copies the second argument to the first argument.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the dodecic extension field element to copy.
+ * @param[in] bit - the condition bit to evaluate.
+ */
+void fp12_copy_sec(fp12_t c, const fp12_t a, dig_t bit);
+
/**
* Assigns zero to a dodecic extension field element.
*
@@ -3628,6 +3705,15 @@ void fp16_field_init(void);
*/
void fp16_copy(fp16_t c, const fp16_t a);
+/**
+ * Conditionally copies the second argument to the first argument.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the sextadecic extension field element to copy.
+ * @param[in] bit - the condition bit to evaluate.
+ */
+void fp16_copy_sec(fp16_t c, const fp16_t a, dig_t bit);
+
/**
* Assigns zero to an sextadecic extension field element.
*
@@ -3975,6 +4061,15 @@ int fp16_srt(fp16_t c, const fp16_t a);
*/
void fp18_copy(fp18_t c, const fp18_t a);
+/**
+ * Conditionally copies the second argument to the first argument.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the octdecic extension field element to copy.
+ * @param[in] bit - the condition bit to evaluate.
+ */
+void fp18_copy_sec(fp18_t c, const fp18_t a, dig_t bit);
+
/**
* Assigns zero to an octdecic extension field element.
*
@@ -4387,6 +4482,15 @@ int fp18_upk_max(fp18_t c, const fp18_t a);
*/
void fp24_copy(fp24_t c, const fp24_t a);
+/**
+ * Conditionally copies the second argument to the first argument.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the 24-degree extension field element to copy.
+ * @param[in] bit - the condition bit to evaluate.
+ */
+void fp24_copy_sec(fp24_t c, const fp24_t a, dig_t bit);
+
/**
* Assigns zero to a 24-degree extension field element.
*
@@ -4770,6 +4874,15 @@ int fp24_upk(fp24_t c, const fp24_t a);
*/
void fp48_copy(fp48_t c, const fp48_t a);
+/**
+ * Conditionally copies the second argument to the first argument.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the 48-degree extension field element to copy.
+ * @param[in] bit - the condition bit to evaluate.
+ */
+void fp48_copy_sec(fp48_t c, const fp48_t a, dig_t bit);
+
/**
* Assigns zero to a 48-extension field element.
*
@@ -5137,6 +5250,15 @@ int fp48_upk(fp48_t c, const fp48_t a);
*/
void fp54_copy(fp54_t c, const fp54_t a);
+/**
+ * Conditionally copies the second argument to the first argument.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the 54-degree extension field element to copy.
+ * @param[in] bit - the condition bit to evaluate.
+ */
+void fp54_copy_sec(fp54_t c, const fp54_t a, dig_t bit);
+
/**
* Assigns zero to a 54-extension field element.
*
diff --git a/include/relic_label.h b/include/relic_label.h
index 81dc60b6f..e030b9128 100644
--- a/include/relic_label.h
+++ b/include/relic_label.h
@@ -134,7 +134,7 @@
#undef util_conv_little
#undef util_conv_char
#undef util_bits_dig
-#undef util_cmp_const
+#undef util_cmp_sec
#undef util_perm
#undef util_printf
#undef util_print_dig
@@ -144,7 +144,7 @@
#define util_conv_little RLC_PREFIX(util_conv_little)
#define util_conv_char RLC_PREFIX(util_conv_char)
#define util_bits_dig RLC_PREFIX(util_bits_dig)
-#define util_cmp_const RLC_PREFIX(util_cmp_const)
+#define util_cmp_sec RLC_PREFIX(util_cmp_sec)
#define util_perm RLC_PREFIX(util_perm)
#define util_printf RLC_PREFIX(util_printf)
#define util_print_dig RLC_PREFIX(util_print_dig)
@@ -158,10 +158,10 @@
#undef dv_print
#undef dv_zero
#undef dv_copy
-#undef dv_copy_cond
-#undef dv_swap_cond
+#undef dv_copy_sec
+#undef dv_swap_sec
#undef dv_cmp
-#undef dv_cmp_const
+#undef dv_cmp_sec
#undef dv_new_dynam
#undef dv_free_dynam
#undef dv_lshd
@@ -170,10 +170,10 @@
#define dv_print RLC_PREFIX(dv_print)
#define dv_zero RLC_PREFIX(dv_zero)
#define dv_copy RLC_PREFIX(dv_copy)
-#define dv_copy_cond RLC_PREFIX(dv_copy_cond)
-#define dv_swap_cond RLC_PREFIX(dv_swap_cond)
+#define dv_copy_sec RLC_PREFIX(dv_copy_sec)
+#define dv_swap_sec RLC_PREFIX(dv_swap_sec)
#define dv_cmp RLC_PREFIX(dv_cmp)
-#define dv_cmp_const RLC_PREFIX(dv_cmp_const)
+#define dv_cmp_sec RLC_PREFIX(dv_cmp_sec)
#define dv_new_dynam RLC_PREFIX(dv_new_dynam)
#define dv_free_dynam RLC_PREFIX(dv_free_dynam)
#define dv_lshd RLC_PREFIX(dv_lshd)
@@ -489,6 +489,7 @@
#undef fp_prime_get_par_sps
#undef fp_param_get_sps
#undef fp_copy
+#undef fp_copy_sec
#undef fp_zero
#undef fp_is_zero
#undef fp_is_even
@@ -586,6 +587,7 @@
#define fp_prime_get_par_sps RLC_PREFIX(fp_prime_get_par_sps)
#define fp_param_get_sps RLC_PREFIX(fp_param_get_sps)
#define fp_copy RLC_PREFIX(fp_copy)
+#define fp_copy_sec RLC_PREFIX(fp_copy_sec)
#define fp_zero RLC_PREFIX(fp_zero)
#define fp_is_zero RLC_PREFIX(fp_is_zero)
#define fp_is_even RLC_PREFIX(fp_is_even)
@@ -919,10 +921,8 @@
#undef ep_curve_get_v2
#undef ep_curve_opt_a
#undef ep_curve_opt_b
-#undef ep_curve_opt_b3
#undef ep_curve_mul_a
#undef ep_curve_mul_b
-#undef ep_curve_mul_b3
#undef ep_curve_is_endom
#undef ep_curve_is_super
#undef ep_curve_is_pairf
@@ -944,7 +944,7 @@
#undef ep_param_get
#undef ep_param_print
#undef ep_param_level
-#undef ep_param_embed
+#undef ep_curve_embed
#undef ep_is_infty
#undef ep_set_infty
#undef ep_copy
@@ -1014,10 +1014,8 @@
#define ep_curve_get_v2 RLC_PREFIX(ep_curve_get_v2)
#define ep_curve_opt_a RLC_PREFIX(ep_curve_opt_a)
#define ep_curve_opt_b RLC_PREFIX(ep_curve_opt_b)
-#define ep_curve_opt_b3 RLC_PREFIX(ep_curve_opt_b3)
#define ep_curve_mul_a RLC_PREFIX(ep_curve_mul_a)
#define ep_curve_mul_b RLC_PREFIX(ep_curve_mul_b)
-#define ep_curve_mul_b3 RLC_PREFIX(ep_curve_mul_b3)
#define ep_curve_is_endom RLC_PREFIX(ep_curve_is_endom)
#define ep_curve_is_super RLC_PREFIX(ep_curve_is_super)
#define ep_curve_is_pairf RLC_PREFIX(ep_curve_is_pairf)
@@ -1039,7 +1037,7 @@
#define ep_param_get RLC_PREFIX(ep_param_get)
#define ep_param_print RLC_PREFIX(ep_param_print)
#define ep_param_level RLC_PREFIX(ep_param_level)
-#define ep_param_embed RLC_PREFIX(ep_param_embed)
+#define ep_curve_embed RLC_PREFIX(ep_curve_embed)
#define ep_is_infty RLC_PREFIX(ep_is_infty)
#define ep_set_infty RLC_PREFIX(ep_set_infty)
#define ep_copy RLC_PREFIX(ep_copy)
@@ -1402,6 +1400,8 @@
#undef ep2_curve_get_b
#undef ep2_curve_opt_a
#undef ep2_curve_opt_b
+#undef ep2_curve_mul_a
+#undef ep2_curve_mul_b
#undef ep2_curve_is_twist
#undef ep2_curve_is_ctmap
#undef ep2_curve_get_gen
@@ -1428,10 +1428,12 @@
#undef ep2_add_basic
#undef ep2_add_slp_basic
#undef ep2_add_projc
+#undef ep2_add_jacob
#undef ep2_sub
#undef ep2_dbl_basic
#undef ep2_dbl_slp_basic
#undef ep2_dbl_projc
+#undef ep2_dbl_jacob
#undef ep2_mul_basic
#undef ep2_mul_slide
#undef ep2_mul_monty
@@ -1474,6 +1476,8 @@
#define ep2_curve_get_b RLC_PREFIX(ep2_curve_get_b)
#define ep2_curve_opt_a RLC_PREFIX(ep2_curve_opt_a)
#define ep2_curve_opt_b RLC_PREFIX(ep2_curve_opt_b)
+#define ep2_curve_mul_a RLC_PREFIX(ep2_curve_mul_a)
+#define ep2_curve_mul_b RLC_PREFIX(ep2_curve_mul_b)
#define ep2_curve_is_twist RLC_PREFIX(ep2_curve_is_twist)
#define ep2_curve_is_ctmap RLC_PREFIX(ep2_curve_is_ctmap)
#define ep2_curve_get_gen RLC_PREFIX(ep2_curve_get_gen)
@@ -1500,10 +1504,12 @@
#define ep2_add_basic RLC_PREFIX(ep2_add_basic)
#define ep2_add_slp_basic RLC_PREFIX(ep2_add_slp_basic)
#define ep2_add_projc RLC_PREFIX(ep2_add_projc)
+#define ep2_add_jacob RLC_PREFIX(ep2_add_jacob)
#define ep2_sub RLC_PREFIX(ep2_sub)
#define ep2_dbl_basic RLC_PREFIX(ep2_dbl_basic)
#define ep2_dbl_slp_basic RLC_PREFIX(ep2_dbl_slp_basic)
#define ep2_dbl_projc RLC_PREFIX(ep2_dbl_projc)
+#define ep2_dbl_jacob RLC_PREFIX(ep2_dbl_jacob)
#define ep2_mul_basic RLC_PREFIX(ep2_mul_basic)
#define ep2_mul_slide RLC_PREFIX(ep2_mul_slide)
#define ep2_mul_monty RLC_PREFIX(ep2_mul_monty)
@@ -2027,6 +2033,7 @@
#undef fp2_field_init
#undef fp2_field_get_qnr
#undef fp2_copy
+#undef fp2_copy_sec
#undef fp2_zero
#undef fp2_is_zero
#undef fp2_rand
@@ -2073,6 +2080,7 @@
#define fp2_field_init RLC_PREFIX(fp2_field_init)
#define fp2_field_get_qnr RLC_PREFIX(fp2_field_get_qnr)
#define fp2_copy RLC_PREFIX(fp2_copy)
+#define fp2_copy_sec RLC_PREFIX(fp2_copy_sec)
#define fp2_zero RLC_PREFIX(fp2_zero)
#define fp2_is_zero RLC_PREFIX(fp2_is_zero)
#define fp2_rand RLC_PREFIX(fp2_rand)
@@ -2157,6 +2165,7 @@
#undef fp3_field_init
#undef fp3_field_get_cnr
#undef fp3_copy
+#undef fp3_copy_sec
#undef fp3_zero
#undef fp3_is_zero
#undef fp3_rand
@@ -2194,6 +2203,7 @@
#define fp3_field_init RLC_PREFIX(fp3_field_init)
#define fp3_field_get_cnr RLC_PREFIX(fp3_field_get_cnr)
#define fp3_copy RLC_PREFIX(fp3_copy)
+#define fp3_copy_sec RLC_PREFIX(fp3_copy_sec)
#define fp3_zero RLC_PREFIX(fp3_zero)
#define fp3_is_zero RLC_PREFIX(fp3_is_zero)
#define fp3_rand RLC_PREFIX(fp3_rand)
@@ -2266,6 +2276,7 @@
#undef fp4_field_init
#undef fp4_copy
+#undef fp4_copy_sec
#undef fp4_zero
#undef fp4_is_zero
#undef fp4_rand
@@ -2302,6 +2313,7 @@
#define fp4_field_init RLC_PREFIX(fp4_field_init)
#define fp4_copy RLC_PREFIX(fp4_copy)
+#define fp4_copy_sec RLC_PREFIX(fp4_copy_sec)
#define fp4_zero RLC_PREFIX(fp4_zero)
#define fp4_is_zero RLC_PREFIX(fp4_is_zero)
#define fp4_rand RLC_PREFIX(fp4_rand)
@@ -2337,6 +2349,7 @@
#define fp4_srt RLC_PREFIX(fp4_srt)
#undef fp6_copy
+#undef fp6_copy_sec
#undef fp6_zero
#undef fp6_is_zero
#undef fp6_rand
@@ -2364,6 +2377,7 @@
#undef fp6_frb
#define fp6_copy RLC_PREFIX(fp6_copy)
+#define fp6_copy_sec RLC_PREFIX(fp6_copy_sec)
#define fp6_zero RLC_PREFIX(fp6_zero)
#define fp6_is_zero RLC_PREFIX(fp6_is_zero)
#define fp6_rand RLC_PREFIX(fp6_rand)
@@ -2392,6 +2406,7 @@
#undef fp8_field_init
#undef fp8_copy
+#undef fp8_copy_sec
#undef fp8_zero
#undef fp8_is_zero
#undef fp8_rand
@@ -2430,6 +2445,7 @@
#define fp8_field_init RLC_PREFIX(fp8_field_init)
#define fp8_copy RLC_PREFIX(fp8_copy)
+#define fp8_copy_sec RLC_PREFIX(fp8_copy_sec)
#define fp8_zero RLC_PREFIX(fp8_zero)
#define fp8_is_zero RLC_PREFIX(fp8_is_zero)
#define fp8_rand RLC_PREFIX(fp8_rand)
@@ -2467,6 +2483,7 @@
#define fp8_srt RLC_PREFIX(fp8_srt)
#undef fp9_copy
+#undef fp9_copy_sec
#undef fp9_zero
#undef fp9_is_zero
#undef fp9_rand
@@ -2495,6 +2512,7 @@
#undef fp9_frb
#define fp9_copy RLC_PREFIX(fp9_copy)
+#define fp9_copy_sec RLC_PREFIX(fp9_copy_sec)
#define fp9_zero RLC_PREFIX(fp9_zero)
#define fp9_is_zero RLC_PREFIX(fp9_is_zero)
#define fp9_rand RLC_PREFIX(fp9_rand)
@@ -2523,6 +2541,7 @@
#define fp9_frb RLC_PREFIX(fp9_frb)
#undef fp12_copy
+#undef fp12_copy_sec
#undef fp12_zero
#undef fp12_is_zero
#undef fp12_rand
@@ -2569,6 +2588,7 @@
#undef fp12_upk_max
#define fp12_copy RLC_PREFIX(fp12_copy)
+#define fp12_copy_sec RLC_PREFIX(fp12_copy_sec)
#define fp12_zero RLC_PREFIX(fp12_zero)
#define fp12_is_zero RLC_PREFIX(fp12_is_zero)
#define fp12_rand RLC_PREFIX(fp12_rand)
@@ -2615,6 +2635,7 @@
#define fp12_upk_max RLC_PREFIX(fp12_upk_max)
#undef fp18_copy
+#undef fp18_copy_sec
#undef fp18_zero
#undef fp18_is_zero
#undef fp18_rand
@@ -2661,6 +2682,7 @@
#undef fp18_upk_max
#define fp18_copy RLC_PREFIX(fp18_copy)
+#define fp18_copy_sec RLC_PREFIX(fp18_copy_sec)
#define fp18_zero RLC_PREFIX(fp18_zero)
#define fp18_is_zero RLC_PREFIX(fp18_is_zero)
#define fp18_rand RLC_PREFIX(fp18_rand)
@@ -2707,6 +2729,7 @@
#define fp18_upk_max RLC_PREFIX(fp18_upk_max)
#undef fp24_copy
+#undef fp24_copy_sec
#undef fp24_zero
#undef fp24_is_zero
#undef fp24_rand
@@ -2750,6 +2773,7 @@
#undef fp24_upk
#define fp24_copy RLC_PREFIX(fp24_copy)
+#define fp24_copy_sec RLC_PREFIX(fp24_copy_sec)
#define fp24_zero RLC_PREFIX(fp24_zero)
#define fp24_is_zero RLC_PREFIX(fp24_is_zero)
#define fp24_rand RLC_PREFIX(fp24_rand)
@@ -2793,6 +2817,7 @@
#define fp24_upk RLC_PREFIX(fp24_upk)
#undef fp48_copy
+#undef fp48_copy_sec
#undef fp48_zero
#undef fp48_is_zero
#undef fp48_rand
@@ -2834,6 +2859,7 @@
#undef fp48_upk
#define fp48_copy RLC_PREFIX(fp48_copy)
+#define fp48_copy_sec RLC_PREFIX(fp48_copy_sec)
#define fp48_zero RLC_PREFIX(fp48_zero)
#define fp48_is_zero RLC_PREFIX(fp48_is_zero)
#define fp48_rand RLC_PREFIX(fp48_rand)
@@ -2875,6 +2901,7 @@
#define fp48_upk RLC_PREFIX(fp48_upk)
#undef fp54_copy
+#undef fp54_copy_sec
#undef fp54_zero
#undef fp54_is_zero
#undef fp54_rand
@@ -2914,6 +2941,7 @@
#undef fp54_upk
#define fp54_copy RLC_PREFIX(fp54_copy)
+#define fp54_copy_sec RLC_PREFIX(fp54_copy_sec)
#define fp54_zero RLC_PREFIX(fp54_zero)
#define fp54_is_zero RLC_PREFIX(fp54_is_zero)
#define fp54_rand RLC_PREFIX(fp54_rand)
diff --git a/include/relic_pc.h b/include/relic_pc.h
index 62a0bfe2a..2fe17788e 100644
--- a/include/relic_pc.h
+++ b/include/relic_pc.h
@@ -84,12 +84,15 @@
#elif FP_PRIME == 330 || FP_PRIME == 765 || FP_PRIME == 766
#define RLC_GT_LOWER fp16_
#define RLC_GT_EMBED 16
+#elif FP_PRIME == 544
+#define RLC_GT_LOWER fp8_
+#define RLC_GT_EMBED 8
#else
#define RLC_GT_LOWER fp12_
#define RLC_GT_EMBED 12
#endif
-#else
+#else /* FP_PRIME >= 1536*/
#define RLC_G1_LOWER ep_
#define RLC_G1_UPPER EP
#define RLC_G2_LOWER ep_
@@ -406,6 +409,15 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t;
*/
#define gt_copy(C, A) RLC_CAT(RLC_GT_LOWER, copy)(C, A)
+/**
+ * Conditionally copies the second argument to the first argument.
+ *
+ * @param[out] C - the result.
+ * @param[in] A - the element to copy.
+ * @param[in] B - the condition bit to evaluate.
+ */
+#define gt_copy_sec(C, A, B) RLC_CAT(RLC_GT_LOWER, copy_sec)(C, A, B)
+
/**
* Compares two elements from G_1.
*
@@ -729,7 +741,16 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t;
* @param[in] P - the element to multiply.
* @param[in] K - the secret scalar.
*/
-#define g1_mul_key(R, P, K) RLC_CAT(RLC_G1_LOWER, mul_lwreg)(R, P, K)
+#define g1_mul_sec(R, P, K) RLC_CAT(RLC_G1_LOWER, mul_lwreg)(R, P, K)
+
+/**
+ * Multiplies an element from G_2 by a secret scalar. Computes R = [k]P.
+ *
+ * @param[out] R - the result.
+ * @param[in] P - the element to multiply.
+ * @param[in] K - the secret scalar.
+ */
+#define g2_mul_sec(R, P, K) RLC_CAT(RLC_G2_LOWER, mul_lwreg)(R, P, K)
/**
* Multiplies an element from a larger group containing G_1 by a scalar.
@@ -910,7 +931,7 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t;
#if FP_PRIME <= 1536
#define gt_frb(C, A, I) RLC_CAT(RLC_GT_LOWER, frb)(C, A, I)
#else
-#define gt_frb(C, A, I) (A)
+#define gt_frb(C, A, I) RLC_CAT(RLC_GT_LOWER, copy)(C, A)
#endif
/**
@@ -1030,6 +1051,15 @@ void g2_mul_gen(g2_t r, const bn_t k);
*/
void gt_exp(gt_t c, const gt_t a, const bn_t b);
+/**
+ * Exponentiates an element from G_T by a secret integer. Computes c = a^b.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the element to exponentiate.
+ * @param[in] b - the integer exponent.
+ */
+void gt_exp_sec(gt_t c, const gt_t a, const bn_t b);
+
/**
* Exponentiates an element from G_T by a small integer. Computes c = a^b.
*
diff --git a/include/relic_pp.h b/include/relic_pp.h
index 2077bb691..541bf2953 100644
--- a/include/relic_pp.h
+++ b/include/relic_pp.h
@@ -493,7 +493,7 @@
#define pp_map_k1(R, P, Q) pp_map_tatep_k1(R, P, Q)
#endif
-/**pp_map
+/**
* Computes a pairing of two prime elliptic curve points defined on an elliptic
* curves of embedding degree 2. Computes e(P, Q).
*
@@ -509,6 +509,16 @@
#define pp_map_k2(R, P, Q) pp_map_tatep_k2(R, P, Q)
#endif
+/**
+ * Computes a pairing of two prime elliptic curve points defined on an elliptic
+ * curves of embedding degree 8. Computes e(P, Q).
+ *
+ * @param[out] R - the result.
+ * @param[in] P - the first elliptic curve point.
+ * @param[in] Q - the second elliptic curve point.
+ */
+#define pp_map_k8(R, P, Q) pp_map_oatep_k8(R, P, Q)
+
/**
* Computes a pairing of two prime elliptic curve points defined on an elliptic
* curve of embedding degree 12. Computes e(P, Q).
@@ -587,6 +597,17 @@
#define pp_map_sim_k2(R, P, Q, M) pp_map_sim_tatep_k2(R, P, Q, M)
#endif
+/**
+ * Computes a multi-pairing of elliptic curve points defined on an elliptic
+ * curve of embedding degree 8. Computes \prod e(P_i, Q_i).
+ *
+ * @param[out] R - the result.
+ * @param[in] P - the first pairing arguments.
+ * @param[in] Q - the second pairing arguments.
+ * @param[in] M - the number of pairings to evaluate.
+ */
+#define pp_map_sim_k8(R, P, Q, M) pp_map_sim_oatep_k8(R, P, Q, M)
+
/**
* Computes a multi-pairing of elliptic curve points defined on an elliptic
* curve of embedding degree 12. Computes \prod e(P_i, Q_i).
@@ -1520,6 +1541,17 @@ void pp_map_sim_weilp_k2(fp2_t r, const ep_t *p, const ep_t *q, int m);
*/
void pp_map_oatep_k8(fp8_t r, const ep_t p, const ep2_t q);
+/**
+ * Computes the optimal ate multi-pairing in a parameterized elliptic
+ * curve with embedding degree 8.
+ *
+ * @param[out] r - the result.
+ * @param[in] q - the first pairing arguments.
+ * @param[in] p - the second pairing arguments.
+ * @param[in] m - the number of pairings to evaluate.
+ */
+void pp_map_sim_oatep_k8(fp8_t r, const ep_t *p, const ep2_t *q, int m);
+
/**
* Computes the Tate pairing of two points in a parameterized elliptic curve
* with embedding degree 12.
diff --git a/include/relic_util.h b/include/relic_util.h
index d24737bba..0f80914f9 100644
--- a/include/relic_util.h
+++ b/include/relic_util.h
@@ -295,7 +295,7 @@ size_t util_bits_dig(dig_t a);
* @param[in] n - the length in bytes of the buffers.
* @return RLC_EQ if they are equal and RLC_NE otherwise.
*/
-int util_cmp_const(const void *a, const void *b, size_t n);
+int util_cmp_sec(const void *a, const void *b, size_t n);
/**
* Computes a random permutation in [0, n-1].
diff --git a/preset/gmp-pbc-bls12-1150.sh b/preset/gmp-pbc-bls12-1150.sh
new file mode 100755
index 000000000..4ed607e08
--- /dev/null
+++ b/preset/gmp-pbc-bls12-1150.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=gmp-sec -DBN_PRECI=1536 -DFP_PRIME=1150 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;JMPDS;JMPDS;SLIDE" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -finline-small-functions -march=native -mtune=native" -DFP_PMERS=off -DFP_QNRES=off -DFPX_METHD="INTEG;INTEG;LAZYR" -DEP_PLAIN=off -DEP_SUPER=off -DPP_METHD="LAZYR;OATEP" $1
diff --git a/preset/gmp-pbc-k13072.sh b/preset/gmp-pbc-k13072.sh
new file mode 100755
index 000000000..5eff63b76
--- /dev/null
+++ b/preset/gmp-pbc-k13072.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+cmake -DCHECK=off -DARITH=gmp -DBN_PRECI=3072 -DFP_PRIME=3072 -DFP_QNRES=off -DFP_METHD="BASIC;COMBA;COMBA;MONTY;JMPDS;JMPDS;SLIDE" -DFPX_METHD="INTEG;INTEG;LAZYR" -DPP_METHD="LAZYR;OATEP" -DCFLAGS="-O2 -funroll-loops -fomit-frame-pointer" -DEP_PLAIN=on -DTESTS=10 -DBENCH=10 $1
diff --git a/preset/x64-pbc-afg16-765.sh b/preset/x64-pbc-fm16-765.sh
similarity index 100%
rename from preset/x64-pbc-afg16-765.sh
rename to preset/x64-pbc-fm16-765.sh
diff --git a/src/bn/relic_bn_mxp.c b/src/bn/relic_bn_mxp.c
index b9080e609..625277f87 100644
--- a/src/bn/relic_bn_mxp.c
+++ b/src/bn/relic_bn_mxp.c
@@ -265,7 +265,7 @@ void bn_mxp_monty(bn_t c, const bn_t a, const bn_t b, const bn_t m) {
bn_grow(tab[1], m->alloc);
for (i = bn_bits(b) - 1; i >= 0; i--) {
j = bn_get_bit(b, i);
- dv_swap_cond(tab[0]->dp, tab[1]->dp, m->alloc, j ^ 1);
+ dv_swap_sec(tab[0]->dp, tab[1]->dp, m->alloc, j ^ 1);
mask = -(j ^ 1);
t = (tab[0]->used ^ tab[1]->used) & mask;
tab[0]->used ^= t;
@@ -277,7 +277,7 @@ void bn_mxp_monty(bn_t c, const bn_t a, const bn_t b, const bn_t m) {
bn_mod(tab[0], tab[0], m, u);
bn_sqr(tab[1], tab[1]);
bn_mod(tab[1], tab[1], m, u);
- dv_swap_cond(tab[0]->dp, tab[1]->dp, m->alloc, j ^ 1);
+ dv_swap_sec(tab[0]->dp, tab[1]->dp, m->alloc, j ^ 1);
mask = -(j ^ 1);
t = (tab[0]->used ^ tab[1]->used) & mask;
tab[0]->used ^= t;
diff --git a/src/cp/relic_cp_bls.c b/src/cp/relic_cp_bls.c
index fac290e3e..6ddb347a9 100644
--- a/src/cp/relic_cp_bls.c
+++ b/src/cp/relic_cp_bls.c
@@ -66,7 +66,7 @@ int cp_bls_sig(g1_t s, const uint8_t *msg, size_t len, const bn_t d) {
RLC_TRY {
g1_new(p);
g1_map(p, msg, len);
- g1_mul_key(s, p, d);
+ g1_mul_sec(s, p, d);
}
RLC_CATCH_ANY {
result = RLC_ERR;
diff --git a/src/cp/relic_cp_ecdsa.c b/src/cp/relic_cp_ecdsa.c
index 24657312d..34f0403dc 100644
--- a/src/cp/relic_cp_ecdsa.c
+++ b/src/cp/relic_cp_ecdsa.c
@@ -173,7 +173,7 @@ int cp_ecdsa_ver(const bn_t r, const bn_t s, const uint8_t *msg, size_t len,
bn_mod(v, v, n);
- cmp = dv_cmp_const(v->dp, r->dp, RLC_MIN(v->used, r->used));
+ cmp = dv_cmp_sec(v->dp, r->dp, RLC_MIN(v->used, r->used));
result = (cmp == RLC_NE ? 0 : 1);
if (v->used != r->used) {
diff --git a/src/cp/relic_cp_ecies.c b/src/cp/relic_cp_ecies.c
index da0a808f2..be64ac32d 100644
--- a/src/cp/relic_cp_ecies.c
+++ b/src/cp/relic_cp_ecies.c
@@ -138,7 +138,7 @@ int cp_ecies_dec(uint8_t *out, size_t *out_len, const ec_t r, const uint8_t *in,
bn_write_bin(_x, l, x);
md_kdf(key, 2 * size, _x, l);
md_hmac(h, in, in_len - RLC_MD_LEN, key + size, size);
- if (util_cmp_const(h, in + in_len - RLC_MD_LEN, RLC_MD_LEN)) {
+ if (util_cmp_sec(h, in + in_len - RLC_MD_LEN, RLC_MD_LEN)) {
result = RLC_ERR;
} else {
if (bc_aes_cbc_dec(out, out_len, in, in_len - RLC_MD_LEN,
diff --git a/src/cp/relic_cp_ecss.c b/src/cp/relic_cp_ecss.c
index ac8c6cac8..7b1c1f776 100644
--- a/src/cp/relic_cp_ecss.c
+++ b/src/cp/relic_cp_ecss.c
@@ -166,7 +166,7 @@ int cp_ecss_ver(bn_t e, bn_t s, const uint8_t *msg, size_t len, const ec_t q) {
bn_mod(ev, ev, n);
- result = dv_cmp_const(ev->dp, e->dp, RLC_MIN(ev->used,
+ result = dv_cmp_sec(ev->dp, e->dp, RLC_MIN(ev->used,
e->used));
result = (result == RLC_NE ? 0 : 1);
diff --git a/src/cp/relic_cp_mklhs.c b/src/cp/relic_cp_mklhs.c
index 96ef56890..2b070a716 100644
--- a/src/cp/relic_cp_mklhs.c
+++ b/src/cp/relic_cp_mklhs.c
@@ -88,7 +88,7 @@ int cp_mklhs_sig(g1_t s, const bn_t m, const char *data, const char *id,
g1_map(a, str, strlen(id) + strlen(tag));
g1_add(s, s, a);
g1_norm(s, s);
- g1_mul_key(s, s, sk);
+ g1_mul_sec(s, s, sk);
}
RLC_CATCH_ANY {
result = RLC_ERR;
diff --git a/src/cp/relic_cp_rsa.c b/src/cp/relic_cp_rsa.c
index c7ea1d67f..863f4d28e 100644
--- a/src/cp/relic_cp_rsa.c
+++ b/src/cp/relic_cp_rsa.c
@@ -938,7 +938,7 @@ int cp_rsa_ver(uint8_t *sig, size_t sig_len, const uint8_t *msg, size_t msg_len,
memset(h1, 0, RLC_MD_LEN);
bn_write_bin(h1, size - pad_len, eb);
/* Everything went ok, so signature status is changed. */
- result = util_cmp_const(h1, h2, RLC_MD_LEN);
+ result = util_cmp_sec(h1, h2, RLC_MD_LEN);
} else {
memcpy(h1 + 8, msg, msg_len);
md_map(h2, h1, RLC_MD_LEN + 8);
@@ -947,7 +947,7 @@ int cp_rsa_ver(uint8_t *sig, size_t sig_len, const uint8_t *msg, size_t msg_len,
bn_write_bin(h1, size - pad_len, eb);
/* Everything went ok, so signature status is changed. */
- result = util_cmp_const(h1, h2, msg_len);
+ result = util_cmp_sec(h1, h2, msg_len);
}
#else
memset(h1, 0, RLC_MAX(msg_len, RLC_MD_LEN));
@@ -956,10 +956,10 @@ int cp_rsa_ver(uint8_t *sig, size_t sig_len, const uint8_t *msg, size_t msg_len,
if (!hash) {
md_map(h2, msg, msg_len);
/* Everything went ok, so signature status is changed. */
- result = util_cmp_const(h1, h2, RLC_MD_LEN);
+ result = util_cmp_sec(h1, h2, RLC_MD_LEN);
} else {
/* Everything went ok, so signature status is changed. */
- result = util_cmp_const(h1, msg, msg_len);
+ result = util_cmp_sec(h1, msg, msg_len);
}
#endif
result = (result == RLC_EQ ? 1 : 0);
diff --git a/src/dv/relic_dv_util.c b/src/dv/relic_dv_util.c
index 5084472a1..8422b636a 100644
--- a/src/dv/relic_dv_util.c
+++ b/src/dv/relic_dv_util.c
@@ -70,20 +70,20 @@ void dv_copy(dig_t *c, const dig_t *a, size_t digits) {
memcpy(c, a, digits * sizeof(dig_t));
}
-void dv_copy_cond(dig_t *c, const dig_t *a, size_t digits, dig_t cond) {
+void dv_copy_sec(dig_t *c, const dig_t *a, size_t digits, dig_t bit) {
dig_t mask, t;
- mask = -cond;
+ mask = -bit;
for (size_t i = 0; i < digits; i++) {
t = (a[i] ^ c[i]) & mask;
c[i] ^= t;
}
}
-void dv_swap_cond(dig_t *c, dig_t *a, size_t digits, dig_t cond) {
+void dv_swap_sec(dig_t *c, dig_t *a, size_t digits, dig_t bit) {
dig_t mask, t;
- mask = -cond;
+ mask = -bit;
for (size_t i = 0; i < digits; i++) {
t = (a[i] ^ c[i]) & mask;
a[i] ^= t;
@@ -106,7 +106,7 @@ int dv_cmp(const dig_t *a, const dig_t *b, size_t size) {
return r;
}
-int dv_cmp_const(const dig_t *a, const dig_t *b, size_t size) {
+int dv_cmp_sec(const dig_t *a, const dig_t *b, size_t size) {
dig_t r = 0;
for (size_t i = 0; i < size; i++) {
diff --git a/src/eb/relic_eb_map.c b/src/eb/relic_eb_map.c
index bbc61810f..2f87783ae 100644
--- a/src/eb/relic_eb_map.c
+++ b/src/eb/relic_eb_map.c
@@ -58,7 +58,7 @@ void eb_map(eb_t p, const uint8_t *msg, size_t len) {
while (1) {
dv_copy(p->x, k->dp, RLC_FB_DIGS);
- eb_rhs(t1, p);
+ eb_rhs(t1, p->x);
/* t0 = 1/x1^2. */
fb_sqr(t0, p->x);
diff --git a/src/eb/relic_eb_mul.c b/src/eb/relic_eb_mul.c
index b23b81141..eaef0d16c 100644
--- a/src/eb/relic_eb_mul.c
+++ b/src/eb/relic_eb_mul.c
@@ -712,7 +712,7 @@ void eb_mul_lodah(eb_t r, const eb_t p, const bn_t k) {
bn_abs(t, k);
bn_add(t, t, n);
bn_add(n, t, n);
- dv_swap_cond(t->dp, n->dp, RLC_MAX(t->used, n->used),
+ dv_swap_sec(t->dp, n->dp, RLC_MAX(t->used, n->used),
bn_get_bit(t, bits) == 0);
t->used = RLC_SEL(t->used, n->used, bn_get_bit(t, bits) == 0);
@@ -743,8 +743,8 @@ void eb_mul_lodah(eb_t r, const eb_t p, const bn_t k) {
fb_mul(r2, x2, z1);
fb_add(r3, r1, r2);
fb_muln_low(r4, r1, r2);
- dv_swap_cond(x1, x2, RLC_FB_DIGS, j ^ 1);
- dv_swap_cond(z1, z2, RLC_FB_DIGS, j ^ 1);
+ dv_swap_sec(x1, x2, RLC_FB_DIGS, j ^ 1);
+ dv_swap_sec(z1, z2, RLC_FB_DIGS, j ^ 1);
fb_sqr(z1, r3);
fb_muln_low(r1, z1, p->x);
fb_addd_low(x1, r1, r4, 2 * RLC_FB_DIGS);
@@ -775,8 +775,8 @@ void eb_mul_lodah(eb_t r, const eb_t p, const bn_t k) {
fb_rdcn_low(x2, x2);
break;
}
- dv_swap_cond(x1, x2, RLC_FB_DIGS, j ^ 1);
- dv_swap_cond(z1, z2, RLC_FB_DIGS, j ^ 1);
+ dv_swap_sec(x1, x2, RLC_FB_DIGS, j ^ 1);
+ dv_swap_sec(z1, z2, RLC_FB_DIGS, j ^ 1);
}
if (fb_is_zero(z1)) {
diff --git a/src/eb/relic_eb_pck.c b/src/eb/relic_eb_pck.c
index 3766a2a2a..b012e47e3 100644
--- a/src/eb/relic_eb_pck.c
+++ b/src/eb/relic_eb_pck.c
@@ -63,7 +63,7 @@ int eb_upk(eb_t r, const eb_t p) {
fb_new(t0);
fb_new(t1);
- eb_rhs(t1, p);
+ eb_rhs(t1, p->x);
fb_sqr(t0, p->x);
/* t0 = 1/x1^2. */
diff --git a/src/eb/relic_eb_util.c b/src/eb/relic_eb_util.c
index fc44b7096..92316d739 100644
--- a/src/eb/relic_eb_util.c
+++ b/src/eb/relic_eb_util.c
@@ -78,7 +78,7 @@ void eb_rand(eb_t p) {
}
}
-void eb_rhs(fb_t rhs, const eb_t p) {
+void eb_rhs(fb_t rhs, const fb_t x) {
fb_t t0, t1;
fb_null(t0);
@@ -89,9 +89,9 @@ void eb_rhs(fb_t rhs, const eb_t p) {
fb_new(t1);
/* t0 = x1^2. */
- fb_sqr(t0, p->x);
+ fb_sqr(t0, x);
/* t1 = x1^3. */
- fb_mul(t1, t0, p->x);
+ fb_mul(t1, t0, x);
/* t1 = x1^3 + a * x1^2 + b. */
switch (eb_curve_opt_a()) {
@@ -171,7 +171,7 @@ int eb_on_curve(const eb_t p) {
eb_norm(t, p);
fb_mul(lhs, t->x, t->y);
- eb_rhs(t->x, t);
+ eb_rhs(t->x, t->x);
fb_sqr(t->y, t->y);
fb_add(lhs, lhs, t->y);
r = (fb_cmp(lhs, t->x) == RLC_EQ) || eb_is_infty(p);
diff --git a/src/ed/relic_ed_map.c b/src/ed/relic_ed_map.c
index e95f3da73..170e53387 100644
--- a/src/ed/relic_ed_map.c
+++ b/src/ed/relic_ed_map.c
@@ -97,7 +97,7 @@ void ed_map_ell2_5mod8(ed_t p, fp_t t) {
fp_mul(p->x, p->x, p->z);
{
const int e1 = fp_cmp(p->x, tv4);
- dv_copy_cond(p->y, tv2, RLC_FP_DIGS, e1 == RLC_EQ);
+ fp_copy_sec(p->y, tv2, e1 == RLC_EQ);
} /* e1 goes out of scope */
/* compute numerator of g(x2) */
@@ -111,7 +111,7 @@ void ed_map_ell2_5mod8(ed_t p, fp_t t) {
fp_mul(tv2, tv2, p->z);
{
const int e2 = fp_cmp(p->x, tv2);
- dv_copy_cond(tv5, tv3, RLC_FP_DIGS, e2 == RLC_EQ);
+ fp_copy_sec(tv5, tv3, e2 == RLC_EQ);
} /* e2 goes out of scope */
/* figure out whether we wanted y1 or y2 and x1 or x2 */
@@ -120,16 +120,16 @@ void ed_map_ell2_5mod8(ed_t p, fp_t t) {
{
const int e3 = fp_cmp(tv2, tv4);
fp_set_dig(p->x, 1);
- dv_copy_cond(p->x, tv1, RLC_FP_DIGS, e3 != RLC_EQ);
+ fp_copy_sec(p->x, tv1, e3 != RLC_EQ);
fp_mul(p->x, p->x, c_486662);
fp_neg(p->x, p->x);
- dv_copy_cond(p->y, tv5, RLC_FP_DIGS, e3 != RLC_EQ);
+ fp_copy_sec(p->y, tv5, e3 != RLC_EQ);
/* fix sign of y */
fp_prime_back(h, p->y);
const int e4 = bn_get_bit(h, 0);
fp_neg(tv2, p->y);
- dv_copy_cond(p->y, tv2, RLC_FP_DIGS, (e3 == RLC_EQ) ^ (e4 == 1));
+ fp_copy_sec(p->y, tv2, (e3 == RLC_EQ) ^ (e4 == 1));
} /* e3 and e4 go out of scope */
fp_add_dig(p->z, tv1, 1);
@@ -147,9 +147,9 @@ void ed_map_ell2_5mod8(ed_t p, fp_t t) {
/* exceptional case: either denominator == 0 */
const int e4 = fp_is_zero(p->z);
fp_set_dig(tv5, 1);
- dv_copy_cond(p->x, p->z, RLC_FP_DIGS, e4); /* set x to 0 */
- dv_copy_cond(p->y, tv5, RLC_FP_DIGS, e4);
- dv_copy_cond(p->z, tv5, RLC_FP_DIGS, e4);
+ dv_copy_sec(p->x, p->z, RLC_FP_DIGS, e4); /* set x to 0 */
+ dv_copy_sec(p->y, tv5, RLC_FP_DIGS, e4);
+ dv_copy_sec(p->z, tv5, RLC_FP_DIGS, e4);
} /* e4 goes out of scope */
/* clear denominator / compute extended coordinates if necessary */
diff --git a/src/ed/relic_ed_mul.c b/src/ed/relic_ed_mul.c
index 65f413a8e..0a9684b9f 100644
--- a/src/ed/relic_ed_mul.c
+++ b/src/ed/relic_ed_mul.c
@@ -149,35 +149,35 @@ static void ed_mul_reg_imp(ed_t r, const ed_t p, const bn_t k) {
n = ((n ^ s) - s) >> 1;
for (j = 0; j < (1 << (RLC_WIDTH - 2)); j++) {
- dv_copy_cond(u->x, t[j]->x, RLC_FP_DIGS, j == n);
- dv_copy_cond(u->y, t[j]->y, RLC_FP_DIGS, j == n);
- dv_copy_cond(u->z, t[j]->z, RLC_FP_DIGS, j == n);
+ fp_copy_sec(u->x, t[j]->x, j == n);
+ fp_copy_sec(u->y, t[j]->y, j == n);
+ fp_copy_sec(u->z, t[j]->z, j == n);
#if ED_ADD == EXTND
- dv_copy_cond(u->t, t[j]->t, RLC_FP_DIGS, j == n);
+ fp_copy_sec(u->t, t[j]->t, j == n);
#endif
}
ed_neg(v, u);
- dv_copy_cond(u->x, v->x, RLC_FP_DIGS, s != 0);
+ fp_copy_sec(u->x, v->x, s != 0);
#if ED_ADD == EXTND
- dv_copy_cond(u->t, v->t, RLC_FP_DIGS, s != 0);
+ fp_copy_sec(u->t, v->t, s != 0);
#endif
ed_add(r, r, u);
}
/* t[0] has an unmodified copy of p. */
ed_sub(u, r, t[0]);
- dv_copy_cond(r->x, u->x, RLC_FP_DIGS, bn_is_even(k));
- dv_copy_cond(r->y, u->y, RLC_FP_DIGS, bn_is_even(k));
- dv_copy_cond(r->z, u->z, RLC_FP_DIGS, bn_is_even(k));
-#if ED_ADD == EXTND
- dv_copy_cond(r->t, u->t, RLC_FP_DIGS, bn_is_even(k));
+ fp_copy_sec(r->x, u->x, bn_is_even(k));
+ fp_copy_sec(r->y, u->y, bn_is_even(k));
+ fp_copy_sec(r->z, u->z, bn_is_even(k));
+#if ED_Afp == EXTND
+ fp_copy_sec(r->t, u->t, bn_is_even(k));
#endif
/* Convert r to affine coordinates. */
ed_norm(r, r);
ed_neg(u, r);
- dv_copy_cond(r->x, u->x, RLC_FP_DIGS, bn_sign(k) == RLC_NEG);
+ fp_copy_sec(r->x, u->x, bn_sign(k) == RLC_NEG);
#if ED_ADD == EXTND
- dv_copy_cond(r->t, u->t, RLC_FP_DIGS, bn_sign(k) == RLC_NEG);
+ fp_copy_sec(r->t, u->t, bn_sign(k) == RLC_NEG);
#endif
}
RLC_CATCH_ANY {
@@ -342,19 +342,19 @@ void ed_mul_monty(ed_t r, const ed_t p, const bn_t k) {
for (int i = bn_bits(k) - 1; i >= 0; i--) {
int j = bn_get_bit(k, i);
- dv_swap_cond(t[0]->x, t[1]->x, RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y, t[1]->y, RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z, t[1]->z, RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x, t[1]->x, RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y, t[1]->y, RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z, t[1]->z, RLC_FP_DIGS, j ^ 1);
#if ED_ADD == EXTND
- dv_swap_cond(t[0]->t, t[1]->t, RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->t, t[1]->t, RLC_FP_DIGS, j ^ 1);
#endif
ed_add(t[0], t[0], t[1]);
ed_dbl(t[1], t[1]);
- dv_swap_cond(t[0]->x, t[1]->x, RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y, t[1]->y, RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z, t[1]->z, RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x, t[1]->x, RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y, t[1]->y, RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z, t[1]->z, RLC_FP_DIGS, j ^ 1);
#if ED_ADD == EXTND
- dv_swap_cond(t[0]->t, t[1]->t, RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->t, t[1]->t, RLC_FP_DIGS, j ^ 1);
#endif
}
diff --git a/src/ed/relic_ed_util.c b/src/ed/relic_ed_util.c
index 8602a16bd..698780ac5 100644
--- a/src/ed/relic_ed_util.c
+++ b/src/ed/relic_ed_util.c
@@ -128,61 +128,46 @@ void ed_blind(ed_t r, const ed_t p) {
}
}
-void ed_rhs(fp_t rhs, const ed_t p) {
- fp_t t0, t1;
-
- fp_null(t0);
- fp_null(t1);
-
- RLC_TRY {
- fp_new(t0);
- fp_new(t1);
-
- // 1 = a * X^2 + Y^2 - d * X^2 * Y^2
- fp_sqr(t0, p->x);
- fp_mul(t0, t0, core_get()->ed_a);
- fp_sqr(t1, p->y);
- fp_add(t1, t1, t0);
- fp_mul(t0, p->x, p->y);
- fp_sqr(t0, t0);
- fp_mul(t0, t0, core_get()->ed_d);
- fp_sub(rhs, t1, t0);
- } RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- } RLC_FINALLY {
- fp_free(t0);
- fp_free(t1);
- }
+void ed_rhs(fp_t rhs, const fp_t x) {
+ /* y^2 * (d * x^2 - 1) = 1a * x^2 - 1. */
+ fp_sqr(rhs, x);
+ fp_mul(rhs, rhs, core_get()->ed_a);
+ fp_sub_dig(rhs, rhs, 1);
}
int ed_on_curve(const ed_t p) {
ed_t t;
- int r = 0;
+ int r = 1;
ed_null(t);
if (fp_is_zero(p->z)) {
- r = 0;
- } else {
- RLC_TRY {
- ed_new(t);
- ed_norm(t, p);
+ return 0;
+ }
+
+ RLC_TRY {
+ ed_new(t);
+ ed_norm(t, p);
- ed_rhs(t->z, t);
+ /* Compute y^2 * (d * x^2 - 1) */
#if ED_ADD == EXTND
- fp_mul(t->y, t->x, t->y);
- r = ((fp_cmp_dig(t->z, 1) == RLC_EQ) &&
- (fp_cmp(t->y, t->t) == RLC_EQ)) || ed_is_infty(p);
-#else
- r = (fp_cmp_dig(t->z, 1) == RLC_EQ) || ed_is_infty(p);
+ fp_mul(t->z, t->x, t->y);
+ r &= (fp_cmp(t->z, t->t) == RLC_EQ);
#endif
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- ed_free(t);
- }
+ fp_sqr(t->z, t->y);
+ fp_sqr(t->t, t->x);
+ fp_mul(t->t, t->t, core_get()->ed_d);
+ fp_sub_dig(t->t, t->t, 1);
+ fp_mul(t->t, t->t, t->z);
+ ed_rhs(t->z, t->x);
+ r &= (fp_cmp(t->t, t->z) == RLC_EQ);
+ r |= ed_is_infty(p);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ ed_free(t);
}
return r;
}
diff --git a/src/ep/relic_ep_add.c b/src/ep/relic_ep_add.c
index e8694421c..dec994be7 100644
--- a/src/ep/relic_ep_add.c
+++ b/src/ep/relic_ep_add.c
@@ -30,6 +30,7 @@
*/
#include "relic_core.h"
+#include "relic_ep_add_tmpl.h"
/*============================================================================*/
/* Private definitions */
@@ -46,70 +47,7 @@
* @param[in] p - the first point to add.
* @param[in] q - the second point to add.
*/
-static void ep_add_basic_imp(ep_t r, fp_t s, const ep_t p, const ep_t q) {
- fp_t t0, t1, t2;
-
- fp_null(t0);
- fp_null(t1);
- fp_null(t2);
-
- RLC_TRY {
- fp_new(t0);
- fp_new(t1);
- fp_new(t2);
-
- /* t0 = x2 - x1. */
- fp_sub(t0, q->x, p->x);
- /* t1 = y2 - y1. */
- fp_sub(t1, q->y, p->y);
-
- /* If t0 is zero. */
- if (fp_is_zero(t0)) {
- if (fp_is_zero(t1)) {
- /* If t1 is zero, q = p, should have doubled. */
- ep_dbl_basic(r, p);
- } else {
- /* If t1 is not zero and t0 is zero, q = -p and r = infinity. */
- ep_set_infty(r);
- }
- } else {
- /* t2 = 1/(x2 - x1). */
- fp_inv(t2, t0);
- /* t2 = lambda = (y2 - y1)/(x2 - x1). */
- fp_mul(t2, t1, t2);
-
- /* x3 = lambda^2 - x2 - x1. */
- fp_sqr(t1, t2);
- fp_sub(t0, t1, p->x);
- fp_sub(t0, t0, q->x);
-
- /* y3 = lambda * (x1 - x3) - y1. */
- fp_sub(t1, p->x, t0);
- fp_mul(t1, t2, t1);
- fp_sub(r->y, t1, p->y);
-
- fp_copy(r->x, t0);
- fp_copy(r->z, p->z);
-
- if (s != NULL) {
- fp_copy(s, t2);
- }
-
- r->coord = BASIC;
- }
- fp_free(t0);
- fp_free(t1);
- fp_free(t2);
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp_free(t0);
- fp_free(t1);
- fp_free(t2);
- }
-}
+TMPL_ADD_BASIC_IMP(ep, fp);
#endif /* EP_ADD == BASIC */
@@ -117,165 +55,13 @@ static void ep_add_basic_imp(ep_t r, fp_t s, const ep_t p, const ep_t q) {
/**
* Adds a point represented in homogeneous coordinates to a point represented in
- * projective coordinates.
+ * affine coordinates on an ordinary prime elliptic curve.
*
* @param[out] r - the result.
* @param[in] p - the projective point.
* @param[in] q - the affine point.
*/
-static void ep_add_projc_mix(ep_t r, const ep_t p, const ep_t q) {
- fp_t t0, t1, t2, t3, t4, t5;
-
- fp_null(t0);
- fp_null(t1);
- fp_null(t2);
- fp_null(t3);
- fp_null(t4);
- fp_null(t5);
-
- RLC_TRY {
- fp_new(t0);
- fp_new(t1);
- fp_new(t2);
- fp_new(t3);
- fp_new(t4);
- fp_new(t5);
-
- /* Formulas for mixed addition from
- * "Complete addition formulas for prime order elliptic curves"
- * by Joost Renes, Craig Costello, and Lejla Batina
- * https://eprint.iacr.org/2015/1060.pdf
- */
-
- fp_mul(t0, p->x, q->x);
- fp_mul(t1, p->y, q->y);
- fp_add(t3, q->x, q->y);
- fp_add(t4, p->x, p->y);
- fp_mul(t3, t3, t4);
- fp_add(t4, t0, t1);
- fp_sub(t3, t3, t4);
-
- if (ep_curve_opt_a() == RLC_ZERO) {
- /* Cost of 11M + 2m_3b + 13a. */
- if (p->coord == BASIC) {
- /* Save 1M + 1m_3b if z1 = 1. */
- fp_add(t4, q->y, p->y);
- fp_add(r->y, q->x, p->x);
- fp_add(r->z, t1, ep_curve_get_b3());
- fp_sub(t1, t1, ep_curve_get_b3());
- } else {
- fp_mul(t4, q->y, p->z);
- fp_add(t4, t4, p->y);
- fp_mul(r->y, q->x, p->z);
- fp_add(r->y, r->y, p->x);
- ep_curve_mul_b3(t2, p->z);
- fp_add(r->z, t1, t2);
- fp_sub(t1, t1, t2);
- }
- fp_dbl(r->x, t0);
- fp_add(t0, t0, r->x);
- ep_curve_mul_b3(r->y, r->y);
- fp_mul(r->x, t4, r->y);
- fp_mul(t2, t3, t1);
- fp_sub(r->x, t2, r->x);
- fp_mul(r->y, t0, r->y);
- fp_mul(t1, t1, r->z);
- fp_add(r->y, t1, r->y);
- fp_mul(t0, t0, t3);
- fp_mul(r->z, r->z, t4);
- fp_add(r->z, r->z, t0);
- } else if (ep_curve_opt_a() == RLC_MIN3) {
- /* Cost of 11M + 2m_b + 23a. */
- if (p->coord == BASIC) {
- /* Save 2M + 3a if z1 = 1. */
- fp_set_dig(t2, 3);
- fp_add(t4, q->y, p->y);
- fp_add(r->y, q->x, p->x);
- fp_sub(r->x, r->y, ep_curve_get_b());
- } else {
- fp_dbl(t2, p->z);
- fp_add(t2, t2, p->z);
- fp_mul(t4, q->y, p->z);
- fp_add(t4, t4, p->y);
- fp_mul(r->y, q->x, p->z);
- fp_add(r->y, r->y, p->x);
- ep_curve_mul_b(r->z, p->z);
- fp_sub(r->x, r->y, r->z);
- }
- fp_dbl(r->z, r->x);
- fp_add(r->x, r->x, r->z);
- fp_sub(r->z, t1, r->x);
- fp_add(r->x, t1, r->x);
- ep_curve_mul_b(r->y, r->y);
- fp_sub(r->y, r->y, t2);
- fp_sub(r->y, r->y, t0);
- fp_dbl(t1, r->y);
- fp_add(r->y, t1, r->y);
- fp_dbl(t1, t0);
- fp_add(t0, t1, t0);
- fp_sub(t0, t0, t2);
- fp_mul(t1, t4, r->y);
- fp_mul(t2, t0, r->y);
- fp_mul(r->y, r->x, r->z);
- fp_add(r->y, r->y, t2);
- fp_mul(r->x, t3, r->x);
- fp_sub(r->x, r->x, t1);
- fp_mul(r->z, t4, r->z);
- fp_mul(t1, t3, t0);
- fp_add(r->z, r->z, t1);
- } else {
- /* Cost of 11M + 3m_a + 2m_3b + 17a. */
- if (p->coord == BASIC) {
- /* Save 1M + 1m_a + 1m_3b if z1 = 1. */
- fp_copy(t2, ep_curve_get_a());
- fp_add(t4, q->x, p->x);
- fp_add(t5, q->y, p->y);
- ep_curve_mul_a(r->z, t4);
- fp_add(r->z, r->z, ep_curve_get_b3());
- } else {
- ep_curve_mul_a(t2, p->z);
- fp_mul(t4, q->x, p->z);
- fp_add(t4, t4, p->x);
- fp_mul(t5, q->y, p->z);
- fp_add(t5, t5, p->y);
- ep_curve_mul_b3(r->x, p->z);
- ep_curve_mul_a(r->z, t4);
- fp_add(r->z, r->x, r->z);
- }
- fp_sub(r->x, t1, r->z);
- fp_add(r->z, t1, r->z);
- fp_mul(r->y, r->x, r->z);
- fp_dbl(t1, t0);
- fp_add(t1, t1, t0);
- ep_curve_mul_b3(t4, t4);
- fp_add(t1, t1, t2);
- fp_sub(t2, t0, t2);
- ep_curve_mul_a(t2, t2);
- fp_add(t4, t4, t2);
- fp_mul(t0, t1, t4);
- fp_add(r->y, r->y, t0);
- fp_mul(t0, t5, t4);
- fp_mul(r->x, t3, r->x);
- fp_sub(r->x, r->x, t0);
- fp_mul(t0, t3, t1);
- fp_mul(r->z, t5, r->z);
- fp_add(r->z, r->z, t0);
- }
-
- r->coord = PROJC;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp_free(t0);
- fp_free(t1);
- fp_free(t2);
- fp_free(t3);
- fp_free(t4);
- fp_free(t5);
- }
-}
+TMPL_ADD_PROJC_MIX(ep, fp);
/**
* Adds two points represented in homogeneous coordinates on an ordinary prime
@@ -285,164 +71,7 @@ static void ep_add_projc_mix(ep_t r, const ep_t p, const ep_t q) {
* @param[in] p - the first point to add.
* @param[in] q - the second point to add.
*/
-static void ep_add_projc_imp(ep_t r, const ep_t p, const ep_t q) {
-#if defined(EP_MIXED) && defined(STRIP)
- /* If code size is a problem, leave only the mixed version. */
- ep_add_projc_mix(r, p, q);
-#else /* General addition. */
-
-#if defined(EP_MIXED) || !defined(STRIP)
- /* Test if z2 = 1 only if mixed coordinates are turned on. */
- if (q->coord == BASIC) {
- ep_add_projc_mix(r, p, q);
- return;
- }
-#endif
- fp_t t0, t1, t2, t3, t4, t5;
-
- fp_null(t0);
- fp_null(t1);
- fp_null(t2);
- fp_null(t3);
- fp_null(t4);
- fp_null(t5);
-
- RLC_TRY {
- fp_new(t0);
- fp_new(t1);
- fp_new(t2);
- fp_new(t3);
- fp_new(t4);
- fp_new(t5);
-
- /* Formulas for point addition from
- * "Complete addition formulas for prime order elliptic curves"
- * by Joost Renes, Craig Costello, and Lejla Batina
- * https://eprint.iacr.org/2015/1060.pdf
- */
- fp_mul(t0, p->x, q->x);
- fp_mul(t1, p->y, q->y);
- fp_mul(t2, p->z, q->z);
- fp_add(t3, p->x, p->y);
- fp_add(t4, q->x, q->y);
- fp_mul(t3, t3, t4);
- fp_add(t4, t0, t1);
- fp_sub(t3, t3, t4);
- if (ep_curve_opt_a() == RLC_ZERO) {
- /* Cost of 12M + 2m_3b + 19a. */
- fp_add(t4, p->y, p->z);
- fp_add(t5, q->y, q->z);
- fp_mul(t4, t4, t5);
- fp_add(t5, t1, t2);
- fp_sub(t4, t4, t5);
- fp_add(r->y, q->x, q->z);
- fp_add(r->x, p->x, p->z);
- fp_mul(r->x, r->x, r->y);
- fp_add(r->y, t0, t2);
- fp_sub(r->y, r->x, r->y);
- fp_dbl(r->x, t0);
- fp_add(t0, t0, r->x);
- ep_curve_mul_b3(t2, t2);
- fp_add(r->z, t1, t2);
- fp_sub(t1, t1, t2);
- ep_curve_mul_b3(r->y, r->y);
- fp_mul(r->x, t4, r->y);
- fp_mul(t2, t3, t1);
- fp_sub(r->x, t2, r->x);
- fp_mul(r->y, t0, r->y);
- fp_mul(t1, t1, r->z);
- fp_add(r->y, t1, r->y);
- fp_mul(t0, t0, t3);
- fp_mul(r->z, r->z, t4);
- fp_add(r->z, r->z, t0);
- } else if (ep_curve_opt_a() == RLC_MIN3) {
- /* Cost of 12M + 2m_b + 29a. */
- fp_add(t4, p->y, p->z);
- fp_add(t5, q->y, q->z);
- fp_mul(t4, t4, t5);
- fp_add(t5, t1, t2);
- fp_sub(t4, t4, t5);
- fp_add(r->x, p->x, p->z);
- fp_add(r->y, q->x, q->z);
- fp_mul(r->x, r->x, r->y);
- fp_add(r->y, t0, t2);
- fp_sub(r->y, r->x, r->y);
- ep_curve_mul_b(r->z, t2);
- fp_sub(r->x, r->y, r->z);
- fp_dbl(r->z, r->x);
- fp_add(r->x, r->x, r->z);
- fp_sub(r->z, t1, r->x);
- fp_add(r->x, t1, r->x);
- ep_curve_mul_b(r->y, r->y);
- fp_dbl(t1, t2);
- fp_add(t2, t1, t2);
- fp_sub(r->y, r->y, t2);
- fp_sub(r->y, r->y, t0);
- fp_dbl(t1, r->y);
- fp_add(r->y, t1, r->y);
- fp_dbl(t1, t0);
- fp_add(t0, t1, t0);
- fp_sub(t0, t0, t2);
- fp_mul(t1, t4, r->y);
- fp_mul(t2, t0, r->y);
- fp_mul(r->y, r->x, r->z);
- fp_add(r->y, r->y, t2);
- fp_mul(r->x, t3, r->x);
- fp_sub(r->x, r->x, t1);
- fp_mul(r->z, t4, r->z);
- fp_mul(t1, t3, t0);
- fp_add(r->z, r->z, t1);
- } else {
- /* Cost of 12M + 3m_a + 2_m3b + 23a. */
- fp_add(t4, p->x, p->z);
- fp_add(t5, q->x, q->z);
- fp_mul(t4, t4, t5);
- fp_add(t5, t0, t2);
- fp_sub(t4, t4, t5);
- fp_add(t5, p->y, p->z);
- fp_add(r->x, q->y, q->z);
- fp_mul(t5, t5, r->x);
- fp_add(r->x, t1, t2);
- fp_sub(t5, t5, r->x);
- ep_curve_mul_a(r->z, t4);
- ep_curve_mul_b3(r->x, t2);
- fp_add(r->z, r->x, r->z);
- fp_sub(r->x, t1, r->z);
- fp_add(r->z, t1, r->z);
- fp_mul(r->y, r->x, r->z);
- fp_dbl(t1, t0);
- fp_add(t1, t1, t0);
- ep_curve_mul_a(t2, t2);
- ep_curve_mul_b3(t4, t4);
- fp_add(t1, t1, t2);
- fp_sub(t2, t0, t2);
- ep_curve_mul_a(t2, t2);
- fp_add(t4, t4, t2);
- fp_mul(t0, t1, t4);
- fp_add(r->y, r->y, t0);
- fp_mul(t0, t5, t4);
- fp_mul(r->x, t3, r->x);
- fp_sub(r->x, r->x, t0);
- fp_mul(t0, t3, t1);
- fp_mul(r->z, t5, r->z);
- fp_add(r->z, r->z, t0);
- }
-
- r->coord = PROJC;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp_free(t0);
- fp_free(t1);
- fp_free(t2);
- fp_free(t3);
- fp_free(t4);
- fp_free(t5);
- }
-#endif
-}
+TMPL_ADD_PROJC_IMP(ep, fp);
#endif /* EP_ADD == PROJC */
@@ -450,123 +79,13 @@ static void ep_add_projc_imp(ep_t r, const ep_t p, const ep_t q) {
/**
* Adds a point represented in Jacobian coordinates to a point represented in
- * projective coordinates.
+ * affine coordinates on an ordinary prime elliptic curve.
*
* @param[out] r - the result.
* @param[in] p - the projective point.
* @param[in] q - the affine point.
*/
-static void ep_add_jacob_mix(ep_t r, const ep_t p, const ep_t q) {
- fp_t t0, t1, t2, t3, t4, t5, t6;
-
- fp_null(t0);
- fp_null(t1);
- fp_null(t2);
- fp_null(t3);
- fp_null(t4);
- fp_null(t5);
- fp_null(t6);
-
- RLC_TRY {
- fp_new(t0);
- fp_new(t1);
- fp_new(t2);
- fp_new(t3);
- fp_new(t4);
- fp_new(t5);
- fp_new(t6);
-
- /* madd-2007-bl formulas: 7M + 4S + 9add + 1*4 + 3*2. */
- /* http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-madd-2007-bl */
-
- if (p->coord != BASIC) {
- /* t0 = z1^2. */
- fp_sqr(t0, p->z);
-
- /* t3 = U2 = x2 * z1^2. */
- fp_mul(t3, q->x, t0);
-
- /* t1 = S2 = y2 * z1^3. */
- fp_mul(t1, t0, p->z);
- fp_mul(t1, t1, q->y);
-
- /* t3 = H = U2 - x1. */
- fp_sub(t3, t3, p->x);
-
- /* t1 = R = 2 * (S2 - y1). */
- fp_sub(t1, t1, p->y);
- fp_dbl(t1, t1);
- } else {
- /* H = x2 - x1. */
- fp_sub(t3, q->x, p->x);
-
- /* t1 = R = 2 * (y2 - y1). */
- fp_sub(t1, q->y, p->y);
- fp_dbl(t1, t1);
- }
-
- /* t2 = HH = H^2. */
- fp_sqr(t2, t3);
-
- /* If H is zero. */
- if (fp_is_zero(t3)) {
- if (fp_is_zero(t1)) {
- /* If I is zero, p = q, should have doubled. */
- ep_dbl_jacob(r, p);
- } else {
- /* If I is not zero, q = -p, r = infinity. */
- ep_set_infty(r);
- }
- } else {
- /* t4 = I = 4*HH. */
- fp_dbl(t4, t2);
- fp_dbl(t4, t4);
-
- /* t5 = J = H * I. */
- fp_mul(t5, t3, t4);
-
- /* t4 = V = x1 * I. */
- fp_mul(t4, p->x, t4);
-
- /* x3 = R^2 - J - 2 * V. */
- fp_sqr(r->x, t1);
- fp_sub(r->x, r->x, t5);
- fp_dbl(t6, t4);
- fp_sub(r->x, r->x, t6);
-
- /* y3 = R * (V - x3) - 2 * Y1 * J. */
- fp_sub(t4, t4, r->x);
- fp_mul(t4, t4, t1);
- fp_mul(t1, p->y, t5);
- fp_dbl(t1, t1);
- fp_sub(r->y, t4, t1);
-
- if (p->coord != BASIC) {
- /* z3 = (z1 + H)^2 - z1^2 - HH. */
- fp_add(r->z, p->z, t3);
- fp_sqr(r->z, r->z);
- fp_sub(r->z, r->z, t0);
- fp_sub(r->z, r->z, t2);
- } else {
- /* z3 = 2 * H. */
- fp_dbl(r->z, t3);
- }
- }
- r->coord = JACOB;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp_free(t0);
- fp_free(t1);
- fp_free(t2);
- fp_free(t3);
- fp_free(t4);
- fp_free(t5);
- fp_free(t6);
- }
-}
+TMPL_ADD_JACOB_MIX(ep, fp);
/**
* Adds two points represented in Jacobian coordinates on an ordinary prime
@@ -576,127 +95,7 @@ static void ep_add_jacob_mix(ep_t r, const ep_t p, const ep_t q) {
* @param[in] p - the first point to add.
* @param[in] q - the second point to add.
*/
-static void ep_add_jacob_imp(ep_t r, const ep_t p, const ep_t q) {
-#if defined(EP_MIXED) && defined(STRIP)
- /* If code size is a problem, leave only the mixed version. */
- ep_add_jacob_mix(r, p, q);
-#else /* General addition. */
-
-#if defined(EP_MIXED) || !defined(STRIP)
- /* Test if z2 = 1 only if mixed coordinates are turned on. */
- if (q->coord == BASIC) {
- ep_add_jacob_mix(r, p, q);
- return;
- }
-#endif
-
- fp_t t0, t1, t2, t3, t4, t5, t6;
-
- fp_null(t0);
- fp_null(t1);
- fp_null(t2);
- fp_null(t3);
- fp_null(t4);
- fp_null(t5);
- fp_null(t6);
-
- RLC_TRY {
- fp_new(t0);
- fp_new(t1);
- fp_new(t2);
- fp_new(t3);
- fp_new(t4);
- fp_new(t5);
- fp_new(t6);
-
- /* add-2007-bl formulas: 11M + 5S + 9add + 4*2 */
- /* http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl */
-
- /* t0 = z1^2. */
- fp_sqr(t0, p->z);
-
- /* t1 = z2^2. */
- fp_sqr(t1, q->z);
-
- /* t2 = U1 = x1 * z2^2. */
- fp_mul(t2, p->x, t1);
-
- /* t3 = U2 = x2 * z1^2. */
- fp_mul(t3, q->x, t0);
-
- /* t6 = z1^2 + z2^2. */
- fp_add(t6, t0, t1);
-
- /* t0 = S2 = y2 * z1^3. */
- fp_mul(t0, t0, p->z);
- fp_mul(t0, t0, q->y);
-
- /* t1 = S1 = y1 * z2^3. */
- fp_mul(t1, t1, q->z);
- fp_mul(t1, t1, p->y);
-
- /* t3 = H = U2 - U1. */
- fp_sub(t3, t3, t2);
-
- /* t0 = R = 2 * (S2 - S1). */
- fp_sub(t0, t0, t1);
- fp_dbl(t0, t0);
-
- /* If E is zero. */
- if (fp_is_zero(t3)) {
- if (fp_is_zero(t0)) {
- /* If I is zero, p = q, should have doubled. */
- ep_dbl_jacob(r, p);
- } else {
- /* If I is not zero, q = -p, r = infinity. */
- ep_set_infty(r);
- }
- } else {
- /* t4 = I = (2*H)^2. */
- fp_dbl(t4, t3);
- fp_sqr(t4, t4);
-
- /* t5 = J = H * I. */
- fp_mul(t5, t3, t4);
-
- /* t4 = V = U1 * I. */
- fp_mul(t4, t2, t4);
-
- /* x3 = R^2 - J - 2 * V. */
- fp_sqr(r->x, t0);
- fp_sub(r->x, r->x, t5);
- fp_dbl(t2, t4);
- fp_sub(r->x, r->x, t2);
-
- /* y3 = R * (V - x3) - 2 * S1 * J. */
- fp_sub(t4, t4, r->x);
- fp_mul(t4, t4, t0);
- fp_mul(t1, t1, t5);
- fp_dbl(t1, t1);
- fp_sub(r->y, t4, t1);
-
- /* z3 = ((z1 + z2)^2 - z1^2 - z2^2) * H. */
- fp_add(r->z, p->z, q->z);
- fp_sqr(r->z, r->z);
- fp_sub(r->z, r->z, t6);
- fp_mul(r->z, r->z, t3);
- }
- r->coord = JACOB;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp_free(t0);
- fp_free(t1);
- fp_free(t2);
- fp_free(t3);
- fp_free(t4);
- fp_free(t5);
- fp_free(t6);
- }
-#endif
-}
+TMPL_ADD_JACOB_IMP(ep, fp);
#endif /* EP_ADD == JACOB */
diff --git a/src/ep/relic_ep_curve.c b/src/ep/relic_ep_curve.c
index 80e3d0ae1..707a7cfdd 100644
--- a/src/ep/relic_ep_curve.c
+++ b/src/ep/relic_ep_curve.c
@@ -91,8 +91,6 @@ static void ep_curve_set_map(void) {
dig_t *c2 = ctx->ep_map_c[2];
dig_t *c3 = ctx->ep_map_c[3];
dig_t *c4 = ctx->ep_map_c[4];
- dig_t *c5 = ctx->ep_map_c[5];
- dig_t *c6 = ctx->ep_map_c[6];
RLC_TRY {
bn_new(t);
@@ -173,42 +171,9 @@ static void ep_curve_set_map(void) {
fp_mul_dig(c3, c3, 4); /* c3 *= 4 */
}
- /* if b = 0, precompute constants. */
- if (ep_curve_opt_b() == RLC_ZERO) {
- dig_t r = 0;
-
- fp_set_dig(c4, -fp_prime_get_qnr());
- fp_neg(c4, c4);
-
- bn_read_raw(t, fp_prime_get(), RLC_FP_DIGS);
- bn_sub_dig(t, t, 1);
- bn_rsh(t, t, 2);
- fp_exp(c5, c4, t);
-
- bn_read_raw(t, fp_prime_get(), RLC_FP_DIGS);
- if ((t->dp[0] & 0xF) == 5) {
- /* n = (3p + 1)/16 */
- bn_mul_dig(t, t, 3);
- bn_add_dig(t, t, 1);
- r = 1;
- } else {
- /* n = (p + 3)/16 */
- bn_add_dig(t, t, 3);
- r = 3;
- }
- bn_rsh(t, t, 4);
- /* Compute d = 1/c^n. */
- fp_exp(c4, c4, t);
- fp_inv(c4, c4);
- fp_exp_dig(c5, c5, r);
- /* Compute 1/sqrt(-1) as well. */
- fp_set_dig(c6, 1);
- fp_neg(c6, c6);
- fp_srt(c6, c6);
- }
-
- /* If a = 0, precompute and store a square root of -3. */
- if (ep_curve_opt_a() == RLC_ZERO) {
+ /* If curve is not supersingular, precompute and store sqrt(-3)
+ * neeed for hashing using the SwiftEC algorithm and variants. */
+ if (!ep_curve_is_super()) {
fp_set_dig(c4, 3);
fp_neg(c4, c4);
if (!fp_srt(c4, c4)) {
@@ -241,12 +206,9 @@ static void ep_curve_set(const fp_t a, const fp_t b, const ep_t g, const bn_t r,
fp_copy(ctx->ep_a, a);
fp_copy(ctx->ep_b, b);
- fp_dbl(ctx->ep_b3, b);
- fp_add(ctx->ep_b3, ctx->ep_b3, b);
detect_opt(&(ctx->ep_opt_a), ctx->ep_a);
detect_opt(&(ctx->ep_opt_b), ctx->ep_b);
- detect_opt(&(ctx->ep_opt_b3), ctx->ep_b3);
ctx->ep_is_ctmap = ctmap;
ep_curve_set_map();
@@ -304,10 +266,6 @@ dig_t *ep_curve_get_b(void) {
return core_get()->ep_b;
}
-dig_t *ep_curve_get_b3(void) {
- return core_get()->ep_b3;
-}
-
#if defined(EP_ENDOM) && (EP_MUL == LWNAF || EP_FIX == COMBS || EP_FIX == LWNAF || EP_SIM == INTER || !defined(STRIP))
dig_t *ep_curve_get_beta(void) {
@@ -347,6 +305,9 @@ void ep_curve_mul_a(fp_t c, const fp_t a) {
case RLC_ONE:
fp_copy(c, a);
break;
+ case RLC_TWO:
+ fp_dbl(c, a);
+ break;
#if FP_RDC != MONTY
case RLC_TINY:
fp_mul_dig(c, a, ctx->ep_a[0]);
@@ -378,26 +339,6 @@ void ep_curve_mul_b(fp_t c, const fp_t a) {
}
}
-void ep_curve_mul_b3(fp_t c, const fp_t a) {
- ctx_t *ctx = core_get();
- switch (ctx->ep_opt_b3) {
- case RLC_ZERO:
- fp_zero(c);
- break;
- case RLC_ONE:
- fp_copy(c, a);
- break;
-#if FP_RDC != MONTY
- case RLC_TINY:
- fp_mul_dig(c, a, ctx->ep_b3[0]);
- break;
-#endif
- default:
- fp_mul(c, a, ctx->ep_b3);
- break;
- }
-}
-
int ep_curve_is_endom(void) {
return core_get()->ep_is_endom;
}
@@ -580,3 +521,57 @@ void ep_curve_set_endom(const fp_t a, const fp_t b, const ep_t g, const bn_t r,
}
#endif
+
+int ep_curve_embed(void) {
+ switch (core_get()->ep_is_pairf) {
+ case EP_K1:
+ return 1;
+ case EP_SS2:
+ return 2;
+ case EP_GMT8:
+ return 8;
+ case EP_BN:
+ case EP_B12:
+ return 12;
+ case EP_N16:
+ case EP_FM16:
+ case EP_K16:
+ return 16;
+ case EP_K18:
+ case EP_FM18:
+ case EP_SG18:
+ return 18;
+ case EP_B24:
+ return 24;
+ case EP_B48:
+ return 48;
+ case EP_SG54:
+ return 54;
+ }
+ return 0;
+}
+
+int ep_curve_frdim(void) {
+ size_t f = 0;
+
+ switch (ep_curve_embed()) {
+ case 1:
+ case 2:
+ case 8:
+ return 1;
+ break;
+ case 12:
+ return 4;
+ break;
+ case 18:
+ return 6;
+ break;
+ case 16:
+ case 24:
+ return 8;
+ break;
+ case 48:
+ return 16;
+ break;
+ }
+}
\ No newline at end of file
diff --git a/src/ep/relic_ep_dbl.c b/src/ep/relic_ep_dbl.c
index 1a160d02c..f8548b6be 100644
--- a/src/ep/relic_ep_dbl.c
+++ b/src/ep/relic_ep_dbl.c
@@ -30,6 +30,7 @@
*/
#include "relic_core.h"
+#include "relic_ep_dbl_tmpl.h"
/*============================================================================*/
/* Private definitions */
@@ -45,77 +46,7 @@
* @param[out] s - the slope.
* @param[in] p - the point to double.
*/
-static void ep_dbl_basic_imp(ep_t r, fp_t s, const ep_t p) {
- fp_t t0, t1, t2;
-
- fp_null(t0);
- fp_null(t1);
- fp_null(t2);
-
- RLC_TRY {
- fp_new(t0);
- fp_new(t1);
- fp_new(t2);
-
- /* t0 = 1/2 * y1. */
- fp_dbl(t0, p->y);
- fp_inv(t0, t0);
-
- /* t1 = 3 * x1^2 + a. */
- fp_sqr(t1, p->x);
- fp_copy(t2, t1);
- fp_dbl(t1, t1);
- fp_add(t1, t1, t2);
-
- switch (ep_curve_opt_a()) {
- case RLC_ZERO:
- break;
- case RLC_ONE:
- fp_add_dig(t1, t1, (dig_t)1);
- break;
-#if FP_RDC != MONTY
- case RLC_TINY:
- fp_add_dig(t1, t1, ep_curve_get_a()[0]);
- break;
-#endif
- default:
- fp_add(t1, t1, ep_curve_get_a());
- break;
- }
-
- /* t1 = (3 * x1^2 + a)/(2 * y1). */
- fp_mul(t1, t1, t0);
-
- if (s != NULL) {
- fp_copy(s, t1);
- }
-
- /* t2 = t1^2. */
- fp_sqr(t2, t1);
-
- /* x3 = t1^2 - 2 * x1. */
- fp_dbl(t0, p->x);
- fp_sub(t0, t2, t0);
-
- /* y3 = t1 * (x1 - x3) - y1. */
- fp_sub(t2, p->x, t0);
- fp_mul(t1, t1, t2);
- fp_sub(r->y, t1, p->y);
-
- fp_copy(r->x, t0);
- fp_copy(r->z, p->z);
-
- r->coord = BASIC;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp_free(t0);
- fp_free(t1);
- fp_free(t2);
- }
-}
+TMPL_DBL_BASIC_IMP(ep, fp);
#endif /* EP_ADD == BASIC */
@@ -128,144 +59,7 @@ static void ep_dbl_basic_imp(ep_t r, fp_t s, const ep_t p) {
* @param r - the result.
* @param p - the point to double.
*/
-static void ep_dbl_projc_imp(ep_t r, const ep_t p) {
- fp_t t0, t1, t2, t3, t4, t5;
-
- fp_null(t0);
- fp_null(t1);
- fp_null(t2);
- fp_null(t3);
- fp_null(t4);
- fp_null(t5);
-
- RLC_TRY {
- fp_new(t0);
- fp_new(t1);
- fp_new(t2);
- fp_new(t3);
- fp_new(t4);
- fp_new(t5);
-
- /* Formulas for point doubling from
- * "Complete addition formulas for prime order elliptic curves"
- * by Joost Renes, Craig Costello, and Lejla Batina
- * https://eprint.iacr.org/2015/1060.pdf
- */
- if (ep_curve_opt_a() == RLC_ZERO) {
- /* Cost of 6M + 2S + 1m_3b + 9a. */
- fp_sqr(t0, p->y);
- fp_mul(t3, p->x, p->y);
-
- if (p->coord == BASIC) {
- /* Save 1M + 1S + 1m_b3 if z1 = 1. */
- fp_copy(t1, p->y);
- fp_copy(t2, ep_curve_get_b3());
- } else {
- fp_mul(t1, p->y, p->z);
- fp_sqr(t2, p->z);
- ep_curve_mul_b3(t2, t2);
- }
- fp_dbl(r->z, t0);
- fp_dbl(r->z, r->z);
- fp_dbl(r->z, r->z);
- fp_mul(r->x, t2, r->z);
- fp_add(r->y, t0, t2);
- fp_mul(r->z, t1, r->z);
- fp_dbl(t1, t2);
- fp_add(t2, t1, t2);
- fp_sub(t0, t0, t2);
- fp_mul(r->y, t0, r->y);
- fp_add(r->y, r->x, r->y);
- fp_mul(r->x, t0, t3);
- fp_dbl(r->x, r->x);
- } else {
- fp_sqr(t0, p->x);
- fp_sqr(t1, p->y);
- fp_mul(t3, p->x, p->y);
- fp_dbl(t3, t3);
- fp_mul(t4, p->y, p->z);
-
- if (ep_curve_opt_a() == RLC_MIN3) {
- /* Cost of 8M + 3S + 2mb + 21a. */
- if (p->coord == BASIC) {
- /* Save 1S + 1m_b + 2a if z1 = 1. */
- fp_set_dig(t2, 3);
- fp_copy(r->y, ep_curve_get_b());
- } else {
- fp_sqr(t2, p->z);
- ep_curve_mul_b(r->y, t2);
- fp_dbl(t5, t2);
- fp_add(t2, t2, t5);
- }
- fp_mul(r->z, p->x, p->z);
- fp_dbl(r->z, r->z);
- fp_sub(r->y, r->y, r->z);
- fp_dbl(r->x, r->y);
- fp_add(r->y, r->x, r->y);
- fp_sub(r->x, t1, r->y);
- fp_add(r->y, t1, r->y);
- fp_mul(r->y, r->x, r->y);
- fp_mul(r->x, t3, r->x);
- ep_curve_mul_b(r->z, r->z);
- fp_sub(t3, r->z, t2);
- fp_sub(t3, t3, t0);
- fp_dbl(r->z, t3);
- fp_add(t3, t3, r->z);
- fp_dbl(r->z, t0);
- fp_add(t0, t0, r->z);
- fp_sub(t0, t0, t2);
- } else {
- /* Common cost of 8M + 3S + 3m_a + 2m_3b + 15a. */
- if (p->coord == BASIC) {
- /* Save 1S + 1m_b + 1m_a if z1 = 1. */
- fp_copy(r->y, ep_curve_get_b3());
- fp_copy(t2, ep_curve_get_a());
- } else {
- fp_sqr(t2, p->z);
- ep_curve_mul_b3(r->y, t2);
- ep_curve_mul_a(t2, t2);
- }
- fp_mul(r->z, p->x, p->z);
- fp_dbl(r->z, r->z);
- ep_curve_mul_a(r->x, r->z);
- fp_add(r->y, r->x, r->y);
- fp_sub(r->x, t1, r->y);
- fp_add(r->y, t1, r->y);
- fp_mul(r->y, r->x, r->y);
- fp_mul(r->x, t3, r->x);
- ep_curve_mul_b3(r->z, r->z);
- fp_sub(t3, t0, t2);
- ep_curve_mul_a(t3, t3);
- fp_add(t3, t3, r->z);
- fp_dbl(r->z, t0);
- fp_add(t0, t0, r->z);
- fp_add(t0, t0, t2);
- }
- /* Common part with renamed variables. */
- fp_mul(t0, t0, t3);
- fp_add(r->y, r->y, t0);
- fp_dbl(t2, t4);
- fp_mul(t0, t2, t3);
- fp_sub(r->x, r->x, t0);
- fp_mul(r->z, t2, t1);
- fp_dbl(r->z, r->z);
- fp_dbl(r->z, r->z);
- }
-
- r->coord = PROJC;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp_free(t0);
- fp_free(t1);
- fp_free(t2);
- fp_free(t3);
- fp_free(t4);
- fp_free(t5);
- }
-}
+TMPL_DBL_PROJC_IMP(ep, fp);
#endif /* EP_ADD == PROJC */
@@ -278,205 +72,7 @@ static void ep_dbl_projc_imp(ep_t r, const ep_t p) {
* @param r - the result.
* @param p - the point to double.
*/
-static void ep_dbl_jacob_imp(ep_t r, const ep_t p) {
- fp_t t0, t1, t2, t3, t4, t5;
-
- fp_null(t1);
- fp_null(t2);
- fp_null(t3);
- fp_null(t4);
- fp_null(t5);
-
- RLC_TRY {
- fp_new(t0);
- fp_new(t1);
- fp_new(t2);
- fp_new(t3);
- fp_new(t4);
- fp_new(t5);
-
- if (p->coord != BASIC && ep_curve_opt_a() == RLC_MIN3) {
- /* dbl-2001-b formulas: 3M + 5S + 8add + 1*4 + 2*8 + 1*3 */
- /* http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b */
-
- /* t0 = delta = z1^2. */
- fp_sqr(t0, p->z);
-
- /* t1 = gamma = y1^2. */
- fp_sqr(t1, p->y);
-
- /* t2 = beta = x1 * y1^2. */
- fp_mul(t2, p->x, t1);
-
- /* t3 = alpha = 3 * (x1 - z1^2) * (x1 + z1^2). */
- fp_sub(t3, p->x, t0);
- fp_add(t4, p->x, t0);
- fp_mul(t4, t3, t4);
- fp_dbl(t3, t4);
- fp_add(t3, t3, t4);
-
- /* x3 = alpha^2 - 8 * beta. */
- fp_dbl(t2, t2);
- fp_dbl(t2, t2);
- fp_dbl(t5, t2);
- fp_sqr(r->x, t3);
- fp_sub(r->x, r->x, t5);
-
- /* z3 = (y1 + z1)^2 - gamma - delta. */
- fp_add(r->z, p->y, p->z);
- fp_sqr(r->z, r->z);
- fp_sub(r->z, r->z, t1);
- fp_sub(r->z, r->z, t0);
-
- /* y3 = alpha * (4 * beta - x3) - 8 * gamma^2. */
- fp_dbl(t1, t1);
- fp_sqr(t1, t1);
- fp_dbl(t1, t1);
- fp_sub(r->y, t2, r->x);
- fp_mul(r->y, r->y, t3);
- fp_sub(r->y, r->y, t1);
- } else if (ep_curve_opt_a() == RLC_ZERO) {
- /* dbl-2009-l formulas: 2M + 5S + 6add + 1*8 + 3*2 + 1*3. */
- /* http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l */
-
- /* A = X1^2 */
- fp_sqr(t0, p->x);
-
- /* B = Y1^2 */
- fp_sqr(t1, p->y);
-
- /* C = B^2 */
- fp_sqr(t2, t1);
-
- /* D = 2*((X1+B)^2-A-C) */
- fp_add(t1, t1, p->x);
- fp_sqr(t1, t1);
- fp_sub(t1, t1, t0);
- fp_sub(t1, t1, t2);
- fp_dbl(t1, t1);
-
- /* E = 3*A */
- fp_dbl(t3, t0);
- fp_add(t0, t3, t0);
-
- /* F = E^2 */
- fp_sqr(t3, t0);
-
- /* Z3 = 2*Y1*Z1 */
- fp_mul(r->z, p->y, p->z);
- fp_dbl(r->z, r->z);
-
- /* X3 = F-2*D */
- fp_sub(r->x, t3, t1);
- fp_sub(r->x, r->x, t1);
-
- /* Y3 = E*(D-X3)-8*C */
- fp_sub(r->y, t1, r->x);
- fp_mul(r->y, r->y, t0);
- fp_dbl(t2, t2);
- fp_dbl(t2, t2);
- fp_dbl(t2, t2);
- fp_sub(r->y, r->y, t2);
- } else {
- /* dbl-2007-bl formulas: 1M + 8S + 1*a + 10add + 1*8 + 2*2 + 1*3 */
- /* http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-2007-bl */
-
- /* t0 = x1^2, t1 = y1^2, t2 = y1^4. */
- fp_sqr(t0, p->x);
- fp_sqr(t1, p->y);
- fp_sqr(t2, t1);
-
- if (p->coord != BASIC) {
- /* t3 = z1^2. */
- fp_sqr(t3, p->z);
-
- if (ep_curve_opt_a() == RLC_ZERO) {
- /* z3 = 2 * y1 * z1. */
- fp_mul(r->z, p->y, p->z);
- fp_dbl(r->z, r->z);
- } else {
- /* z3 = (y1 + z1)^2 - y1^2 - z1^2. */
- fp_add(r->z, p->y, p->z);
- fp_sqr(r->z, r->z);
- fp_sub(r->z, r->z, t1);
- fp_sub(r->z, r->z, t3);
- }
- } else {
- /* z3 = 2 * y1. */
- fp_dbl(r->z, p->y);
- }
-
- /* t4 = S = 2*((x1 + y1^2)^2 - x1^2 - y1^4). */
- fp_add(t4, p->x, t1);
- fp_sqr(t4, t4);
- fp_sub(t4, t4, t0);
- fp_sub(t4, t4, t2);
- fp_dbl(t4, t4);
-
- /* t5 = M = 3 * x1^2 + a * z1^4. */
- fp_dbl(t5, t0);
- fp_add(t5, t5, t0);
- if (p->coord != BASIC) {
- fp_sqr(t3, t3);
- switch (ep_curve_opt_a()) {
- case RLC_ZERO:
- break;
- case RLC_ONE:
- fp_add(t5, t5, t3);
- break;
- case RLC_TINY:
- fp_mul_dig(t1, t3, ep_curve_get_a()[0]);
- fp_add(t5, t5, t1);
- break;
- default:
- fp_mul(t1, t3, ep_curve_get_a());
- fp_add(t5, t5, t1);
- break;
- }
- } else {
- switch (ep_curve_opt_a()) {
- case RLC_ZERO:
- break;
- case RLC_ONE:
- fp_add_dig(t5, t5, (dig_t)1);
- break;
- case RLC_TINY:
- fp_add_dig(t5, t5, ep_curve_get_a()[0]);
- break;
- default:
- fp_add(t5, t5, ep_curve_get_a());
- break;
- }
- }
-
- /* x3 = T = M^2 - 2 * S. */
- fp_sqr(r->x, t5);
- fp_dbl(t1, t4);
- fp_sub(r->x, r->x, t1);
-
- /* y3 = M * (S - T) - 8 * y1^4. */
- fp_dbl(t2, t2);
- fp_dbl(t2, t2);
- fp_dbl(t2, t2);
- fp_sub(t4, t4, r->x);
- fp_mul(t5, t5, t4);
- fp_sub(r->y, t5, t2);
- }
-
- r->coord = JACOB;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp_free(t0);
- fp_free(t1);
- fp_free(t2);
- fp_free(t3);
- fp_free(t4);
- fp_free(t5);
- }
-}
+TMPL_DBL_JACOB_IMP(ep, fp);
#endif /* EP_ADD == JACOB */
diff --git a/src/ep/relic_ep_map.c b/src/ep/relic_ep_map.c
index 714efdf5b..4b7841b7a 100644
--- a/src/ep/relic_ep_map.c
+++ b/src/ep/relic_ep_map.c
@@ -31,7 +31,7 @@
#include "relic_core.h"
#include "relic_md.h"
-#include "relic_tmpl_map.h"
+#include "relic_ep_map_tmpl.h"
/*============================================================================*/
/* Private definitions */
@@ -57,20 +57,19 @@ TMPL_MAP_ISOGENY_MAP(ep, fp, iso);
#endif /* EP_CTMAP */
-#define EP_MAP_COPY_COND(O, I, C) dv_copy_cond(O, I, RLC_FP_DIGS, C)
/**
* Simplified SWU mapping from Section 4 of
* "Fast and simple constant-time hashing to the BLS12-381 Elliptic Curve"
*/
-TMPL_MAP_SSWU(ep, fp, dig_t, EP_MAP_COPY_COND);
+TMPL_MAP_SSWU(ep, fp, dig_t);
/**
* Shallue--van de Woestijne map, based on the definition from
* draft-irtf-cfrg-hash-to-curve-06, Section 6.6.1
*/
-TMPL_MAP_SVDW(ep, fp, dig_t, EP_MAP_COPY_COND);
+TMPL_MAP_SVDW(ep, fp, dig_t);
-#undef EP_MAP_COPY_COND
+#undef EP_MAP_copy_sec
/**
* Maps an array of uniformly random bytes to a point in a prime elliptic
@@ -120,7 +119,7 @@ static void ep_map_from_field(ep_t p, const uint8_t *uniform_bytes, size_t len,
/* compare sign of y and sign of t; fix if necessary */ \
neg = neg != fp_is_even(PT->y); \
fp_neg(t, PT->y); \
- dv_copy_cond(PT->y, t, RLC_FP_DIGS, neg); \
+ dv_copy_sec(PT->y, t, RLC_FP_DIGS, neg); \
} while (0)
/* first map invocation */
@@ -180,7 +179,7 @@ void ep_map_basic(ep_t p, const uint8_t *msg, size_t len) {
fp_set_dig(p->z, 1);
while (1) {
- ep_rhs(t0, p);
+ ep_rhs(t0, p->x);
if (fp_smb(t0) == 1) {
fp_srt(p->y, t0);
@@ -240,14 +239,29 @@ void ep_map_swift(ep_t p, const uint8_t *msg, size_t len) {
/* enough space for two field elements plus extra bytes for uniformity */
const size_t len_per_elm = (FP_PRIME + ep_param_level() + 7) / 8;
uint8_t s, *pseudo_random_bytes = RLC_ALLOCA(uint8_t, 2 * len_per_elm + 1);
- fp_t a, b, c, t, u, v, w, y, x1, y1, z1;
+ fp_t a, b, c, d, e, f, t, u, v, w, y, x1, y1, z1, den[3];
ctx_t *ctx = core_get();
bn_t k;
+ if (ep_curve_is_super()) {
+ RLC_FREE(pseudo_random_bytes);
+ RLC_THROW(ERR_NO_CONFIG);
+ return;
+ }
+
+ if (ctx->mod18 % 3 == 2) {
+ RLC_FREE(pseudo_random_bytes);
+ RLC_THROW(ERR_NO_CONFIG);
+ return;
+ }
+
bn_null(k);
fp_null(a);
fp_null(b);
fp_null(c);
+ fp_null(d);
+ fp_null(e);
+ fp_null(f);
fp_null(t);
fp_null(u);
fp_null(v);
@@ -256,12 +270,18 @@ void ep_map_swift(ep_t p, const uint8_t *msg, size_t len) {
fp_null(x1);
fp_null(y1);
fp_null(z1);
+ fp_null(den[0]);
+ fp_null(den[1]);
+ fp_null(den[2]);
RLC_TRY {
bn_new(k);
fp_new(a);
fp_new(b);
fp_new(c);
+ fp_new(d);
+ fp_new(e);
+ fp_new(f);
fp_new(t);
fp_new(u);
fp_new(v);
@@ -270,6 +290,9 @@ void ep_map_swift(ep_t p, const uint8_t *msg, size_t len) {
fp_new(x1);
fp_new(y1);
fp_new(z1);
+ fp_new(den[0]);
+ fp_new(den[1]);
+ fp_new(den[2]);
md_xmd(pseudo_random_bytes, 2 * len_per_elm + 1, msg, len,
(const uint8_t *)"RELIC", 5);
@@ -280,298 +303,137 @@ void ep_map_swift(ep_t p, const uint8_t *msg, size_t len) {
fp_prime_conv(t, k);
s = pseudo_random_bytes[2 * len_per_elm] & 1;
- fp_copy(a, ep_curve_get_a());
+ if (ep_curve_opt_b() == RLC_ZERO) {
+ fp_sqr(a, u);
+ fp_sqr(b, a);
+ fp_mul(c, b, a);
+ if (ep_curve_opt_a() == RLC_ONE) {
+ fp_add_dig(c, c, 64);
+ } else {
+ fp_dbl(f, ep_curve_get_a());
+ fp_dbl(f, f);
+ fp_sqr(e, f);
+ fp_mul(e, e, f);
+ fp_add(c, c, e);
+ }
+ fp_sqr(d, t);
- if ((ep_curve_opt_b() == RLC_ZERO) && (ctx->mod8 == 1)) {
- /* This is the approach due to Koshelev introduced in
- * https://eprint.iacr.org/2021/1034.pdf */
- if (fp_is_sqr(a)) {
- /* Compute t^2 = 3c*sqrt(a)*(2c^3*x^6 - 3*c^2*x^4 - 3*c*x^2 + 2).*/
- /* Compute w = 3*c. */
- fp_set_dig(c, -fp_prime_get_qnr());
- fp_neg(c, c);
- fp_dbl(w, c);
- fp_add(w, w, c);
+ fp_mul(v, a, d);
+ fp_mul(v, v, u);
+ fp_mul_dig(v, v, 24);
+ fp_mul(v, v, ctx->ep_map_c[4]);
- /* Compute x^2, x^4 and x^6 in sequence. */
- fp_sqr(z1, u);
- fp_sqr(y1, z1);
- fp_mul(t, z1, y1);
+ fp_sub_dig(p->x, ctx->ep_map_c[4], 1);
+ fp_hlv(p->x, p->x);
- fp_dbl(t, t);
- fp_mul(t, t, c);
- fp_mul(t, t, c);
- fp_mul(t, t, c);
-
- fp_mul(v, y1, c);
- fp_mul(v, v, w);
- fp_sub(t, t, v);
-
- /* v = -3*c*x^2. */
- fp_mul(v, w, z1);
- fp_neg(v, v);
- fp_add(t, t, v);
- fp_add_dig(t, t, 2);
-
- /* Assume a = 1 for simplicitly. */
- fp_mul(t, t, w);
- fp_mul(t, t, ctx->ep_map_c[6]);
- dig_t c1 = fp_is_sqr(t);
- /* If t is not square, compute u = 1/(uc), t = sqrt(t/c)/(c*u^3)*/
- fp_inv(v, c);
- fp_inv(x1, u);
- fp_mul(y1, t, v);
- /* If t is a square, extract its square root. */
- dv_copy_cond(t, y1, RLC_FP_DIGS, !c1);
- fp_srt(t, t);
- fp_mul(y1, t, v);
- fp_sqr(y, x1);
- fp_mul(y, y, x1);
- fp_mul(y1, y1, y);
- fp_mul(x1, x1, v);
- dv_copy_cond(u, x1, RLC_FP_DIGS, !c1);
- dv_copy_cond(t, y1, RLC_FP_DIGS, !c1);
-
- /* Compute x = sqrt(a)*(c*x^2 - 2)/(-3*c*x^2). */
- fp_sqr(z1, u);
- fp_mul(v, w, z1);
- fp_neg(v, v);
- fp_inv(v, v);
- fp_mul(p->x, z1, c);
- fp_sub_dig(p->x, p->x, 2);
- fp_mul(p->x, p->x, v);
- fp_mul(p->x, p->x, ctx->ep_map_c[6]);
-
- /* Compute y = y*2*sqrt(a)/(3^2*c^2*x^3). */
- fp_mul(z1, z1, u);
- fp_sqr(w, w);
- fp_mul(w, w, z1);
- fp_inv(w, w);
- fp_dbl(p->y, ctx->ep_map_c[6]);
- fp_mul(p->y, p->y, t);
- fp_mul(p->y, p->y, w);
- fp_set_dig(p->z, 1);
- p->coord = BASIC;
- } else {
- /* Compute c = 3*a^2, t^2 = 6a(9u^5 − 14au^3 + 3cu).*/
- fp_neg(a, a);
- fp_sqr(c, a);
+ fp_sqr(w, b);
+ fp_mul(y, v, a);
+ if (ep_curve_opt_a() == RLC_ONE) {
fp_dbl(t, c);
- fp_add(c, c, t);
- fp_dbl(t, c);
- fp_add(t, t, c);
- fp_mul(t, t, u);
-
- fp_sqr(v, u);
- fp_mul(w, v, u);
- fp_mul(x1, w, a);
- fp_mul_dig(x1, x1, 14);
- fp_sub(t, t, x1);
-
- fp_mul(w, w, v);
- fp_dbl(x1, w);
- fp_add(w, w, x1);
- fp_dbl(x1, w);
- fp_add(w, w, x1);
- fp_add(t, t, w);
- fp_mul(t, t, a);
fp_dbl(t, t);
- fp_dbl(x1, t);
- fp_add(t, t, x1);
- dig_t c1 = fp_is_sqr(t);
- /* If t is not square, compute u = a/u, t = a*sqrt(a*t)/u^3*/
- fp_inv(x1, u);
- fp_mul(y1, t, a);
- /* If t is a square, extract its square root. */
- dv_copy_cond(t, y1, RLC_FP_DIGS, !c1);
- fp_srt(t, t);
- fp_mul(y1, t, a);
- fp_sqr(y, x1);
- fp_mul(y, y, x1);
- fp_mul(y1, y1, y);
- fp_mul(x1, x1, a);
- dv_copy_cond(u, x1, RLC_FP_DIGS, !c1);
- dv_copy_cond(t, y1, RLC_FP_DIGS, !c1);
-
- /* Compute x = 2^4*i*3*a^2*u / (3*(3*u^2 - a))^2. */
- fp_copy(y, ctx->ep_map_c[6]);
- fp_mul(c, c, u);
- fp_mul(x1, c, y);
- fp_dbl(x1, x1);
- fp_dbl(x1, x1);
- fp_dbl(x1, x1);
- fp_dbl(p->x, x1);
- fp_sqr(v, u);
- fp_dbl(z1, v);
- fp_add(z1, z1, v);
- fp_sub(z1, z1, a);
- fp_dbl(p->z, z1);
- fp_add(p->z, p->z, z1);
-
- /* Compute y = 3*2*(i-1)*a*(3^2*u^2 + a)*t / (3*(3*u^2 - a))^3. */
- fp_sub_dig(y, y, 1);
- fp_mul(y1, y, a);
- fp_dbl(y1, y1);
- fp_dbl(p->y, y1);
- fp_add(p->y, p->y, y1);
- fp_mul(p->y, p->y, t);
- fp_dbl(y1, v);
- fp_add(y1, y1, v);
- fp_dbl(v, y1);
- fp_add(y1, y1, v);
- fp_add(y1, y1, a);
- fp_mul(p->y, p->y, y1);
-
- /* Multiply by cofactor. */
- p->coord = JACOB;
- ep_norm(p, p);
- }
- } else if ((ep_curve_opt_b() == RLC_ZERO) && (ctx->mod8 != 1)) {
- /* This is the approach due to Koshelev introduced in
- * https://eprint.iacr.org/2021/1604.pdf */
- fp_set_dig(c, -fp_prime_get_qnr());
- fp_neg(c, c);
-
- /* u = t0, t = t1, v = t0^4, y = t1^4, w = c^2, z1 = 8*a^2*c. */
- fp_sqr(v, u);
- fp_sqr(v, v);
- fp_sqr(y, t);
- fp_sqr(y, y);
- fp_sqr(w, c);
- fp_sqr(z1, a);
- fp_mul(z1, z1, c);
- fp_dbl(z1, z1);
- fp_dbl(z1, z1);
- fp_dbl(z1, z1);
- /* w = c^2*t0^4+t1^4, y1 = c^4*t0^8, x1 = 2*c^2*t0^4*t1^4, y = t1^8. */
- fp_mul(w, w, v);
- fp_sqr(y1, w);
- fp_mul(x1, w, y);
- fp_dbl(x1, x1);
- fp_add(w, w, y);
- fp_sqr(y, y);
- /* w = den = 8*a^2*c(c^2*t0^4 + t1^4), z1 = 16*a^3*c^2. */
- fp_mul(w, w, z1);
- fp_inv(p->z, w);
- fp_mul(z1, z1, c);
- fp_mul(z1, z1, a);
- fp_dbl(z1, z1);
- /* v = num2 = c^4*t0^8 - 2*c^2t0^4*t1^4 + t1^8 - 16*a^3*c^2*/
- fp_sub(v, y1, x1);
- fp_add(v, v, y);
- fp_sub(v, v, z1);
- /* w = num0 = t0 * ac(-3*c^4t0^8 + 2c^2*t0^4*t1^4 + t1^8 + 16*a^3*c^2)*/
- fp_add(w, y, z1);
- fp_add(w, w, x1);
- fp_sub(w, w, y1);
- fp_sub(w, w, y1);
- fp_sub(w, w, y1);
- fp_mul(w, w, u);
- fp_mul(w, w, c);
- fp_mul(w, w, a);
- /* z1 = num1 = t1 * ac^2(c^4t0^8 + 2c^2t0^4*t1^4 - 3^t1^8 + 16a^3c^2)*/
- fp_sub(z1, z1, y);
- fp_sub(z1, z1, y);
- fp_sub(z1, z1, y);
- fp_add(z1, z1, x1);
- fp_add(z1, z1, y1);
- fp_mul(z1, z1, t);
- fp_mul(z1, z1, c);
- fp_mul(z1, z1, c);
- fp_mul(z1, z1, a);
- /* v2 = num2/den = v/w. */
- fp_mul(w, w, p->z);
- fp_mul(z1, z1, p->z);
- fp_mul(v, v, p->z);
- fp_inv(v, v);
-
- bn_read_raw(k, fp_prime_get(), RLC_FP_DIGS);
- if ((k->dp[0] & 0xF) == 5) {
- /* n = (3p + 1)/16 */
- bn_mul_dig(k, k, 3);
- bn_add_dig(k, k, 1);
- } else if ((k->dp[0] & 0xF) == 13) {
- /* n = (p + 3)/16 */
- bn_add_dig(k, k, 3);
} else {
- RLC_THROW(ERR_NO_VALID);
+ fp_mul(t, f, c);
}
- bn_rsh(k, k, 4);
- /* Compute x1 = f = (1/v2)^3 + a*(1/v2) = (1/v2)((1/v2)^2 + a). */
- fp_sqr(x1, v);
- fp_add(x1, x1, a);
- fp_mul(x1, x1, v);
- /* Compute y = theta, zp = theta^4. */
- fp_exp(y, x1, k);
- fp_sqr(p->z, y);
- fp_sqr(p->z, p->z);
- /* Perform the base change from (t0,t1) to (u0, u1). */
- fp_sqr(u, u);
- fp_mul(u, u, c);
- fp_sqr(t, t);
- fp_mul(t, t, c);
- /* Compute c = i^r * f. */
- fp_mul(c, ctx->ep_map_c[5], x1);
- fp_sqr(p->y, y);
- /* We use zp as temporary, but there is no problem with \psi. */
- int index = 0;
- fp_copy(y1, u);
- fp_copy(a, v);
- fp_sqr(b, y);
- fp_copy(p->x, a);
- fp_copy(p->y, b);
- for (int m = 0; m < 4; m++) {
- fp_mul(y1, y1, ctx->ep_map_c[5]);
- index += (fp_bits(y1) < fp_bits(u));
+ fp_add(y, y, t);
+ fp_mul(y, y, p->x);
+
+ fp_add(den[0], c, v);
+ fp_mul(den[0], den[0], u);
+ fp_mul(den[0], den[0], ctx->ep_map_c[4]);
+ fp_mul(den[0], den[0], p->x);
+ fp_dbl(den[0], den[0]);
+ fp_neg(den[0], den[0]);
+ fp_mul(den[1], den[0], p->x);
+ if (ep_curve_opt_a() == RLC_ONE) {
+ fp_sub_dig(den[2], a, 4);
+ } else {
+ fp_sub(den[2], a, f);
}
- /* Apply consecutive endomorphisms. */
- for (int m = 0; m < 4; m++) {
- fp_neg(a, a);
- fp_mul(b, b, ep_curve_get_beta());
- dv_copy_cond(p->x, a, RLC_FP_DIGS, m < index);
- dv_copy_cond(p->y, b, RLC_FP_DIGS, m < index);
+ fp_sqr(den[2], den[2]);
+ fp_mul_dig(den[2], den[2], 216);
+ fp_dbl(den[2], den[2]);
+ fp_neg(den[2], den[2]);
+ fp_mul(den[2], den[2], b);
+ fp_mul(den[2], den[2], d);
+
+ if (fp_is_zero(den[0]) || fp_is_zero(den[1]) || fp_is_zero(den[2])) {
+ ep_set_infty(p);
+ } else {
+ fp_inv_sim(den, den, 3);
+ if (ep_curve_opt_a() == RLC_ONE) {
+ fp_dbl(a, a);
+ fp_dbl(a, a);
+ fp_dbl(a, a);
+ fp_dbl(a, a);
+ fp_add(y1, a, v);
+ fp_dbl(y1, y1);
+ fp_dbl(y1, y1);
+ } else {
+ fp_mul(y1, f, v);
+ fp_mul(u, a, e);
+ fp_add(y1, y1, u);
+ }
+ fp_add(y1, y1, w);
+ fp_mul(z1, y, p->x);
+ fp_add(x1, y1, z1);
+ fp_add(y1, y1, y);
+
+ if (ep_curve_opt_a() == RLC_ONE) {
+ fp_dbl(e, b);
+ fp_dbl(e, e);
+ fp_add(z1, a, e);
+ } else {
+ fp_mul(z1, f, a);
+ fp_add(z1, z1, b);
+ fp_mul(z1, z1, f);
+ }
+ fp_dbl(t, z1);
+ fp_add(z1, z1, t);
+ fp_sub(z1, c, z1);
+ fp_sub(z1, z1, v);
+ fp_mul(z1, z1, v);
+ if (ep_curve_opt_a() == RLC_ONE) {
+ fp_dbl(a, a);
+ fp_dbl(a, a);
+ fp_dbl(a, a);
+ fp_set_dig(d, 64);
+ fp_sqr(d, d);
+ } else {
+ fp_dbl(a, u);
+ fp_sqr(d, e);
+ }
+ fp_add(a, a, w);
+ fp_mul(u, a, b);
+ fp_sub(z1, u, z1);
+ fp_add(z1, z1, d);
+
+ fp_mul(x1, x1, den[0]);
+ fp_mul(y1, y1, den[1]);
+ fp_mul(z1, z1, den[2]);
+
+ ep_rhs(t, x1);
+ ep_rhs(u, y1);
+ ep_rhs(v, z1);
+
+ int c2 = fp_is_sqr(u);
+ int c3 = fp_is_sqr(v);
+
+ fp_copy_sec(t, u, c2);
+ fp_copy_sec(x1, y1, c2);
+ fp_copy_sec(t, v, c3);
+ fp_copy_sec(x1, z1, c3);
+
+ if (!fp_srt(t, t)) {
+ RLC_THROW(ERR_NO_VALID);
+ }
+ fp_neg(u, t);
+ fp_copy_sec(t, u, fp_is_even(t) ^ s);
+
+ fp_copy(p->x, x1);
+ fp_copy(p->y, t);
+ fp_set_dig(p->z, 1);
+ p->coord = BASIC;
}
- fp_neg(y1, x1);
- /* Compute 1/d * 1/theta. */
- fp_inv(y, y);
- fp_mul(y, y, ctx->ep_map_c[4]);
- dig_t c0 = fp_cmp(p->z, x1) == RLC_EQ;
- dig_t c1 = fp_cmp(p->z, y1) == RLC_EQ;
- dig_t c2 = fp_cmp(p->z, c) == RLC_EQ;
- fp_neg(c, c);
- dig_t c3 = fp_cmp(p->z, c) == RLC_EQ;
- c2 = !c0 && !c1 && c2;
- c3 = !c0 && !c1 && !c2 && c3;
- fp_copy(p->z, ctx->ep_map_c[6]);
- fp_mul(p->z, p->z, p->y);
- dv_copy_cond(p->y, p->z, RLC_FP_DIGS, c1);
- fp_copy(y1, ctx->ep_map_c[4]);
- /* Convert from projective coordinates on the surface to affine. */
- fp_mul(u, u, v);
- fp_mul(t, t, v);
- fp_sqr(v, v);
- fp_mul(w, w, v);
- fp_mul(z1, z1, v);
- /* Compute (x,y) = (x0/(d*theta)^2, y0/(d*theta)^3). */
- fp_sqr(y1, y);
- fp_mul(u, u, y1);
- fp_mul(w, w, y);
- fp_mul(w, w, y1);
- dv_copy_cond(p->x, u, RLC_FP_DIGS, c2);
- dv_copy_cond(p->y, w, RLC_FP_DIGS, c2);
- /* Compute (x,y) = (x1/(d^3*theta)^2, y1/(d^3*theta)^3). */
- fp_mul(z1, z1, y);
- fp_mul(t, t, y1);
- fp_mul(z1, z1, y1);
- fp_sqr(y, ctx->ep_map_c[4]);
- fp_mul(z1, z1, y);
- fp_sqr(y, y);
- fp_mul(t, t, y);
- fp_mul(z1, z1, y);
- dv_copy_cond(p->x, t, RLC_FP_DIGS, c3);
- dv_copy_cond(p->y, z1, RLC_FP_DIGS, c3);
- p->coord = BASIC;
- fp_set_dig(p->z, 1);
} else {
/* This is the SwiftEC case per se. */
if (ep_curve_opt_a() != RLC_ZERO) {
@@ -623,16 +485,16 @@ void ep_map_swift(ep_t p, const uint8_t *msg, size_t len) {
int c2 = fp_is_sqr(u);
int c3 = fp_is_sqr(v);
- dv_swap_cond(x1, y1, RLC_FP_DIGS, c2);
- dv_swap_cond(t, u, RLC_FP_DIGS, c2);
- dv_swap_cond(x1, z1, RLC_FP_DIGS, c3);
- dv_swap_cond(t, v, RLC_FP_DIGS, c3);
+ fp_copy_sec(x1, y1, c2);
+ fp_copy_sec(t, u, c2);
+ fp_copy_sec(x1, z1, c3);
+ fp_copy_sec(t, v, c3);
if (!fp_srt(t, t)) {
RLC_THROW(ERR_NO_VALID);
}
fp_neg(u, t);
- dv_swap_cond(t, u, RLC_FP_DIGS, fp_is_even(t) ^ s);
+ fp_copy_sec(t, u, fp_is_even(t) ^ s);
fp_copy(p->x, x1);
fp_copy(p->y, t);
@@ -652,6 +514,9 @@ void ep_map_swift(ep_t p, const uint8_t *msg, size_t len) {
fp_free(a);
fp_free(b);
fp_free(c);
+ fp_free(d);
+ fp_free(e);
+ fp_free(f);
fp_free(t);
fp_free(u);
fp_free(v);
@@ -660,6 +525,9 @@ void ep_map_swift(ep_t p, const uint8_t *msg, size_t len) {
fp_free(x1);
fp_free(y1);
fp_free(z1);
+ fp_free(den[0]);
+ fp_free(den[1]);
+ fp_free(den[2]);
RLC_FREE(pseudo_random_bytes);
}
}
diff --git a/src/ep/relic_ep_mul.c b/src/ep/relic_ep_mul.c
index db0fda139..c79cf404d 100644
--- a/src/ep/relic_ep_mul.c
+++ b/src/ep/relic_ep_mul.c
@@ -208,39 +208,35 @@ static void ep_mul_naf_imp(ep_t r, const ep_t p, const bn_t k) {
#endif /* EP_PLAIN || EP_SUPER */
#endif /* EP_MUL == LWNAF */
+#if EP_MUL == LWREG || !defined(STRIP)
#if defined(EP_ENDOM)
static void ep_mul_reg_glv(ep_t r, const ep_t p, const bn_t k) {
- int i, j, n0, n1, s0, s1, b0, b1;
- int8_t _s0, _s1, reg0[RLC_FP_BITS + 1], reg1[RLC_FP_BITS + 1];
- bn_t n, _k, k0, k1, v1[3], v2[3];
- ep_t q, t[1 << (RLC_WIDTH - 2)], u, v, w;
+ int8_t reg[2][RLC_FP_BITS + 1], s[2], b[2], c0, c1, n0, n1;
+ bn_t n, _k[2], v1[3], v2[3];
+ ep_t q, t[1 << (RLC_WIDTH - 2)], u, w;
size_t l;
bn_null(n);
- bn_null(_k);
- bn_null(k0);
- bn_null(k1);
+ bn_null(_k[0]);
+ bn_null(_k[1]);
ep_null(q);
ep_null(u);
- ep_null(v);
ep_null(w);
RLC_TRY {
bn_new(n);
- bn_new(_k);
- bn_new(k0);
- bn_new(k1);
+ bn_new(_k[0]);
+ bn_new(_k[1]);
ep_new(q);
ep_new(u);
- ep_new(v);
ep_new(w);
- for (i = 0; i < (1 << (RLC_WIDTH - 2)); i++) {
+ for (size_t i = 0; i < (1 << (RLC_WIDTH - 2)); i++) {
ep_null(t[i]);
ep_new(t[i]);
}
- for (i = 0; i < 3; i++) {
+ for (size_t i = 0; i < 3; i++) {
bn_null(v1[i]);
bn_null(v2[i]);
bn_new(v1[i]);
@@ -251,27 +247,25 @@ static void ep_mul_reg_glv(ep_t r, const ep_t p, const bn_t k) {
ep_curve_get_v1(v1);
ep_curve_get_v2(v2);
- bn_mod(_k, k, n);
+ bn_mod(_k[0], k, n);
- bn_rec_glv(k0, k1, _k, n, (const bn_t *)v1, (const bn_t *)v2);
- s0 = bn_sign(k0);
- s1 = bn_sign(k1);
- bn_abs(k0, k0);
- bn_abs(k1, k1);
- b0 = bn_is_even(k0);
- b1 = bn_is_even(k1);
- k0->dp[0] |= b0;
- k1->dp[0] |= b1;
-
- ep_copy(q, p);
- ep_neg(t[0], p);
- dv_copy_cond(q->y, t[0]->y, RLC_FP_DIGS, s0 != RLC_POS);
+ bn_rec_glv(_k[0], _k[1], _k[0], n, (const bn_t *)v1, (const bn_t *)v2);
+ for (size_t i = 0; i < 2; i++) {
+ s[i] = bn_sign(_k[i]);
+ bn_abs(_k[i], _k[i]);
+ b[i] = bn_is_even(_k[i]);
+ _k[i]->dp[0] |= b[i];
+ }
+
+ ep_norm(t[0], p);
+ ep_neg(q, t[0]);
+ dv_copy_sec(q->y, t[0]->y, RLC_FP_DIGS, s[0] == RLC_POS);
ep_tab(t, q, RLC_WIDTH);
l = RLC_FP_BITS + 1;
- bn_rec_reg(reg0, &l, k0, bn_bits(n)/2, RLC_WIDTH);
+ bn_rec_reg(reg[0], &l, _k[0], bn_bits(n) >> 1, RLC_WIDTH);
l = RLC_FP_BITS + 1;
- bn_rec_reg(reg1, &l, k1, bn_bits(n)/2, RLC_WIDTH);
+ bn_rec_reg(reg[1], &l, _k[1], bn_bits(n) >> 1, RLC_WIDTH);
#if defined(EP_MIXED)
fp_set_dig(u->z, 1);
@@ -281,53 +275,51 @@ static void ep_mul_reg_glv(ep_t r, const ep_t p, const bn_t k) {
u->coord = w->coord = EP_ADD;
#endif
ep_set_infty(r);
- for (i = l - 1; i >= 0; i--) {
- for (j = 0; j < RLC_WIDTH - 1; j++) {
+ for (int i = l - 1; i >= 0; i--) {
+ for (size_t j = 0; j < RLC_WIDTH - 1; j++) {
ep_dbl(r, r);
}
- n0 = reg0[i];
- _s0 = (n0 >> 7);
- n0 = ((n0 ^ _s0) - _s0) >> 1;
- n1 = reg1[i];
- _s1 = (n1 >> 7);
- n1 = ((n1 ^ _s1) - _s1) >> 1;
-
- for (j = 0; j < (1 << (RLC_WIDTH - 2)); j++) {
- dv_copy_cond(u->x, t[j]->x, RLC_FP_DIGS, j == n0);
- dv_copy_cond(w->x, t[j]->x, RLC_FP_DIGS, j == n1);
- dv_copy_cond(u->y, t[j]->y, RLC_FP_DIGS, j == n0);
- dv_copy_cond(w->y, t[j]->y, RLC_FP_DIGS, j == n1);
-#if !defined(EP_MIXED)
- dv_copy_cond(u->z, t[j]->z, RLC_FP_DIGS, j == n0);
- dv_copy_cond(w->z, t[j]->z, RLC_FP_DIGS, j == n1);
+ n0 = reg[0][i];
+ c0 = (n0 >> 7);
+ n0 = ((n0 ^ c0) - c0) >> 1;
+ n1 = reg[1][i];
+ c1 = (n1 >> 7);
+ n1 = ((n1 ^ c1) - c1) >> 1;
+
+ for (size_t j = 0; j < (1 << (RLC_WIDTH - 2)); j++) {
+ fp_copy_sec(u->x, t[j]->x, j == n0);
+ fp_copy_sec(w->x, t[j]->x, j == n1);
+ fp_copy_sec(u->y, t[j]->y, j == n0);
+ fp_copy_sec(w->y, t[j]->y, j == n1);
+#if !defined(EP_fpXED)
+ fp_copy_sec(u->z, t[j]->z, j == n0);
+ fp_copy_sec(w->z, t[j]->z, j == n1);
#endif
}
- ep_neg(v, u);
- dv_copy_cond(u->y, v->y, RLC_FP_DIGS, _s0 != 0);
- ep_add(r, r, u);
+ ep_neg(q, u);
+ fp_copy_sec(q->y, u->y, c0 == 0);
+ ep_add(r, r, q);
ep_psi(w, w);
ep_neg(q, w);
- dv_copy_cond(w->y, q->y, RLC_FP_DIGS, s0 != s1);
- ep_neg(q, w);
- dv_copy_cond(w->y, q->y, RLC_FP_DIGS, _s1 != 0);
+ fp_copy_sec(w->y, q->y, (c1 != 0) ^ (s[0] != s[1]));
ep_add(r, r, w);
}
/* t[0] has an unmodified copy of p. */
ep_sub(u, r, t[0]);
- dv_copy_cond(r->x, u->x, RLC_FP_DIGS, b0);
- dv_copy_cond(r->y, u->y, RLC_FP_DIGS, b0);
- dv_copy_cond(r->z, u->z, RLC_FP_DIGS, b0);
+ fp_copy_sec(r->x, u->x, b[0]);
+ fp_copy_sec(r->y, u->y, b[0]);
+ fp_copy_sec(r->z, u->z, b[0]);
ep_psi(w, t[0]);
ep_neg(q, w);
- dv_copy_cond(w->y, q->y, RLC_FP_DIGS, s0 != s1);
- ep_sub(u, r, w);
- dv_copy_cond(r->x, u->x, RLC_FP_DIGS, b1);
- dv_copy_cond(r->y, u->y, RLC_FP_DIGS, b1);
- dv_copy_cond(r->z, u->z, RLC_FP_DIGS, b1);
+ fp_copy_sec(q->y, w->y, s[0] == s[1]);
+ ep_sub(u, r, q);
+ fp_copy_sec(r->x, u->x, b[1]);
+ fp_copy_sec(r->y, u->y, b[1]);
+ fp_copy_sec(r->z, u->z, b[1]);
/* Convert r to affine coordinates. */
ep_norm(r, r);
@@ -337,18 +329,16 @@ static void ep_mul_reg_glv(ep_t r, const ep_t p, const bn_t k) {
}
RLC_FINALLY {
bn_free(n);
- bn_free(_k);
- bn_free(k0);
- bn_free(k1);
+ bn_free(_k[0]);
+ bn_free(_k[1]);
bn_free(n);
ep_free(q);
ep_free(u);
- ep_free(v);
ep_free(w);
- for (i = 0; i < 1 << (RLC_WIDTH - 2); i++) {
+ for (size_t i = 0; i < 1 << (RLC_WIDTH - 2); i++) {
ep_free(t[i]);
}
- for (i = 0; i < 3; i++) {
+ for (size_t i = 0; i < 3; i++) {
bn_free(v1[i]);
bn_free(v2[i]);
}
@@ -408,25 +398,25 @@ static void ep_mul_reg_imp(ep_t r, const ep_t p, const bn_t k) {
n = ((n ^ s) - s) >> 1;
for (j = 0; j < (1 << (RLC_WIDTH - 2)); j++) {
- dv_copy_cond(u->x, t[j]->x, RLC_FP_DIGS, j == n);
- dv_copy_cond(u->y, t[j]->y, RLC_FP_DIGS, j == n);
+ fp_copy_sec(u->x, t[j]->x, j == n);
+ fp_copy_sec(u->y, t[j]->y, j == n);
#if !defined(EP_MIXED)
- dv_copy_cond(u->z, t[j]->z, RLC_FP_DIGS, j == n);
+ fp_copy_sec(u->z, t[j]->z, j == n);
#endif
}
ep_neg(v, u);
- dv_copy_cond(u->y, v->y, RLC_FP_DIGS, s != 0);
+ fp_copy_sec(u->y, v->y, s != 0);
ep_add(r, r, u);
}
/* t[0] has an unmodified copy of p. */
ep_sub(u, r, t[0]);
- dv_copy_cond(r->x, u->x, RLC_FP_DIGS, bn_is_even(k));
- dv_copy_cond(r->y, u->y, RLC_FP_DIGS, bn_is_even(k));
- dv_copy_cond(r->z, u->z, RLC_FP_DIGS, bn_is_even(k));
+ fp_copy_sec(r->x, u->x, bn_is_even(k));
+ fp_copy_sec(r->y, u->y, bn_is_even(k));
+ fp_copy_sec(r->z, u->z, bn_is_even(k));
/* Convert r to affine coordinates. */
ep_norm(r, r);
ep_neg(u, r);
- dv_copy_cond(r->y, u->y, RLC_FP_DIGS, bn_sign(k) == RLC_NEG);
+ fp_copy_sec(r->y, u->y, bn_sign(k) == RLC_NEG);
}
RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
@@ -443,6 +433,7 @@ static void ep_mul_reg_imp(ep_t r, const ep_t p, const bn_t k) {
}
#endif /* EP_PLAIN || EP_SUPER */
+#endif /* EP_MUL == LWREG */
/*============================================================================*/
/* Public definitions */
@@ -612,7 +603,7 @@ void ep_mul_monty(ep_t r, const ep_t p, const bn_t k) {
bn_abs(l, _k);
bn_add(l, l, n);
bn_add(n, l, n);
- dv_swap_cond(l->dp, n->dp, RLC_MAX(l->used, n->used),
+ dv_swap_sec(l->dp, n->dp, RLC_MAX(l->used, n->used),
bn_get_bit(l, bits) == 0);
l->used = RLC_SEL(l->used, n->used, bn_get_bit(l, bits) == 0);
@@ -625,14 +616,14 @@ void ep_mul_monty(ep_t r, const ep_t p, const bn_t k) {
for (int i = bits - 1; i >= 0; i--) {
int j = bn_get_bit(l, i);
- dv_swap_cond(t[0]->x, t[1]->x, RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y, t[1]->y, RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z, t[1]->z, RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x, t[1]->x, RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y, t[1]->y, RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z, t[1]->z, RLC_FP_DIGS, j ^ 1);
ep_add(t[0], t[0], t[1]);
ep_dbl(t[1], t[1]);
- dv_swap_cond(t[0]->x, t[1]->x, RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y, t[1]->y, RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z, t[1]->z, RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x, t[1]->x, RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y, t[1]->y, RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z, t[1]->z, RLC_FP_DIGS, j ^ 1);
}
ep_norm(r, t[0]);
diff --git a/src/ep/relic_ep_mul_cof.c b/src/ep/relic_ep_mul_cof.c
index e80b3b861..2101f6ece 100644
--- a/src/ep/relic_ep_mul_cof.c
+++ b/src/ep/relic_ep_mul_cof.c
@@ -149,7 +149,7 @@ void ep_mul_cof(ep_t r, const ep_t p) {
default:
/* multiply by cofactor to get the correct group. */
ep_curve_get_cof(k);
- ep_mul_basic(r, p, k);
+ ep_mul_big(r, p, k);
}
} RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
diff --git a/src/ep/relic_ep_param.c b/src/ep/relic_ep_param.c
index 81e10d48c..c2b9a25ed 100644
--- a/src/ep/relic_ep_param.c
+++ b/src/ep/relic_ep_param.c
@@ -660,18 +660,6 @@
#endif
#if defined(EP_ENDOM) && FP_PRIME == 765
-/**
- * Parameters for a 765-bit pairing-friendly prime curve.
- */
-/** @{ */
-#define N16_P765_A "1"
-#define N16_P765_B "0"
-#define N16_P765_X "71A955588AD4E8236811AA1770428A86CA487504E3964600E51FAD83E8EDF03883360471538D685B7CA156BC9AD56E6FED4BE76C099A752E70E867A8FD79CDFBD0C00294E59C4F2F348302FB270336BE8D2EC25E6234D33CB33C8840BC059D4"
-#define N16_P765_Y "F6DEB4CAA67257010A3286CECBE4E4127D53701CF5897E3426F675BEFE36F60CD0E779433306B0A34C826584307F96100ECA6EB01F69637C2EB0B295E6C13E9721A5EA0FC05A04B47FC565AEBF41016525A69F554BC9D68D9EF2B5CD77D1D4"
-#define N16_P765_R "9965D956A0DBC8AF273C0100000000000000000000000000000000000000000000000000000000000000000000000001"
-#define N16_P765_H "26597655A836F22BC9CF003FFFFFFFFFFFFFA30FAB330D5A7F0000000000000000000000384F01000000000000000000"
-/** @} */
-
/**
* Parameters for a 765-bit pairing-friendly prime curve.
*/
@@ -704,10 +692,10 @@
/** @{ */
#define N16_P766_A "1"
#define N16_P766_B "0"
-#define N16_P766_X "09B60388917DF4F526CE1869B8A069F7722A4EABF0543BAE29B7CABACC1BE50626878F5CC3C5157ADCC6B80DE516239BE3CCC8E66173CBD91092C87B1AAEBF072F3C92CC5B6A8F33A6A2A165AC171A76C4687274BA0E54A7C049F0781D6EB3F5"
-#define N16_P766_Y "280BAA585CD0AB9090B8AB2990410AA093511C661554ACC497D77B67BE3B3CCDDFBCBE296A0119EF8F8FA19D613CA25D16232EF4A5A019C6FDD4C2F0F8DBC238C84F07326BACB3D0478AB5596DCC8BCAD483BF2C4AD89A6C29683E85E77DF120"
-#define N16_P766_R "FFFFFF8401001A46937D417AB554F4F3438C3F42C66CBA08998426591ED55EBA6A16CB364728D491BC20010000000001"
-#define N16_P766_H "3FFFFFE100400691A4DF505EAD553D3CD0E38FD0B1746ED22B12363612FBBA252C222C274D60ADA6C3F09E1010080100"
+#define N16_P766_X "177E5E088795AE368F68ADB4938F647BCCB7D0BCB70456E3B3BC0C6EE12FA3D0E1DFC2FD81C215EC25E602DE8BCEE98A7F8FC23E4A296B9DDEF34BB90A27DD4804B90F7783FE2C891A820941DB16535E1FD73E73038A520AAE396F0949D7E46D"
+#define N16_P766_Y "1CE39931AB952C962CBF6F4E8BE79D6AD3D931B2B100185707032C109C9476305F44D30E1D551E965D44D661327D878EC47ED7A9D1DCDDCA96091E74FB4FF6D42CE809579AB9C72417C55849377E4BA31A0B5F687D840E4CE99E63D583050147"
+#define N16_P766_R "FFFF7000238FFAF4807374994CF93FE6E28D406881B18D350193FE6E3E533E4073749FEBD2000238FFFFDC0000010001"
+#define N16_P766_H "3FFFDC0008E3FEBD201CDD26533E4FF9B8A3D019F36C69AB3FF0479FDCFCBD856CEE5D9B2D34778FD7D2F6D2DC004204"
/** @} */
#endif
@@ -726,6 +714,20 @@
/** @} */
#endif
+#if defined(EP_ENDOM) && FP_PRIME == 1150
+/**
+ * Parameters for a 383-bit pairing-friendly prime curve.
+ */
+/** @{ */
+#define B12_P1150_A "0"
+#define B12_P1150_B "1"
+#define B12_P1150_X "1C9E4A85748AF56BFCDB28AA09E80CF55FFED5E25D92B882B3CAB4202EDA1DEAA62DA8D3B9C204FF9C0647A1BCC17EB60CB7F57D1FA5CFE131200DC511C6636B898515C2C714B1F07ADFB97874E7B9E22D3D7206B327792949E05EA8B5CAF91AA486D72C522A4BDD387B63E5EF12374F1FB766B86CE65ACAC5EF3E05826EC1AE3C18D2A14C1181915DA9A7C3760152D1"
+#define B12_P1150_Y "3116D7FDB1130460DF71722020D3B32FBBBB01A6A77C999B13EE9C0C3DE4D6CA81E886AC80F933A31A78F0850DD9ED0A8DE122C179481FEF031A50910D7A726BB3F1BAE5E8AC186EDEE69C85A043169308C06B4277E65BDE0AD872F58938F84033ED21E9DC0A6DEE2957BA884AE9582CE5AD88C00CFA4D323E686FF864F872C2EEAD356A43E9BB4A59452C08F4E89E9A"
+#define B12_P1150_R "C5C1000000000000001B30F00000000000003622EC6000034BC000057869AF00005703000575ED588100ABBDB4005D60C600000BA2C6103D98AD58000B730C000210975450006301E00100052800004000108000050000000000200000000001"
+#define B12_P1150_H "4B00000000000000000528000000000000000A16B00000014000000058000000000B00000055555555556AAAAAAAAAAC"
+/** @} */
+#endif
+
#if defined(EP_SUPER) && FP_PRIME == 1536
/**
* Parameters for a 1536-bit supersingular elliptic curve.
@@ -1176,11 +1178,6 @@ void ep_param_set(int param) {
break;
#endif
#if defined(EP_ENDOM) && FP_PRIME == 765
- case N16_P765:
- ASSIGN(N16_P765, N16_765);
- endom = 1;
- pairf = EP_N16;
- break;
case FM16_P765:
ASSIGN(FM16_P765, FM16_765);
endom = 1;
@@ -1206,6 +1203,13 @@ void ep_param_set(int param) {
pairf = EP_FM18;
break;
#endif
+#if defined(EP_ENDOM) && FP_PRIME == 1150
+ case B12_P1150:
+ ASSIGN(B12_P1150, B12_1150);
+ endom = 1;
+ pairf = EP_B12;
+ break;
+#endif
#if defined(EP_SUPER) && FP_PRIME == 1536
case SS_P1536:
ASSIGN(SS_P1536, SS_1536);
@@ -1482,13 +1486,14 @@ int ep_param_set_any_endom(void) {
//ep_param_set(SG18_P638);
#endif
#elif FP_PRIME == 765
- ep_param_set(N16_P765);
- //ep_param_set(FM16_P765);
+ ep_param_set(FM16_P765);
#elif FP_PRIME == 766
//ep_param_set(K16_P766);
ep_param_set(N16_P766);
#elif FP_PRIME == 768
ep_param_set(FM18_P768);
+#elif FP_PRIME == 1150
+ ep_param_set(B12_P1150);
#else
r = RLC_ERR;
#endif
@@ -1603,8 +1608,7 @@ int ep_param_set_any_pairf(void) {
extension = 3;
#endif
#elif FP_PRIME == 765
- ep_param_set(N16_P765);
- //ep_param_set(FM16_P765);
+ ep_param_set(FM16_P765);
type = RLC_EP_MTYPE;
extension = 4;
#elif FP_PRIME == 766
@@ -1616,6 +1620,10 @@ int ep_param_set_any_pairf(void) {
ep_param_set(FM18_P768);
type = RLC_EP_MTYPE;
extension = 3;
+#elif FP_PRIME == 1150
+ ep_param_set(B12_P1150);
+ type = RLC_EP_MTYPE;
+ extension = 2;
#elif FP_PRIME == 1536
ep_param_set(SS_P1536);
extension = 1;
@@ -1765,8 +1773,8 @@ void ep_param_print(void) {
case SG18_P638:
util_banner("Curve SG18-P638:", 0);
break;
- case N16_P765:
- util_banner("Curve N16-P765:", 0);
+ case N16_P766:
+ util_banner("Curve N16-P766:", 0);
break;
case FM16_P765:
util_banner("Curve FM16-P765:", 0);
@@ -1777,6 +1785,9 @@ void ep_param_print(void) {
case FM18_P768:
util_banner("Curve FM18-P768:", 0);
break;
+ case B12_P1150:
+ util_banner("Curve B12-P1150:", 0);
+ break;
case SS_P1536:
util_banner("Curve SS-P1536:", 0);
break;
@@ -1836,7 +1847,7 @@ int ep_param_level(void) {
case B12_P455:
return 140;
case NIST_P384:
- case N16_P765:
+ case B12_P1150:
case FM16_P765:
case K16_P766:
case FM18_P768:
@@ -1852,32 +1863,3 @@ int ep_param_level(void) {
}
return 0;
}
-
-int ep_param_embed(void) {
- switch (core_get()->ep_is_pairf) {
- case EP_K1:
- return 1;
- case EP_SS2:
- return 2;
- case EP_GMT8:
- return 8;
- case EP_BN:
- case EP_B12:
- return 12;
- case EP_N16:
- case EP_FM16:
- case EP_K16:
- return 16;
- case EP_K18:
- case EP_FM18:
- case EP_SG18:
- return 18;
- case EP_B24:
- return 24;
- case EP_B48:
- return 48;
- case EP_SG54:
- return 54;
- }
- return 0;
-}
diff --git a/src/ep/relic_ep_pck.c b/src/ep/relic_ep_pck.c
index 2aac19239..54f3859b1 100644
--- a/src/ep/relic_ep_pck.c
+++ b/src/ep/relic_ep_pck.c
@@ -89,7 +89,7 @@ int ep_upk(ep_t r, const ep_t p) {
bn_new(halfQ);
bn_new(yValue);
- ep_rhs(t, p);
+ ep_rhs(t, p->x);
/* t0 = sqrt(x1^3 + a * x1 + b). */
result = fp_srt(t, t);
diff --git a/src/ep/relic_ep_util.c b/src/ep/relic_ep_util.c
index 0229fa228..a39269949 100644
--- a/src/ep/relic_ep_util.c
+++ b/src/ep/relic_ep_util.c
@@ -107,7 +107,7 @@ void ep_blind(ep_t r, const ep_t p) {
}
}
-void ep_rhs(fp_t rhs, const ep_t p) {
+void ep_rhs(fp_t rhs, const fp_t x) {
fp_t t0;
fp_null(t0);
@@ -116,7 +116,7 @@ void ep_rhs(fp_t rhs, const ep_t p) {
fp_new(t0);
/* t0 = x1^2. */
- fp_sqr(t0, p->x);
+ fp_sqr(t0, x);
/* t0 = x1^2 + a */
switch (ep_curve_opt_a()) {
@@ -142,7 +142,7 @@ void ep_rhs(fp_t rhs, const ep_t p) {
}
/* t0 = x1^3 + a * x */
- fp_mul(t0, t0, p->x);
+ fp_mul(t0, t0, x);
/* t0 = x1^3 + a * x + b */
switch (ep_curve_opt_b()) {
@@ -185,7 +185,7 @@ int ep_on_curve(const ep_t p) {
ep_new(t);
ep_norm(t, p);
- ep_rhs(t->x, t);
+ ep_rhs(t->x, t->x);
fp_sqr(t->y, t->y);
r = (fp_cmp(t->x, t->y) == RLC_EQ) || ep_is_infty(p);
} RLC_CATCH_ANY {
diff --git a/src/epx/relic_ep2_add.c b/src/epx/relic_ep2_add.c
index 2e4f563dc..599e73373 100644
--- a/src/epx/relic_ep2_add.c
+++ b/src/epx/relic_ep2_add.c
@@ -24,13 +24,14 @@
/**
* @file
*
- * Implementation of addition on prime elliptic curves over quadratic
- * extensions.
+ * Implementation of addition on prime elliptic curves over a quadratic
+ * extension field.
*
* @ingroup epx
*/
#include "relic_core.h"
+#include "relic_ep_add_tmpl.h"
/*============================================================================*/
/* Private definitions */
@@ -42,312 +43,62 @@
* Adds two points represented in affine coordinates on an ordinary prime
* elliptic curve.
*
- * @param r - the result.
- * @param s - the resulting slope.
- * @param p - the first point to add.
- * @param q - the second point to add.
+ * @param[out] r - the result.
+ * @param[out] s - the slope.
+ * @param[in] p - the first point to add.
+ * @param[in] q - the second point to add.
*/
-static void ep2_add_basic_imp(ep2_t r, fp2_t s, const ep2_t p, const ep2_t q) {
- fp2_t t0, t1, t2;
-
- fp2_null(t0);
- fp2_null(t1);
- fp2_null(t2);
-
- RLC_TRY {
- fp2_new(t0);
- fp2_new(t1);
- fp2_new(t2);
-
- /* t0 = x2 - x1. */
- fp2_sub(t0, q->x, p->x);
- /* t1 = y2 - y1. */
- fp2_sub(t1, q->y, p->y);
-
- /* If t0 is zero. */
- if (fp2_is_zero(t0)) {
- if (fp2_is_zero(t1)) {
- /* If t1 is zero, q = p, should have doubled. */
- ep2_dbl_slp_basic(r, s, p);
- } else {
- /* If t1 is not zero and t0 is zero, q = -p and r = infty. */
- ep2_set_infty(r);
- }
- } else {
- /* t2 = 1/(x2 - x1). */
- fp2_inv(t2, t0);
- /* t2 = lambda = (y2 - y1)/(x2 - x1). */
- fp2_mul(t2, t1, t2);
-
- /* x3 = lambda^2 - x2 - x1. */
- fp2_sqr(t1, t2);
- fp2_sub(t0, t1, p->x);
- fp2_sub(t0, t0, q->x);
-
- /* y3 = lambda * (x1 - x3) - y1. */
- fp2_sub(t1, p->x, t0);
- fp2_mul(t1, t2, t1);
- fp2_sub(r->y, t1, p->y);
-
- fp2_copy(r->x, t0);
- fp2_copy(r->z, p->z);
-
- if (s != NULL) {
- fp2_copy(s, t2);
- }
-
- r->coord = BASIC;
- }
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp2_free(t0);
- fp2_free(t1);
- fp2_free(t2);
- }
-}
+TMPL_ADD_BASIC_IMP(ep2, fp2);
#endif /* EP_ADD == BASIC */
-#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
+#if EP_ADD == PROJC || !defined(STRIP)
-#if defined(EP_MIXED) || !defined(STRIP)
+/**
+ * Adds a point represented in homogeneous coordinates to a point represented in
+ * affine coordinates on an ordinary prime elliptic curve.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the projective point.
+ * @param[in] q - the affine point.
+ */
+TMPL_ADD_PROJC_MIX(ep2, fp2);
/**
- * Adds a point represented in affine coordinates to a point represented in
- * projective coordinates.
+ * Adds two points represented in homogeneous coordinates on an ordinary prime
+ * elliptic curve.
*
- * @param r - the result.
- * @param s - the slope.
- * @param p - the affine point.
- * @param q - the projective point.
+ * @param[out] r - the result.
+ * @param[in] p - the first point to add.
+ * @param[in] q - the second point to add.
*/
-static void ep2_add_projc_mix(ep2_t r, const ep2_t p, const ep2_t q) {
- fp2_t t0, t1, t2, t3, t4, t5, t6;
+TMPL_ADD_PROJC_IMP(ep2, fp2);
- fp2_null(t0);
- fp2_null(t1);
- fp2_null(t2);
- fp2_null(t3);
- fp2_null(t4);
- fp2_null(t5);
- fp2_null(t6);
+#endif /* EP_ADD == PROJC */
- RLC_TRY {
- fp2_new(t0);
- fp2_new(t1);
- fp2_new(t2);
- fp2_new(t3);
- fp2_new(t4);
- fp2_new(t5);
- fp2_new(t6);
-
- if (p->coord != BASIC) {
- /* t0 = z1^2. */
- fp2_sqr(t0, p->z);
-
- /* t3 = U2 = x2 * z1^2. */
- fp2_mul(t3, q->x, t0);
-
- /* t1 = S2 = y2 * z1^3. */
- fp2_mul(t1, t0, p->z);
- fp2_mul(t1, t1, q->y);
-
- /* t3 = H = U2 - x1. */
- fp2_sub(t3, t3, p->x);
-
- /* t1 = R = 2 * (S2 - y1). */
- fp2_sub(t1, t1, p->y);
- } else {
- /* H = x2 - x1. */
- fp2_sub(t3, q->x, p->x);
-
- /* t1 = R = 2 * (y2 - y1). */
- fp2_sub(t1, q->y, p->y);
- }
-
- /* t2 = HH = H^2. */
- fp2_sqr(t2, t3);
-
- /* If E is zero. */
- if (fp2_is_zero(t3)) {
- if (fp2_is_zero(t1)) {
- /* If I is zero, p = q, should have doubled. */
- ep2_dbl_projc(r, p);
- } else {
- /* If I is not zero, q = -p, r = infinity. */
- ep2_set_infty(r);
- }
- } else {
- /* t5 = J = H * HH. */
- fp2_mul(t5, t3, t2);
-
- /* t4 = V = x1 * HH. */
- fp2_mul(t4, p->x, t2);
-
- /* x3 = R^2 - J - 2 * V. */
- fp2_sqr(r->x, t1);
- fp2_sub(r->x, r->x, t5);
- fp2_dbl(t6, t4);
- fp2_sub(r->x, r->x, t6);
-
- /* y3 = R * (V - x3) - Y1 * J. */
- fp2_sub(t4, t4, r->x);
- fp2_mul(t4, t4, t1);
- fp2_mul(t1, p->y, t5);
- fp2_sub(r->y, t4, t1);
-
- if (p->coord != BASIC) {
- /* z3 = z1 * H. */
- fp2_mul(r->z, p->z, t3);
- } else {
- /* z3 = H. */
- fp2_copy(r->z, t3);
- }
- }
- r->coord = PROJC;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp2_free(t0);
- fp2_free(t1);
- fp2_free(t2);
- fp2_free(t3);
- fp2_free(t4);
- fp2_free(t5);
- fp2_free(t6);
- }
-}
+#if EP_ADD == JACOB || !defined(STRIP)
-#endif
+/**
+ * Adds a point represented in Jacobian coordinates to a point represented in
+ * affine coordinates on an ordinary prime elliptic curve.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the projective point.
+ * @param[in] q - the affine point.
+ */
+TMPL_ADD_JACOB_MIX(ep2, fp2);
/**
- * Adds two points represented in projective coordinates on an ordinary prime
+ * Adds two points represented in Jacobian coordinates on an ordinary prime
* elliptic curve.
*
- * @param r - the result.
- * @param p - the first point to add.
- * @param q - the second point to add.
+ * @param[out] r - the result.
+ * @param[in] p - the first point to add.
+ * @param[in] q - the second point to add.
*/
-static void ep2_add_projc_imp(ep2_t r, const ep2_t p, const ep2_t q) {
-#if defined(EP_MIXED) && defined(STRIP)
- ep2_add_projc_mix(r, p, q);
-#else /* General addition. */
- fp2_t t0, t1, t2, t3, t4, t5, t6;
-
- fp2_null(t0);
- fp2_null(t1);
- fp2_null(t2);
- fp2_null(t3);
- fp2_null(t4);
- fp2_null(t5);
- fp2_null(t6);
+TMPL_ADD_JACOB_IMP(ep2, fp2);
- RLC_TRY {
- fp2_new(t0);
- fp2_new(t1);
- fp2_new(t2);
- fp2_new(t3);
- fp2_new(t4);
- fp2_new(t5);
- fp2_new(t6);
-
- if (q->coord == BASIC) {
- ep2_add_projc_mix(r, p, q);
- } else {
- /* t0 = z1^2. */
- fp2_sqr(t0, p->z);
-
- /* t1 = z2^2. */
- fp2_sqr(t1, q->z);
-
- /* t2 = U1 = x1 * z2^2. */
- fp2_mul(t2, p->x, t1);
-
- /* t3 = U2 = x2 * z1^2. */
- fp2_mul(t3, q->x, t0);
-
- /* t6 = z1^2 + z2^2. */
- fp2_add(t6, t0, t1);
-
- /* t0 = S2 = y2 * z1^3. */
- fp2_mul(t0, t0, p->z);
- fp2_mul(t0, t0, q->y);
-
- /* t1 = S1 = y1 * z2^3. */
- fp2_mul(t1, t1, q->z);
- fp2_mul(t1, t1, p->y);
-
- /* t3 = H = U2 - U1. */
- fp2_sub(t3, t3, t2);
-
- /* t0 = R = 2 * (S2 - S1). */
- fp2_sub(t0, t0, t1);
-
- fp2_dbl(t0, t0);
-
- /* If E is zero. */
- if (fp2_is_zero(t3)) {
- if (fp2_is_zero(t0)) {
- /* If I is zero, p = q, should have doubled. */
- ep2_dbl_projc(r, p);
- } else {
- /* If I is not zero, q = -p, r = infinity. */
- ep2_set_infty(r);
- }
- } else {
- /* t4 = I = (2*H)^2. */
- fp2_dbl(t4, t3);
- fp2_sqr(t4, t4);
-
- /* t5 = J = H * I. */
- fp2_mul(t5, t3, t4);
-
- /* t4 = V = U1 * I. */
- fp2_mul(t4, t2, t4);
-
- /* x3 = R^2 - J - 2 * V. */
- fp2_sqr(r->x, t0);
- fp2_sub(r->x, r->x, t5);
- fp2_dbl(t2, t4);
- fp2_sub(r->x, r->x, t2);
-
- /* y3 = R * (V - x3) - 2 * S1 * J. */
- fp2_sub(t4, t4, r->x);
- fp2_mul(t4, t4, t0);
- fp2_mul(t1, t1, t5);
- fp2_dbl(t1, t1);
- fp2_sub(r->y, t4, t1);
-
- /* z3 = ((z1 + z2)^2 - z1^2 - z2^2) * H. */
- fp2_add(r->z, p->z, q->z);
- fp2_sqr(r->z, r->z);
- fp2_sub(r->z, r->z, t6);
- fp2_mul(r->z, r->z, t3);
- }
- }
- r->coord = PROJC;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp2_free(t0);
- fp2_free(t1);
- fp2_free(t2);
- fp2_free(t3);
- fp2_free(t4);
- fp2_free(t5);
- fp2_free(t6);
- }
-#endif
-}
-
-#endif /* EP_ADD == PROJC */
+#endif /* EP_ADD == JACOB */
/*============================================================================*/
/* Public definitions */
@@ -385,7 +136,7 @@ void ep2_add_slp_basic(ep2_t r, fp2_t s, const ep2_t p, const ep2_t q) {
#endif
-#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
+#if EP_ADD == PROJC || !defined(STRIP)
void ep2_add_projc(ep2_t r, const ep2_t p, const ep2_t q) {
if (ep2_is_infty(p)) {
@@ -398,13 +149,25 @@ void ep2_add_projc(ep2_t r, const ep2_t p, const ep2_t q) {
return;
}
- if (p == q) {
- /* TODO: This is a quick hack. Should we fix this? */
- ep2_dbl(r, p);
+ ep2_add_projc_imp(r, p, q);
+}
+
+#endif
+
+#if EP_ADD == JACOB || !defined(STRIP)
+
+void ep2_add_jacob(ep2_t r, const ep2_t p, const ep2_t q) {
+ if (ep2_is_infty(p)) {
+ ep2_copy(r, q);
return;
}
- ep2_add_projc_imp(r, p, q);
+ if (ep2_is_infty(q)) {
+ ep2_copy(r, p);
+ return;
+ }
+
+ ep2_add_jacob_imp(r, p, q);
}
#endif
@@ -421,7 +184,6 @@ void ep2_sub(ep2_t r, const ep2_t p, const ep2_t q) {
RLC_TRY {
ep2_new(t);
-
ep2_neg(t, q);
ep2_add(r, p, t);
}
diff --git a/src/epx/relic_ep2_cmp.c b/src/epx/relic_ep2_cmp.c
index 8c44a9eba..1b265c6ab 100644
--- a/src/epx/relic_ep2_cmp.c
+++ b/src/epx/relic_ep2_cmp.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of utilities for prime elliptic curves over quadratic
- * extensions.
+ * Implementation of utilities for prime elliptic curves over a quadratic
+ * extension field.
*
* @ingroup epx
*/
@@ -37,46 +37,69 @@
/*============================================================================*/
int ep2_cmp(const ep2_t p, const ep2_t q) {
- ep2_t r, s;
- int result = RLC_NE;
+ ep2_t r, s;
+ int result = RLC_NE;
if (ep2_is_infty(p) && ep2_is_infty(q)) {
return RLC_EQ;
}
- ep2_null(r);
- ep2_null(s);
+ ep2_null(r);
+ ep2_null(s);
- RLC_TRY {
- ep2_new(r);
- ep2_new(s);
+ RLC_TRY {
+ ep2_new(r);
+ ep2_new(s);
- if ((p->coord != BASIC) && (q->coord != BASIC)) {
- /* If the two points are not normalized, it is faster to compare
- * x1 * z2^2 == x2 * z1^2 and y1 * z2^3 == y2 * z1^3. */
- fp2_sqr(r->z, p->z);
- fp2_sqr(s->z, q->z);
- fp2_mul(r->x, p->x, s->z);
- fp2_mul(s->x, q->x, r->z);
- fp2_mul(r->z, r->z, p->z);
- fp2_mul(s->z, s->z, q->z);
- fp2_mul(r->y, p->y, s->z);
- fp2_mul(s->y, q->y, r->z);
- } else {
- ep2_norm(r, p);
- ep2_norm(s, q);
- }
+ switch (q->coord) {
+ case PROJC:
+ /* If q is in homogeneous projective coordinates, compute
+ * x1 * z2 and y1 * z2. */
+ fp2_mul(r->x, p->x, q->z);
+ fp2_mul(r->y, p->y, q->z);
+ break;
+ case JACOB:
+ /* If q is in Jacobian projective coordinates, compute
+ * x2 * z1^2 and y2 * z1^3. */
+ fp2_sqr(r->z, q->z);
+ fp2_mul(r->x, p->x, r->z);
+ fp2_mul(r->z, r->z, q->z);
+ fp2_mul(r->y, p->y, r->z);
+ break;
+ default:
+ ep2_copy(r, p);
+ break;
+ }
- if ((fp2_cmp(r->x, s->x) == RLC_EQ) &&
+ switch (p->coord) {
+ /* Now do the same for the other point. */
+ case PROJC:
+ fp2_mul(s->x, q->x, p->z);
+ fp2_mul(s->y, q->y, p->z);
+ break;
+ case JACOB:
+ fp2_sqr(s->z, p->z);
+ fp2_mul(s->x, q->x, s->z);
+ fp2_mul(s->z, s->z, p->z);
+ fp2_mul(s->y, q->y, s->z);
+ break;
+ default:
+ ep2_copy(s, q);
+ break;
+ }
+
+ if ((fp2_cmp(r->x, s->x) == RLC_EQ) &&
(fp2_cmp(r->y, s->y) == RLC_EQ)) {
- result = RLC_EQ;
- }
- } RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- } RLC_FINALLY {
- ep2_free(r);
- ep2_free(s);
- }
+ result = RLC_EQ;
+ }
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ ep2_free(r);
+ ep2_free(s);
+ }
- return result;
+ return result;
}
diff --git a/src/epx/relic_ep2_curve.c b/src/epx/relic_ep2_curve.c
index 3ec781ba0..99ccdb978 100644
--- a/src/epx/relic_ep2_curve.c
+++ b/src/epx/relic_ep2_curve.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of configuration of prime elliptic curves over quadratic
- * extensions.
+ * Implementation of configuration of prime elliptic curves over a quadratic
+ * extension field.
*
* @ingroup epx
*/
@@ -53,8 +53,8 @@
#define BN_P158_Y1 "074866EA7BD0AB4C67C77F70E0467F1FF32D800D"
#define BN_P158_R "240000006ED000007FE96000419F59800C9FFD81"
#define BN_P158_H "240000006ED000007FEA200041A07F800CA06E0D"
-#define BN_P158_MAPU0 "0"
-#define BN_P158_MAPU1 "-1"
+#define BN_P158_MAPU0 "0"
+#define BN_P158_MAPU1 "-1"
/** @} */
#endif
@@ -70,8 +70,8 @@
#define BN_P254_Y1 "0EBB2B0E7C8B15268F6D4456F5F38D37B09006FFD739C9578A2D1AEC6B3ACE9B"
#define BN_P254_R "2523648240000001BA344D8000000007FF9F800000000010A10000000000000D"
#define BN_P254_H "2523648240000001BA344D8000000008C2A2800000000016AD00000000000019"
-#define BN_P254_MAPU0 "0"
-#define BN_P254_MAPU1 "-1"
+#define BN_P254_MAPU0 "0"
+#define BN_P254_MAPU1 "-1"
/** @} */
#endif
@@ -87,8 +87,8 @@
#define BN_P256_Y1 "A033144CA161E3E3271624B3F0CC1CE607ACD2CBCE9E9253C732CF3E1016DEE7"
#define BN_P256_R "B64000000000FF2F2200000085FD547FD8001F44B6B7F4B7C2BC818F7B6BEF99"
#define BN_P256_H "B64000000000FF2F2200000085FD548188001F44B6B9232AC2BC818FB05BDDC5"
-#define BN_P256_MAPU0 "0"
-#define BN_P256_MAPU1 "-1"
+#define BN_P256_MAPU0 "0"
+#define BN_P256_MAPU1 "-1"
/** @} */
#endif
@@ -104,8 +104,8 @@
#define SM9_P256_Y1 "17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96"
#define SM9_P256_R "B640000002A3A6F1D603AB4FF58EC74449F2934B18EA8BEEE56EE19CD69ECF25"
#define SM9_P256_H "B640000002A3A6F1D603AB4FF58EC745F9F2934B1C0B51C8E57054B2F003BBD5"
-#define SM9_P256_MAPU0 "-1"
-#define SM9_P256_MAPU1 "0"
+#define SM9_P256_MAPU0 "-1"
+#define SM9_P256_MAPU1 "0"
/** @} */
#endif
@@ -168,8 +168,8 @@
#define BN_P382_Y1 "09CAC2932F3C894CCE129ECBB49AFD4BFF94C10B5DF37AB469E3455F16EFDD304721F689BFF864A92ACB3F4DF52678ED"
#define BN_P382_R "24009015183F94892D996CC179C6D1666F82CEFBE47879BB46E4CDA2E2E2281D08DC008E80108252004200000000000D"
#define BN_P382_H "24009015183F94892D996CC179C6D1666F82CEFBE47879BC06E64DD9A31E2BEF09B400A08016832A005A000000000019"
-#define BN_P382_MAPU0 "0"
-#define BN_P382_MAPU1 "-1"
+#define BN_P382_MAPU0 "0"
+#define BN_P382_MAPU1 "-1"
/** @} */
#endif
@@ -185,8 +185,8 @@
#define B12_P383_Y1 "1459B073246773B35CBCBFC9318AC47DDC1C284887D1DA4BE13593ACC0E45B748AF4115011A3EA730A7DB21A83562411"
#define B12_P383_R "1002001800C00B809C04401C81698B381DE05F095A120D3973B2099EBFEBC0001"
#define B12_P383_H "1C78E45562AB68EE641721902ED56C9B45EB1276A5C15CB19C7BF81F7A7B6F22053BAC3422240A3F4A7E3C25D470E7BABDB8A2E1E1793BF9CEBDD1BF2EFE30E5"
-#define B12_P383_MAPU0 "0"
-#define B12_P383_MAPU1 "1"
+#define B12_P383_MAPU0 "0"
+#define B12_P383_MAPU1 "1"
/** @} */
#endif
@@ -202,8 +202,8 @@
#define BN_P446_Y1 "91F93BEB46071DEDF410DC5A7662DD8B4BBC8BE5D3A8662009A4C2C0577F82A2337D208379F21C65F90FE1D90482CC48DEC83BFB8AD8E45"
#define BN_P446_R "2400000000000000002400000002D00000000D800000021C00000017A0000000870000000AD400000054C000000156000000126000000061"
#define BN_P446_H "2400000000000000002400000002D00000000D800000021C0000001860000000870000000B340000005AC00000016200000013E00000006D"
-#define BN_P446_MAPU0 "0"
-#define BN_P446_MAPU1 "1"
+#define BN_P446_MAPU0 "0"
+#define BN_P446_MAPU1 "1"
/** @} */
#endif
@@ -219,8 +219,8 @@
#define B12_P446_Y1 "10ACDEBE52C1499796809283C38E100C4BA9FA0699696BF9F8647CB18EE632A4DDDAA771A78C031F868FAFA07E8642CCA633FE6F99B744C4"
#define B12_P446_R "511B70539F27995B34995830FA4D04C98CCC4C050BC7BB9B0E8D8CA34610428001400040001"
#define B12_P446_H "2DAEE3988A06F1BB3444D5780484639BF731D657742BF556901567CEFE5C3DD2555CB74C3560CED298D5147F8E24B79369C54C81E026DD55B51D6A75088593E6A92EFCE555594000638E5"
-#define B12_P446_MAPU0 "0"
-#define B12_P446_MAPU1 "1"
+#define B12_P446_MAPU0 "0"
+#define B12_P446_MAPU1 "1"
/** @} */
#endif
@@ -236,21 +236,21 @@
#define B12_P455_Y1 "24AC244C6F31FDAC1214CA62AB4DB7BA9B5F0D54D56A3D5C680044225C3AAF9815C272A15AA1D28FB6AC9EB7B0BE6916450794A617AFFB4EF9"
#define B12_P455_R "10000080000380002E0000F10004F00025E000750001D1000A00000400001C00007FFFFC00001"
#define B12_P455_H "1C71C8E38E4C71C8238726432AFAC33B9D05A24A43A2531F1F9DE9B4C688A0B7A2716C48868F7C7D716F8AB8D45A1B9B21F9EB90E83876E4E18AD09613EC7DCAF8B8E238558711C838C718E5"
-#define B12_P455_MAPU0 "0"
-#define B12_P455_MAPU1 "1"
+#define B12_P455_MAPU0 "0"
+#define B12_P455_MAPU1 "1"
/** @} */
#endif
#if defined(EP_ENDOM) && FP_PRIME == 544
/** @{ */
-#define GMT8_P544_A0 "0"
-#define GMT8_P544_A1 "2"
-#define GMT8_P544_B0 "0"
-#define GMT8_P544_B1 "0"
-#define GMT8_P544_X0 "1EE84A939A46EAE4287805E2FFABBCED3605B74F5FD7E545F390D2E3D34AD0C60851EA65A18CF92396B9318FCAB3205D79C8D03E928590F719E4086A1C42AF2D40EB6C3A"
-#define GMT8_P544_X1 "065F721D63381C07D1BF556D65A3A82B0E969BA031FB3812F49709926D5159324DFB685048D4EAFC914F893A0D5382868D1D252619AA964149258DCC1A86B68775F36A82"
-#define GMT8_P544_Y0 "9B80046683050F459F48D7CE4C83992D5B044718326AEE2DD86F3E5557BD240441A763BC40030F21FC3A64483B450330930BAFA62E7B573B565404A9DB2A5BFF7D6994D4"
-#define GMT8_P544_Y1 "AB457A64E140799D3D9B77ECEA828957F3AEADB3278FEE32E9AD77F068DD2F95B469607E8CE3CE5705276F869CFB18270C0A8FC8D8AD0D17545F4DCCC9E599853A7BAB76"
+#define GMT8_P544_A0 "0"
+#define GMT8_P544_A1 "2"
+#define GMT8_P544_B0 "0"
+#define GMT8_P544_B1 "0"
+#define GMT8_P544_X0 "1EE84A939A46EAE4287805E2FFABBCED3605B74F5FD7E545F390D2E3D34AD0C60851EA65A18CF92396B9318FCAB3205D79C8D03E928590F719E4086A1C42AF2D40EB6C3A"
+#define GMT8_P544_X1 "065F721D63381C07D1BF556D65A3A82B0E969BA031FB3812F49709926D5159324DFB685048D4EAFC914F893A0D5382868D1D252619AA964149258DCC1A86B68775F36A82"
+#define GMT8_P544_Y0 "9B80046683050F459F48D7CE4C83992D5B044718326AEE2DD86F3E5557BD240441A763BC40030F21FC3A64483B450330930BAFA62E7B573B565404A9DB2A5BFF7D6994D4"
+#define GMT8_P544_Y1 "AB457A64E140799D3D9B77ECEA828957F3AEADB3278FEE32E9AD77F068DD2F95B469607E8CE3CE5705276F869CFB18270C0A8FC8D8AD0D17545F4DCCC9E599853A7BAB76"
#define GMT8_P544_R "FF0060739E18D7594A978B0AB6AE4CE3DBFD52A9D00197603FFFDF0000000101"
#define GMT8_P544_H "8A0A079FC7C3D421A4986FAAA10A6593F60BC94E32AEE8067E35551B86D59F0F61BD6A750917746236DD39CB4710BD44B7BE86F0A8E5324DFE802973060F04BF37C018705B78072182D139A8D2BD338A630511676FDAFD47C60DB5393F9DFC96089B1FFB60B78FB2"
#define GMT8_P544_MAPU0 "0"
@@ -270,8 +270,8 @@
#define BN_P638_Y1 "1A650343ACEF6895FE4EC59B49F40E043DEB05DEF170DFD71B44CAB9496E2EADD034EC0E9238544556902D2D51AB93D224DC757AD720F4DE8ED3BFA4E22DB0ECE92369F681543F23A908A9B319D5FAEF"
#define BN_P638_R "23FFFFFDC000000D7FFFFFB8000001D3FFFFF942D000165E3FFF94870000D52FFFFDD0E00008DE55600086550021E555FFFFF54FFFF4EAC000000049800154D9FFFFFFFFFFFFEDA00000000000000061"
#define BN_P638_H "23FFFFFDC000000D7FFFFFB8000001D3FFFFF942D000165E3FFF94870000D52FFFFDD0E00008DE562000864F0021E561FFFFF4EFFFF4EC400000004F800160C1FFFFFFFFFFFFEC20000000000000006D"
-#define BN_P638_MAPU0 "0"
-#define BN_P638_MAPU1 "1"
+#define BN_P638_MAPU0 "0"
+#define BN_P638_MAPU1 "1"
/** @} */
#endif
@@ -287,8 +287,25 @@
#define B12_P638_Y1 "3795191221DB4917EEE4B7B85BC7D7CA0C60E82116064463FED0892BA82ACECF905E6DB8083C5F589F04DB80E3203C1B2BEB52ACDED6DF96FC515F36761E7152AEED13369A504FE38C4FF93860B89550"
#define B12_P638_R "50F94035FF4000FFFFFFFFFFF9406BFDC0040000000000000035FB801DFFBFFFFFFFFFFFFFFF401BFF80000000000000000000FFC01"
#define B12_P638_H "2D88688DBA18275F5801BFFD4DDE93725697788C46C7B4BC8050639BA17EA2158B6784CCACDDECE490643943E5376D29C71C96B894056CCCC13C3DC6AAAAAA0F89601DC2979B3721C71C71C8B38CB8AEFEEB9E1C71C71C71C4B9FED17AE51B8E38E38E38E38FC954E8C65"
-#define B12_P638_MAPU0 "0"
-#define B12_P638_MAPU1 "1"
+#define B12_P638_MAPU0 "0"
+#define B12_P638_MAPU1 "1"
+/** @} */
+#endif
+
+#if defined(EP_ENDOM) && FP_PRIME == 1150
+/** @{ */
+#define B12_P1150_A0 "0"
+#define B12_P1150_A1 "0"
+#define B12_P1150_B0 "20"
+#define B12_P1150_B1 "1"
+#define B12_P1150_X0 "4E1E10FAFC4A9E497CA939E1A8D1CF8893750CC24D82E0ED0C492C1FA618AB2FF7A02F95B12B8234C2E42B74DF654EF090ED50AD9EBF2E727F27B6CD6F368F84AB2AF7318C02994534DE0C863AC311527D3AFC2C2A4BD1A921899BD6B02CC89106FAB128E698C87928158FD2A79AABDC262097BACA9E7B226225E82DEB020FFEA5125F8F00213F5860A0217A6CCB165"
+#define B12_P1150_X1 "4E0131D6174E76582E6456DC0D1D3C32BFD89F7910DD17E18C83CD8F9C658D0448A87F327AD1B7676521B2E2E0D12C4A001431F5DEE3C3E36A543D8A380ABC3CEC68488B8793A9BF98946B6994F18EC71D843B9CA980858B48C64833D7F327BBBEDBB3255D16813D550B8456140B28C587C1415C445AE12371EDB8FDC90B2E79132DB4C91AD26BE1C1B5E88E6DEA271"
+#define B12_P1150_Y0 "6DDD7AA03804184D92896703D977BE38F4185F860B61EE1D6F8D586158C7B5D50905CEDE8B9313CC447F11F0C3FD83858E89E3AF93D902990383C6016138600F6A982713E0ED83D02240F89014822BCB3B5F5CD92312019DF5CDF6E9F9133761F76FFC6A63440C4DE8795057B5C184CE94A8BF49C3C7DF5AD4A691769981CA88BA23529EAD7A474ACCFA9915566548E"
+#define B12_P1150_Y1 "D302BD36809044D5F86AAD68CBB100A01B504668BF5F520D0F12C2654B5A8783E6348B69958016D814548DC1380CE8CC760CFDF7832FFC51A039C6461FF93DBFB91271969B19EACDDB805038EE619DBCFC725BB34D5D5489FBCC2603ED09B35BBA11813F15468929CF817511E890F8AB76A749AF6C7A88E495DCDA0848324A4DC0DC566B98FDEE53ED8AAE8EC2AC19C"
+#define B12_P1150_R "C5C1000000000000001B30F00000000000003622EC6000034BC000057869AF00005703000575ED588100ABBDB4005D60C600000BA2C6103D98AD58000B730C000210975450006301E00100052800004000108000050000000000200000000001"
+#define B12_P1150_H "10F92DB9000000000004AAEC92E000000000099D3161ABC0D94249423783DA57023447266F56A9EBD69D80C7566A16D9BA9FBE7158549609DC9A0A3AA8118DCA532B07515F0AFC55A9B3F5EF6D796B3CE40C5705D3C1A799E87E283A56736E303655930FE3A33D221A3188B1CA2886B457B6998AE042390CED049D27C756A249FBA914ED3D1CC2CA3A96C10101BDBDA7F906593201A323F4EBDE9F7D48EBA93923F5727B11CA0DF5F1E65565D555573C71EBC71C81C71C71C71CB8E38E38E390"
+#define B12_P1150_MAPU0 "0"
+#define B12_P1150_MAPU1 "1"
/** @} */
#endif
@@ -640,6 +657,69 @@ int ep2_curve_opt_b(void) {
return core_get()->ep2_opt_b;
}
+void ep2_curve_mul_a(fp2_t c, const fp2_t a) {
+ ctx_t *ctx = core_get();
+
+ if (ep2_curve_is_twist() == RLC_EP_MTYPE) {
+ switch (ep_curve_opt_a()) {
+ case RLC_ZERO:
+ fp2_zero(c);
+ break;
+ case RLC_ONE:
+ fp2_copy(c, a);
+ break;
+ case RLC_TWO:
+ fp2_dbl(c, a);
+ break;
+ default:
+ fp_mul(c[0], a[0], ep_curve_get_a());
+ fp_mul(c[1], a[1], ep_curve_get_a());
+ break;
+ }
+ fp2_mul_art(c, c);
+ } else {
+ switch (ctx->ep2_opt_a) {
+ case RLC_ZERO:
+ fp2_zero(c);
+ break;
+ case RLC_ONE:
+ fp2_copy(c, a);
+ break;
+ case RLC_TWO:
+ fp2_dbl(c, a);
+ break;
+#if FP_RDC != MONTY
+ case RLC_TINY:
+ fp2_mul_dig(c, a, ctx->ep2_a[0]);
+ break;
+#endif
+ default:
+ fp2_mul(c, a, ctx->ep2_a);
+ break;
+ }
+ }
+}
+
+void ep2_curve_mul_b(fp2_t c, const fp2_t a) {
+ ctx_t *ctx = core_get();
+ switch (ctx->ep2_opt_b) {
+ case RLC_ZERO:
+ fp2_zero(c);
+ break;
+ case RLC_ONE:
+ fp2_copy(c, a);
+ break;
+#if FP_RDC != MONTY
+ case RLC_TINY:
+ fp2_mul_dig(c, a, ctx->ep2_b[0]);
+ break;
+#endif
+ default:
+ fp2_mul(c, a, ctx->ep2_b);
+ break;
+ }
+}
+
int ep2_curve_is_twist(void) {
return core_get()->ep2_is_twist;
}
@@ -781,6 +861,10 @@ void ep2_curve_set_twist(int type) {
case B12_P638:
ASSIGN(B12_P638);
break;
+#elif FP_PRIME == 1150
+ case B12_P1150:
+ ASSIGN(B12_P1150);
+ break;
#endif
default:
(void)str;
diff --git a/src/epx/relic_ep2_dbl.c b/src/epx/relic_ep2_dbl.c
index a1abb3d1b..b8ab8f07b 100644
--- a/src/epx/relic_ep2_dbl.c
+++ b/src/epx/relic_ep2_dbl.c
@@ -24,13 +24,14 @@
/**
* @file
*
- * Implementation of doubling on elliptic prime curves over quadratic
- * extensions.
+ * Implementation of doubling on elliptic prime curves over a quadratic
+ * extension field.
*
* @ingroup epx
*/
#include "relic_core.h"
+#include "relic_ep_dbl_tmpl.h"
/*============================================================================*/
/* Private definitions */
@@ -43,198 +44,41 @@
* elliptic curve.
*
* @param[out] r - the result.
- * @param[out] s - the resulting slope.
+ * @param[out] s - the slope.
* @param[in] p - the point to double.
*/
-static void ep2_dbl_basic_imp(ep2_t r, fp2_t s, const ep2_t p) {
- fp2_t t0, t1, t2;
-
- fp2_null(t0);
- fp2_null(t1);
- fp2_null(t2);
-
- RLC_TRY {
- fp2_new(t0);
- fp2_new(t1);
- fp2_new(t2);
-
- /* t0 = 1/(2 * y1). */
- fp2_dbl(t0, p->y);
- fp2_inv(t0, t0);
-
- /* t1 = 3 * x1^2 + a. */
- fp2_sqr(t1, p->x);
- fp2_copy(t2, t1);
- fp2_dbl(t1, t1);
- fp2_add(t1, t1, t2);
-
- fp2_add(t1, t1, ep2_curve_get_a());
-
- /* t1 = (3 * x1^2 + a)/(2 * y1). */
- fp2_mul(t1, t1, t0);
-
- if (s != NULL) {
- fp2_copy(s, t1);
- }
-
- /* t2 = t1^2. */
- fp2_sqr(t2, t1);
-
- /* x3 = t1^2 - 2 * x1. */
- fp2_dbl(t0, p->x);
- fp2_sub(t0, t2, t0);
-
- /* y3 = t1 * (x1 - x3) - y1. */
- fp2_sub(t2, p->x, t0);
- fp2_mul(t1, t1, t2);
-
- fp2_sub(r->y, t1, p->y);
-
- fp2_copy(r->x, t0);
- fp2_copy(r->z, p->z);
-
- r->coord = BASIC;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp2_free(t0);
- fp2_free(t1);
- fp2_free(t2);
- }
-}
+TMPL_DBL_BASIC_IMP(ep2, fp2);
#endif /* EP_ADD == BASIC */
-#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
+#if EP_ADD == PROJC || !defined(STRIP)
/**
- * Doubles a point represented in affine coordinates on an ordinary prime
+ * Doubles a point represented in projective coordinates on an ordinary prime
* elliptic curve.
*
- * @param[out] r - the result.
- * @param[in] p - the point to double.
+ * @param r - the result.
+ * @param p - the point to double.
*/
-static void ep2_dbl_projc_imp(ep2_t r, const ep2_t p) {
- fp2_t t0, t1, t2, t3, t4, t5;
-
- fp2_null(t0);
- fp2_null(t1);
- fp2_null(t2);
- fp2_null(t3);
- fp2_null(t4);
- fp2_null(t5);
-
- RLC_TRY {
- fp2_new(t0);
- fp2_new(t1);
- fp2_new(t2);
- fp2_new(t3);
- fp2_new(t4);
- fp2_new(t5);
-
- if (ep_curve_opt_a() == RLC_ZERO) {
- fp2_sqr(t0, p->x);
- fp2_add(t2, t0, t0);
- fp2_add(t0, t2, t0);
-
- fp2_sqr(t3, p->y);
- fp2_mul(t1, t3, p->x);
- fp2_add(t1, t1, t1);
- fp2_add(t1, t1, t1);
- fp2_sqr(r->x, t0);
- fp2_add(t2, t1, t1);
- fp2_sub(r->x, r->x, t2);
- fp2_mul(r->z, p->z, p->y);
- fp2_add(r->z, r->z, r->z);
- fp2_add(t3, t3, t3);
-
- fp2_sqr(t3, t3);
- fp2_add(t3, t3, t3);
- fp2_sub(t1, t1, r->x);
- fp2_mul(r->y, t0, t1);
- fp2_sub(r->y, r->y, t3);
- } else {
- /* dbl-2007-bl formulas: 1M + 8S + 1*a + 10add + 1*8 + 2*2 + 1*3 */
- /* http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-2007-bl */
-
- /* t0 = x1^2, t1 = y1^2, t2 = y1^4. */
- fp2_sqr(t0, p->x);
- fp2_sqr(t1, p->y);
- fp2_sqr(t2, t1);
-
- if (p->coord != BASIC) {
- /* t3 = z1^2. */
- fp2_sqr(t3, p->z);
+TMPL_DBL_PROJC_IMP(ep2, fp2);
- if (ep_curve_get_a() == RLC_ZERO) {
- /* z3 = 2 * y1 * z1. */
- fp2_mul(r->z, p->y, p->z);
- fp2_dbl(r->z, r->z);
- } else {
- /* z3 = (y1 + z1)^2 - y1^2 - z1^2. */
- fp2_add(r->z, p->y, p->z);
- fp2_sqr(r->z, r->z);
- fp2_sub(r->z, r->z, t1);
- fp2_sub(r->z, r->z, t3);
- }
- } else {
- /* z3 = 2 * y1. */
- fp2_dbl(r->z, p->y);
- }
-
- /* t4 = S = 2*((x1 + y1^2)^2 - x1^2 - y1^4). */
- fp2_add(t4, p->x, t1);
- fp2_sqr(t4, t4);
- fp2_sub(t4, t4, t0);
- fp2_sub(t4, t4, t2);
- fp2_dbl(t4, t4);
-
- /* t5 = M = 3 * x1^2 + a * z1^4. */
- fp2_dbl(t5, t0);
- fp2_add(t5, t5, t0);
- if (p->coord != BASIC) {
- fp2_sqr(t3, t3);
- fp2_mul(t1, t3, ep2_curve_get_a());
- fp2_add(t5, t5, t1);
- } else {
- fp2_add(t5, t5, ep2_curve_get_a());
- }
-
- /* x3 = T = M^2 - 2 * S. */
- fp2_sqr(r->x, t5);
- fp2_dbl(t1, t4);
- fp2_sub(r->x, r->x, t1);
+#endif /* EP_ADD == PROJC */
- /* y3 = M * (S - T) - 8 * y1^4. */
- fp2_dbl(t2, t2);
- fp2_dbl(t2, t2);
- fp2_dbl(t2, t2);
- fp2_sub(t4, t4, r->x);
- fp2_mul(t5, t5, t4);
- fp2_sub(r->y, t5, t2);
- }
+#if EP_ADD == JACOB || !defined(STRIP)
- r->coord = PROJC;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp2_free(t0);
- fp2_free(t1);
- fp2_free(t2);
- fp2_free(t3);
- fp2_free(t4);
- fp2_free(t5);
- }
-}
+/**
+ * Doubles a point represented in Jacobian coordinates on an ordinary prime
+ * elliptic curve.
+ *
+ * @param r - the result.
+ * @param p - the point to double.
+ */
+TMPL_DBL_JACOB_IMP(ep2, fp2);
-#endif /* EP_ADD == PROJC */
+#endif /* EP_ADD == JACOB */
/*============================================================================*/
- /* Public definitions */
+/* Public definitions */
/*============================================================================*/
#if EP_ADD == BASIC || !defined(STRIP)
@@ -244,7 +88,6 @@ void ep2_dbl_basic(ep2_t r, const ep2_t p) {
ep2_set_infty(r);
return;
}
-
ep2_dbl_basic_imp(r, NULL, p);
}
@@ -259,7 +102,7 @@ void ep2_dbl_slp_basic(ep2_t r, fp2_t s, const ep2_t p) {
#endif
-#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
+#if EP_ADD == PROJC || !defined(STRIP)
void ep2_dbl_projc(ep2_t r, const ep2_t p) {
if (ep2_is_infty(p)) {
@@ -271,3 +114,16 @@ void ep2_dbl_projc(ep2_t r, const ep2_t p) {
}
#endif
+
+#if EP_ADD == JACOB || !defined(STRIP)
+
+void ep2_dbl_jacob(ep2_t r, const ep2_t p) {
+ if (ep2_is_infty(p)) {
+ ep2_set_infty(r);
+ return;
+ }
+
+ ep2_dbl_jacob_imp(r, p);
+}
+
+#endif
diff --git a/src/epx/relic_ep2_frb.c b/src/epx/relic_ep2_frb.c
index b43695e04..2b330927f 100644
--- a/src/epx/relic_ep2_frb.c
+++ b/src/epx/relic_ep2_frb.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of frobenius action on prime elliptic curves over
- * quadratic extensions.
+ * Implementation of frobenius action on prime elliptic curves over a quadratic
+ * extension field.
*
* @ingroup epx
*/
diff --git a/src/epx/relic_ep2_map.c b/src/epx/relic_ep2_map.c
index 229d5f349..2445deed3 100644
--- a/src/epx/relic_ep2_map.c
+++ b/src/epx/relic_ep2_map.c
@@ -25,14 +25,14 @@
* @file
*
* Implementation of hashing to a prime elliptic curve over a quadratic
- * extension.
+ * extension field.
*
* @ingroup epx
*/
#include "relic_core.h"
#include "relic_md.h"
-#include "relic_tmpl_map.h"
+#include "relic_ep_map_tmpl.h"
/*============================================================================*/
/* Private definitions */
@@ -58,19 +58,12 @@ TMPL_MAP_ISOGENY_MAP(ep2, fp2, iso2)
/**
* Simplified SWU mapping.
*/
-#define EP2_MAP_COPY_COND(O, I, C) \
- do { \
- dv_copy_cond(O[0], I[0], RLC_FP_DIGS, C); \
- dv_copy_cond(O[1], I[1], RLC_FP_DIGS, C); \
- } while (0)
-TMPL_MAP_SSWU(ep2, fp2, fp_t, EP2_MAP_COPY_COND)
+TMPL_MAP_SSWU(ep2, fp2, fp_t)
/**
* Shallue--van de Woestijne map.
*/
-TMPL_MAP_SVDW(ep2, fp2, fp_t, EP2_MAP_COPY_COND)
-
-#undef EP2_MAP_COPY_COND
+TMPL_MAP_SVDW(ep2, fp2, fp_t)
/* caution: this function overwrites k, which it uses as an auxiliary variable */
static inline int fp2_sgn0(const fp2_t t, bn_t k) {
@@ -140,8 +133,7 @@ static void ep2_map_from_field(ep2_t p, const uint8_t *r, size_t len) {
/* compare sign of y to sign of t; fix if necessary */ \
neg = neg != fp2_sgn0(PT->y, k); \
fp2_neg(t, PT->y); \
- dv_copy_cond(PT->y[0], t[0], RLC_FP_DIGS, neg); \
- dv_copy_cond(PT->y[1], t[1], RLC_FP_DIGS, neg); \
+ fp2_copy_sec(PT->y, t, neg); \
} while (0)
/* first map invocation */
@@ -201,7 +193,7 @@ void ep2_map_basic(ep2_t p, const uint8_t *msg, size_t len) {
fp2_set_dig(p->z, 1);
while (1) {
- ep2_rhs(t0, p);
+ ep2_rhs(t0, p->x);
if (fp2_is_sqr(t0) == 1) {
fp2_srt(p->y, t0);
@@ -257,12 +249,18 @@ void ep2_map_swift(ep2_t p, const uint8_t *msg, size_t len) {
/* enough space for two field elements plus extra bytes for uniformity */
const size_t elm = (FP_PRIME + ep_param_level() + 7) / 8;
uint8_t t0z, t0, t1, sign, *r = RLC_ALLOCA(uint8_t, 4 * elm + 1);
- fp2_t t, u, v, w, y, x1, y1, z1;
+ fp2_t a, b, c, d, e, f, t, u, v, w, y, x1, y1, z1, den[3];
ctx_t *ctx = core_get();
dig_t c2, c3;
bn_t k;
bn_null(k);
+ fp2_null(a);
+ fp2_null(b);
+ fp2_null(c);
+ fp2_null(d);
+ fp2_null(e);
+ fp2_null(f);
fp2_null(t);
fp2_null(u);
fp2_null(v);
@@ -274,6 +272,12 @@ void ep2_map_swift(ep2_t p, const uint8_t *msg, size_t len) {
RLC_TRY {
bn_new(k);
+ fp2_new(a);
+ fp2_new(b);
+ fp2_new(c);
+ fp2_new(d);
+ fp2_new(e);
+ fp2_new(f);
fp2_new(t);
fp2_new(u);
fp2_new(v);
@@ -296,85 +300,216 @@ void ep2_map_swift(ep2_t p, const uint8_t *msg, size_t len) {
sign = r[0] & 1;
r -= 4 * elm;
- /* Assume that a = 0. */
- fp2_sqr(x1, u);
- fp2_mul(x1, x1, u);
- fp2_sqr(y1, t);
- fp2_add(x1, x1, ctx->ep2_b);
- fp2_sub(x1, x1, y1);
- fp2_dbl(y1, y1);
- fp2_add(y1, y1, x1);
- fp2_copy(z1, u);
- fp_mul(z1[0], z1[0], ctx->ep_map_c[4]);
- fp_mul(z1[1], z1[1], ctx->ep_map_c[4]);
- fp2_mul(x1, x1, z1);
- fp2_mul(z1, z1, t);
- fp2_dbl(z1, z1);
-
- fp2_dbl(y, y1);
- fp2_sqr(y, y);
- fp2_mul(v, y1, u);
- fp2_sub(v, x1, v);
- fp2_mul(v, v, z1);
- fp2_mul(w, y1, z1);
- fp2_dbl(w, w);
-
- if (fp2_is_zero(w)) {
- ep2_set_infty(p);
- } else {
- fp2_inv(w, w);
- fp2_mul(x1, v, w);
- fp2_add(y1, u, x1);
- fp2_neg(y1, y1);
- fp2_mul(z1, y, w);
- fp2_sqr(z1, z1);
- fp2_add(z1, z1, u);
-
- fp2_sqr(t, x1);
- fp2_mul(t, t, x1);
- fp2_add(t, t, ctx->ep2_b);
-
- fp2_sqr(u, y1);
- fp2_mul(u, u, y1);
- fp2_add(u, u, ctx->ep2_b);
-
- fp2_sqr(v, z1);
- fp2_mul(v, v, z1);
- fp2_add(v, v, ctx->ep2_b);
-
- c2 = fp2_is_sqr(u);
- c3 = fp2_is_sqr(v);
-
- for (int i = 0; i < 2; i++) {
- dv_swap_cond(x1[i], y1[i], RLC_FP_DIGS, c2);
- dv_swap_cond(t[i], u[i], RLC_FP_DIGS, c2);
- dv_swap_cond(x1[i], z1[i], RLC_FP_DIGS, c3);
- dv_swap_cond(t[i], v[i], RLC_FP_DIGS, c3);
+ if (ep2_curve_opt_b() == RLC_ZERO) {
+ fp2_sqr(a, u);
+ fp2_sqr(b, a);
+ fp2_mul(c, b, a);
+ if (ep2_curve_opt_a() == RLC_ONE) {
+ fp2_add_dig(c, c, 64);
+ } else {
+ fp2_dbl(f, ep2_curve_get_a());
+ fp2_dbl(f, f);
+ fp2_sqr(e, f);
+ fp2_mul(e, e, f);
+ fp2_add(c, c, e);
}
-
- if (!fp2_srt(t, t)) {
+ fp2_sqr(d, t);
+
+ fp2_mul(v, a, d);
+ fp2_mul(v, v, u);
+ fp2_mul_dig(v, v, 24);
+ fp_mul(v[0], v[0], ctx->ep_map_c[4]);
+ fp_mul(v[1], v[1], ctx->ep_map_c[4]);
+
+ fp_sub_dig(p->x[0], ctx->ep_map_c[4], 1);
+ fp_hlv(p->x[0], p->x[0]);
+
+ fp2_sqr(w, b);
+ fp2_mul(y, v, a);
+ if (ep2_curve_opt_a() == RLC_ONE) {
+ fp2_dbl(t, c);
+ fp2_dbl(t, t);
+ } else {
+ fp2_mul(t, f, c);
+ }
+ fp2_add(y, y, t);
+ fp_mul(y[0], y[0], p->x[0]);
+ fp_mul(y[1], y[1], p->x[0]);
+
+ fp2_add(den[0], c, v);
+ fp2_mul(den[0], den[0], u);
+ fp_mul(den[0][0], den[0][0], ctx->ep_map_c[4]);
+ fp_mul(den[0][1], den[0][1], ctx->ep_map_c[4]);
+ fp_mul(den[0][0], den[0][0], p->x[0]);
+ fp_mul(den[0][1], den[0][1], p->x[0]);
+ fp2_dbl(den[0], den[0]);
+ fp2_neg(den[0], den[0]);
+ fp_mul(den[1][0], den[0][0], p->x[0]);
+ fp_mul(den[1][1], den[0][1], p->x[0]);
+ if (ep_curve_opt_a() == RLC_ONE) {
+ fp2_sub_dig(den[2], a, 4);
+ } else {
+ fp2_sub(den[2], a, f);
+ }
+ fp2_sqr(den[2], den[2]);
+ fp2_mul_dig(den[2], den[2], 216);
+ fp2_dbl(den[2], den[2]);
+ fp2_neg(den[2], den[2]);
+ fp2_mul(den[2], den[2], b);
+ fp2_mul(den[2], den[2], d);
+
+ if (fp2_is_zero(den[0]) || fp2_is_zero(den[1]) || fp2_is_zero(den[2])) {
+ ep2_set_infty(p);
+ } else {
+ fp2_inv_sim(den, den, 3);
+ if (ep2_curve_opt_a() == RLC_ONE) {
+ fp2_dbl(a, a);
+ fp2_dbl(a, a);
+ fp2_dbl(a, a);
+ fp2_dbl(a, a);
+ fp2_add(y1, a, v);
+ fp2_dbl(y1, y1);
+ fp2_dbl(y1, y1);
+ } else {
+ fp2_mul(y1, f, v);
+ fp2_mul(u, a, e);
+ fp2_add(y1, y1, u);
+ }
+ fp2_add(y1, y1, w);
+ fp_mul(z1[0], y[0], p->x[0]);
+ fp_mul(z1[1], y[1], p->x[0]);
+ fp2_add(x1, y1, z1);
+ fp2_add(y1, y1, y);
+
+ if (ep2_curve_opt_a() == RLC_ONE) {
+ fp2_dbl(e, b);
+ fp2_dbl(e, e);
+ fp2_add(z1, a, e);
+ } else {
+ fp2_mul(z1, f, a);
+ fp2_add(z1, z1, b);
+ fp2_mul(z1, z1, f);
+ }
+ fp2_dbl(t, z1);
+ fp2_add(z1, z1, t);
+ fp2_sub(z1, c, z1);
+ fp2_sub(z1, z1, v);
+ fp2_mul(z1, z1, v);
+ if (ep2_curve_opt_a() == RLC_ONE) {
+ fp2_dbl(a, a);
+ fp2_dbl(a, a);
+ fp2_dbl(a, a);
+ fp2_set_dig(d, 64);
+ fp2_sqr(d, d);
+ } else {
+ fp2_dbl(a, u);
+ fp2_sqr(d, e);
+ }
+ fp2_add(a, a, w);
+ fp2_mul(u, a, b);
+ fp2_sub(z1, u, z1);
+ fp2_add(z1, z1, d);
+
+ fp2_mul(x1, x1, den[0]);
+ fp2_mul(y1, y1, den[1]);
+ fp2_mul(z1, z1, den[2]);
+
+ ep2_rhs(t, x1);
+ ep2_rhs(u, y1);
+ ep2_rhs(v, z1);
+
+ int c2 = fp2_is_sqr(u);
+ int c3 = fp2_is_sqr(v);
+
+ fp2_copy_sec(t, u, c2);
+ fp2_copy_sec(x1, y1, c2);
+ fp2_copy_sec(t, v, c3);
+ fp2_copy_sec(x1, z1, c3);
+
+ if (!fp2_srt(t, t)) {
+ RLC_THROW(ERR_NO_VALID);
+ }
+ fp2_neg(u, t);
+ fp2_copy_sec(t, u, fp_is_even(t[0]) ^ sign);
+
+ fp2_copy(p->x, x1);
+ fp2_copy(p->y, t);
+ fp2_set_dig(p->z, 1);
+ p->coord = BASIC;
+ }
+ } else {
+ if (ep2_curve_opt_a() != RLC_ZERO) {
RLC_THROW(ERR_NO_VALID);
+ } else {
+ /* Assume that a = 0. */
+ fp2_sqr(x1, u);
+ fp2_mul(x1, x1, u);
+ fp2_sqr(y1, t);
+ fp2_add(x1, x1, ctx->ep2_b);
+ fp2_sub(x1, x1, y1);
+ fp2_dbl(y1, y1);
+ fp2_add(y1, y1, x1);
+ fp2_copy(z1, u);
+ fp_mul(z1[0], z1[0], ctx->ep_map_c[4]);
+ fp_mul(z1[1], z1[1], ctx->ep_map_c[4]);
+ fp2_mul(x1, x1, z1);
+ fp2_mul(z1, z1, t);
+ fp2_dbl(z1, z1);
+
+ fp2_dbl(y, y1);
+ fp2_sqr(y, y);
+ fp2_mul(v, y1, u);
+ fp2_sub(v, x1, v);
+ fp2_mul(v, v, z1);
+ fp2_mul(w, y1, z1);
+ fp2_dbl(w, w);
+
+ if (fp2_is_zero(w)) {
+ ep2_set_infty(p);
+ } else {
+ fp2_inv(w, w);
+ fp2_mul(x1, v, w);
+ fp2_add(y1, u, x1);
+ fp2_neg(y1, y1);
+ fp2_mul(z1, y, w);
+ fp2_sqr(z1, z1);
+ fp2_add(z1, z1, u);
+
+ ep2_rhs(t, x1);
+ ep2_rhs(u, y1);
+ ep2_rhs(v, z1);
+
+ c2 = fp2_is_sqr(u);
+ c3 = fp2_is_sqr(v);
+
+ fp2_copy_sec(x1, y1, c2);
+ fp2_copy_sec(t, u, c2);
+ fp2_copy_sec(x1, z1, c3);
+ fp2_copy_sec(t, v, c3);
+
+ if (!fp2_srt(t, t)) {
+ RLC_THROW(ERR_NO_VALID);
+ }
+
+ t0z = fp_is_zero(t[0]);
+ fp_prime_back(k, t[0]);
+ t0 = bn_get_bit(k, 0);
+ fp_prime_back(k, t[1]);
+ t1 = bn_get_bit(k, 0);
+ /* t[0] == 0 ? sgn0(t[1]) : sgn0(t[0]) */
+ sign ^= (t0 | (t0z & t1));
+
+ fp2_neg(u, t);
+ fp2_copy_sec(t, u, sign);
+
+ fp2_copy(p->x, x1);
+ fp2_copy(p->y, t);
+ fp2_set_dig(p->z, 1);
+ p->coord = BASIC;
+ }
}
-
- t0z = fp_is_zero(t[0]);
- fp_prime_back(k, t[0]);
- t0 = bn_get_bit(k, 0);
- fp_prime_back(k, t[1]);
- t1 = bn_get_bit(k, 0);
- /* t[0] == 0 ? sgn0(t[1]) : sgn0(t[0]) */
- sign ^= (t0 | (t0z & t1));
-
- fp2_neg(u, t);
- dv_swap_cond(t[0], u[0], RLC_FP_DIGS, sign);
- dv_swap_cond(t[1], u[1], RLC_FP_DIGS, sign);
-
- fp2_copy(p->x, x1);
- fp2_copy(p->y, t);
- fp2_set_dig(p->z, 1);
- p->coord = BASIC;
-
- ep2_mul_cof(p, p);
}
+ ep2_mul_cof(p, p);
}
RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
diff --git a/src/epx/relic_ep2_mul.c b/src/epx/relic_ep2_mul.c
index 698f026b6..68904d8f5 100644
--- a/src/epx/relic_ep2_mul.c
+++ b/src/epx/relic_ep2_mul.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of point multiplication on prime elliptic curves over
- * quadratic extensions.
+ * Implementation of point multiplication on prime elliptic curves over a
+ * quadratic extension field.
*
* @ingroup epx
*/
@@ -36,11 +36,11 @@
/* Private definitions */
/*============================================================================*/
-#if EP_MUL == LWNAF || !defined(STRIP)
-
#if defined(EP_ENDOM)
-static void ep2_mul_glv_imp(ep2_t r, const ep2_t p, const bn_t k) {
+#if EP_MUL == LWNAF || !defined(STRIP)
+
+static void ep2_mul_gls_imp(ep2_t r, const ep2_t p, const bn_t k) {
size_t l, _l[4];
bn_t n, _k[4], u;
int8_t naf[4][RLC_FP_BITS + 1];
@@ -110,10 +110,133 @@ static void ep2_mul_glv_imp(ep2_t r, const ep2_t p, const bn_t k) {
}
}
+#endif /* EP_MUL == LWNAF */
+
+#if EP_MUL == LWREG || !defined(STRIP)
+
+static void ep2_mul_reg_gls(ep2_t r, const ep2_t p, const bn_t k) {
+ int8_t reg[4][RLC_FP_BITS + 1], b[4], s[4], c0, n0;
+ ep2_t q, w, t[4][1 << (RLC_WIDTH - 2)];
+ bn_t n, _k[4], u;
+ size_t l, len, _l[4];
+
+ bn_null(n);
+ bn_null(u);
+ ep2_null(q);
+ ep2_null(w);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(u);
+ ep2_new(q);
+ ep2_new(w);
+ for (size_t i = 0; i < 4; i++) {
+ bn_null(_k[i]);
+ bn_new(_k[i]);
+ for (size_t j = 0; j < (1 << (RLC_WIDTH - 2)); j++) {
+ ep2_null(t[i][j]);
+ ep2_new(t[i][j]);
+ }
+ }
+
+ ep2_curve_get_ord(n);
+ fp_prime_get_par(u);
+ bn_mod(_k[0], k, n);
+ bn_rec_frb(_k, 4, _k[0], u, n, ep_curve_is_pairf() == EP_BN);
+
+ l = 0;
+ /* Make some extra room for BN curves that grow subscalars by 1. */
+ len = bn_bits(u) + (ep_curve_is_pairf() == EP_BN);
+ ep2_norm(t[0][0], p);
+ for (size_t i = 0; i < 4; i++) {
+ s[i] = bn_sign(_k[i]);
+ bn_abs(_k[i], _k[i]);
+ b[i] = bn_is_even(_k[i]);
+ _k[i]->dp[0] |= b[i];
+
+ _l[i] = RLC_FP_BITS + 1;
+ bn_rec_reg(reg[i], &_l[i], _k[i], len, RLC_WIDTH);
+ l = RLC_MAX(l, _l[i]);
+
+ /* Apply Frobenius before flipping sign to build table. */
+ if (i > 0) {
+ ep2_frb(t[i][0], t[i - 1][0], 1);
+ }
+ }
+
+ for (size_t i = 0; i < 4; i++) {
+ ep2_neg(q, t[i][0]);
+ fp2_copy_sec(q->y, t[i][0]->y, s[i] == RLC_POS);
+ ep2_tab(t[i], q, RLC_WIDTH);
+ }
+
+#if defined(EP_MIXED)
+ fp2_set_dig(w->z, 1);
+ w->coord = BASIC;
+#else
+ w->coord = = EP_ADD;
+#endif
+
+ ep2_set_infty(r);
+ for (int j = l - 1; j >= 0; j--) {
+ for (size_t i = 0; i < RLC_WIDTH - 1; i++) {
+ ep2_dbl(r, r);
+ }
+
+ for (size_t i = 0; i < 4; i++) {
+ n0 = reg[i][j];
+ c0 = (n0 >> 7);
+ n0 = ((n0 ^ c0) - c0) >> 1;
+
+ for (size_t m = 0; m < (1 << (RLC_WIDTH - 2)); m++) {
+ fp2_copy_sec(w->x, t[i][m]->x, m == n0);
+ fp2_copy_sec(w->y, t[i][m]->y, m == n0);
+ #if !defined(EP_MIXED)
+ fp2_copy_sec(w->z, t[i][m]->z, m == n0);
+ #endif
+ }
+
+ ep2_neg(q, w);
+ fp2_copy_sec(q->y, w->y, c0 == 0);
+ ep2_add(r, r, q);
+ }
+ }
+
+ for (size_t i = 0; i < 4; i++) {
+ /* Tables are built with points already negated, so no need here. */
+ ep2_sub(q, r, t[i][0]);
+ fp2_copy_sec(r->x, q->x, b[i]);
+ fp2_copy_sec(r->y, q->y, b[i]);
+ fp2_copy_sec(r->z, q->z, b[i]);
+ }
+
+ /* Convert r to affine coordinates. */
+ ep2_norm(r, r);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ bn_free(u);
+ ep2_free(q);
+ ep2_free(w);
+ for (int i = 0; i < 4; i++) {
+ bn_free(_k[i]);
+ for (size_t j = 0; j < (1 << (RLC_WIDTH - 2)); j++) {
+ ep2_free(t[i][j]);
+ }
+ }
+ }
+}
+
+#endif /* EP_MUL == LWREG */
#endif /* EP_ENDOM */
#if defined(EP_PLAIN) || defined(EP_SUPER)
+#if EP_MUL == LWNAF || !defined(STRIP)
+
static void ep2_mul_naf_imp(ep2_t r, const ep2_t p, const bn_t k) {
size_t l;
int8_t n, naf[RLC_FP_BITS + 1];
@@ -161,9 +284,95 @@ static void ep2_mul_naf_imp(ep2_t r, const ep2_t p, const bn_t k) {
}
}
-#endif /* EP_PLAIN || EP_SUPER */
#endif /* EP_MUL == LWNAF */
+#if EP_MUL == LWREG || !defined(STRIP)
+
+static void ep2_mul_reg_imp(ep2_t r, const ep2_t p, const bn_t k) {
+ bn_t _k;
+ int8_t s, reg[1 + RLC_CEIL(RLC_FP_BITS + 1, RLC_WIDTH - 1)];
+ ep2_t t[1 << (RLC_WIDTH - 2)], u, v;
+ size_t l, n;
+
+ bn_null(_k);
+
+ RLC_TRY {
+ bn_new(_k);
+ ep2_new(u);
+ ep2_new(v);
+ /* Prepare the precomputation table. */
+ for (size_t i = 0; i < (1 << (RLC_WIDTH - 2)); i++) {
+ ep2_null(t[i]);
+ ep2_new(t[i]);
+ }
+ /* Compute the precomputation table. */
+ ep2_tab(t, p, RLC_WIDTH);
+
+ ep2_curve_get_ord(_k);
+ n = bn_bits(_k);
+
+ /* Make a copy of the scalar for processing. */
+ bn_abs(_k, k);
+ _k->dp[0] |= 1;
+
+ /* Compute the regular w-NAF representation of k. */
+ l = RLC_CEIL(n, RLC_WIDTH - 1) + 1;
+ bn_rec_reg(reg, &l, _k, n, RLC_WIDTH);
+
+#if defined(EP_MIXED)
+ fp2_set_dig(u->z, 1);
+ u->coord = BASIC;
+#else
+ u->coord = EP_ADD;
+#endif
+ ep2_set_infty(r);
+ for (int i = l - 1; i >= 0; i--) {
+ for (size_t j = 0; j < RLC_WIDTH - 1; j++) {
+ ep2_dbl(r, r);
+ }
+
+ n = reg[i];
+ s = (n >> 7);
+ n = ((n ^ s) - s) >> 1;
+
+ for (size_t j = 0; j < (1 << (RLC_WIDTH - 2)); j++) {
+ fp2_copy_sec(u->x, t[j]->x, j == n);
+ fp2_copy_sec(u->y, t[j]->y, j == n);
+#if !defined(EP_MIXED)
+ fp_copy_sec(u->z, t[j]->z, j == n);
+#endif
+ }
+ ep2_neg(v, u);
+ fp2_copy_sec(u->y, v->y, s != 0);
+ ep2_add(r, r, u);
+ }
+ /* t[0] has an unmodified copy of p. */
+ ep2_sub(u, r, t[0]);
+ fp2_copy_sec(r->x, u->x, bn_is_even(k));
+ fp2_copy_sec(r->y, u->y, bn_is_even(k));
+ fp2_copy_sec(r->z, u->z, bn_is_even(k));
+ /* Convert r to affine coordinates. */
+ ep2_norm(r, r);
+ ep2_neg(u, r);
+ fp2_copy_sec(r->y, u->y, bn_sign(k) == RLC_NEG);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ /* Free the precomputation table. */
+ for (size_t i = 0; i < (1 << (RLC_WIDTH - 2)); i++) {
+ ep2_free(t[i]);
+ }
+ bn_free(_k);
+ ep2_free(u);
+ ep2_free(v);
+ }
+}
+
+#endif /* EP_MUL == LWREG */
+#endif /* EP_PLAIN || EP_SUPER */
+
/*============================================================================*/
/* Public definitions */
/*============================================================================*/
@@ -326,7 +535,7 @@ void ep2_mul_monty(ep2_t r, const ep2_t p, const bn_t k) {
bn_abs(l, _k);
bn_add(l, l, n);
bn_add(n, l, n);
- dv_swap_cond(l->dp, n->dp, RLC_MAX(l->used, n->used),
+ dv_swap_sec(l->dp, n->dp, RLC_MAX(l->used, n->used),
bn_get_bit(l, bits) == 0);
l->used = RLC_SEL(l->used, n->used, bn_get_bit(l, bits) == 0);
@@ -339,20 +548,20 @@ void ep2_mul_monty(ep2_t r, const ep2_t p, const bn_t k) {
for (int i = bits - 1; i >= 0; i--) {
int j = bn_get_bit(l, i);
- dv_swap_cond(t[0]->x[0], t[1]->x[0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->x[1], t[1]->x[1], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y[0], t[1]->y[0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y[1], t[1]->y[1], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z[0], t[1]->z[0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z[1], t[1]->z[1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x[0], t[1]->x[0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x[1], t[1]->x[1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y[0], t[1]->y[0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y[1], t[1]->y[1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z[0], t[1]->z[0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z[1], t[1]->z[1], RLC_FP_DIGS, j ^ 1);
ep2_add(t[0], t[0], t[1]);
ep2_dbl(t[1], t[1]);
- dv_swap_cond(t[0]->x[0], t[1]->x[0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->x[1], t[1]->x[1], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y[0], t[1]->y[0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y[1], t[1]->y[1], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z[0], t[1]->z[0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z[1], t[1]->z[1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x[0], t[1]->x[0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x[1], t[1]->x[1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y[0], t[1]->y[0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y[1], t[1]->y[1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z[0], t[1]->z[0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z[1], t[1]->z[1], RLC_FP_DIGS, j ^ 1);
}
ep2_norm(r, t[0]);
@@ -380,7 +589,7 @@ void ep2_mul_lwnaf(ep2_t r, const ep2_t p, const bn_t k) {
#if defined(EP_ENDOM)
if (ep_curve_is_endom()) {
- ep2_mul_glv_imp(r, p, k);
+ ep2_mul_gls_imp(r, p, k);
return;
}
#endif
@@ -392,6 +601,28 @@ void ep2_mul_lwnaf(ep2_t r, const ep2_t p, const bn_t k) {
#endif
+#if EP_MUL == LWREG || !defined(STRIP)
+
+void ep2_mul_lwreg(ep2_t r, const ep2_t p, const bn_t k) {
+ if (bn_is_zero(k) || ep2_is_infty(p)) {
+ ep2_set_infty(r);
+ return;
+ }
+
+#if defined(EP_ENDOM)
+ if (ep_curve_is_endom()) {
+ ep2_mul_reg_gls(r, p, k);
+ return;
+ }
+#endif
+
+#if defined(EP_PLAIN) || defined(EP_SUPER)
+ ep2_mul_reg_imp(r, p, k);
+#endif
+}
+
+#endif
+
void ep2_mul_gen(ep2_t r, const bn_t k) {
if (bn_is_zero(k)) {
ep2_set_infty(r);
diff --git a/src/epx/relic_ep2_mul_cof.c b/src/epx/relic_ep2_mul_cof.c
index ee8be325a..edc10dd2b 100644
--- a/src/epx/relic_ep2_mul_cof.c
+++ b/src/epx/relic_ep2_mul_cof.c
@@ -25,14 +25,13 @@
* @file
*
* Implementation of point multiplication of a prime elliptic curve over a
- * quadratic extension by the curve cofactor.
+ * quadratic extension field by the curve cofactor.
*
* @ingroup epx
*/
#include "relic_core.h"
#include "relic_md.h"
-#include "relic_tmpl_map.h"
/*============================================================================*/
/* Private definitions */
@@ -166,7 +165,7 @@ void ep2_mul_cof(ep2_t r, const ep2_t p) {
default:
/* Now, multiply by cofactor to get the correct group. */
ep2_curve_get_cof(k);
- ep2_mul_basic(r, p, k);
+ ep2_mul_big(r, p, k);
break;
}
} RLC_CATCH_ANY {
diff --git a/src/epx/relic_ep2_mul_fix.c b/src/epx/relic_ep2_mul_fix.c
index 075c9227a..200db4c89 100644
--- a/src/epx/relic_ep2_mul_fix.c
+++ b/src/epx/relic_ep2_mul_fix.c
@@ -25,7 +25,7 @@
* @file
*
* Implementation of fixed point multiplication on a prime elliptic curve over
- * a quadratic extension.
+ * a quadratic extension field.
*
* @ingroup epx
*/
diff --git a/src/epx/relic_ep2_mul_sim.c b/src/epx/relic_ep2_mul_sim.c
index 51f9f8df6..c39c432f6 100644
--- a/src/epx/relic_ep2_mul_sim.c
+++ b/src/epx/relic_ep2_mul_sim.c
@@ -25,7 +25,7 @@
* @file
*
* Implementation of simultaneous point multiplication on a prime elliptic
- * curve over a quadratic extension.
+ * curve over a quadratic extension field.
*
* @ingroup epx
*/
diff --git a/src/epx/relic_ep2_neg.c b/src/epx/relic_ep2_neg.c
index bde5c68de..16225e986 100644
--- a/src/epx/relic_ep2_neg.c
+++ b/src/epx/relic_ep2_neg.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of point negation on elliptic prime curves over quadratic
- * extensions.
+ * Implementation of point negation on elliptic prime curves over a quadratic
+ * extension field.
*
* @ingroup epx
*/
diff --git a/src/epx/relic_ep2_norm.c b/src/epx/relic_ep2_norm.c
index 3276649d3..0010b976a 100644
--- a/src/epx/relic_ep2_norm.c
+++ b/src/epx/relic_ep2_norm.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of point normalization on prime elliptic curves over quadratic
- * extensions.
+ * Implementation of point normalization on prime elliptic curves over a
+ * quadratic extension.
*
* @ingroup epx
*/
@@ -43,36 +43,45 @@
*
* @param r - the result.
* @param p - the point to normalize.
+ * @param inv - the flag to indicate if z is already inverted.
*/
-static void ep2_norm_imp(ep2_t r, const ep2_t p, int inverted) {
+static void ep2_norm_imp(ep2_t r, const ep2_t p, int inv) {
if (p->coord != BASIC) {
- fp2_t t0, t1;
+ fp2_t t;
- fp2_null(t0);
- fp2_null(t1);
+ fp2_null(t);
RLC_TRY {
+ fp2_new(t);
- fp2_new(t0);
- fp2_new(t1);
-
- if (inverted) {
- fp2_copy(t1, p->z);
+ if (inv) {
+ fp2_copy(r->z, p->z);
} else {
- fp2_inv(t1, p->z);
+ fp2_inv(r->z, p->z);
+ }
+
+ switch (p->coord) {
+ case PROJC:
+ fp2_mul(r->x, p->x, r->z);
+ fp2_mul(r->y, p->y, r->z);
+ break;
+ case JACOB:
+ fp2_sqr(t, r->z);
+ fp2_mul(r->x, p->x, t);
+ fp2_mul(t, t, r->z);
+ fp2_mul(r->y, p->y, t);
+ break;
+ default:
+ ep2_copy(r, p);
+ break;
}
- fp2_sqr(t0, t1);
- fp2_mul(r->x, p->x, t0);
- fp2_mul(t0, t0, t1);
- fp2_mul(r->y, p->y, t0);
fp2_set_dig(r->z, 1);
}
RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
}
RLC_FINALLY {
- fp2_free(t0);
- fp2_free(t1);
+ fp2_free(t);
}
}
@@ -92,17 +101,18 @@ void ep2_norm(ep2_t r, const ep2_t p) {
}
if (p->coord == BASIC) {
- /* If the point is represented in affine coordinates, we just copy it. */
+ /* If the point is represented in affine coordinates, just copy it. */
ep2_copy(r, p);
+ return;
}
#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
ep2_norm_imp(r, p, 0);
-#endif
+#endif /* EP_ADD == PROJC */
}
void ep2_norm_sim(ep2_t *r, const ep2_t *t, int n) {
int i;
- fp2_t *a = RLC_ALLOCA(fp2_t, n);
+ fp2_t* a = RLC_ALLOCA(fp2_t, n);
RLC_TRY {
if (a == NULL) {
@@ -114,19 +124,20 @@ void ep2_norm_sim(ep2_t *r, const ep2_t *t, int n) {
fp2_copy(a[i], t[i]->z);
}
- fp2_inv_sim(a, a, n);
+ fp2_inv_sim(a, (const fp2_t *)a, n);
for (i = 0; i < n; i++) {
fp2_copy(r[i]->x, t[i]->x);
fp2_copy(r[i]->y, t[i]->y);
- fp2_copy(r[i]->z, a[i]);
+ if (!ep2_is_infty(t[i])) {
+ fp2_copy(r[i]->z, a[i]);
+ }
}
-
#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
for (i = 0; i < n; i++) {
ep2_norm_imp(r[i], r[i], 1);
}
-#endif
+#endif /* EP_ADD == PROJC */
}
RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
diff --git a/src/epx/relic_ep2_pck.c b/src/epx/relic_ep2_pck.c
index 699ebde41..6fd8e2abd 100644
--- a/src/epx/relic_ep2_pck.c
+++ b/src/epx/relic_ep2_pck.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of point compression on prime elliptic curves over quadratic
- * extensions.
+ * Implementation of point compression on prime elliptic curves over a quadratic
+ * extension field.
*
* @ingroup epx
*/
@@ -85,7 +85,7 @@ int ep2_upk(ep2_t r, const ep2_t p) {
bn_new(halfQ);
bn_new(yValue);
- ep2_rhs(t, p);
+ ep2_rhs(t, p->x);
/* t0 = sqrt(x1^3 + a * x1 + b). */
result = fp2_srt(t, t);
diff --git a/src/epx/relic_ep2_util.c b/src/epx/relic_ep2_util.c
index b61668ace..4ac588532 100644
--- a/src/epx/relic_ep2_util.c
+++ b/src/epx/relic_ep2_util.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of comparison for points on prime elliptic curves over
- * quadratic extensions.
+ * Implementation of comparison for points on prime elliptic curves over a
+ * quadratic extension field.
*
* @ingroup epx
*/
@@ -89,13 +89,18 @@ void ep2_blind(ep2_t r, const ep2_t p) {
#if EP_ADD == BASIC
(void)rand;
ep2_copy(r, p);
-#else
+#elif EP_ADD == PROJC
+ fp2_mul(r->x, p->x, rand);
+ fp2_mul(r->y, p->y, rand);
+ fp2_mul(r->z, p->z, rand);
+ r->coord = PROJC;
+#elif EP_ADD == JACOB
fp2_mul(r->z, p->z, rand);
fp2_mul(r->y, p->y, rand);
fp2_sqr(rand, rand);
fp2_mul(r->x, r->x, rand);
fp2_mul(r->y, r->y, rand);
- r->coord = EP_ADD;
+ r->coord = JACOB;
#endif
} RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
@@ -104,7 +109,7 @@ void ep2_blind(ep2_t r, const ep2_t p) {
}
}
-void ep2_rhs(fp2_t rhs, const ep2_t p) {
+void ep2_rhs(fp2_t rhs, const fp2_t x) {
fp2_t t0;
fp2_null(t0);
@@ -112,7 +117,7 @@ void ep2_rhs(fp2_t rhs, const ep2_t p) {
RLC_TRY {
fp2_new(t0);
- fp2_sqr(t0, p->x); /* x1^2 */
+ fp2_sqr(t0, x); /* x1^2 */
switch (ep2_curve_opt_a()) {
case RLC_ZERO:
@@ -136,7 +141,7 @@ void ep2_rhs(fp2_t rhs, const ep2_t p) {
break;
}
- fp2_mul(t0, t0, p->x); /* x1^3 + a * x */
+ fp2_mul(t0, t0, x); /* x1^3 + a * x */
switch (ep2_curve_opt_b()) {
case RLC_ZERO:
@@ -180,7 +185,7 @@ int ep2_on_curve(const ep2_t p) {
ep2_norm(t, p);
- ep2_rhs(t->x, t);
+ ep2_rhs(t->x, t->x);
fp2_sqr(t->y, t->y);
r = (fp2_cmp(t->x, t->y) == RLC_EQ) || ep2_is_infty(p);
diff --git a/src/epx/relic_ep3_add.c b/src/epx/relic_ep3_add.c
index 3c3626342..d8a7667a6 100644
--- a/src/epx/relic_ep3_add.c
+++ b/src/epx/relic_ep3_add.c
@@ -24,13 +24,14 @@
/**
* @file
*
- * Implementation of addition on prime elliptic curves over quadratic
- * extensions.
+ * Implementation of addition on prime elliptic curves over a cubic extension
+ * field.
*
* @ingroup epx
*/
#include "relic_core.h"
+#include "relic_ep_add_tmpl.h"
/*============================================================================*/
/* Private definitions */
@@ -42,312 +43,62 @@
* Adds two points represented in affine coordinates on an ordinary prime
* elliptic curve.
*
- * @param r - the result.
- * @param s - the resulting slope.
- * @param p - the first point to add.
- * @param q - the second point to add.
+ * @param[out] r - the result.
+ * @param[out] s - the slope.
+ * @param[in] p - the first point to add.
+ * @param[in] q - the second point to add.
*/
-static void ep3_add_basic_imp(ep3_t r, fp3_t s, const ep3_t p, const ep3_t q) {
- fp3_t t0, t1, t2;
-
- fp3_null(t0);
- fp3_null(t1);
- fp3_null(t2);
-
- RLC_TRY {
- fp3_new(t0);
- fp3_new(t1);
- fp3_new(t2);
-
- /* t0 = x2 - x1. */
- fp3_sub(t0, q->x, p->x);
- /* t1 = y2 - y1. */
- fp3_sub(t1, q->y, p->y);
-
- /* If t0 is zero. */
- if (fp3_is_zero(t0)) {
- if (fp3_is_zero(t1)) {
- /* If t1 is zero, q = p, should have doubled. */
- ep3_dbl_slp_basic(r, s, p);
- } else {
- /* If t1 is not zero and t0 is zero, q = -p and r = infty. */
- ep3_set_infty(r);
- }
- } else {
- /* t2 = 1/(x2 - x1). */
- fp3_inv(t2, t0);
- /* t2 = lambda = (y2 - y1)/(x2 - x1). */
- fp3_mul(t2, t1, t2);
-
- /* x3 = lambda^2 - x2 - x1. */
- fp3_sqr(t1, t2);
- fp3_sub(t0, t1, p->x);
- fp3_sub(t0, t0, q->x);
-
- /* y3 = lambda * (x1 - x3) - y1. */
- fp3_sub(t1, p->x, t0);
- fp3_mul(t1, t2, t1);
- fp3_sub(r->y, t1, p->y);
-
- fp3_copy(r->x, t0);
- fp3_copy(r->z, p->z);
-
- if (s != NULL) {
- fp3_copy(s, t2);
- }
-
- r->coord = BASIC;
- }
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp3_free(t0);
- fp3_free(t1);
- fp3_free(t2);
- }
-}
+TMPL_ADD_BASIC_IMP(ep3, fp3);
#endif /* EP_ADD == BASIC */
-#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
+#if EP_ADD == PROJC || !defined(STRIP)
-#if defined(EP_MIXED) || !defined(STRIP)
+/**
+ * Adds a point represented in homogeneous coordinates to a point represented in
+ * affine coordinates on an ordinary prime elliptic curve.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the projective point.
+ * @param[in] q - the affine point.
+ */
+TMPL_ADD_PROJC_MIX(ep3, fp3);
/**
- * Adds a point represented in affine coordinates to a point represented in
- * projective coordinates.
+ * Adds two points represented in homogeneous coordinates on an ordinary prime
+ * elliptic curve.
*
- * @param r - the result.
- * @param s - the slope.
- * @param p - the affine point.
- * @param q - the projective point.
+ * @param[out] r - the result.
+ * @param[in] p - the first point to add.
+ * @param[in] q - the second point to add.
*/
-static void ep3_add_projc_mix(ep3_t r, const ep3_t p, const ep3_t q) {
- fp3_t t0, t1, t2, t3, t4, t5, t6;
+TMPL_ADD_PROJC_IMP(ep3, fp3);
- fp3_null(t0);
- fp3_null(t1);
- fp3_null(t2);
- fp3_null(t3);
- fp3_null(t4);
- fp3_null(t5);
- fp3_null(t6);
+#endif /* EP_ADD == PROJC */
- RLC_TRY {
- fp3_new(t0);
- fp3_new(t1);
- fp3_new(t2);
- fp3_new(t3);
- fp3_new(t4);
- fp3_new(t5);
- fp3_new(t6);
-
- if (p->coord != BASIC) {
- /* t0 = z1^2. */
- fp3_sqr(t0, p->z);
-
- /* t3 = U2 = x2 * z1^2. */
- fp3_mul(t3, q->x, t0);
-
- /* t1 = S2 = y2 * z1^3. */
- fp3_mul(t1, t0, p->z);
- fp3_mul(t1, t1, q->y);
-
- /* t3 = H = U2 - x1. */
- fp3_sub(t3, t3, p->x);
-
- /* t1 = R = 2 * (S2 - y1). */
- fp3_sub(t1, t1, p->y);
- } else {
- /* H = x2 - x1. */
- fp3_sub(t3, q->x, p->x);
-
- /* t1 = R = 2 * (y2 - y1). */
- fp3_sub(t1, q->y, p->y);
- }
-
- /* t2 = HH = H^2. */
- fp3_sqr(t2, t3);
-
- /* If E is zero. */
- if (fp3_is_zero(t3)) {
- if (fp3_is_zero(t1)) {
- /* If I is zero, p = q, should have doubled. */
- ep3_dbl_projc(r, p);
- } else {
- /* If I is not zero, q = -p, r = infinity. */
- ep3_set_infty(r);
- }
- } else {
- /* t5 = J = H * HH. */
- fp3_mul(t5, t3, t2);
-
- /* t4 = V = x1 * HH. */
- fp3_mul(t4, p->x, t2);
-
- /* x3 = R^2 - J - 2 * V. */
- fp3_sqr(r->x, t1);
- fp3_sub(r->x, r->x, t5);
- fp3_dbl(t6, t4);
- fp3_sub(r->x, r->x, t6);
-
- /* y3 = R * (V - x3) - Y1 * J. */
- fp3_sub(t4, t4, r->x);
- fp3_mul(t4, t4, t1);
- fp3_mul(t1, p->y, t5);
- fp3_sub(r->y, t4, t1);
-
- if (p->coord != BASIC) {
- /* z3 = z1 * H. */
- fp3_mul(r->z, p->z, t3);
- } else {
- /* z3 = H. */
- fp3_copy(r->z, t3);
- }
- }
- r->coord = PROJC;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp3_free(t0);
- fp3_free(t1);
- fp3_free(t2);
- fp3_free(t3);
- fp3_free(t4);
- fp3_free(t5);
- fp3_free(t6);
- }
-}
+#if EP_ADD == JACOB || !defined(STRIP)
-#endif
+/**
+ * Adds a point represented in Jacobian coordinates to a point represented in
+ * affine coordinates on an ordinary prime elliptic curve.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the projective point.
+ * @param[in] q - the affine point.
+ */
+TMPL_ADD_JACOB_MIX(ep3, fp3);
/**
- * Adds two points represented in projective coordinates on an ordinary prime
+ * Adds two points represented in Jacobian coordinates on an ordinary prime
* elliptic curve.
*
- * @param r - the result.
- * @param p - the first point to add.
- * @param q - the second point to add.
+ * @param[out] r - the result.
+ * @param[in] p - the first point to add.
+ * @param[in] q - the second point to add.
*/
-static void ep3_add_projc_imp(ep3_t r, const ep3_t p, const ep3_t q) {
-#if defined(EP_MIXED) && defined(STRIP)
- ep3_add_projc_mix(r, p, q);
-#else /* General addition. */
- fp3_t t0, t1, t2, t3, t4, t5, t6;
-
- fp3_null(t0);
- fp3_null(t1);
- fp3_null(t2);
- fp3_null(t3);
- fp3_null(t4);
- fp3_null(t5);
- fp3_null(t6);
+TMPL_ADD_JACOB_IMP(ep3, fp3);
- RLC_TRY {
- fp3_new(t0);
- fp3_new(t1);
- fp3_new(t2);
- fp3_new(t3);
- fp3_new(t4);
- fp3_new(t5);
- fp3_new(t6);
-
- if (q->coord == BASIC) {
- ep3_add_projc_mix(r, p, q);
- } else {
- /* t0 = z1^2. */
- fp3_sqr(t0, p->z);
-
- /* t1 = z2^2. */
- fp3_sqr(t1, q->z);
-
- /* t2 = U1 = x1 * z2^2. */
- fp3_mul(t2, p->x, t1);
-
- /* t3 = U2 = x2 * z1^2. */
- fp3_mul(t3, q->x, t0);
-
- /* t6 = z1^2 + z2^2. */
- fp3_add(t6, t0, t1);
-
- /* t0 = S2 = y2 * z1^3. */
- fp3_mul(t0, t0, p->z);
- fp3_mul(t0, t0, q->y);
-
- /* t1 = S1 = y1 * z2^3. */
- fp3_mul(t1, t1, q->z);
- fp3_mul(t1, t1, p->y);
-
- /* t3 = H = U2 - U1. */
- fp3_sub(t3, t3, t2);
-
- /* t0 = R = 2 * (S2 - S1). */
- fp3_sub(t0, t0, t1);
-
- fp3_dbl(t0, t0);
-
- /* If E is zero. */
- if (fp3_is_zero(t3)) {
- if (fp3_is_zero(t0)) {
- /* If I is zero, p = q, should have doubled. */
- ep3_dbl_projc(r, p);
- } else {
- /* If I is not zero, q = -p, r = infinity. */
- ep3_set_infty(r);
- }
- } else {
- /* t4 = I = (2*H)^2. */
- fp3_dbl(t4, t3);
- fp3_sqr(t4, t4);
-
- /* t5 = J = H * I. */
- fp3_mul(t5, t3, t4);
-
- /* t4 = V = U1 * I. */
- fp3_mul(t4, t2, t4);
-
- /* x3 = R^2 - J - 2 * V. */
- fp3_sqr(r->x, t0);
- fp3_sub(r->x, r->x, t5);
- fp3_dbl(t2, t4);
- fp3_sub(r->x, r->x, t2);
-
- /* y3 = R * (V - x3) - 2 * S1 * J. */
- fp3_sub(t4, t4, r->x);
- fp3_mul(t4, t4, t0);
- fp3_mul(t1, t1, t5);
- fp3_dbl(t1, t1);
- fp3_sub(r->y, t4, t1);
-
- /* z3 = ((z1 + z2)^2 - z1^2 - z2^2) * H. */
- fp3_add(r->z, p->z, q->z);
- fp3_sqr(r->z, r->z);
- fp3_sub(r->z, r->z, t6);
- fp3_mul(r->z, r->z, t3);
- }
- }
- r->coord = PROJC;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp3_free(t0);
- fp3_free(t1);
- fp3_free(t2);
- fp3_free(t3);
- fp3_free(t4);
- fp3_free(t5);
- fp3_free(t6);
- }
-#endif
-}
-
-#endif /* EP_ADD == PROJC */
+#endif /* EP_ADD == JACOB */
/*============================================================================*/
/* Public definitions */
@@ -385,7 +136,7 @@ void ep3_add_slp_basic(ep3_t r, fp3_t s, const ep3_t p, const ep3_t q) {
#endif
-#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
+#if EP_ADD == PROJC || !defined(STRIP)
void ep3_add_projc(ep3_t r, const ep3_t p, const ep3_t q) {
if (ep3_is_infty(p)) {
@@ -398,13 +149,25 @@ void ep3_add_projc(ep3_t r, const ep3_t p, const ep3_t q) {
return;
}
- if (p == q) {
- /* TODO: This is a quick hack. Should we fix this? */
- ep3_dbl(r, p);
+ ep3_add_projc_imp(r, p, q);
+}
+
+#endif
+
+#if EP_ADD == JACOB || !defined(STRIP)
+
+void ep3_add_jacob(ep3_t r, const ep3_t p, const ep3_t q) {
+ if (ep3_is_infty(p)) {
+ ep3_copy(r, q);
return;
}
- ep3_add_projc_imp(r, p, q);
+ if (ep3_is_infty(q)) {
+ ep3_copy(r, p);
+ return;
+ }
+
+ ep3_add_jacob_imp(r, p, q);
}
#endif
@@ -421,7 +184,6 @@ void ep3_sub(ep3_t r, const ep3_t p, const ep3_t q) {
RLC_TRY {
ep3_new(t);
-
ep3_neg(t, q);
ep3_add(r, p, t);
}
diff --git a/src/epx/relic_ep3_cmp.c b/src/epx/relic_ep3_cmp.c
index 265a65c98..10078af81 100644
--- a/src/epx/relic_ep3_cmp.c
+++ b/src/epx/relic_ep3_cmp.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of utilities for prime elliptic curves over quadratic
- * extensions.
+ * Implementation of utilities for prime elliptic curves over a cubic
+ * extension field.
*
* @ingroup epx
*/
@@ -37,46 +37,68 @@
/*============================================================================*/
int ep3_cmp(const ep3_t p, const ep3_t q) {
- ep3_t r, s;
- int result = RLC_NE;
+ ep3_t r, s;
+ int result = RLC_NE;
if (ep3_is_infty(p) && ep3_is_infty(q)) {
return RLC_EQ;
}
- ep3_null(r);
- ep3_null(s);
+ ep3_null(r);
+ ep3_null(s);
- RLC_TRY {
- ep3_new(r);
- ep3_new(s);
+ RLC_TRY {
+ ep3_new(r);
+ ep3_new(s);
- if ((p->coord != BASIC) && (q->coord != BASIC)) {
- /* If the two points are not normalized, it is faster to compare
- * x1 * z2^2 == x2 * z1^2 and y1 * z2^3 == y2 * z1^3. */
- fp3_sqr(r->z, p->z);
- fp3_sqr(s->z, q->z);
- fp3_mul(r->x, p->x, s->z);
- fp3_mul(s->x, q->x, r->z);
- fp3_mul(r->z, r->z, p->z);
- fp3_mul(s->z, s->z, q->z);
- fp3_mul(r->y, p->y, s->z);
- fp3_mul(s->y, q->y, r->z);
- } else {
- ep3_norm(r, p);
- ep3_norm(s, q);
- }
+ switch (q->coord) {
+ case PROJC:
+ /* If q is in homogeneous projective coordinates, compute
+ * x1 * z2 and y1 * z2. */
+ fp3_mul(r->x, p->x, q->z);
+ fp3_mul(r->y, p->y, q->z);
+ break;
+ case JACOB:
+ /* If q is in Jacobian projective coordinates, compute
+ * x2 * z1^2 and y2 * z1^3. */
+ fp3_sqr(r->z, q->z);
+ fp3_mul(r->x, p->x, r->z);
+ fp3_mul(r->z, r->z, q->z);
+ fp3_mul(r->y, p->y, r->z);
+ break;
+ default:
+ ep3_copy(r, p);
+ break;
+ }
- if ((fp3_cmp(r->x, s->x) == RLC_EQ) &&
- (fp3_cmp(r->y, s->y) == RLC_EQ)) {
- result = RLC_EQ;
- }
- } RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- } RLC_FINALLY {
- ep3_free(r);
- ep3_free(s);
- }
+ switch (p->coord) {
+ /* Now do the same for the other point. */
+ case PROJC:
+ fp3_mul(s->x, q->x, p->z);
+ fp3_mul(s->y, q->y, p->z);
+ break;
+ case JACOB:
+ fp3_sqr(s->z, p->z);
+ fp3_mul(s->x, q->x, s->z);
+ fp3_mul(s->z, s->z, p->z);
+ fp3_mul(s->y, q->y, s->z);
+ break;
+ default:
+ ep3_copy(s, q);
+ break;
+ }
- return result;
+ if ((fp3_cmp(r->x, s->x) == RLC_EQ) && (fp3_cmp(r->y, s->y) == RLC_EQ)) {
+ result = RLC_EQ;
+ }
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ ep3_free(r);
+ ep3_free(s);
+ }
+
+ return result;
}
diff --git a/src/epx/relic_ep3_curve.c b/src/epx/relic_ep3_curve.c
index 8bb97eff3..ff9ba52a1 100644
--- a/src/epx/relic_ep3_curve.c
+++ b/src/epx/relic_ep3_curve.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of configuration of prime elliptic curves over quartic
- * extensions.
+ * Implementation of configuration of prime elliptic curves over a cubic
+ * extension field.
*
* @ingroup epx
*/
@@ -241,6 +241,49 @@ int ep3_curve_opt_b(void) {
return core_get()->ep3_opt_b;
}
+void ep3_curve_mul_a(fp3_t c, const fp3_t a) {
+ ctx_t *ctx = core_get();
+ switch (ctx->ep3_opt_a) {
+ case RLC_ZERO:
+ fp3_zero(c);
+ break;
+ case RLC_ONE:
+ fp3_copy(c, a);
+ break;
+ case RLC_TWO:
+ fp3_dbl(c, a);
+ break;
+#if FP_RDC != MONTY
+ case RLC_TINY:
+ fp3_mul_dig(c, a, ctx->ep3_a[0]);
+ break;
+#endif
+ default:
+ fp3_mul(c, a, ctx->ep3_a);
+ break;
+ }
+}
+
+void ep3_curve_mul_b(fp3_t c, const fp3_t a) {
+ ctx_t *ctx = core_get();
+ switch (ctx->ep3_opt_b) {
+ case RLC_ZERO:
+ fp3_zero(c);
+ break;
+ case RLC_ONE:
+ fp3_copy(c, a);
+ break;
+#if FP_RDC != MONTY
+ case RLC_TINY:
+ fp3_mul_dig(c, a, ctx->ep3_b[0]);
+ break;
+#endif
+ default:
+ fp3_mul(c, a, ctx->ep3_b);
+ break;
+ }
+}
+
int ep3_curve_is_twist(void) {
return core_get()->ep3_is_twist;
}
@@ -249,12 +292,12 @@ void ep3_curve_get_gen(ep3_t g) {
ep3_copy(g, core_get()->ep3_g);
}
-void ep3_curve_get_a(fp3_t a) {
- fp3_copy(a, core_get()->ep3_a);
+fp_t *ep3_curve_get_a(void) {
+ return core_get()->ep3_a;
}
-void ep3_curve_get_b(fp3_t b) {
- fp3_copy(b, core_get()->ep3_b);
+fp_t *ep3_curve_get_b(void) {
+ return core_get()->ep3_b;
}
void ep3_curve_get_ord(bn_t n) {
diff --git a/src/epx/relic_ep3_dbl.c b/src/epx/relic_ep3_dbl.c
index 27b09b10c..fa4da39b6 100644
--- a/src/epx/relic_ep3_dbl.c
+++ b/src/epx/relic_ep3_dbl.c
@@ -24,13 +24,14 @@
/**
* @file
*
- * Implementation of doubling on elliptic prime curves over quartic
- * extensions.
+ * Implementation of doubling on elliptic prime curves over a cubic extension
+ * field.
*
* @ingroup epx
*/
#include "relic_core.h"
+#include "relic_ep_dbl_tmpl.h"
/*============================================================================*/
/* Private definitions */
@@ -43,201 +44,41 @@
* elliptic curve.
*
* @param[out] r - the result.
- * @param[out] s - the resulting slope.
+ * @param[out] s - the slope.
* @param[in] p - the point to double.
*/
-static void ep3_dbl_basic_imp(ep3_t r, fp3_t s, const ep3_t p) {
- fp3_t t0, t1, t2;
-
- fp3_null(t0);
- fp3_null(t1);
- fp3_null(t2);
-
- RLC_TRY {
- fp3_new(t0);
- fp3_new(t1);
- fp3_new(t2);
-
- /* t0 = 1/(2 * y1). */
- fp3_dbl(t0, p->y);
- fp3_inv(t0, t0);
-
- /* t1 = 3 * x1^2 + a. */
- fp3_sqr(t1, p->x);
- fp3_copy(t2, t1);
- fp3_dbl(t1, t1);
- fp3_add(t1, t1, t2);
-
- ep3_curve_get_a(t2);
- fp3_add(t1, t1, t2);
-
- /* t1 = (3 * x1^2 + a)/(2 * y1). */
- fp3_mul(t1, t1, t0);
-
- if (s != NULL) {
- fp3_copy(s, t1);
- }
-
- /* t2 = t1^2. */
- fp3_sqr(t2, t1);
-
- /* x3 = t1^2 - 2 * x1. */
- fp3_dbl(t0, p->x);
- fp3_sub(t0, t2, t0);
-
- /* y3 = t1 * (x1 - x3) - y1. */
- fp3_sub(t2, p->x, t0);
- fp3_mul(t1, t1, t2);
-
- fp3_sub(r->y, t1, p->y);
-
- fp3_copy(r->x, t0);
- fp3_copy(r->z, p->z);
-
- r->coord = BASIC;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp3_free(t0);
- fp3_free(t1);
- fp3_free(t2);
- }
-}
+TMPL_DBL_BASIC_IMP(ep3, fp3);
#endif /* EP_ADD == BASIC */
-#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
+#if EP_ADD == PROJC || !defined(STRIP)
/**
- * Doubles a point represented in affine coordinates on an ordinary prime
+ * Doubles a point represented in projective coordinates on an ordinary prime
* elliptic curve.
*
- * @param[out] r - the result.
- * @param[in] p - the point to double.
+ * @param r - the result.
+ * @param p - the point to double.
*/
-static void ep3_dbl_projc_imp(ep3_t r, const ep3_t p) {
- fp3_t t0, t1, t2, t3, t4, t5;
-
- fp3_null(t0);
- fp3_null(t1);
- fp3_null(t2);
- fp3_null(t3);
- fp3_null(t4);
- fp3_null(t5);
-
- RLC_TRY {
- fp3_new(t0);
- fp3_new(t1);
- fp3_new(t2);
- fp3_new(t3);
- fp3_new(t4);
- fp3_new(t5);
-
- if (ep_curve_opt_a() == RLC_ZERO) {
- fp3_sqr(t0, p->x);
- fp3_add(t2, t0, t0);
- fp3_add(t0, t2, t0);
-
- fp3_sqr(t3, p->y);
- fp3_mul(t1, t3, p->x);
- fp3_add(t1, t1, t1);
- fp3_add(t1, t1, t1);
- fp3_sqr(r->x, t0);
- fp3_add(t2, t1, t1);
- fp3_sub(r->x, r->x, t2);
- fp3_mul(r->z, p->z, p->y);
- fp3_add(r->z, r->z, r->z);
- fp3_add(t3, t3, t3);
-
- fp3_sqr(t3, t3);
- fp3_add(t3, t3, t3);
- fp3_sub(t1, t1, r->x);
- fp3_mul(r->y, t0, t1);
- fp3_sub(r->y, r->y, t3);
- } else {
- /* dbl-2007-bl formulas: 1M + 8S + 1*a + 10add + 1*8 + 2*2 + 1*3 */
- /* http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-2007-bl */
-
- /* t0 = x1^2, t1 = y1^2, t2 = y1^4. */
- fp3_sqr(t0, p->x);
- fp3_sqr(t1, p->y);
- fp3_sqr(t2, t1);
-
- if (p->coord != BASIC) {
- /* t3 = z1^2. */
- fp3_sqr(t3, p->z);
+TMPL_DBL_PROJC_IMP(ep3, fp3);
- if (ep_curve_get_a() == RLC_ZERO) {
- /* z3 = 2 * y1 * z1. */
- fp3_mul(r->z, p->y, p->z);
- fp3_dbl(r->z, r->z);
- } else {
- /* z3 = (y1 + z1)^2 - y1^2 - z1^2. */
- fp3_add(r->z, p->y, p->z);
- fp3_sqr(r->z, r->z);
- fp3_sub(r->z, r->z, t1);
- fp3_sub(r->z, r->z, t3);
- }
- } else {
- /* z3 = 2 * y1. */
- fp3_dbl(r->z, p->y);
- }
-
- /* t4 = S = 2*((x1 + y1^2)^2 - x1^2 - y1^4). */
- fp3_add(t4, p->x, t1);
- fp3_sqr(t4, t4);
- fp3_sub(t4, t4, t0);
- fp3_sub(t4, t4, t2);
- fp3_dbl(t4, t4);
-
- /* t5 = M = 3 * x1^2 + a * z1^4. */
- fp3_dbl(t5, t0);
- fp3_add(t5, t5, t0);
- if (p->coord != BASIC) {
- fp3_sqr(t3, t3);
- ep3_curve_get_a(t1);
- fp3_mul(t1, t3, t1);
- fp3_add(t5, t5, t1);
- } else {
- ep3_curve_get_a(t1);
- fp3_add(t5, t5, t1);
- }
-
- /* x3 = T = M^2 - 2 * S. */
- fp3_sqr(r->x, t5);
- fp3_dbl(t1, t4);
- fp3_sub(r->x, r->x, t1);
+#endif /* EP_ADD == PROJC */
- /* y3 = M * (S - T) - 8 * y1^4. */
- fp3_dbl(t2, t2);
- fp3_dbl(t2, t2);
- fp3_dbl(t2, t2);
- fp3_sub(t4, t4, r->x);
- fp3_mul(t5, t5, t4);
- fp3_sub(r->y, t5, t2);
- }
+#if EP_ADD == JACOB || !defined(STRIP)
- r->coord = PROJC;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp3_free(t0);
- fp3_free(t1);
- fp3_free(t2);
- fp3_free(t3);
- fp3_free(t4);
- fp3_free(t5);
- }
-}
+/**
+ * Doubles a point represented in Jacobian coordinates on an ordinary prime
+ * elliptic curve.
+ *
+ * @param r - the result.
+ * @param p - the point to double.
+ */
+TMPL_DBL_JACOB_IMP(ep3, fp3);
-#endif /* EP_ADD == PROJC */
+#endif /* EP_ADD == JACOB */
/*============================================================================*/
- /* Public definitions */
+/* Public definitions */
/*============================================================================*/
#if EP_ADD == BASIC || !defined(STRIP)
@@ -247,7 +88,6 @@ void ep3_dbl_basic(ep3_t r, const ep3_t p) {
ep3_set_infty(r);
return;
}
-
ep3_dbl_basic_imp(r, NULL, p);
}
@@ -262,7 +102,7 @@ void ep3_dbl_slp_basic(ep3_t r, fp3_t s, const ep3_t p) {
#endif
-#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
+#if EP_ADD == PROJC || !defined(STRIP)
void ep3_dbl_projc(ep3_t r, const ep3_t p) {
if (ep3_is_infty(p)) {
@@ -274,3 +114,16 @@ void ep3_dbl_projc(ep3_t r, const ep3_t p) {
}
#endif
+
+#if EP_ADD == JACOB || !defined(STRIP)
+
+void ep3_dbl_jacob(ep3_t r, const ep3_t p) {
+ if (ep3_is_infty(p)) {
+ ep3_set_infty(r);
+ return;
+ }
+
+ ep3_dbl_jacob_imp(r, p);
+}
+
+#endif
diff --git a/src/epx/relic_ep3_frb.c b/src/epx/relic_ep3_frb.c
index 1384425f1..ecff8a278 100644
--- a/src/epx/relic_ep3_frb.c
+++ b/src/epx/relic_ep3_frb.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of frobenius action on prime elliptic curves over
- * quadratic extensions.
+ * Implementation of frobenius action on prime elliptic curves over a cubic
+ * extension field.
*
* @ingroup epx
*/
diff --git a/src/epx/relic_ep3_map.c b/src/epx/relic_ep3_map.c
index 8550ea179..29388c842 100644
--- a/src/epx/relic_ep3_map.c
+++ b/src/epx/relic_ep3_map.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of hashing to a prime elliptic curve over a quadratic
- * extension.
+ * Implementation of hashing to a prime elliptic curve over a cubic extension
+ * field.
*
* @ingroup epx
*/
@@ -115,29 +115,17 @@ void ep3_map(ep3_t p, const uint8_t *msg, size_t len) {
fp3_sqr(z1, z1);
fp3_add(z1, z1, u);
- ep3_curve_get_b(w);
-
- fp3_sqr(t, x1);
- fp3_mul(t, t, x1);
- fp3_add(t, t, w);
-
- fp3_sqr(u, y1);
- fp3_mul(u, u, y1);
- fp3_add(u, u, w);
-
- fp3_sqr(v, z1);
- fp3_mul(v, v, z1);
- fp3_add(v, v, w);
+ ep3_rhs(t, x1);
+ ep3_rhs(u, y1);
+ ep3_rhs(v, z1);
c2 = fp3_is_sqr(u);
c3 = fp3_is_sqr(v);
- for (int i = 0; i < 3; i++) {
- dv_swap_cond(x1[i], y1[i], RLC_FP_DIGS, c2);
- dv_swap_cond(t[i], u[i], RLC_FP_DIGS, c2);
- dv_swap_cond(x1[i], z1[i], RLC_FP_DIGS, c3);
- dv_swap_cond(t[i], v[i], RLC_FP_DIGS, c3);
- }
+ fp3_copy_sec(t, u, c2);
+ fp3_copy_sec(x1, y1, c2);
+ fp3_copy_sec(t, v, c3);
+ fp3_copy_sec(x1, z1, c3);
if (!fp3_srt(t, t)) {
RLC_THROW(ERR_NO_VALID);
@@ -156,9 +144,7 @@ void ep3_map(ep3_t p, const uint8_t *msg, size_t len) {
sign ^= (t0 | (t0z & (t1 | (t1z & t2))));
fp3_neg(u, t);
- dv_swap_cond(t[0], u[0], RLC_FP_DIGS, sign);
- dv_swap_cond(t[1], u[1], RLC_FP_DIGS, sign);
- dv_swap_cond(t[2], u[2], RLC_FP_DIGS, sign);
+ fp3_copy_sec(t, u, sign);
fp3_copy(p->x, x1);
fp3_copy(p->y, t);
diff --git a/src/epx/relic_ep3_mul.c b/src/epx/relic_ep3_mul.c
index 4ea09a1ee..a814664fb 100644
--- a/src/epx/relic_ep3_mul.c
+++ b/src/epx/relic_ep3_mul.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of point multiplication on prime elliptic curves over
- * quadratic extensions.
+ * Implementation of point multiplication on prime elliptic curves over a
+ * cubic extensions.
*
* @ingroup epx
*/
@@ -36,8 +36,6 @@
/* Private definitions */
/*============================================================================*/
-#if EP_MUL == LWNAF || !defined(STRIP)
-
#if defined(EP_ENDOM)
static void ep3_psi(ep3_t r, const ep3_t p) {
@@ -85,6 +83,8 @@ static void ep3_psi(ep3_t r, const ep3_t p) {
}
}
+#if EP_MUL == LWNAF || !defined(STRIP)
+
static void ep3_mul_glv_imp(ep3_t r, const ep3_t p, const bn_t k) {
int i, j;
size_t l, _l[6];
@@ -165,10 +165,133 @@ static void ep3_mul_glv_imp(ep3_t r, const ep3_t p, const bn_t k) {
}
}
+#endif /* EP_MUL == LWNAF */
+
+#if EP_MUL == LWREG || !defined(STRIP)
+
+static void ep3_mul_reg_gls(ep3_t r, const ep3_t p, const bn_t k) {
+ int8_t reg[6][RLC_FP_BITS + 1], b[6], s[6], c0, n0;
+ ep3_t q, w, t[6][1 << (RLC_WIDTH - 2)];
+ bn_t n, _k[6], u;
+ size_t l, len, _l[6];
+
+ bn_null(n);
+ bn_null(u);
+ ep3_null(q);
+ ep3_null(w);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(u);
+ ep3_new(q);
+ ep3_new(w);
+ for (size_t i = 0; i < 6; i++) {
+ bn_null(_k[i]);
+ bn_new(_k[i]);
+ for (size_t j = 0; j < (1 << (RLC_WIDTH - 2)); j++) {
+ ep3_null(t[i][j]);
+ ep3_new(t[i][j]);
+ }
+ }
+
+ ep3_curve_get_ord(n);
+ fp_prime_get_par(u);
+ bn_mod(_k[0], k, n);
+ bn_rec_frb(_k, 6, _k[0], u, n, ep_curve_is_pairf() == EP_BN);
+
+ l = 0;
+ /* Make some extra room for BN curves that grow subscalars by 1. */
+ len = bn_bits(u) + (ep_curve_is_pairf() == EP_BN);
+ ep3_norm(t[0][0], p);
+ for (size_t i = 0; i < 6; i++) {
+ s[i] = bn_sign(_k[i]);
+ bn_abs(_k[i], _k[i]);
+ b[i] = bn_is_even(_k[i]);
+ _k[i]->dp[0] |= b[i];
+
+ _l[i] = RLC_FP_BITS + 1;
+ bn_rec_reg(reg[i], &_l[i], _k[i], len, RLC_WIDTH);
+ l = RLC_MAX(l, _l[i]);
+
+ /* Apply Frobenius before flipping sign to build table. */
+ if (i > 0) {
+ ep3_psi(t[i][0], t[i - 1][0]);
+ }
+ }
+
+ for (size_t i = 0; i < 6; i++) {
+ ep3_neg(q, t[i][0]);
+ fp3_copy_sec(q->y, t[i][0]->y, s[i] == RLC_POS);
+ ep3_tab(t[i], q, RLC_WIDTH);
+ }
+
+#if defined(EP_MIXED)
+ fp3_set_dig(w->z, 1);
+ w->coord = BASIC;
+#else
+ w->coord = = EP_ADD;
+#endif
+
+ ep3_set_infty(r);
+ for (int j = l - 1; j >= 0; j--) {
+ for (size_t i = 0; i < RLC_WIDTH - 1; i++) {
+ ep3_dbl(r, r);
+ }
+
+ for (size_t i = 0; i < 6; i++) {
+ n0 = reg[i][j];
+ c0 = (n0 >> 7);
+ n0 = ((n0 ^ c0) - c0) >> 1;
+
+ for (size_t m = 0; m < (1 << (RLC_WIDTH - 2)); m++) {
+ fp3_copy_sec(w->x, t[i][m]->x, m == n0);
+ fp3_copy_sec(w->y, t[i][m]->y, m == n0);
+ #if !defined(EP_MIXED)
+ fp3_copy_sec(w->z, t[i][m]->z, m == n0);
+ #endif
+ }
+
+ ep3_neg(q, w);
+ fp3_copy_sec(q->y, w->y, c0 == 0);
+ ep3_add(r, r, q);
+ }
+ }
+
+ for (size_t i = 0; i < 6; i++) {
+ /* Tables are built with points already negated, so no need here. */
+ ep3_sub(q, r, t[i][0]);
+ fp3_copy_sec(r->x, q->x, b[i]);
+ fp3_copy_sec(r->y, q->y, b[i]);
+ fp3_copy_sec(r->z, q->z, b[i]);
+ }
+
+ /* Convert r to affine coordinates. */
+ ep3_norm(r, r);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ bn_free(u);
+ ep3_free(q);
+ ep3_free(w);
+ for (int i = 0; i < 6; i++) {
+ bn_free(_k[i]);
+ for (size_t j = 0; j < (1 << (RLC_WIDTH - 2)); j++) {
+ ep3_free(t[i][j]);
+ }
+ }
+ }
+}
+
+#endif /* EP_MUL == LWREG */
#endif /* EP_ENDOM */
#if defined(EP_PLAIN) || defined(EP_SUPER)
+#if EP_MUL == LWNAF || !defined(STRIP)
+
static void ep3_mul_naf_imp(ep3_t r, const ep3_t p, const bn_t k) {
int i, n;
int8_t naf[RLC_FP_BITS + 1];
@@ -217,9 +340,95 @@ static void ep3_mul_naf_imp(ep3_t r, const ep3_t p, const bn_t k) {
}
}
-#endif /* EP_PLAIN || EP_SUPER */
#endif /* EP_MUL == LWNAF */
+#if EP_MUL == LWREG || !defined(STRIP)
+
+static void ep3_mul_reg_imp(ep3_t r, const ep3_t p, const bn_t k) {
+ bn_t _k;
+ int8_t s, reg[1 + RLC_CEIL(RLC_FP_BITS + 1, RLC_WIDTH - 1)];
+ ep3_t t[1 << (RLC_WIDTH - 2)], u, v;
+ size_t l, n;
+
+ bn_null(_k);
+
+ RLC_TRY {
+ bn_new(_k);
+ ep3_new(u);
+ ep3_new(v);
+ /* Prepare the precomputation table. */
+ for (size_t i = 0; i < (1 << (RLC_WIDTH - 2)); i++) {
+ ep3_null(t[i]);
+ ep3_new(t[i]);
+ }
+ /* Compute the precomputation table. */
+ ep3_tab(t, p, RLC_WIDTH);
+
+ ep3_curve_get_ord(_k);
+ n = bn_bits(_k);
+
+ /* Make a copy of the scalar for processing. */
+ bn_abs(_k, k);
+ _k->dp[0] |= 1;
+
+ /* Compute the regular w-NAF representation of k. */
+ l = RLC_CEIL(n, RLC_WIDTH - 1) + 1;
+ bn_rec_reg(reg, &l, _k, n, RLC_WIDTH);
+
+#if defined(EP_MIXED)
+ fp3_set_dig(u->z, 1);
+ u->coord = BASIC;
+#else
+ u->coord = EP_ADD;
+#endif
+ ep3_set_infty(r);
+ for (int i = l - 1; i >= 0; i--) {
+ for (size_t j = 0; j < RLC_WIDTH - 1; j++) {
+ ep3_dbl(r, r);
+ }
+
+ n = reg[i];
+ s = (n >> 7);
+ n = ((n ^ s) - s) >> 1;
+
+ for (size_t j = 0; j < (1 << (RLC_WIDTH - 2)); j++) {
+ fp3_copy_sec(u->x, t[j]->x, j == n);
+ fp3_copy_sec(u->y, t[j]->y, j == n);
+#if !defined(EP_MIXED)
+ fp_copy_sec(u->z, t[j]->z, j == n);
+#endif
+ }
+ ep3_neg(v, u);
+ fp3_copy_sec(u->y, v->y, s != 0);
+ ep3_add(r, r, u);
+ }
+ /* t[0] has an unmodified copy of p. */
+ ep3_sub(u, r, t[0]);
+ fp3_copy_sec(r->x, u->x, bn_is_even(k));
+ fp3_copy_sec(r->y, u->y, bn_is_even(k));
+ fp3_copy_sec(r->z, u->z, bn_is_even(k));
+ /* Convert r to affine coordinates. */
+ ep3_norm(r, r);
+ ep3_neg(u, r);
+ fp3_copy_sec(r->y, u->y, bn_sign(k) == RLC_NEG);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ /* Free the precomputation table. */
+ for (size_t i = 0; i < (1 << (RLC_WIDTH - 2)); i++) {
+ ep3_free(t[i]);
+ }
+ bn_free(_k);
+ ep3_free(u);
+ ep3_free(v);
+ }
+}
+
+#endif /* EP_MUL == LWREG */
+#endif /* EP_PLAIN || EP_SUPER */
+
/*============================================================================*/
/* Public definitions */
/*============================================================================*/
@@ -383,7 +592,7 @@ void ep3_mul_monty(ep3_t r, const ep3_t p, const bn_t k) {
bn_abs(l, _k);
bn_add(l, l, n);
bn_add(n, l, n);
- dv_swap_cond(l->dp, n->dp, RLC_MAX(l->used, n->used),
+ dv_swap_sec(l->dp, n->dp, RLC_MAX(l->used, n->used),
bn_get_bit(l, bits) == 0);
l->used = RLC_SEL(l->used, n->used, bn_get_bit(l, bits) == 0);
@@ -396,26 +605,26 @@ void ep3_mul_monty(ep3_t r, const ep3_t p, const bn_t k) {
for (int i = bits - 1; i >= 0; i--) {
int j = bn_get_bit(l, i);
- dv_swap_cond(t[0]->x[0], t[1]->x[0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->x[1], t[1]->x[1], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->x[2], t[1]->x[2], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y[0], t[1]->y[0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y[1], t[1]->y[1], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y[2], t[1]->y[2], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z[0], t[1]->z[0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z[1], t[1]->z[1], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z[2], t[1]->z[2], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x[0], t[1]->x[0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x[1], t[1]->x[1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x[2], t[1]->x[2], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y[0], t[1]->y[0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y[1], t[1]->y[1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y[2], t[1]->y[2], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z[0], t[1]->z[0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z[1], t[1]->z[1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z[2], t[1]->z[2], RLC_FP_DIGS, j ^ 1);
ep3_add(t[0], t[0], t[1]);
ep3_dbl(t[1], t[1]);
- dv_swap_cond(t[0]->x[0], t[1]->x[0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->x[1], t[1]->x[1], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->x[2], t[1]->x[2], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y[0], t[1]->y[0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y[1], t[1]->y[1], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y[2], t[1]->y[2], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z[0], t[1]->z[0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z[1], t[1]->z[1], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z[2], t[1]->z[2], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x[0], t[1]->x[0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x[1], t[1]->x[1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x[2], t[1]->x[2], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y[0], t[1]->y[0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y[1], t[1]->y[1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y[2], t[1]->y[2], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z[0], t[1]->z[0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z[1], t[1]->z[1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z[2], t[1]->z[2], RLC_FP_DIGS, j ^ 1);
}
ep3_norm(r, t[0]);
@@ -455,6 +664,28 @@ void ep3_mul_lwnaf(ep3_t r, const ep3_t p, const bn_t k) {
#endif
+#if EP_MUL == LWREG || !defined(STRIP)
+
+void ep3_mul_lwreg(ep3_t r, const ep3_t p, const bn_t k) {
+ if (bn_is_zero(k) || ep3_is_infty(p)) {
+ ep3_set_infty(r);
+ return;
+ }
+
+#if defined(EP_ENDOM)
+ if (ep_curve_is_endom()) {
+ ep3_mul_reg_gls(r, p, k);
+ return;
+ }
+#endif
+
+#if defined(EP_PLAIN) || defined(EP_SUPER)
+ ep3_mul_reg_imp(r, p, k);
+#endif
+}
+
+#endif
+
void ep3_mul_gen(ep3_t r, const bn_t k) {
if (bn_is_zero(k)) {
ep3_set_infty(r);
diff --git a/src/epx/relic_ep3_mul_cof.c b/src/epx/relic_ep3_mul_cof.c
index a0deca806..8314a44c7 100644
--- a/src/epx/relic_ep3_mul_cof.c
+++ b/src/epx/relic_ep3_mul_cof.c
@@ -25,14 +25,13 @@
* @file
*
* Implementation of point multiplication of a prime elliptic curve over a
- * quadratic extension by the curve cofactor.
+ * cubic extension field by the curve cofactor.
*
* @ingroup epx
*/
#include "relic_core.h"
#include "relic_md.h"
-#include "relic_tmpl_map.h"
/*============================================================================*/
/* Private definitions */
@@ -318,7 +317,7 @@ void ep3_mul_cof(ep3_t r, const ep3_t p) {
default:
/* Now, multiply by cofactor to get the correct group. */
ep3_curve_get_cof(k);
- ep3_mul_basic(r, p, k);
+ ep3_mul_big(r, p, k);
break;
}
} RLC_CATCH_ANY {
diff --git a/src/epx/relic_ep3_mul_fix.c b/src/epx/relic_ep3_mul_fix.c
index 66276d5a2..efde195e1 100644
--- a/src/epx/relic_ep3_mul_fix.c
+++ b/src/epx/relic_ep3_mul_fix.c
@@ -25,7 +25,7 @@
* @file
*
* Implementation of fixed point multiplication on a prime elliptic curve over
- * a quadratic extension.
+ * a cubic extension field.
*
* @ingroup epx
*/
diff --git a/src/epx/relic_ep3_mul_sim.c b/src/epx/relic_ep3_mul_sim.c
index 408232a57..625948fa4 100644
--- a/src/epx/relic_ep3_mul_sim.c
+++ b/src/epx/relic_ep3_mul_sim.c
@@ -25,7 +25,7 @@
* @file
*
* Implementation of simultaneous point multiplication on a prime elliptic
- * curve over a quartic extension.
+ * curve over a cubic extension field.
*
* @ingroup epx
*/
diff --git a/src/epx/relic_ep3_neg.c b/src/epx/relic_ep3_neg.c
index 1c076cda8..56594da96 100644
--- a/src/epx/relic_ep3_neg.c
+++ b/src/epx/relic_ep3_neg.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of point negation on elliptic prime curves over quadratic
- * extensions.
+ * Implementation of point negation on elliptic prime curves over a cubic
+ * extension field.
*
* @ingroup epx
*/
diff --git a/src/epx/relic_ep3_norm.c b/src/epx/relic_ep3_norm.c
index 0015c2711..5f8b853e6 100644
--- a/src/epx/relic_ep3_norm.c
+++ b/src/epx/relic_ep3_norm.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of point normalization on prime elliptic curves over quadratic
- * extensions.
+ * Implementation of point normalization on prime elliptic curves over a cubic
+ * extension field.
*
* @ingroup epx
*/
@@ -43,36 +43,45 @@
*
* @param r - the result.
* @param p - the point to normalize.
+ * @param inv - the flag to indicate if z is already inverted.
*/
-static void ep3_norm_imp(ep3_t r, const ep3_t p, int inverted) {
+static void ep3_norm_imp(ep3_t r, const ep3_t p, int inv) {
if (p->coord != BASIC) {
- fp3_t t0, t1;
+ fp3_t t;
- fp3_null(t0);
- fp3_null(t1);
+ fp3_null(t);
RLC_TRY {
+ fp3_new(t);
- fp3_new(t0);
- fp3_new(t1);
-
- if (inverted) {
- fp3_copy(t1, p->z);
+ if (inv) {
+ fp3_copy(r->z, p->z);
} else {
- fp3_inv(t1, p->z);
+ fp3_inv(r->z, p->z);
+ }
+
+ switch (p->coord) {
+ case PROJC:
+ fp3_mul(r->x, p->x, r->z);
+ fp3_mul(r->y, p->y, r->z);
+ break;
+ case JACOB:
+ fp3_sqr(t, r->z);
+ fp3_mul(r->x, p->x, t);
+ fp3_mul(t, t, r->z);
+ fp3_mul(r->y, p->y, t);
+ break;
+ default:
+ ep3_copy(r, p);
+ break;
}
- fp3_sqr(t0, t1);
- fp3_mul(r->x, p->x, t0);
- fp3_mul(t0, t0, t1);
- fp3_mul(r->y, p->y, t0);
fp3_set_dig(r->z, 1);
}
RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
}
RLC_FINALLY {
- fp3_free(t0);
- fp3_free(t1);
+ fp3_free(t);
}
}
@@ -92,17 +101,18 @@ void ep3_norm(ep3_t r, const ep3_t p) {
}
if (p->coord == BASIC) {
- /* If the point is represented in affine coordinates, we just copy it. */
+ /* If the point is represented in affine coordinates, just copy it. */
ep3_copy(r, p);
+ return;
}
#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
ep3_norm_imp(r, p, 0);
-#endif
+#endif /* EP_ADD == PROJC */
}
void ep3_norm_sim(ep3_t *r, const ep3_t *t, int n) {
int i;
- fp3_t *a = RLC_ALLOCA(fp3_t, n);
+ fp3_t* a = RLC_ALLOCA(fp3_t, n);
RLC_TRY {
if (a == NULL) {
@@ -114,18 +124,20 @@ void ep3_norm_sim(ep3_t *r, const ep3_t *t, int n) {
fp3_copy(a[i], t[i]->z);
}
- fp3_inv_sim(a, a, n);
+ fp3_inv_sim(a, (const fp3_t *)a, n);
for (i = 0; i < n; i++) {
fp3_copy(r[i]->x, t[i]->x);
fp3_copy(r[i]->y, t[i]->y);
- fp3_copy(r[i]->z, a[i]);
+ if (!ep3_is_infty(t[i])) {
+ fp3_copy(r[i]->z, a[i]);
+ }
}
#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
for (i = 0; i < n; i++) {
ep3_norm_imp(r[i], r[i], 1);
}
-#endif
+#endif /* EP_ADD == PROJC */
}
RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
diff --git a/src/epx/relic_ep3_util.c b/src/epx/relic_ep3_util.c
index ec7129aeb..a3b9676b2 100644
--- a/src/epx/relic_ep3_util.c
+++ b/src/epx/relic_ep3_util.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of comparison for points on prime elliptic curves over
- * quartic extensions.
+ * Implementation of comparison for points on prime elliptic curves over a
+ * cubic extension field.
*
* @ingroup epx
*/
@@ -89,13 +89,18 @@ void ep3_blind(ep3_t r, const ep3_t p) {
#if EP_ADD == BASIC
(void)rand;
ep3_copy(r, p);
-#else
+#elif EP_ADD == PROJC
+ fp3_mul(r->x, p->x, rand);
+ fp3_mul(r->y, p->y, rand);
+ fp3_mul(r->z, p->z, rand);
+ r->coord = PROJC;
+#elif EP_ADD == JACOB
fp3_mul(r->z, p->z, rand);
fp3_mul(r->y, p->y, rand);
fp3_sqr(rand, rand);
fp3_mul(r->x, r->x, rand);
fp3_mul(r->y, r->y, rand);
- r->coord = EP_ADD;
+ r->coord = JACOB;
#endif
} RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
@@ -104,17 +109,15 @@ void ep3_blind(ep3_t r, const ep3_t p) {
}
}
-void ep3_rhs(fp3_t rhs, const ep3_t p) {
- fp3_t t0, t1;
+void ep3_rhs(fp3_t rhs, const fp3_t x) {
+ fp3_t t0;
fp3_null(t0);
- fp3_null(t1);
RLC_TRY {
fp3_new(t0);
- fp3_new(t1);
- fp3_sqr(t0, p->x); /* x1^2 */
+ fp3_sqr(t0, x); /* x1^2 */
switch (ep3_curve_opt_a()) {
case RLC_ZERO:
@@ -130,17 +133,15 @@ void ep3_rhs(fp3_t rhs, const ep3_t p) {
fp_add_dig(t0[0], t0[0], 2);
break;
case RLC_TINY:
- ep3_curve_get_a(t1);
- fp3_mul_dig(t0, t0, t1[0][0]);
+ fp3_mul_dig(t0, t0, ep3_curve_get_a()[0][0]);
break;
#endif
default:
- ep3_curve_get_a(t1);
- fp3_add(t0, t0, t1);
+ fp3_add(t0, t0, ep3_curve_get_a());
break;
}
- fp3_mul(t0, t0, p->x); /* x1^3 + a * x */
+ fp3_mul(t0, t0, x); /* x1^3 + a * x */
switch (ep3_curve_opt_b()) {
case RLC_ZERO:
@@ -156,13 +157,11 @@ void ep3_rhs(fp3_t rhs, const ep3_t p) {
fp3_add_dig(t0, t0, 2);
break;
case RLC_TINY:
- ep3_curve_get_b(t1);
- fp3_mul_dig(t0, t0, t1[0][0]);
+ fp3_mul_dig(t0, t0, ep3_curve_get_b()[0][0]);
break;
#endif
default:
- ep3_curve_get_b(t1);
- fp3_add(t0, t0, t1);
+ fp3_add(t0, t0, ep3_curve_get_b());
break;
}
@@ -171,11 +170,9 @@ void ep3_rhs(fp3_t rhs, const ep3_t p) {
RLC_THROW(ERR_CAUGHT);
} RLC_FINALLY {
fp3_free(t0);
- fp3_free(t1);
}
}
-
int ep3_on_curve(const ep3_t p) {
ep3_t t;
int r = 0;
@@ -187,7 +184,7 @@ int ep3_on_curve(const ep3_t p) {
ep3_norm(t, p);
- ep3_rhs(t->x, t);
+ ep3_rhs(t->x, t->x);
fp3_sqr(t->y, t->y);
r = (fp3_cmp(t->x, t->y) == RLC_EQ) || ep3_is_infty(p);
diff --git a/src/epx/relic_ep4_add.c b/src/epx/relic_ep4_add.c
index 57fda0cfc..4c9c3ff1e 100644
--- a/src/epx/relic_ep4_add.c
+++ b/src/epx/relic_ep4_add.c
@@ -24,13 +24,14 @@
/**
* @file
*
- * Implementation of addition on prime elliptic curves over quartic
- * extensions.
+ * Implementation of addition on prime elliptic curves over a quartic
+ * extension field.
*
* @ingroup epx
*/
#include "relic_core.h"
+#include "relic_ep_add_tmpl.h"
/*============================================================================*/
/* Private definitions */
@@ -42,312 +43,62 @@
* Adds two points represented in affine coordinates on an ordinary prime
* elliptic curve.
*
- * @param r - the result.
- * @param s - the resulting slope.
- * @param p - the first point to add.
- * @param q - the second point to add.
+ * @param[out] r - the result.
+ * @param[out] s - the slope.
+ * @param[in] p - the first point to add.
+ * @param[in] q - the second point to add.
*/
-static void ep4_add_basic_imp(ep4_t r, fp4_t s, const ep4_t p, const ep4_t q) {
- fp4_t t0, t1, t2;
-
- fp4_null(t0);
- fp4_null(t1);
- fp4_null(t2);
-
- RLC_TRY {
- fp4_new(t0);
- fp4_new(t1);
- fp4_new(t2);
-
- /* t0 = x2 - x1. */
- fp4_sub(t0, q->x, p->x);
- /* t1 = y2 - y1. */
- fp4_sub(t1, q->y, p->y);
-
- /* If t0 is zero. */
- if (fp4_is_zero(t0)) {
- if (fp4_is_zero(t1)) {
- /* If t1 is zero, q = p, should have doubled. */
- ep4_dbl_slp_basic(r, s, p);
- } else {
- /* If t1 is not zero and t0 is zero, q = -p and r = infty. */
- ep4_set_infty(r);
- }
- } else {
- /* t2 = 1/(x2 - x1). */
- fp4_inv(t2, t0);
- /* t2 = lambda = (y2 - y1)/(x2 - x1). */
- fp4_mul(t2, t1, t2);
-
- /* x3 = lambda^2 - x2 - x1. */
- fp4_sqr(t1, t2);
- fp4_sub(t0, t1, p->x);
- fp4_sub(t0, t0, q->x);
-
- /* y3 = lambda * (x1 - x3) - y1. */
- fp4_sub(t1, p->x, t0);
- fp4_mul(t1, t2, t1);
- fp4_sub(r->y, t1, p->y);
-
- fp4_copy(r->x, t0);
- fp4_copy(r->z, p->z);
-
- if (s != NULL) {
- fp4_copy(s, t2);
- }
-
- r->coord = BASIC;
- }
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp4_free(t0);
- fp4_free(t1);
- fp4_free(t2);
- }
-}
+TMPL_ADD_BASIC_IMP(ep4, fp4);
#endif /* EP_ADD == BASIC */
-#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
+#if EP_ADD == PROJC || !defined(STRIP)
-#if defined(EP_MIXED) || !defined(STRIP)
+/**
+ * Adds a point represented in homogeneous coordinates to a point represented in
+ * affine coordinates on an ordinary prime elliptic curve.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the projective point.
+ * @param[in] q - the affine point.
+ */
+TMPL_ADD_PROJC_MIX(ep4, fp4);
/**
- * Adds a point represented in affine coordinates to a point represented in
- * projective coordinates.
+ * Adds two points represented in homogeneous coordinates on an ordinary prime
+ * elliptic curve.
*
- * @param r - the result.
- * @param s - the slope.
- * @param p - the affine point.
- * @param q - the projective point.
+ * @param[out] r - the result.
+ * @param[in] p - the first point to add.
+ * @param[in] q - the second point to add.
*/
-static void ep4_add_projc_mix(ep4_t r, const ep4_t p, const ep4_t q) {
- fp4_t t0, t1, t2, t3, t4, t5, t6;
+TMPL_ADD_PROJC_IMP(ep4, fp4);
- fp4_null(t0);
- fp4_null(t1);
- fp4_null(t2);
- fp4_null(t3);
- fp4_null(t4);
- fp4_null(t5);
- fp4_null(t6);
+#endif /* EP_ADD == PROJC */
- RLC_TRY {
- fp4_new(t0);
- fp4_new(t1);
- fp4_new(t2);
- fp4_new(t3);
- fp4_new(t4);
- fp4_new(t5);
- fp4_new(t6);
-
- if (p->coord != BASIC) {
- /* t0 = z1^2. */
- fp4_sqr(t0, p->z);
-
- /* t3 = U2 = x2 * z1^2. */
- fp4_mul(t3, q->x, t0);
-
- /* t1 = S2 = y2 * z1^3. */
- fp4_mul(t1, t0, p->z);
- fp4_mul(t1, t1, q->y);
-
- /* t3 = H = U2 - x1. */
- fp4_sub(t3, t3, p->x);
-
- /* t1 = R = 2 * (S2 - y1). */
- fp4_sub(t1, t1, p->y);
- } else {
- /* H = x2 - x1. */
- fp4_sub(t3, q->x, p->x);
-
- /* t1 = R = 2 * (y2 - y1). */
- fp4_sub(t1, q->y, p->y);
- }
-
- /* t2 = HH = H^2. */
- fp4_sqr(t2, t3);
-
- /* If E is zero. */
- if (fp4_is_zero(t3)) {
- if (fp4_is_zero(t1)) {
- /* If I is zero, p = q, should have doubled. */
- ep4_dbl_projc(r, p);
- } else {
- /* If I is not zero, q = -p, r = infinity. */
- ep4_set_infty(r);
- }
- } else {
- /* t5 = J = H * HH. */
- fp4_mul(t5, t3, t2);
-
- /* t4 = V = x1 * HH. */
- fp4_mul(t4, p->x, t2);
-
- /* x3 = R^2 - J - 2 * V. */
- fp4_sqr(r->x, t1);
- fp4_sub(r->x, r->x, t5);
- fp4_dbl(t6, t4);
- fp4_sub(r->x, r->x, t6);
-
- /* y3 = R * (V - x3) - Y1 * J. */
- fp4_sub(t4, t4, r->x);
- fp4_mul(t4, t4, t1);
- fp4_mul(t1, p->y, t5);
- fp4_sub(r->y, t4, t1);
-
- if (p->coord != BASIC) {
- /* z3 = z1 * H. */
- fp4_mul(r->z, p->z, t3);
- } else {
- /* z3 = H. */
- fp4_copy(r->z, t3);
- }
- }
- r->coord = PROJC;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp4_free(t0);
- fp4_free(t1);
- fp4_free(t2);
- fp4_free(t3);
- fp4_free(t4);
- fp4_free(t5);
- fp4_free(t6);
- }
-}
+#if EP_ADD == JACOB || !defined(STRIP)
-#endif
+/**
+ * Adds a point represented in Jacobian coordinates to a point represented in
+ * affine coordinates on an ordinary prime elliptic curve.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the projective point.
+ * @param[in] q - the affine point.
+ */
+TMPL_ADD_JACOB_MIX(ep4, fp4);
/**
- * Adds two points represented in projective coordinates on an ordinary prime
+ * Adds two points represented in Jacobian coordinates on an ordinary prime
* elliptic curve.
*
- * @param r - the result.
- * @param p - the first point to add.
- * @param q - the second point to add.
+ * @param[out] r - the result.
+ * @param[in] p - the first point to add.
+ * @param[in] q - the second point to add.
*/
-static void ep4_add_projc_imp(ep4_t r, const ep4_t p, const ep4_t q) {
-#if defined(EP_MIXED) && defined(STRIP)
- ep4_add_projc_mix(r, p, q);
-#else /* General addition. */
- fp4_t t0, t1, t2, t3, t4, t5, t6;
-
- fp4_null(t0);
- fp4_null(t1);
- fp4_null(t2);
- fp4_null(t3);
- fp4_null(t4);
- fp4_null(t5);
- fp4_null(t6);
+TMPL_ADD_JACOB_IMP(ep4, fp4);
- RLC_TRY {
- fp4_new(t0);
- fp4_new(t1);
- fp4_new(t2);
- fp4_new(t3);
- fp4_new(t4);
- fp4_new(t5);
- fp4_new(t6);
-
- if (q->coord == BASIC) {
- ep4_add_projc_mix(r, p, q);
- } else {
- /* t0 = z1^2. */
- fp4_sqr(t0, p->z);
-
- /* t1 = z2^2. */
- fp4_sqr(t1, q->z);
-
- /* t2 = U1 = x1 * z2^2. */
- fp4_mul(t2, p->x, t1);
-
- /* t3 = U2 = x2 * z1^2. */
- fp4_mul(t3, q->x, t0);
-
- /* t6 = z1^2 + z2^2. */
- fp4_add(t6, t0, t1);
-
- /* t0 = S2 = y2 * z1^3. */
- fp4_mul(t0, t0, p->z);
- fp4_mul(t0, t0, q->y);
-
- /* t1 = S1 = y1 * z2^3. */
- fp4_mul(t1, t1, q->z);
- fp4_mul(t1, t1, p->y);
-
- /* t3 = H = U2 - U1. */
- fp4_sub(t3, t3, t2);
-
- /* t0 = R = 2 * (S2 - S1). */
- fp4_sub(t0, t0, t1);
-
- fp4_dbl(t0, t0);
-
- /* If E is zero. */
- if (fp4_is_zero(t3)) {
- if (fp4_is_zero(t0)) {
- /* If I is zero, p = q, should have doubled. */
- ep4_dbl_projc(r, p);
- } else {
- /* If I is not zero, q = -p, r = infinity. */
- ep4_set_infty(r);
- }
- } else {
- /* t4 = I = (2*H)^2. */
- fp4_dbl(t4, t3);
- fp4_sqr(t4, t4);
-
- /* t5 = J = H * I. */
- fp4_mul(t5, t3, t4);
-
- /* t4 = V = U1 * I. */
- fp4_mul(t4, t2, t4);
-
- /* x3 = R^2 - J - 2 * V. */
- fp4_sqr(r->x, t0);
- fp4_sub(r->x, r->x, t5);
- fp4_dbl(t2, t4);
- fp4_sub(r->x, r->x, t2);
-
- /* y3 = R * (V - x3) - 2 * S1 * J. */
- fp4_sub(t4, t4, r->x);
- fp4_mul(t4, t4, t0);
- fp4_mul(t1, t1, t5);
- fp4_dbl(t1, t1);
- fp4_sub(r->y, t4, t1);
-
- /* z3 = ((z1 + z2)^2 - z1^2 - z2^2) * H. */
- fp4_add(r->z, p->z, q->z);
- fp4_sqr(r->z, r->z);
- fp4_sub(r->z, r->z, t6);
- fp4_mul(r->z, r->z, t3);
- }
- }
- r->coord = PROJC;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp4_free(t0);
- fp4_free(t1);
- fp4_free(t2);
- fp4_free(t3);
- fp4_free(t4);
- fp4_free(t5);
- fp4_free(t6);
- }
-#endif
-}
-
-#endif /* EP_ADD == PROJC */
+#endif /* EP_ADD == JACOB */
/*============================================================================*/
/* Public definitions */
@@ -385,7 +136,7 @@ void ep4_add_slp_basic(ep4_t r, fp4_t s, const ep4_t p, const ep4_t q) {
#endif
-#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
+#if EP_ADD == PROJC || !defined(STRIP)
void ep4_add_projc(ep4_t r, const ep4_t p, const ep4_t q) {
if (ep4_is_infty(p)) {
@@ -398,13 +149,25 @@ void ep4_add_projc(ep4_t r, const ep4_t p, const ep4_t q) {
return;
}
- if (p == q) {
- /* TODO: This is a quick hack. Should we fix this? */
- ep4_dbl(r, p);
+ ep4_add_projc_imp(r, p, q);
+}
+
+#endif
+
+#if EP_ADD == JACOB || !defined(STRIP)
+
+void ep4_add_jacob(ep4_t r, const ep4_t p, const ep4_t q) {
+ if (ep4_is_infty(p)) {
+ ep4_copy(r, q);
return;
}
- ep4_add_projc_imp(r, p, q);
+ if (ep4_is_infty(q)) {
+ ep4_copy(r, p);
+ return;
+ }
+
+ ep4_add_jacob_imp(r, p, q);
}
#endif
@@ -421,7 +184,6 @@ void ep4_sub(ep4_t r, const ep4_t p, const ep4_t q) {
RLC_TRY {
ep4_new(t);
-
ep4_neg(t, q);
ep4_add(r, p, t);
}
diff --git a/src/epx/relic_ep4_cmp.c b/src/epx/relic_ep4_cmp.c
index d98f37a35..9df11b6a1 100644
--- a/src/epx/relic_ep4_cmp.c
+++ b/src/epx/relic_ep4_cmp.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of utilities for prime elliptic curves over quadratic
- * extensions.
+ * Implementation of utilities for prime elliptic curves over a quartic
+ * extension field.
*
* @ingroup epx
*/
@@ -37,46 +37,68 @@
/*============================================================================*/
int ep4_cmp(const ep4_t p, const ep4_t q) {
- ep4_t r, s;
- int result = RLC_NE;
+ ep4_t r, s;
+ int result = RLC_NE;
if (ep4_is_infty(p) && ep4_is_infty(q)) {
return RLC_EQ;
}
- ep4_null(r);
- ep4_null(s);
+ ep4_null(r);
+ ep4_null(s);
- RLC_TRY {
- ep4_new(r);
- ep4_new(s);
+ RLC_TRY {
+ ep4_new(r);
+ ep4_new(s);
- if ((p->coord != BASIC) && (q->coord != BASIC)) {
- /* If the two points are not normalized, it is faster to compare
- * x1 * z2^2 == x2 * z1^2 and y1 * z2^3 == y2 * z1^3. */
- fp4_sqr(r->z, p->z);
- fp4_sqr(s->z, q->z);
- fp4_mul(r->x, p->x, s->z);
- fp4_mul(s->x, q->x, r->z);
- fp4_mul(r->z, r->z, p->z);
- fp4_mul(s->z, s->z, q->z);
- fp4_mul(r->y, p->y, s->z);
- fp4_mul(s->y, q->y, r->z);
- } else {
- ep4_norm(r, p);
- ep4_norm(s, q);
- }
+ switch (q->coord) {
+ case PROJC:
+ /* If q is in homogeneous projective coordinates, compute
+ * x1 * z2 and y1 * z2. */
+ fp4_mul(r->x, p->x, q->z);
+ fp4_mul(r->y, p->y, q->z);
+ break;
+ case JACOB:
+ /* If q is in Jacobian projective coordinates, compute
+ * x2 * z1^2 and y2 * z1^3. */
+ fp4_sqr(r->z, q->z);
+ fp4_mul(r->x, p->x, r->z);
+ fp4_mul(r->z, r->z, q->z);
+ fp4_mul(r->y, p->y, r->z);
+ break;
+ default:
+ ep4_copy(r, p);
+ break;
+ }
- if ((fp4_cmp(r->x, s->x) == RLC_EQ) &&
- (fp4_cmp(r->y, s->y) == RLC_EQ)) {
- result = RLC_EQ;
- }
- } RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- } RLC_FINALLY {
- ep4_free(r);
- ep4_free(s);
- }
+ switch (p->coord) {
+ /* Now do the same for the other point. */
+ case PROJC:
+ fp4_mul(s->x, q->x, p->z);
+ fp4_mul(s->y, q->y, p->z);
+ break;
+ case JACOB:
+ fp4_sqr(s->z, p->z);
+ fp4_mul(s->x, q->x, s->z);
+ fp4_mul(s->z, s->z, p->z);
+ fp4_mul(s->y, q->y, s->z);
+ break;
+ default:
+ ep4_copy(s, q);
+ break;
+ }
- return result;
+ if ((fp4_cmp(r->x, s->x) == RLC_EQ) && (fp4_cmp(r->y, s->y) == RLC_EQ)) {
+ result = RLC_EQ;
+ }
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ ep4_free(r);
+ ep4_free(s);
+ }
+
+ return result;
}
diff --git a/src/epx/relic_ep4_curve.c b/src/epx/relic_ep4_curve.c
index cb695d924..21e8a87fe 100644
--- a/src/epx/relic_ep4_curve.c
+++ b/src/epx/relic_ep4_curve.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of configuration of prime elliptic curves over quartic
- * extensions.
+ * Implementation of configuration of prime elliptic curves over a quartic
+ * extension field.
*
* @ingroup epx
*/
@@ -130,29 +130,6 @@
/** @} */
#endif
-#if defined(EP_ENDOM) && FP_PRIME == 765
-/** @{ */
-#define N16_P765_A0 "0"
-#define N16_P765_A1 "0"
-#define N16_P765_A2 "1"
-#define N16_P765_A3 "0"
-#define N16_P765_B0 "0"
-#define N16_P765_B1 "0"
-#define N16_P765_B2 "0"
-#define N16_P765_B3 "0"
-#define N16_P765_X0 "004C4A977FFCA75E15AEB9C8B8EAB0CAB30A488EF0424C9658FB8A05E4CA6A1E2997FAD9F0DE053D69751CBA6F49059CB2E0BAC08AA25A575BC1E1468E2E1BD78FB87C2ABCA3C20AB55B8B18F5266CD05FC4B26DFB091FB4A130312132D09614"
-#define N16_P765_X1 "0EE552F7143FA01D9919C462036AEC50C76BE752823C49910EF121F05B22494897A213DDF33166C6F8CA16995A83B9526EADE2D74366C349313DD126CC89249F282C1F3715BB690A1AD176F53F6EF6D75873E8A857FC0794F2AE1AE7C12D8F8B"
-#define N16_P765_X2 "14A32856133B3D59AC0DC99C3D34D830A7003BF41CED95B126BF0D2BAAB3C92A0E24CAFE5B6030F0FBD29E7CF08F808787A273B171B05C50CD052A3C031288BFBDE6CF4F53270477B12621F35193B5FAD47E6A77B33BD2B9FF9D3687AE6AE48D"
-#define N16_P765_X3 "0C478BC2CC455CDE662F112B2C4F9B24A0DA57515A44DD61591E3F3532AA8C640D84CAFADECADAE4D249D1038F3D030E173CFA87C51BF90BF49B1DFAB84B9ACC0ABD72349A3ADAB2BF056EF39AB6101F1D89C6C9D7761BFC9D5E0E050E299138"
-#define N16_P765_Y0 "00DEDAE825C143B4DFCB3A8B5F87BA7BADE72AF792AB7DFF198FE234AE16D8B5B45D9B033415FD4B59099DAFEF8A5782AC4D86BCD555AFCBA31111E07E34D1233A59505BEABB6FDEDE470A5182D0B6DDE2E48BE313D445EA0D11062D109382D6"
-#define N16_P765_Y1 "0D77B57018036B23B857B823374756FC62C05244E47D5237961304B9B7BFDE3BE874B58B5F7B4805726BB0042CEEFF3FBF76F7EBEA3D36CC1E46BBAF4819F76DB1BFBC05E8577D4E992407C245418170CE03D6DD3A153DCC217F995191749773"
-#define N16_P765_Y2 "0ADFD23B22ABAF4C64ECE323D37878D1D437EB77860ABF4EC0C2ADA1054D4BAB06422FF17E3A59FE4AE7B254F2228138A50E819616A6F6F44671CE2FB19962D4687510516A6786E06060560D714FF35C05C7F3B8600E5ADBE796DC7FD331C8C4"
-#define N16_P765_Y3 "0E9EA14175A8DAA9C83F5A6C7CCBE6E7CBE534B5AEB9A92B8689F73AF7356EEC955FBE18F6D687561E3D13D781DCB3B90C78392093343E30FE68A5E92A61434F366945C20896A3AD11856AF4B4558791CA9BDE9598734BBE1B33CE618E809982"
-#define N16_P765_R "9965D956A0DBC8AF273C0100000000000000000000000000000000000000000000000000000000000000000000000001"
-#define N16_P765_H "719C0F18991838D271B16518B194F6F145242127E49DC9A094D6CB692E28DC5F17FFA92321BB6498A829BA8C587373ED1198514FA52F945FEF0BD7DB7AEECF44BA1DC59375BEFBFC8467B4B2DCB8BC87E9FBD6615875E2CDA99813230882AE3B19CC78906339C451CE982DED4C8C2B44D01B86D2440D89A5F5AC3BF04E1393A4DC6712246A0E6F966D734F449D38655E7BF22CC56C0609840678EB8285D561CE1E65F73F1142F3C526CA2E28484D72F0B0492E78604F0AAB2DBBD13A082DFB9513D5C0D5C6CCFD13A6D3DA2EEC9A2AEFD40EC51A940F59D64F45BADB3EBEB96FCDAE11951717C5DF0125F274306A90C0FCF19D34FCB0D37683A2743F8C3ECAFE55863AA6B35BD14C7A894E6D7DC05D12E0D551AE0E46AB11D80610EA749AAEA445FE78651B64091AB67E32F33AA4CE905E2AF4A64A03B25A5C08233C52CBB94BF8000E13C04000003C08000000002"
-/** @} */
-#endif
-
#if defined(EP_ENDOM) && FP_PRIME == 765
/** @{ */
#define FM16_P765_A0 "0"
@@ -209,16 +186,16 @@
#define N16_P766_B1 "0"
#define N16_P766_B2 "0"
#define N16_P766_B3 "0"
-#define N16_P766_X0 "2DD92375B2A68D713D1D997683DA3E93B0C1713870A6759B37076504F22AFEC776AA9986FFE48F5507793DB266C9C563D26B64423B653977CC9D7A3EA67D52CF708A55E0110E1F21E4676EEC13FF37228D05B74FC124AC6F15931F84039FFF5B"
-#define N16_P766_X1 "3BFCCB56ED55A4FBC07136D3577EA5DC5D1ED55079EA0CD7FA75F945D616AF8957935ABF77D532AE66E568CE090109867C58114CD9AE9CCF220BAE9B22148BBEF77A0AF557527A4F87D36CD84DD481FCF78ED87C388E0D4777456B0DF240898E"
-#define N16_P766_X2 "1B9DAFE0399513AE63149C5BD87F531A00A9BA81BB42FE35C499BBAD9B985EDDDB94EEEAF944C21B6E36B25768CB3A6EB5EAD839BDEB05E1F86819BCAFD5EB0EF82EFC64D62223CD23ED960D645D213D8B2DE094FE2F78F0C34AFC09EBD39B65"
-#define N16_P766_X3 "B22A088D63FC479596ED186B382DECBB180CC51CD5615F1CE9D600B4BCD81DCAFB9369A86E261767B75C2CE12BD4AE372311F8E9E328BA006D52021D1F09DC51B853C3365FCD61B4DA1BD24AB504CE63E11EB4FB0C2FA56704E009A7D1B1944"
-#define N16_P766_Y0 "2AB5268BD543054A99076F5DD83E2D8947CC9DBBCCB125C29D791386412830E074378F94D1CC70891ADDF24CE9398490D3F27FBA8EE7F6CB2D71DFE01112BBD0B9B21FE566393AC278562B4390F0673762FB29A6540186B515A0AB9DB96E848C"
-#define N16_P766_Y1 "36962D909FC17BD54162AD530987217464D81007D2B07CEBFEDD9E7ACAC7423242132E11169B1F49A9DCDD3EA9EFF0A24CE7AA7A68BFADFD3E07B0517D47F097AB0F9568B54E8AAE190A2D53D430D1118570C0B5EB878364BA9900A44D97505B"
-#define N16_P766_Y2 "2B259E06C780DA39E283C221C392A9EE03ACE066967A30A5A4ADEE49E2ECA40DCAAD4CD234FABAA4CFAB20105EE1BEE54403CC17D5BE544B926A699495A5923C6EC7575A64EE412BFAF4C67E4C449F28814D26C4B8F85947EABF97E3818A3097"
-#define N16_P766_Y3 "1495AA76C3DA6431BF12D17B346AEDF5EFE50F4F7135F2618075887884DDA700FCC2918462DDE2CF728034461ECCB4C1F76892A809192939D069D3BA3A06D7F7FD94C1E08D74261C847C3E6DCD36B8D93B87D8277EC23300619530B5A5584B8C"
-#define N16_P766_R "FFFFFF8401001A46937D417AB554F4F3438C3F42C66CBA08998426591ED55EBA6A16CB364728D491BC20010000000001"
-#define N16_P766_H "FFFFFC9C0705A529AA711C4917897B571AB9D0963B7F885C31C06824D3F2584BA226785992D5E850AA5C0B13502F293A1681AF78BC665FEB126F7C4BA70D01AE2CE52E02140F5C16C4AF3B3A49E6351F191B54245F28C8C4C335ECA923DBF5FF15EBDFF8D29E3B70B027074B50A2AF3622E60B09A63B11B30F61AD59875B59751803A75D55EF5123CED27A3E7F29D20CD2617F6532FDCB87592DF3A6720415EB7871CE9D858844438E66F90066DB58804FB9F54832AEEC21CBACEB00A49D6D5AE806679C4AC7DAD3DBD527E4D81095E256780325B815449FA6C11EF0D70D8AEE93923245E95D8CE60384D06F98BC9AC3D2E91CD725371F495C8B2D1E5161377E801D7732A37179669E91008D8152B75C19324815BD89CCB54EC01212F5B906604C08A55DB203EA6049568FFAA1B88B74657771B64387FF992C5CB64A9E758DEC94FE63AB50F5B88140B2AC32248382"
+#define N16_P766_X0 "36097A5BDF2276730FCAC23EA21B0C85D46B013D5A33B2D403BD82155F681BC3A1213F7AD40BFD5B64409C6B909A44F1AC391DE4222B56C55CC74DCB5DCEC23696575F80C402A1256C267F9D1CA325558C3357B116AC85CF856E51590FE7C34F"
+#define N16_P766_X1 "17CC3006229289EEC6AAA00FD81F17F26CECDE216E03B5DF64B61FEBA6DFF9D3F032642D66F8E5D4DE44934FB1CB99AFB0A6A939ADAFDA1E6197A474C3BBDDBA71E6120B3AAFE1007A8D0F360651B316312F902B1EB346DD2B276FEEE75ABDD1"
+#define N16_P766_X2 "2B79EC9BDF7F80A86DD7F3CE18A3D1FAAEAEDE9312797735EA7F090760B4730CEE401EF9CAB0978C14E967FCE1CEEF5660DFA40F367F698D0CDE9C0F0EF361D70E186EA991CD0F6DB63FE88C45EC5909DFC866862C7B1D1DE6A04843761E5E3"
+#define N16_P766_X3 "2005908CF374B24B1C7CF8C5CE656D04515082E61F3088C28D58B9E0249CA864AF1773F479D3272C567311FB287E579547743E8CA51A9D4B45FF5D3D6B4A2BB1865B6E4FB045953D716C68A73095A74CCDDAD5AFCEA74E676D37452916B5CB24"
+#define N16_P766_Y0 "137A898DDF4399F2ABB29920707790495F645B373F419C4E2A96DA05B90488BED334F2B8A44AF71C92D947009618358A14F8DE18F0D777F0DE4F98625C4024DBEB8EA858A7AEFAEC093EA12ED7A7C70142AE3583D27982B26AFD75FB441A4B66"
+#define N16_P766_Y1 "4D0ADEC5B4B77DFBEB78227FC664F7520A469DBEA674C845F64B537ABFB808F9857EEFBDE088D0422C919ECD562D7C668A42F6C2DAB0B26D7C4D4C3B835CBEA2A843CD3A449B44F0D6D4026512670C3600B02CEFDF9BBF21975B596DD732C13"
+#define N16_P766_Y2 "2FCE7D8564D037E95317C3110542BB780D8824436B6F3626C8A4BF1D1C1FB7C1FDF12E7BC52D9F19914404EF71873EFB36C95AF0C6635329D556431A902BA01186D968C0D4BF55F17F7FED3072D77D9DE8D151135952C6EE7855E8F6176B4D66"
+#define N16_P766_Y3 "2BAD268ACF32E9D617EC80588A3F1063C5565008B9DF82E8E9B8451F874C36157A280057EF467E0BFCA1FE7AF5C79CDCD055011B2F0F14764B8F1C97BEA256BD5A40FC8020486507E52413A11B70F8D6A3ACF396D5F0D8902950A3E3821B4C64"
+#define N16_P766_R "FFFF7000238FFAF4807374994CF93FE6E28D406881B18D350193FE6E3E533E4073749FEBD2000238FFFFDC0000010001"
+#define N16_P766_H "FFFC10079DE659DE808DDCE130F752738172840B38A5FC5FC7E040BFD9DCEE27BC5A7B95CED5C4229B3FA11F8F6FAE01BE1FBBBAF34CEF81E7CAFC72FAA4ECB8710AB4E1097D5F96BC6E8A5A88DE77C8B1F025B2691EEE839B4DBE2AC3433AA9E3567E22C5F26F401F6D0458C5F931050EB64B76A27B1D74E69AF8751AB329F9AA6F80C46E4F46D6727D476002C6DD1893DDC185AE4BE7842818B8DF91045FAF7F0A85549CFF3D6F3F45C0010E9F70243663C0840EEE489118422163CFDA9A843ABA6C408D3EC6C858FEDF4BDE93A28C7FD16B34CC1E1074ADB78D9F4F7F5E96DC4F0C5DCA4F360BCB4933A50ABAC5204B89055875059167BA03E0402A1CB965B48313B481483B26F3F1192C673BC76FBDA8395741062530251758B6B86500570F6C3FAF490A5C01D1B62653C6C1DF188A9358877DC50DAB36655B01F092A8AF90F6259FB91E5D57E2DA8FDD5F06A2"
/** @} */
#endif
@@ -358,6 +335,67 @@ int ep4_curve_opt_b(void) {
return core_get()->ep4_opt_b;
}
+void ep4_curve_mul_a(fp4_t c, const fp4_t a) {
+ ctx_t *ctx = core_get();
+ if (ep4_curve_is_twist() == RLC_EP_MTYPE) {
+ switch (ctx->ep_opt_a) {
+ case RLC_ZERO:
+ fp4_zero(c);
+ break;
+ case RLC_ONE:
+ fp4_copy(c, a);
+ break;
+ case RLC_TWO:
+ fp4_dbl(c, a);
+ break;
+ default:
+ fp4_mul(c, a, ctx->ep4_a);
+ break;
+ }
+ fp4_mul_art(c, c);
+ } else {
+ switch (ctx->ep8_opt_a) {
+ case RLC_ZERO:
+ fp4_zero(c);
+ break;
+ case RLC_ONE:
+ fp4_copy(c, a);
+ break;
+ case RLC_TWO:
+ fp4_dbl(c, a);
+ break;
+#if FP_RDC != MONTY
+ case RLC_TINY:
+ fp4_mul_dig(c, a, ctx->ep4_a[0]);
+ break;
+#endif
+ default:
+ fp4_mul(c, a, ctx->ep4_a);
+ break;
+ }
+ }
+}
+
+void ep4_curve_mul_b(fp4_t c, const fp4_t a) {
+ ctx_t *ctx = core_get();
+ switch (ctx->ep4_opt_b) {
+ case RLC_ZERO:
+ fp4_zero(c);
+ break;
+ case RLC_ONE:
+ fp4_copy(c, a);
+ break;
+#if FP_RDC != MONTY
+ case RLC_TINY:
+ fp4_mul_dig(c, a, ctx->ep4_b[0]);
+ break;
+#endif
+ default:
+ fp4_mul(c, a, ctx->ep4_b);
+ break;
+ }
+}
+
int ep4_curve_is_twist(void) {
return core_get()->ep4_is_twist;
}
@@ -366,12 +404,12 @@ void ep4_curve_get_gen(ep4_t g) {
ep4_copy(g, core_get()->ep4_g);
}
-void ep4_curve_get_a(fp4_t a) {
- fp4_copy(a, core_get()->ep4_a);
+fp2_t *ep4_curve_get_a(void) {
+ return core_get()->ep4_a;
}
-void ep4_curve_get_b(fp4_t b) {
- fp4_copy(b, core_get()->ep4_b);
+fp2_t *ep4_curve_get_b(void) {
+ return core_get()->ep4_b;
}
void ep4_curve_get_ord(bn_t n) {
@@ -444,9 +482,6 @@ void ep4_curve_set_twist(int type) {
ASSIGN(B24_P509);
break;
#elif FP_PRIME == 765
- case N16_P765:
- ASSIGN(N16_P765);
- break;
case FM16_P765:
ASSIGN(FM16_P765);
break;
diff --git a/src/epx/relic_ep4_dbl.c b/src/epx/relic_ep4_dbl.c
index 6aa82b9e9..d3978bba1 100644
--- a/src/epx/relic_ep4_dbl.c
+++ b/src/epx/relic_ep4_dbl.c
@@ -24,13 +24,14 @@
/**
* @file
*
- * Implementation of doubling on elliptic prime curves over quartic
- * extensions.
+ * Implementation of doubling on elliptic prime curves over a quartic extension
+ * field.
*
* @ingroup epx
*/
#include "relic_core.h"
+#include "relic_ep_dbl_tmpl.h"
/*============================================================================*/
/* Private definitions */
@@ -43,201 +44,41 @@
* elliptic curve.
*
* @param[out] r - the result.
- * @param[out] s - the resulting slope.
+ * @param[out] s - the slope.
* @param[in] p - the point to double.
*/
-static void ep4_dbl_basic_imp(ep4_t r, fp4_t s, const ep4_t p) {
- fp4_t t0, t1, t2;
-
- fp4_null(t0);
- fp4_null(t1);
- fp4_null(t2);
-
- RLC_TRY {
- fp4_new(t0);
- fp4_new(t1);
- fp4_new(t2);
-
- /* t0 = 1/(2 * y1). */
- fp4_dbl(t0, p->y);
- fp4_inv(t0, t0);
-
- /* t1 = 3 * x1^2 + a. */
- fp4_sqr(t1, p->x);
- fp4_copy(t2, t1);
- fp4_dbl(t1, t1);
- fp4_add(t1, t1, t2);
-
- ep4_curve_get_a(t2);
- fp4_add(t1, t1, t2);
-
- /* t1 = (3 * x1^2 + a)/(2 * y1). */
- fp4_mul(t1, t1, t0);
-
- if (s != NULL) {
- fp4_copy(s, t1);
- }
-
- /* t2 = t1^2. */
- fp4_sqr(t2, t1);
-
- /* x3 = t1^2 - 2 * x1. */
- fp4_dbl(t0, p->x);
- fp4_sub(t0, t2, t0);
-
- /* y3 = t1 * (x1 - x3) - y1. */
- fp4_sub(t2, p->x, t0);
- fp4_mul(t1, t1, t2);
-
- fp4_sub(r->y, t1, p->y);
-
- fp4_copy(r->x, t0);
- fp4_copy(r->z, p->z);
-
- r->coord = BASIC;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp4_free(t0);
- fp4_free(t1);
- fp4_free(t2);
- }
-}
+TMPL_DBL_BASIC_IMP(ep4, fp4);
#endif /* EP_ADD == BASIC */
-#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
+#if EP_ADD == PROJC || !defined(STRIP)
/**
- * Doubles a point represented in affine coordinates on an ordinary prime
+ * Doubles a point represented in projective coordinates on an ordinary prime
* elliptic curve.
*
- * @param[out] r - the result.
- * @param[in] p - the point to double.
+ * @param r - the result.
+ * @param p - the point to double.
*/
-static void ep4_dbl_projc_imp(ep4_t r, const ep4_t p) {
- fp4_t t0, t1, t2, t3, t4, t5;
-
- fp4_null(t0);
- fp4_null(t1);
- fp4_null(t2);
- fp4_null(t3);
- fp4_null(t4);
- fp4_null(t5);
-
- RLC_TRY {
- fp4_new(t0);
- fp4_new(t1);
- fp4_new(t2);
- fp4_new(t3);
- fp4_new(t4);
- fp4_new(t5);
-
- if (ep_curve_opt_a() == RLC_ZERO) {
- fp4_sqr(t0, p->x);
- fp4_add(t2, t0, t0);
- fp4_add(t0, t2, t0);
-
- fp4_sqr(t3, p->y);
- fp4_mul(t1, t3, p->x);
- fp4_add(t1, t1, t1);
- fp4_add(t1, t1, t1);
- fp4_sqr(r->x, t0);
- fp4_add(t2, t1, t1);
- fp4_sub(r->x, r->x, t2);
- fp4_mul(r->z, p->z, p->y);
- fp4_add(r->z, r->z, r->z);
- fp4_add(t3, t3, t3);
-
- fp4_sqr(t3, t3);
- fp4_add(t3, t3, t3);
- fp4_sub(t1, t1, r->x);
- fp4_mul(r->y, t0, t1);
- fp4_sub(r->y, r->y, t3);
- } else {
- /* dbl-2007-bl formulas: 1M + 8S + 1*a + 10add + 1*8 + 2*2 + 1*3 */
- /* http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-2007-bl */
-
- /* t0 = x1^2, t1 = y1^2, t2 = y1^4. */
- fp4_sqr(t0, p->x);
- fp4_sqr(t1, p->y);
- fp4_sqr(t2, t1);
-
- if (p->coord != BASIC) {
- /* t3 = z1^2. */
- fp4_sqr(t3, p->z);
+TMPL_DBL_PROJC_IMP(ep4, fp4);
- if (ep_curve_get_a() == RLC_ZERO) {
- /* z3 = 2 * y1 * z1. */
- fp4_mul(r->z, p->y, p->z);
- fp4_dbl(r->z, r->z);
- } else {
- /* z3 = (y1 + z1)^2 - y1^2 - z1^2. */
- fp4_add(r->z, p->y, p->z);
- fp4_sqr(r->z, r->z);
- fp4_sub(r->z, r->z, t1);
- fp4_sub(r->z, r->z, t3);
- }
- } else {
- /* z3 = 2 * y1. */
- fp4_dbl(r->z, p->y);
- }
-
- /* t4 = S = 2*((x1 + y1^2)^2 - x1^2 - y1^4). */
- fp4_add(t4, p->x, t1);
- fp4_sqr(t4, t4);
- fp4_sub(t4, t4, t0);
- fp4_sub(t4, t4, t2);
- fp4_dbl(t4, t4);
-
- /* t5 = M = 3 * x1^2 + a * z1^4. */
- fp4_dbl(t5, t0);
- fp4_add(t5, t5, t0);
- if (p->coord != BASIC) {
- fp4_sqr(t3, t3);
- ep4_curve_get_a(t1);
- fp4_mul(t1, t3, t1);
- fp4_add(t5, t5, t1);
- } else {
- ep4_curve_get_a(t1);
- fp4_add(t5, t5, t1);
- }
-
- /* x3 = T = M^2 - 2 * S. */
- fp4_sqr(r->x, t5);
- fp4_dbl(t1, t4);
- fp4_sub(r->x, r->x, t1);
+#endif /* EP_ADD == PROJC */
- /* y3 = M * (S - T) - 8 * y1^4. */
- fp4_dbl(t2, t2);
- fp4_dbl(t2, t2);
- fp4_dbl(t2, t2);
- fp4_sub(t4, t4, r->x);
- fp4_mul(t5, t5, t4);
- fp4_sub(r->y, t5, t2);
- }
+#if EP_ADD == JACOB || !defined(STRIP)
- r->coord = PROJC;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp4_free(t0);
- fp4_free(t1);
- fp4_free(t2);
- fp4_free(t3);
- fp4_free(t4);
- fp4_free(t5);
- }
-}
+/**
+ * Doubles a point represented in Jacobian coordinates on an ordinary prime
+ * elliptic curve.
+ *
+ * @param r - the result.
+ * @param p - the point to double.
+ */
+TMPL_DBL_JACOB_IMP(ep4, fp4);
-#endif /* EP_ADD == PROJC */
+#endif /* EP_ADD == JACOB */
/*============================================================================*/
- /* Public definitions */
+/* Public definitions */
/*============================================================================*/
#if EP_ADD == BASIC || !defined(STRIP)
@@ -247,7 +88,6 @@ void ep4_dbl_basic(ep4_t r, const ep4_t p) {
ep4_set_infty(r);
return;
}
-
ep4_dbl_basic_imp(r, NULL, p);
}
@@ -262,7 +102,7 @@ void ep4_dbl_slp_basic(ep4_t r, fp4_t s, const ep4_t p) {
#endif
-#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
+#if EP_ADD == PROJC || !defined(STRIP)
void ep4_dbl_projc(ep4_t r, const ep4_t p) {
if (ep4_is_infty(p)) {
@@ -274,3 +114,16 @@ void ep4_dbl_projc(ep4_t r, const ep4_t p) {
}
#endif
+
+#if EP_ADD == JACOB || !defined(STRIP)
+
+void ep4_dbl_jacob(ep4_t r, const ep4_t p) {
+ if (ep4_is_infty(p)) {
+ ep4_set_infty(r);
+ return;
+ }
+
+ ep4_dbl_jacob_imp(r, p);
+}
+
+#endif
diff --git a/src/epx/relic_ep4_frb.c b/src/epx/relic_ep4_frb.c
index 0cea9557d..601aef677 100644
--- a/src/epx/relic_ep4_frb.c
+++ b/src/epx/relic_ep4_frb.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of frobenius action on prime elliptic curves over
- * quartic extensions.
+ * Implementation of frobenius action on prime elliptic curves over a quartic
+ * extension field.
*
* @ingroup epx
*/
diff --git a/src/epx/relic_ep4_map.c b/src/epx/relic_ep4_map.c
index 24a9cfab0..7c47ffe00 100644
--- a/src/epx/relic_ep4_map.c
+++ b/src/epx/relic_ep4_map.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of hashing to a prime elliptic curve over a quadratic
- * extension.
+ * Implementation of hashing to a prime elliptic curve over a quartic extension
+ * field.
*
* @ingroup epx
*/
@@ -41,13 +41,15 @@ void ep4_map(ep4_t p, const uint8_t *msg, size_t len) {
/* enough space for two field elements plus extra bytes for uniformity */
const size_t elm = (FP_PRIME + ep_param_level() + 7) / 8;
uint8_t t0z, t0, t1, s[2], sign, *h = RLC_ALLOCA(uint8_t, 8 * elm + 1);
- fp4_t a, c, t, u, v, w, y, x1, y1, z1;
+ fp4_t a, b, c, d, t, u, v, w, y, x1, y1, z1, den[3];
ctx_t *ctx = core_get();
bn_t k;
bn_null(k);
fp4_null(a);
+ fp4_null(b);
fp4_null(c);
+ fp4_null(d);
fp4_null(t);
fp4_null(u);
fp4_null(v);
@@ -56,11 +58,16 @@ void ep4_map(ep4_t p, const uint8_t *msg, size_t len) {
fp4_null(x1);
fp4_null(y1);
fp4_null(z1);
+ fp4_null(den[0]);
+ fp4_null(den[1]);
+ fp4_null(den[2]);
RLC_TRY {
bn_new(k);
fp4_new(a);
+ fp4_new(b);
fp4_new(c);
+ fp4_new(d);
fp4_new(t);
fp4_new(u);
fp4_new(v);
@@ -69,214 +76,205 @@ void ep4_map(ep4_t p, const uint8_t *msg, size_t len) {
fp4_new(x1);
fp4_new(y1);
fp4_new(z1);
+ fp4_new(den[0]);
+ fp4_new(den[1]);
+ fp4_new(den[2]);
- if (ep4_curve_opt_b() == RLC_ZERO) {
- /* This is the approach due to Koshelev introduced in
- * https://eprint.iacr.org/2021/1034.pdf */
-
- md_xmd(h, 4 * elm + 1, msg, len, (const uint8_t *)"RELIC", 5);
- for (int i = 0; i < 2; i++) {
- for (int j = 0; j < 2; j++) {
- bn_read_bin(k, h, elm);
- fp_prime_conv(u[i][j], k);
- h += elm;
- }
+ md_xmd(h, 8 * elm + 1, msg, len, (const uint8_t *)"RELIC", 5);
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < 2; j++) {
+ bn_read_bin(k, h, elm);
+ fp_prime_conv(u[i][j], k);
+ h += elm;
+ bn_read_bin(k, h, elm);
+ fp_prime_conv(t[i][j], k);
+ h += elm;
}
- h -= 4*elm;
-
- /* Compute c = 3*a^2, t^2 = 6a(9u^5 − 14au^3 + 3cu).*/
- ep4_curve_get_a(a);
- fp4_neg(a, a);
- fp4_sqr(c, a);
- fp4_dbl(t, c);
- fp4_add(c, c, t);
- fp4_dbl(t, c);
- fp4_add(t, t, c);
- fp4_mul(t, t, u);
-
- fp4_sqr(v, u);
- fp4_mul(w, v, u);
- fp4_mul(x1, w, a);
- fp4_mul_dig(x1, x1, 14);
- fp4_sub(t, t, x1);
-
- fp4_mul(w, w, v);
- fp4_dbl(x1, w);
- fp4_add(w, w, x1);
- fp4_dbl(x1, w);
- fp4_add(w, w, x1);
- fp4_add(t, t, w);
- fp4_mul(t, t, a);
- fp4_dbl(t, t);
- fp4_dbl(x1, t);
- fp4_add(t, t, x1);
- dig_t c1 = fp4_is_sqr(t);
- /* If t is not square, compute u = a/u, t = a*sqrt(a*t)/u^3*/
- fp4_inv(x1, u);
- fp4_mul(y1, t, a);
- /* If t is a square, extract its square root. */
- dv_copy_cond(t[0][0], y1[0][0], RLC_FP_DIGS, !c1);
- dv_copy_cond(t[0][1], y1[0][1], RLC_FP_DIGS, !c1);
- dv_copy_cond(t[1][0], y1[1][0], RLC_FP_DIGS, !c1);
- dv_copy_cond(t[1][1], y1[1][1], RLC_FP_DIGS, !c1);
- fp4_srt(t, t);
- fp4_mul(y1, t, a);
- fp4_sqr(y, x1);
- fp4_mul(y, y, x1);
- fp4_mul(y1, y1, y);
- fp4_mul(x1, x1, a);
- dv_copy_cond(u[0][0], x1[0][0], RLC_FP_DIGS, !c1);
- dv_copy_cond(u[0][1], x1[0][1], RLC_FP_DIGS, !c1);
- dv_copy_cond(u[1][0], x1[1][0], RLC_FP_DIGS, !c1);
- dv_copy_cond(u[1][1], x1[1][1], RLC_FP_DIGS, !c1);
- dv_copy_cond(t[0][0], y1[0][0], RLC_FP_DIGS, !c1);
- dv_copy_cond(t[0][1], y1[0][1], RLC_FP_DIGS, !c1);
- dv_copy_cond(t[1][0], y1[1][0], RLC_FP_DIGS, !c1);
- dv_copy_cond(t[1][1], y1[1][1], RLC_FP_DIGS, !c1);
-
- /* Compute x = 2^4*i*3*a^2*u / (3*(3*u^2 - a))^2. */
- fp4_zero(y);
- fp_copy(y[0][0], ctx->ep_map_c[6]);
- fp4_mul(c, c, u);
- for (int i = 0; i < 2; i++) {
- for (int j = 0; j < 2; j++) {
- fp_mul(x1[i][j], c[i][j], y[0][0]);
- }
- }
- fp4_dbl(x1, x1);
- fp4_dbl(x1, x1);
- fp4_dbl(x1, x1);
- fp4_dbl(p->x, x1);
- fp4_sqr(v, u);
- fp4_dbl(z1, v);
- fp4_add(z1, z1, v);
- fp4_sub(z1, z1, a);
- fp4_dbl(p->z, z1);
- fp4_add(p->z, p->z, z1);
+ }
+ sign = h[0] & 1;
+ h -= 8*elm;
- /* Compute y = 3*2*(i-1)*a*(3^2*u^2 + a)*t / (3*(3*u^2 - a))^3. */
- fp_sub_dig(y[0][0], y[0][0], 1);
- fp4_mul(y1, y, a);
- fp4_dbl(y1, y1);
- fp4_dbl(p->y, y1);
- fp4_add(p->y, p->y, y1);
- fp4_mul(p->y, p->y, t);
- fp4_dbl(y1, v);
- fp4_add(y1, y1, v);
- fp4_dbl(v, y1);
- fp4_add(y1, y1, v);
- fp4_add(y1, y1, a);
- fp4_mul(p->y, p->y, y1);
+ if (ep_curve_opt_b() == RLC_ZERO) {
+ fp4_sqr(a, u);
+ fp4_sqr(b, a);
+ fp4_mul(c, b, a);
+ fp4_dbl(p->y, ep4_curve_get_a());
+ fp4_dbl(p->y, p->y);
+ fp4_sqr(p->z, p->y);
+ fp4_mul(p->z, p->z, p->y);
+ fp4_add(c, c, p->z);
+ fp4_sqr(d, t);
- /* Multiply by cofactor. */
- p->coord = JACOB;
- ep4_norm(p, p);
- }
+ fp4_mul(v, a, d);
+ fp4_mul(v, v, u);
+ fp4_mul_dig(v, v, 24);
+ fp_mul(v[0][0], v[0][0], core_get()->ep_map_c[4]);
+ fp_mul(v[0][1], v[0][1], core_get()->ep_map_c[4]);
+ fp_mul(v[1][0], v[1][0], core_get()->ep_map_c[4]);
+ fp_mul(v[1][1], v[1][1], core_get()->ep_map_c[4]);
- if (ep_curve_opt_a() == RLC_ZERO) {
- md_xmd(h, 8 * elm + 1, msg, len, (const uint8_t *)"RELIC", 5);
- for (int i = 0; i < 2; i++) {
- for (int j = 0; j < 2; j++) {
- bn_read_bin(k, h, elm);
- fp_prime_conv(u[i][j], k);
- h += elm;
- bn_read_bin(k, h, elm);
- fp_prime_conv(t[i][j], k);
- h += elm;
- }
- }
- sign = h[0] & 1;
- h -= 8*elm;
+ fp4_zero(p->x);
+ fp_sub_dig(p->x[0][0], core_get()->ep_map_c[4], 1);
+ fp_hlv(p->x[0][0], p->x[0][0]);
- fp4_sqr(x1, u);
- fp4_mul(x1, x1, u);
- fp4_sqr(y1, t);
- fp4_add(x1, x1, ctx->ep4_b);
- fp4_sub(x1, x1, y1);
- fp4_dbl(y1, y1);
- fp4_add(y1, y1, x1);
- fp4_copy(z1, u);
- fp_mul(z1[0][0], z1[0][0], ctx->ep_map_c[4]);
- fp_mul(z1[0][1], z1[0][1], ctx->ep_map_c[4]);
- fp_mul(z1[1][0], z1[1][0], ctx->ep_map_c[4]);
- fp_mul(z1[1][1], z1[1][1], ctx->ep_map_c[4]);
- fp4_mul(x1, x1, z1);
- fp4_mul(z1, z1, t);
- fp4_dbl(z1, z1);
+ fp4_sqr(w, b);
+ fp4_mul(y, v, a);
+ fp4_mul(t, p->y, c);
+ fp4_add(y, y, t);
+ fp_mul(y[0][0], y[0][0], p->x[0][0]);
+ fp_mul(y[0][1], y[0][1], p->x[0][0]);
+ fp_mul(y[1][0], y[1][0], p->x[0][0]);
+ fp_mul(y[1][1], y[1][1], p->x[0][0]);
- fp4_dbl(y, y1);
- fp4_sqr(y, y);
- fp4_mul(v, y1, u);
- fp4_sub(v, x1, v);
- fp4_mul(v, v, z1);
- fp4_mul(w, y1, z1);
- fp4_dbl(w, w);
+ fp4_add(den[0], c, v);
+ fp4_mul(den[0], den[0], u);
+ fp_mul(den[0][0][0], den[0][0][0], core_get()->ep_map_c[4]);
+ fp_mul(den[0][0][1], den[0][0][1], core_get()->ep_map_c[4]);
+ fp_mul(den[0][1][0], den[0][1][0], core_get()->ep_map_c[4]);
+ fp_mul(den[0][1][1], den[0][1][1], core_get()->ep_map_c[4]);
+ fp4_mul(den[0], den[0], p->x);
+ fp4_dbl(den[0], den[0]);
+ fp4_neg(den[0], den[0]);
+ fp4_mul(den[1], den[0], p->x);
+ fp4_sub(den[2], a, p->y);
+ fp4_sqr(den[2], den[2]);
+ fp4_mul_dig(den[2], den[2], 216);
+ fp4_dbl(den[2], den[2]);
+ fp4_neg(den[2], den[2]);
+ fp4_mul(den[2], den[2], b);
+ fp4_mul(den[2], den[2], d);
- if (fp4_is_zero(w)) {
+ if (fp4_is_zero(den[0]) || fp4_is_zero(den[1]) || fp4_is_zero(den[2])) {
ep4_set_infty(p);
} else {
- fp4_inv(w, w);
- fp4_mul(x1, v, w);
- fp4_add(y1, u, x1);
- fp4_neg(y1, y1);
- fp4_mul(z1, y, w);
- fp4_sqr(z1, z1);
- fp4_add(z1, z1, u);
-
- ep4_curve_get_b(w);
+ fp4_inv_sim(den, den, 3);
+ fp4_mul(t, a, p->z);
+ fp4_mul(y1, p->y, v);
+ fp4_add(y1, y1, t);
+ fp4_add(y1, y1, w);
+ fp_mul(z1[0][0], y[0][0], p->x[0][0]);
+ fp_mul(z1[0][1], y[0][1], p->x[0][0]);
+ fp_mul(z1[1][0], y[1][0], p->x[0][0]);
+ fp_mul(z1[1][1], y[1][1], p->x[0][0]);
+ fp4_add(x1, y1, z1);
+ fp4_add(y1, y1, y);
+ fp4_mul(z1, a, p->y);
+ fp4_add(z1, z1, b);
+ fp4_mul(z1, z1, p->y);
+ fp4_dbl(p->x, z1);
+ fp4_add(z1, z1, p->x);
+ fp4_add(z1, z1, v);
+ fp4_sub(z1, c, z1);
+ fp4_mul(z1, z1, v);
+ fp4_sqr(p->z, p->z);
+ fp4_sub(z1, p->z, z1);
+ fp4_add(w, w, t);
+ fp4_add(w, w, t);
+ fp4_mul(w, w, b);
+ fp4_add(z1, z1, w);
- fp4_sqr(t, x1);
- fp4_mul(t, t, x1);
- fp4_add(t, t, w);
+ fp4_mul(x1, x1, den[0]);
+ fp4_mul(y1, y1, den[1]);
+ fp4_mul(z1, z1, den[2]);
+
+ ep4_rhs(t, x1);
+ ep4_rhs(u, y1);
+ ep4_rhs(v, z1);
- fp4_sqr(u, y1);
- fp4_mul(u, u, y1);
- fp4_add(u, u, w);
-
- fp4_sqr(v, z1);
- fp4_mul(v, v, z1);
- fp4_add(v, v, w);
+ int c2 = fp4_is_sqr(u);
+ int c3 = fp4_is_sqr(v);
- dig_t c2 = fp4_is_sqr(u);
- dig_t c3 = fp4_is_sqr(v);
-
- for (int i = 0; i < 2; i++) {
- for (int j = 0; j < 2; j++) {
- dv_swap_cond(x1[i][j], y1[i][j], RLC_FP_DIGS, c2);
- dv_swap_cond(t[i][j], u[i][j], RLC_FP_DIGS, c2);
- dv_swap_cond(x1[i][j], z1[i][j], RLC_FP_DIGS, c3);
- dv_swap_cond(t[i][j], v[i][j], RLC_FP_DIGS, c3);
- }
- }
+ fp4_copy_sec(t, u, c2);
+ fp4_copy_sec(x1, y1, c2);
+ fp4_copy_sec(t, v, c3);
+ fp4_copy_sec(x1, z1, c3);
if (!fp4_srt(t, t)) {
RLC_THROW(ERR_NO_VALID);
}
-
- for (int i = 0; i < 2; i++) {
- t0z = fp_is_zero(t[i][0]);
- fp_prime_back(k, t[i][0]);
- t0 = bn_get_bit(k, 0);
- fp_prime_back(k, t[i][1]);
- t1 = bn_get_bit(k, 0);
- /* t[0] == 0 ? sgn0(t[1]) : sgn0(t[0]) */
- s[i] = t0 | (t0z & t1);
- }
-
- t0z = fp2_is_zero(t[0]);
- sign ^= (s[0] | (t0z & s[1]));
-
fp4_neg(u, t);
- dv_swap_cond(t[0][0], u[0][0], RLC_FP_DIGS, sign);
- dv_swap_cond(t[0][1], u[0][1], RLC_FP_DIGS, sign);
- dv_swap_cond(t[1][0], u[1][0], RLC_FP_DIGS, sign);
- dv_swap_cond(t[1][1], u[1][1], RLC_FP_DIGS, sign);
+ fp4_copy_sec(t, u, fp_is_even(t[0][0]) ^ sign);
fp4_copy(p->x, x1);
fp4_copy(p->y, t);
fp4_set_dig(p->z, 1);
p->coord = BASIC;
}
+ } else {
+ if (ep_curve_opt_a() == RLC_ZERO) {
+ fp4_sqr(x1, u);
+ fp4_mul(x1, x1, u);
+ fp4_sqr(y1, t);
+ fp4_add(x1, x1, ctx->ep4_b);
+ fp4_sub(x1, x1, y1);
+ fp4_dbl(y1, y1);
+ fp4_add(y1, y1, x1);
+ fp4_copy(z1, u);
+ fp_mul(z1[0][0], z1[0][0], ctx->ep_map_c[4]);
+ fp_mul(z1[0][1], z1[0][1], ctx->ep_map_c[4]);
+ fp_mul(z1[1][0], z1[1][0], ctx->ep_map_c[4]);
+ fp_mul(z1[1][1], z1[1][1], ctx->ep_map_c[4]);
+ fp4_mul(x1, x1, z1);
+ fp4_mul(z1, z1, t);
+ fp4_dbl(z1, z1);
+
+ fp4_dbl(y, y1);
+ fp4_sqr(y, y);
+ fp4_mul(v, y1, u);
+ fp4_sub(v, x1, v);
+ fp4_mul(v, v, z1);
+ fp4_mul(w, y1, z1);
+ fp4_dbl(w, w);
+
+ if (fp4_is_zero(w)) {
+ ep4_set_infty(p);
+ } else {
+ fp4_inv(w, w);
+ fp4_mul(x1, v, w);
+ fp4_add(y1, u, x1);
+ fp4_neg(y1, y1);
+ fp4_mul(z1, y, w);
+ fp4_sqr(z1, z1);
+ fp4_add(z1, z1, u);
+
+ ep4_rhs(t, x1);
+ ep4_rhs(u, y1);
+ ep4_rhs(v, z1);
+
+ dig_t c2 = fp4_is_sqr(u);
+ dig_t c3 = fp4_is_sqr(v);
+
+ fp4_copy_sec(x1, y1, c2);
+ fp4_copy_sec(t, u, c2);
+ fp4_copy_sec(x1, z1, c3);
+ fp4_copy_sec(t, v, c3);
+
+ if (!fp4_srt(t, t)) {
+ RLC_THROW(ERR_NO_VALID);
+ }
+
+ for (int i = 0; i < 2; i++) {
+ t0z = fp_is_zero(t[i][0]);
+ fp_prime_back(k, t[i][0]);
+ t0 = bn_get_bit(k, 0);
+ fp_prime_back(k, t[i][1]);
+ t1 = bn_get_bit(k, 0);
+ /* t[0] == 0 ? sgn0(t[1]) : sgn0(t[0]) */
+ s[i] = t0 | (t0z & t1);
+ }
+
+ t0z = fp2_is_zero(t[0]);
+ sign ^= (s[0] | (t0z & s[1]));
+
+ fp4_neg(u, t);
+ fp4_copy_sec(t, u, sign);
+
+ fp4_copy(p->x, x1);
+ fp4_copy(p->y, t);
+ fp4_set_dig(p->z, 1);
+ p->coord = BASIC;
+ }
+ }
}
ep4_mul_cof(p, p);
@@ -287,7 +285,9 @@ void ep4_map(ep4_t p, const uint8_t *msg, size_t len) {
RLC_FINALLY {
bn_free(k);
fp4_free(a);
+ fp4_free(b);
fp4_free(c);
+ fp4_free(d);
fp4_free(t);
fp4_free(u);
fp4_free(v);
@@ -296,6 +296,9 @@ void ep4_map(ep4_t p, const uint8_t *msg, size_t len) {
fp4_free(x1);
fp4_free(y1);
fp4_free(z1);
+ fp4_free(den[0]);
+ fp4_free(den[1]);
+ fp4_free(den[2]);
RLC_FREE(h);
}
}
diff --git a/src/epx/relic_ep4_mul.c b/src/epx/relic_ep4_mul.c
index 41bf5390b..a6cb8a5ba 100644
--- a/src/epx/relic_ep4_mul.c
+++ b/src/epx/relic_ep4_mul.c
@@ -24,20 +24,17 @@
/**
* @file
*
- * Implementation of point multiplication on prime elliptic curves over
- * quadratic extensions.
+ * Implementation of point multiplication on prime elliptic curves over a
+ * quartic extension field.
*
* @ingroup epx
*/
-
#include "relic_core.h"
/*============================================================================*/
/* Private definitions */
/*============================================================================*/
-#if EP_MUL == LWNAF || !defined(STRIP)
-
#if defined(EP_ENDOM)
static void ep4_psi(ep4_t r, const ep4_t p) {
@@ -53,6 +50,8 @@ static void ep4_psi(ep4_t r, const ep4_t p) {
RLC_TRY {
ep4_new(q);
+ ep4_copy(r, p);
+
switch (ep_curve_is_pairf()) {
case EP_K16:
/* u = (2*p^5 - p) mod r */
@@ -81,6 +80,8 @@ static void ep4_psi(ep4_t r, const ep4_t p) {
}
}
+#if EP_MUL == LWNAF || !defined(STRIP)
+
static void ep4_mul_glv_imp(ep4_t r, const ep4_t p, const bn_t k) {
size_t l, _l[8];
bn_t n, _k[8], u;
@@ -154,10 +155,133 @@ static void ep4_mul_glv_imp(ep4_t r, const ep4_t p, const bn_t k) {
}
}
+#endif /* EP_MUL == LWNAF */
+
+#if EP_MUL == LWREG || !defined(STRIP)
+
+static void ep4_mul_reg_gls(ep4_t r, const ep4_t p, const bn_t k) {
+ int8_t reg[8][RLC_FP_BITS + 1], b[8], s[8], c0, n0;
+ ep4_t q, w, t[8][1 << (RLC_WIDTH - 2)];
+ bn_t n, _k[8], u;
+ size_t l, len, _l[8];
+
+ bn_null(n);
+ bn_null(u);
+ ep4_null(q);
+ ep4_null(w);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(u);
+ ep4_new(q);
+ ep4_new(w);
+ for (size_t i = 0; i < 8; i++) {
+ bn_null(_k[i]);
+ bn_new(_k[i]);
+ for (size_t j = 0; j < (1 << (RLC_WIDTH - 2)); j++) {
+ ep4_null(t[i][j]);
+ ep4_new(t[i][j]);
+ }
+ }
+
+ ep4_curve_get_ord(n);
+ fp_prime_get_par(u);
+ bn_mod(_k[0], k, n);
+ bn_rec_frb(_k, 8, _k[0], u, n, ep_curve_is_pairf() == EP_BN);
+
+ l = 0;
+ /* Make some extra room for BN curves that grow subscalars by 1. */
+ len = bn_bits(u) + (ep_curve_is_pairf() == EP_BN);
+ ep4_norm(t[0][0], p);
+ for (size_t i = 0; i < 8; i++) {
+ s[i] = bn_sign(_k[i]);
+ bn_abs(_k[i], _k[i]);
+ b[i] = bn_is_even(_k[i]);
+ _k[i]->dp[0] |= b[i];
+
+ _l[i] = RLC_FP_BITS + 1;
+ bn_rec_reg(reg[i], &_l[i], _k[i], len, RLC_WIDTH);
+ l = RLC_MAX(l, _l[i]);
+
+ /* Apply Frobenius before flipping sign to build table. */
+ if (i > 0) {
+ ep4_psi(t[i][0], t[i - 1][0]);
+ }
+ }
+
+ for (size_t i = 0; i < 8; i++) {
+ ep4_neg(q, t[i][0]);
+ fp4_copy_sec(q->y, t[i][0]->y, s[i] == RLC_POS);
+ ep4_tab(t[i], q, RLC_WIDTH);
+ }
+
+#if defined(EP_MIXED)
+ fp4_set_dig(w->z, 1);
+ w->coord = BASIC;
+#else
+ w->coord = = EP_ADD;
+#endif
+
+ ep4_set_infty(r);
+ for (int j = l - 1; j >= 0; j--) {
+ for (size_t i = 0; i < RLC_WIDTH - 1; i++) {
+ ep4_dbl(r, r);
+ }
+
+ for (size_t i = 0; i < 8; i++) {
+ n0 = reg[i][j];
+ c0 = (n0 >> 7);
+ n0 = ((n0 ^ c0) - c0) >> 1;
+
+ for (size_t m = 0; m < (1 << (RLC_WIDTH - 2)); m++) {
+ fp4_copy_sec(w->x, t[i][m]->x, m == n0);
+ fp4_copy_sec(w->y, t[i][m]->y, m == n0);
+ #if !defined(EP_MIXED)
+ fp4_copy_sec(w->z, t[i][m]->z, m == n0);
+ #endif
+ }
+
+ ep4_neg(q, w);
+ fp4_copy_sec(q->y, w->y, c0 == 0);
+ ep4_add(r, r, q);
+ }
+ }
+
+ for (size_t i = 0; i < 8; i++) {
+ /* Tables are built with points already negated, so no need here. */
+ ep4_sub(q, r, t[i][0]);
+ fp4_copy_sec(r->x, q->x, b[i]);
+ fp4_copy_sec(r->y, q->y, b[i]);
+ fp4_copy_sec(r->z, q->z, b[i]);
+ }
+
+ /* Convert r to affine coordinates. */
+ ep4_norm(r, r);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ bn_free(u);
+ ep4_free(q);
+ ep4_free(w);
+ for (int i = 0; i < 4; i++) {
+ bn_free(_k[i]);
+ for (size_t j = 0; j < (1 << (RLC_WIDTH - 2)); j++) {
+ ep4_free(t[i][j]);
+ }
+ }
+ }
+}
+
+#endif /* EP_MUL == LWREG */
#endif /* EP_ENDOM */
#if defined(EP_PLAIN) || defined(EP_SUPER)
+#if EP_MUL == LWNAF || !defined(STRIP)
+
static void ep4_mul_naf_imp(ep4_t r, const ep4_t p, const bn_t k) {
int i, n;
int8_t naf[RLC_FP_BITS + 1];
@@ -206,9 +330,95 @@ static void ep4_mul_naf_imp(ep4_t r, const ep4_t p, const bn_t k) {
}
}
-#endif /* EP_PLAIN || EP_SUPER */
#endif /* EP_MUL == LWNAF */
+#if EP_MUL == LWREG || !defined(STRIP)
+
+static void ep4_mul_reg_imp(ep4_t r, const ep4_t p, const bn_t k) {
+ bn_t _k;
+ int8_t s, reg[1 + RLC_CEIL(RLC_FP_BITS + 1, RLC_WIDTH - 1)];
+ ep4_t t[1 << (RLC_WIDTH - 2)], u, v;
+ size_t l, n;
+
+ bn_null(_k);
+
+ RLC_TRY {
+ bn_new(_k);
+ ep4_new(u);
+ ep4_new(v);
+ /* Prepare the precomputation table. */
+ for (size_t i = 0; i < (1 << (RLC_WIDTH - 2)); i++) {
+ ep4_null(t[i]);
+ ep4_new(t[i]);
+ }
+ /* Compute the precomputation table. */
+ ep4_tab(t, p, RLC_WIDTH);
+
+ ep4_curve_get_ord(_k);
+ n = bn_bits(_k);
+
+ /* Make a copy of the scalar for processing. */
+ bn_abs(_k, k);
+ _k->dp[0] |= 1;
+
+ /* Compute the regular w-NAF representation of k. */
+ l = RLC_CEIL(n, RLC_WIDTH - 1) + 1;
+ bn_rec_reg(reg, &l, _k, n, RLC_WIDTH);
+
+#if defined(EP_MIXED)
+ fp4_set_dig(u->z, 1);
+ u->coord = BASIC;
+#else
+ u->coord = EP_ADD;
+#endif
+ ep4_set_infty(r);
+ for (int i = l - 1; i >= 0; i--) {
+ for (size_t j = 0; j < RLC_WIDTH - 1; j++) {
+ ep4_dbl(r, r);
+ }
+
+ n = reg[i];
+ s = (n >> 7);
+ n = ((n ^ s) - s) >> 1;
+
+ for (size_t j = 0; j < (1 << (RLC_WIDTH - 2)); j++) {
+ fp4_copy_sec(u->x, t[j]->x, j == n);
+ fp4_copy_sec(u->y, t[j]->y, j == n);
+#if !defined(EP_MIXED)
+ fp_copy_sec(u->z, t[j]->z, j == n);
+#endif
+ }
+ ep4_neg(v, u);
+ fp4_copy_sec(u->y, v->y, s != 0);
+ ep4_add(r, r, u);
+ }
+ /* t[0] has an unmodified copy of p. */
+ ep4_sub(u, r, t[0]);
+ fp4_copy_sec(r->x, u->x, bn_is_even(k));
+ fp4_copy_sec(r->y, u->y, bn_is_even(k));
+ fp4_copy_sec(r->z, u->z, bn_is_even(k));
+ /* Convert r to affine coordinates. */
+ ep4_norm(r, r);
+ ep4_neg(u, r);
+ fp4_copy_sec(r->y, u->y, bn_sign(k) == RLC_NEG);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ /* Free the precomputation table. */
+ for (size_t i = 0; i < (1 << (RLC_WIDTH - 2)); i++) {
+ ep4_free(t[i]);
+ }
+ bn_free(_k);
+ ep4_free(u);
+ ep4_free(v);
+ }
+}
+
+#endif /* EP_MUL == LWREG */
+#endif /* EP_PLAIN || EP_SUPER */
+
/*============================================================================*/
/* Public definitions */
/*============================================================================*/
@@ -371,7 +581,7 @@ void ep4_mul_monty(ep4_t r, const ep4_t p, const bn_t k) {
bn_abs(l, _k);
bn_add(l, l, n);
bn_add(n, l, n);
- dv_swap_cond(l->dp, n->dp, RLC_MAX(l->used, n->used),
+ dv_swap_sec(l->dp, n->dp, RLC_MAX(l->used, n->used),
bn_get_bit(l, bits) == 0);
l->used = RLC_SEL(l->used, n->used, bn_get_bit(l, bits) == 0);
@@ -384,32 +594,32 @@ void ep4_mul_monty(ep4_t r, const ep4_t p, const bn_t k) {
for (int i = bits - 1; i >= 0; i--) {
int j = bn_get_bit(l, i);
- dv_swap_cond(t[0]->x[0][0], t[1]->x[0][0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->x[0][1], t[1]->x[0][1], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->x[1][0], t[1]->x[1][0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->x[1][1], t[1]->x[1][1], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y[0][0], t[1]->y[0][0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y[0][1], t[1]->y[0][1], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y[1][0], t[1]->y[1][0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y[1][1], t[1]->y[1][1], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z[0][0], t[1]->z[0][0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z[0][1], t[1]->z[0][1], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z[1][0], t[1]->z[1][0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z[1][1], t[1]->z[1][1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x[0][0], t[1]->x[0][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x[0][1], t[1]->x[0][1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x[1][0], t[1]->x[1][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x[1][1], t[1]->x[1][1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y[0][0], t[1]->y[0][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y[0][1], t[1]->y[0][1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y[1][0], t[1]->y[1][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y[1][1], t[1]->y[1][1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z[0][0], t[1]->z[0][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z[0][1], t[1]->z[0][1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z[1][0], t[1]->z[1][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z[1][1], t[1]->z[1][1], RLC_FP_DIGS, j ^ 1);
ep4_add(t[0], t[0], t[1]);
ep4_dbl(t[1], t[1]);
- dv_swap_cond(t[0]->x[0][0], t[1]->x[0][0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->x[0][1], t[1]->x[0][1], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->x[1][0], t[1]->x[1][0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->x[1][1], t[1]->x[1][1], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y[0][0], t[1]->y[0][0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y[0][1], t[1]->y[0][1], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y[1][0], t[1]->y[1][0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y[1][1], t[1]->y[1][1], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z[0][0], t[1]->z[0][0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z[0][1], t[1]->z[0][1], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z[1][0], t[1]->z[1][0], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z[1][1], t[1]->z[1][1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x[0][0], t[1]->x[0][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x[0][1], t[1]->x[0][1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x[1][0], t[1]->x[1][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x[1][1], t[1]->x[1][1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y[0][0], t[1]->y[0][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y[0][1], t[1]->y[0][1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y[1][0], t[1]->y[1][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y[1][1], t[1]->y[1][1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z[0][0], t[1]->z[0][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z[0][1], t[1]->z[0][1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z[1][0], t[1]->z[1][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z[1][1], t[1]->z[1][1], RLC_FP_DIGS, j ^ 1);
}
ep4_norm(r, t[0]);
@@ -449,6 +659,28 @@ void ep4_mul_lwnaf(ep4_t r, const ep4_t p, const bn_t k) {
#endif
+#if EP_MUL == LWREG || !defined(STRIP)
+
+void ep4_mul_lwreg(ep4_t r, const ep4_t p, const bn_t k) {
+ if (bn_is_zero(k) || ep4_is_infty(p)) {
+ ep4_set_infty(r);
+ return;
+ }
+
+#if defined(EP_ENDOM)
+ if (ep_curve_is_endom()) {
+ ep4_mul_reg_gls(r, p, k);
+ return;
+ }
+#endif
+
+#if defined(EP_PLAIN) || defined(EP_SUPER)
+ ep4_mul_reg_imp(r, p, k);
+#endif
+}
+
+#endif
+
void ep4_mul_gen(ep4_t r, const bn_t k) {
if (bn_is_zero(k)) {
ep4_set_infty(r);
diff --git a/src/epx/relic_ep4_mul_cof.c b/src/epx/relic_ep4_mul_cof.c
index 65d4f7f64..459a64f87 100644
--- a/src/epx/relic_ep4_mul_cof.c
+++ b/src/epx/relic_ep4_mul_cof.c
@@ -25,14 +25,13 @@
* @file
*
* Implementation of point multiplication of a prime elliptic curve over a
- * quartic extension by the curve cofactor.
+ * quartic extension field by the curve cofactor.
*
* @ingroup epx
*/
#include "relic_core.h"
#include "relic_md.h"
-#include "relic_tmpl_map.h"
/*============================================================================*/
/* Public definitions */
@@ -370,7 +369,7 @@ void ep4_mul_cof(ep4_t r, const ep4_t p) {
default:
/* Now, multiply by cofactor to get the correct group. */
ep4_curve_get_cof(k);
- ep4_mul_basic(r, p, k);
+ ep4_mul_big(r, p, k);
break;
}
} RLC_CATCH_ANY {
diff --git a/src/epx/relic_ep4_mul_fix.c b/src/epx/relic_ep4_mul_fix.c
index 33b8dac4c..9aa789bbb 100644
--- a/src/epx/relic_ep4_mul_fix.c
+++ b/src/epx/relic_ep4_mul_fix.c
@@ -25,7 +25,7 @@
* @file
*
* Implementation of fixed point multiplication on a prime elliptic curve over
- * a quartic extension.
+ * a quartic extension field.
*
* @ingroup epx
*/
diff --git a/src/epx/relic_ep4_mul_sim.c b/src/epx/relic_ep4_mul_sim.c
index 719332f38..ff4c62c3b 100644
--- a/src/epx/relic_ep4_mul_sim.c
+++ b/src/epx/relic_ep4_mul_sim.c
@@ -25,7 +25,7 @@
* @file
*
* Implementation of simultaneous point multiplication on a prime elliptic
- * curve over a quartic extension.
+ * curve over a quartic extension field.
*
* @ingroup epx
*/
diff --git a/src/epx/relic_ep4_neg.c b/src/epx/relic_ep4_neg.c
index 604fc116e..f2cf6b952 100644
--- a/src/epx/relic_ep4_neg.c
+++ b/src/epx/relic_ep4_neg.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of point negation on elliptic prime curves over quartic
- * extensions.
+ * Implementation of point negation on elliptic prime curves over a quartic
+ * extension field.
*
* @ingroup epx
*/
diff --git a/src/epx/relic_ep4_norm.c b/src/epx/relic_ep4_norm.c
index ca2646dd5..6576d3ace 100644
--- a/src/epx/relic_ep4_norm.c
+++ b/src/epx/relic_ep4_norm.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of point normalization on prime elliptic curves over quartic
- * extensions.
+ * Implementation of point normalization on prime elliptic curves over a quartic
+ * extension field.
*
* @ingroup epx
*/
@@ -43,36 +43,45 @@
*
* @param r - the result.
* @param p - the point to normalize.
+ * @param inv - the flag to indicate if z is already inverted.
*/
-static void ep4_norm_imp(ep4_t r, const ep4_t p, int inverted) {
+static void ep4_norm_imp(ep4_t r, const ep4_t p, int inv) {
if (p->coord != BASIC) {
- fp4_t t0, t1;
+ fp4_t t;
- fp4_null(t0);
- fp4_null(t1);
+ fp4_null(t);
RLC_TRY {
+ fp4_new(t);
- fp4_new(t0);
- fp4_new(t1);
-
- if (inverted) {
- fp4_copy(t1, p->z);
+ if (inv) {
+ fp4_copy(r->z, p->z);
} else {
- fp4_inv(t1, p->z);
+ fp4_inv(r->z, p->z);
+ }
+
+ switch (p->coord) {
+ case PROJC:
+ fp4_mul(r->x, p->x, r->z);
+ fp4_mul(r->y, p->y, r->z);
+ break;
+ case JACOB:
+ fp4_sqr(t, r->z);
+ fp4_mul(r->x, p->x, t);
+ fp4_mul(t, t, r->z);
+ fp4_mul(r->y, p->y, t);
+ break;
+ default:
+ ep4_copy(r, p);
+ break;
}
- fp4_sqr(t0, t1);
- fp4_mul(r->x, p->x, t0);
- fp4_mul(t0, t0, t1);
- fp4_mul(r->y, p->y, t0);
fp4_set_dig(r->z, 1);
}
RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
}
RLC_FINALLY {
- fp4_free(t0);
- fp4_free(t1);
+ fp4_free(t);
}
}
@@ -92,17 +101,18 @@ void ep4_norm(ep4_t r, const ep4_t p) {
}
if (p->coord == BASIC) {
- /* If the point is represented in affine coordinates, we just copy it. */
+ /* If the point is represented in affine coordinates, just copy it. */
ep4_copy(r, p);
+ return;
}
#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
ep4_norm_imp(r, p, 0);
-#endif
+#endif /* EP_ADD == PROJC */
}
void ep4_norm_sim(ep4_t *r, const ep4_t *t, int n) {
int i;
- fp4_t *a = RLC_ALLOCA(fp4_t, n);
+ fp4_t* a = RLC_ALLOCA(fp4_t, n);
RLC_TRY {
if (a == NULL) {
@@ -114,18 +124,20 @@ void ep4_norm_sim(ep4_t *r, const ep4_t *t, int n) {
fp4_copy(a[i], t[i]->z);
}
- fp4_inv_sim(a, a, n);
+ fp4_inv_sim(a, (const fp4_t *)a, n);
for (i = 0; i < n; i++) {
fp4_copy(r[i]->x, t[i]->x);
fp4_copy(r[i]->y, t[i]->y);
- fp4_copy(r[i]->z, a[i]);
+ if (!ep4_is_infty(t[i])) {
+ fp4_copy(r[i]->z, a[i]);
+ }
}
#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
for (i = 0; i < n; i++) {
ep4_norm_imp(r[i], r[i], 1);
}
-#endif
+#endif /* EP_ADD == PROJC */
}
RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
diff --git a/src/epx/relic_ep4_util.c b/src/epx/relic_ep4_util.c
index c41642956..8564d9cca 100644
--- a/src/epx/relic_ep4_util.c
+++ b/src/epx/relic_ep4_util.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of comparison for points on prime elliptic curves over
- * quartic extensions.
+ * Implementation of comparison for points on prime elliptic curves over a
+ * quartic extension field.
*
* @ingroup epx
*/
@@ -89,13 +89,18 @@ void ep4_blind(ep4_t r, const ep4_t p) {
#if EP_ADD == BASIC
(void)rand;
ep4_copy(r, p);
-#else
+#elif EP_ADD == PROJC
+ fp4_mul(r->x, p->x, rand);
+ fp4_mul(r->y, p->y, rand);
+ fp4_mul(r->z, p->z, rand);
+ r->coord = PROJC;
+#elif EP_ADD == JACOB
fp4_mul(r->z, p->z, rand);
fp4_mul(r->y, p->y, rand);
fp4_sqr(rand, rand);
fp4_mul(r->x, r->x, rand);
fp4_mul(r->y, r->y, rand);
- r->coord = EP_ADD;
+ r->coord = JACOB;
#endif
} RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
@@ -104,17 +109,15 @@ void ep4_blind(ep4_t r, const ep4_t p) {
}
}
-void ep4_rhs(fp4_t rhs, const ep4_t p) {
- fp4_t t0, t1;
+void ep4_rhs(fp4_t rhs, const fp4_t x) {
+ fp4_t t0;
fp4_null(t0);
- fp4_null(t1);
RLC_TRY {
fp4_new(t0);
- fp4_new(t1);
- fp4_sqr(t0, p->x); /* x1^2 */
+ fp4_sqr(t0, x);
switch (ep4_curve_opt_a()) {
case RLC_ZERO:
@@ -130,17 +133,15 @@ void ep4_rhs(fp4_t rhs, const ep4_t p) {
fp_add_dig(t0[0][0], t0[0][0], 2);
break;
case RLC_TINY:
- ep4_curve_get_a(t1);
- fp4_mul_dig(t0, t0, t1[0][0][0]);
+ fp4_mul_dig(t0, t0, ep4_curve_get_a()[0][0][0]);
break;
#endif
default:
- ep4_curve_get_a(t1);
- fp4_add(t0, t0, t1);
+ fp4_add(t0, t0, ep4_curve_get_a());
break;
}
- fp4_mul(t0, t0, p->x); /* x1^3 + a * x */
+ fp4_mul(t0, t0, x);
switch (ep4_curve_opt_b()) {
case RLC_ZERO:
@@ -156,13 +157,11 @@ void ep4_rhs(fp4_t rhs, const ep4_t p) {
fp_add_dig(t0[0][0], t0[0][0], 2);
break;
case RLC_TINY:
- ep4_curve_get_b(t1);
- fp4_mul_dig(t0, t0, t1[0][0][0]);
+ fp4_mul_dig(t0, t0, ep4_curve_get_b()[0][0][0]);
break;
#endif
default:
- ep4_curve_get_b(t1);
- fp4_add(t0, t0, t1);
+ fp4_add(t0, t0, ep4_curve_get_b());
break;
}
@@ -171,11 +170,9 @@ void ep4_rhs(fp4_t rhs, const ep4_t p) {
RLC_THROW(ERR_CAUGHT);
} RLC_FINALLY {
fp4_free(t0);
- fp4_free(t1);
}
}
-
int ep4_on_curve(const ep4_t p) {
ep4_t t;
int r = 0;
@@ -187,7 +184,7 @@ int ep4_on_curve(const ep4_t p) {
ep4_norm(t, p);
- ep4_rhs(t->x, t);
+ ep4_rhs(t->x, t->x);
fp4_sqr(t->y, t->y);
r = (fp4_cmp(t->x, t->y) == RLC_EQ) || ep4_is_infty(p);
diff --git a/src/epx/relic_ep8_add.c b/src/epx/relic_ep8_add.c
index 15dde9000..687998124 100644
--- a/src/epx/relic_ep8_add.c
+++ b/src/epx/relic_ep8_add.c
@@ -24,13 +24,14 @@
/**
* @file
*
- * Implementation of addition on prime elliptic curves over quartic
- * extensions.
+ * Implementation of addition on prime elliptic curves over an octic extension
+ * field.
*
* @ingroup epx
*/
#include "relic_core.h"
+#include "relic_ep_add_tmpl.h"
/*============================================================================*/
/* Private definitions */
@@ -42,312 +43,62 @@
* Adds two points represented in affine coordinates on an ordinary prime
* elliptic curve.
*
- * @param r - the result.
- * @param s - the resulting slope.
- * @param p - the first point to add.
- * @param q - the second point to add.
+ * @param[out] r - the result.
+ * @param[out] s - the slope.
+ * @param[in] p - the first point to add.
+ * @param[in] q - the second point to add.
*/
-static void ep8_add_basic_imp(ep8_t r, fp8_t s, const ep8_t p, const ep8_t q) {
- fp8_t t0, t1, t2;
-
- fp8_null(t0);
- fp8_null(t1);
- fp8_null(t2);
-
- RLC_TRY {
- fp8_new(t0);
- fp8_new(t1);
- fp8_new(t2);
-
- /* t0 = x2 - x1. */
- fp8_sub(t0, q->x, p->x);
- /* t1 = y2 - y1. */
- fp8_sub(t1, q->y, p->y);
-
- /* If t0 is zero. */
- if (fp8_is_zero(t0)) {
- if (fp8_is_zero(t1)) {
- /* If t1 is zero, q = p, should have doubled. */
- ep8_dbl_slp_basic(r, s, p);
- } else {
- /* If t1 is not zero and t0 is zero, q = -p and r = infty. */
- ep8_set_infty(r);
- }
- } else {
- /* t2 = 1/(x2 - x1). */
- fp8_inv(t2, t0);
- /* t2 = lambda = (y2 - y1)/(x2 - x1). */
- fp8_mul(t2, t1, t2);
-
- /* x3 = lambda^2 - x2 - x1. */
- fp8_sqr(t1, t2);
- fp8_sub(t0, t1, p->x);
- fp8_sub(t0, t0, q->x);
-
- /* y3 = lambda * (x1 - x3) - y1. */
- fp8_sub(t1, p->x, t0);
- fp8_mul(t1, t2, t1);
- fp8_sub(r->y, t1, p->y);
-
- fp8_copy(r->x, t0);
- fp8_copy(r->z, p->z);
-
- if (s != NULL) {
- fp8_copy(s, t2);
- }
-
- r->coord = BASIC;
- }
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp8_free(t0);
- fp8_free(t1);
- fp8_free(t2);
- }
-}
+TMPL_ADD_BASIC_IMP(ep8, fp8);
#endif /* EP_ADD == BASIC */
-#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
+#if EP_ADD == PROJC || !defined(STRIP)
-#if defined(EP_MIXED) || !defined(STRIP)
+/**
+ * Adds a point represented in homogeneous coordinates to a point represented in
+ * affine coordinates on an ordinary prime elliptic curve.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the projective point.
+ * @param[in] q - the affine point.
+ */
+TMPL_ADD_PROJC_MIX(ep8, fp8);
/**
- * Adds a point represented in affine coordinates to a point represented in
- * projective coordinates.
+ * Adds two points represented in homogeneous coordinates on an ordinary prime
+ * elliptic curve.
*
- * @param r - the result.
- * @param s - the slope.
- * @param p - the affine point.
- * @param q - the projective point.
+ * @param[out] r - the result.
+ * @param[in] p - the first point to add.
+ * @param[in] q - the second point to add.
*/
-static void ep8_add_projc_mix(ep8_t r, const ep8_t p, const ep8_t q) {
- fp8_t t0, t1, t2, t3, t4, t5, t6;
+TMPL_ADD_PROJC_IMP(ep8, fp8);
- fp8_null(t0);
- fp8_null(t1);
- fp8_null(t2);
- fp8_null(t3);
- fp8_null(t4);
- fp8_null(t5);
- fp8_null(t6);
+#endif /* EP_ADD == PROJC */
- RLC_TRY {
- fp8_new(t0);
- fp8_new(t1);
- fp8_new(t2);
- fp8_new(t3);
- fp8_new(t4);
- fp8_new(t5);
- fp8_new(t6);
-
- if (p->coord != BASIC) {
- /* t0 = z1^2. */
- fp8_sqr(t0, p->z);
-
- /* t3 = U2 = x2 * z1^2. */
- fp8_mul(t3, q->x, t0);
-
- /* t1 = S2 = y2 * z1^3. */
- fp8_mul(t1, t0, p->z);
- fp8_mul(t1, t1, q->y);
-
- /* t3 = H = U2 - x1. */
- fp8_sub(t3, t3, p->x);
-
- /* t1 = R = 2 * (S2 - y1). */
- fp8_sub(t1, t1, p->y);
- } else {
- /* H = x2 - x1. */
- fp8_sub(t3, q->x, p->x);
-
- /* t1 = R = 2 * (y2 - y1). */
- fp8_sub(t1, q->y, p->y);
- }
-
- /* t2 = HH = H^2. */
- fp8_sqr(t2, t3);
-
- /* If E is zero. */
- if (fp8_is_zero(t3)) {
- if (fp8_is_zero(t1)) {
- /* If I is zero, p = q, should have doubled. */
- ep8_dbl_projc(r, p);
- } else {
- /* If I is not zero, q = -p, r = infinity. */
- ep8_set_infty(r);
- }
- } else {
- /* t5 = J = H * HH. */
- fp8_mul(t5, t3, t2);
-
- /* t4 = V = x1 * HH. */
- fp8_mul(t4, p->x, t2);
-
- /* x3 = R^2 - J - 2 * V. */
- fp8_sqr(r->x, t1);
- fp8_sub(r->x, r->x, t5);
- fp8_dbl(t6, t4);
- fp8_sub(r->x, r->x, t6);
-
- /* y3 = R * (V - x3) - Y1 * J. */
- fp8_sub(t4, t4, r->x);
- fp8_mul(t4, t4, t1);
- fp8_mul(t1, p->y, t5);
- fp8_sub(r->y, t4, t1);
-
- if (p->coord != BASIC) {
- /* z3 = z1 * H. */
- fp8_mul(r->z, p->z, t3);
- } else {
- /* z3 = H. */
- fp8_copy(r->z, t3);
- }
- }
- r->coord = PROJC;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp8_free(t0);
- fp8_free(t1);
- fp8_free(t2);
- fp8_free(t3);
- fp8_free(t4);
- fp8_free(t5);
- fp8_free(t6);
- }
-}
+#if EP_ADD == JACOB || !defined(STRIP)
-#endif
+/**
+ * Adds a point represented in Jacobian coordinates to a point represented in
+ * affine coordinates on an ordinary prime elliptic curve.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the projective point.
+ * @param[in] q - the affine point.
+ */
+TMPL_ADD_JACOB_MIX(ep8, fp8);
/**
- * Adds two points represented in projective coordinates on an ordinary prime
+ * Adds two points represented in Jacobian coordinates on an ordinary prime
* elliptic curve.
*
- * @param r - the result.
- * @param p - the first point to add.
- * @param q - the second point to add.
+ * @param[out] r - the result.
+ * @param[in] p - the first point to add.
+ * @param[in] q - the second point to add.
*/
-static void ep8_add_projc_imp(ep8_t r, const ep8_t p, const ep8_t q) {
-#if defined(EP_MIXED) && defined(STRIP)
- ep8_add_projc_mix(r, p, q);
-#else /* General addition. */
- fp8_t t0, t1, t2, t3, t4, t5, t6;
-
- fp8_null(t0);
- fp8_null(t1);
- fp8_null(t2);
- fp8_null(t3);
- fp8_null(t4);
- fp8_null(t5);
- fp8_null(t6);
+TMPL_ADD_JACOB_IMP(ep8, fp8);
- RLC_TRY {
- fp8_new(t0);
- fp8_new(t1);
- fp8_new(t2);
- fp8_new(t3);
- fp8_new(t4);
- fp8_new(t5);
- fp8_new(t6);
-
- if (q->coord == BASIC) {
- ep8_add_projc_mix(r, p, q);
- } else {
- /* t0 = z1^2. */
- fp8_sqr(t0, p->z);
-
- /* t1 = z2^2. */
- fp8_sqr(t1, q->z);
-
- /* t2 = U1 = x1 * z2^2. */
- fp8_mul(t2, p->x, t1);
-
- /* t3 = U2 = x2 * z1^2. */
- fp8_mul(t3, q->x, t0);
-
- /* t6 = z1^2 + z2^2. */
- fp8_add(t6, t0, t1);
-
- /* t0 = S2 = y2 * z1^3. */
- fp8_mul(t0, t0, p->z);
- fp8_mul(t0, t0, q->y);
-
- /* t1 = S1 = y1 * z2^3. */
- fp8_mul(t1, t1, q->z);
- fp8_mul(t1, t1, p->y);
-
- /* t3 = H = U2 - U1. */
- fp8_sub(t3, t3, t2);
-
- /* t0 = R = 2 * (S2 - S1). */
- fp8_sub(t0, t0, t1);
-
- fp8_dbl(t0, t0);
-
- /* If E is zero. */
- if (fp8_is_zero(t3)) {
- if (fp8_is_zero(t0)) {
- /* If I is zero, p = q, should have doubled. */
- ep8_dbl_projc(r, p);
- } else {
- /* If I is not zero, q = -p, r = infinity. */
- ep8_set_infty(r);
- }
- } else {
- /* t4 = I = (2*H)^2. */
- fp8_dbl(t4, t3);
- fp8_sqr(t4, t4);
-
- /* t5 = J = H * I. */
- fp8_mul(t5, t3, t4);
-
- /* t4 = V = U1 * I. */
- fp8_mul(t4, t2, t4);
-
- /* x3 = R^2 - J - 2 * V. */
- fp8_sqr(r->x, t0);
- fp8_sub(r->x, r->x, t5);
- fp8_dbl(t2, t4);
- fp8_sub(r->x, r->x, t2);
-
- /* y3 = R * (V - x3) - 2 * S1 * J. */
- fp8_sub(t4, t4, r->x);
- fp8_mul(t4, t4, t0);
- fp8_mul(t1, t1, t5);
- fp8_dbl(t1, t1);
- fp8_sub(r->y, t4, t1);
-
- /* z3 = ((z1 + z2)^2 - z1^2 - z2^2) * H. */
- fp8_add(r->z, p->z, q->z);
- fp8_sqr(r->z, r->z);
- fp8_sub(r->z, r->z, t6);
- fp8_mul(r->z, r->z, t3);
- }
- }
- r->coord = PROJC;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp8_free(t0);
- fp8_free(t1);
- fp8_free(t2);
- fp8_free(t3);
- fp8_free(t4);
- fp8_free(t5);
- fp8_free(t6);
- }
-#endif
-}
-
-#endif /* EP_ADD == PROJC */
+#endif /* EP_ADD == JACOB */
/*============================================================================*/
/* Public definitions */
@@ -385,7 +136,7 @@ void ep8_add_slp_basic(ep8_t r, fp8_t s, const ep8_t p, const ep8_t q) {
#endif
-#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
+#if EP_ADD == PROJC || !defined(STRIP)
void ep8_add_projc(ep8_t r, const ep8_t p, const ep8_t q) {
if (ep8_is_infty(p)) {
@@ -398,13 +149,25 @@ void ep8_add_projc(ep8_t r, const ep8_t p, const ep8_t q) {
return;
}
- if (p == q) {
- /* TODO: This is a quick hack. Should we fix this? */
- ep8_dbl(r, p);
+ ep8_add_projc_imp(r, p, q);
+}
+
+#endif
+
+#if EP_ADD == JACOB || !defined(STRIP)
+
+void ep8_add_jacob(ep8_t r, const ep8_t p, const ep8_t q) {
+ if (ep8_is_infty(p)) {
+ ep8_copy(r, q);
return;
}
- ep8_add_projc_imp(r, p, q);
+ if (ep8_is_infty(q)) {
+ ep8_copy(r, p);
+ return;
+ }
+
+ ep8_add_jacob_imp(r, p, q);
}
#endif
@@ -421,7 +184,6 @@ void ep8_sub(ep8_t r, const ep8_t p, const ep8_t q) {
RLC_TRY {
ep8_new(t);
-
ep8_neg(t, q);
ep8_add(r, p, t);
}
diff --git a/src/epx/relic_ep8_cmp.c b/src/epx/relic_ep8_cmp.c
index cf00e38a6..4e57b8a80 100644
--- a/src/epx/relic_ep8_cmp.c
+++ b/src/epx/relic_ep8_cmp.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of utilities for prime elliptic curves over quadratic
- * extensions.
+ * Implementation of utilities for prime elliptic curves over an octic
+ * extension field.
*
* @ingroup epx
*/
@@ -37,46 +37,68 @@
/*============================================================================*/
int ep8_cmp(const ep8_t p, const ep8_t q) {
- ep8_t r, s;
- int result = RLC_NE;
+ ep8_t r, s;
+ int result = RLC_NE;
if (ep8_is_infty(p) && ep8_is_infty(q)) {
return RLC_EQ;
}
- ep8_null(r);
- ep8_null(s);
+ ep8_null(r);
+ ep8_null(s);
- RLC_TRY {
- ep8_new(r);
- ep8_new(s);
+ RLC_TRY {
+ ep8_new(r);
+ ep8_new(s);
- if ((p->coord != BASIC) && (q->coord != BASIC)) {
- /* If the two points are not normalized, it is faster to compare
- * x1 * z2^2 == x2 * z1^2 and y1 * z2^3 == y2 * z1^3. */
- fp8_sqr(r->z, p->z);
- fp8_sqr(s->z, q->z);
- fp8_mul(r->x, p->x, s->z);
- fp8_mul(s->x, q->x, r->z);
- fp8_mul(r->z, r->z, p->z);
- fp8_mul(s->z, s->z, q->z);
- fp8_mul(r->y, p->y, s->z);
- fp8_mul(s->y, q->y, r->z);
- } else {
- ep8_norm(r, p);
- ep8_norm(s, q);
- }
+ switch (q->coord) {
+ case PROJC:
+ /* If q is in homogeneous projective coordinates, compute
+ * x1 * z2 and y1 * z2. */
+ fp8_mul(r->x, p->x, q->z);
+ fp8_mul(r->y, p->y, q->z);
+ break;
+ case JACOB:
+ /* If q is in Jacobian projective coordinates, compute
+ * x2 * z1^2 and y2 * z1^3. */
+ fp8_sqr(r->z, q->z);
+ fp8_mul(r->x, p->x, r->z);
+ fp8_mul(r->z, r->z, q->z);
+ fp8_mul(r->y, p->y, r->z);
+ break;
+ default:
+ ep8_copy(r, p);
+ break;
+ }
- if ((fp8_cmp(r->x, s->x) == RLC_EQ) &&
- (fp8_cmp(r->y, s->y) == RLC_EQ)) {
- result = RLC_EQ;
- }
- } RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- } RLC_FINALLY {
- ep8_free(r);
- ep8_free(s);
- }
+ switch (p->coord) {
+ /* Now do the same for the other point. */
+ case PROJC:
+ fp8_mul(s->x, q->x, p->z);
+ fp8_mul(s->y, q->y, p->z);
+ break;
+ case JACOB:
+ fp8_sqr(s->z, p->z);
+ fp8_mul(s->x, q->x, s->z);
+ fp8_mul(s->z, s->z, p->z);
+ fp8_mul(s->y, q->y, s->z);
+ break;
+ default:
+ ep8_copy(s, q);
+ break;
+ }
- return result;
+ if ((fp8_cmp(r->x, s->x) == RLC_EQ) && (fp8_cmp(r->y, s->y) == RLC_EQ)) {
+ result = RLC_EQ;
+ }
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ ep8_free(r);
+ ep8_free(s);
+ }
+
+ return result;
}
diff --git a/src/epx/relic_ep8_curve.c b/src/epx/relic_ep8_curve.c
index 90d130d07..02dae23b6 100644
--- a/src/epx/relic_ep8_curve.c
+++ b/src/epx/relic_ep8_curve.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of configuration of prime elliptic curves over octic
- * extensions.
+ * Implementation of configuration of prime elliptic curves over an octic
+ * extension field.
*
* @ingroup epx
*/
@@ -221,6 +221,49 @@ int ep8_curve_opt_b(void) {
return core_get()->ep8_opt_b;
}
+void ep8_curve_mul_a(fp8_t c, const fp8_t a) {
+ ctx_t *ctx = core_get();
+ switch (ctx->ep8_opt_a) {
+ case RLC_ZERO:
+ fp8_zero(c);
+ break;
+ case RLC_ONE:
+ fp8_copy(c, a);
+ break;
+ case RLC_TWO:
+ fp8_dbl(c, a);
+ break;
+#if FP_RDC != MONTY
+ case RLC_TINY:
+ fp8_mul_dig(c, a, ctx->ep8_a[0]);
+ break;
+#endif
+ default:
+ fp8_mul(c, a, ctx->ep8_a);
+ break;
+ }
+}
+
+void ep8_curve_mul_b(fp8_t c, const fp8_t a) {
+ ctx_t *ctx = core_get();
+ switch (ctx->ep8_opt_b) {
+ case RLC_ZERO:
+ fp8_zero(c);
+ break;
+ case RLC_ONE:
+ fp8_copy(c, a);
+ break;
+#if FP_RDC != MONTY
+ case RLC_TINY:
+ fp8_mul_dig(c, a, ctx->ep8_b[0]);
+ break;
+#endif
+ default:
+ fp8_mul(c, a, ctx->ep8_b);
+ break;
+ }
+}
+
int ep8_curve_is_twist(void) {
return core_get()->ep8_is_twist;
}
@@ -229,12 +272,12 @@ void ep8_curve_get_gen(ep8_t g) {
ep8_copy(g, core_get()->ep8_g);
}
-void ep8_curve_get_a(fp8_t a) {
- fp8_copy(a, core_get()->ep8_a);
+fp4_t *ep8_curve_get_a(void) {
+ return core_get()->ep8_a;
}
-void ep8_curve_get_b(fp8_t b) {
- fp8_copy(b, core_get()->ep8_b);
+fp4_t *ep8_curve_get_b(void) {
+ return core_get()->ep8_b;
}
void ep8_curve_get_ord(bn_t n) {
diff --git a/src/epx/relic_ep8_dbl.c b/src/epx/relic_ep8_dbl.c
index 0139e9f8d..76e62b41d 100644
--- a/src/epx/relic_ep8_dbl.c
+++ b/src/epx/relic_ep8_dbl.c
@@ -24,13 +24,14 @@
/**
* @file
*
- * Implementation of doubling on elliptic prime curves over quartic
- * extensions.
+ * Implementation of doubling on elliptic prime curves over an octic extension
+ * field.
*
* @ingroup epx
*/
#include "relic_core.h"
+#include "relic_ep_dbl_tmpl.h"
/*============================================================================*/
/* Private definitions */
@@ -43,201 +44,41 @@
* elliptic curve.
*
* @param[out] r - the result.
- * @param[out] s - the resulting slope.
+ * @param[out] s - the slope.
* @param[in] p - the point to double.
*/
-static void ep8_dbl_basic_imp(ep8_t r, fp8_t s, const ep8_t p) {
- fp8_t t0, t1, t2;
-
- fp8_null(t0);
- fp8_null(t1);
- fp8_null(t2);
-
- RLC_TRY {
- fp8_new(t0);
- fp8_new(t1);
- fp8_new(t2);
-
- /* t0 = 1/(2 * y1). */
- fp8_dbl(t0, p->y);
- fp8_inv(t0, t0);
-
- /* t1 = 3 * x1^2 + a. */
- fp8_sqr(t1, p->x);
- fp8_copy(t2, t1);
- fp8_dbl(t1, t1);
- fp8_add(t1, t1, t2);
-
- ep8_curve_get_a(t2);
- fp8_add(t1, t1, t2);
-
- /* t1 = (3 * x1^2 + a)/(2 * y1). */
- fp8_mul(t1, t1, t0);
-
- if (s != NULL) {
- fp8_copy(s, t1);
- }
-
- /* t2 = t1^2. */
- fp8_sqr(t2, t1);
-
- /* x3 = t1^2 - 2 * x1. */
- fp8_dbl(t0, p->x);
- fp8_sub(t0, t2, t0);
-
- /* y3 = t1 * (x1 - x3) - y1. */
- fp8_sub(t2, p->x, t0);
- fp8_mul(t1, t1, t2);
-
- fp8_sub(r->y, t1, p->y);
-
- fp8_copy(r->x, t0);
- fp8_copy(r->z, p->z);
-
- r->coord = BASIC;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp8_free(t0);
- fp8_free(t1);
- fp8_free(t2);
- }
-}
+TMPL_DBL_BASIC_IMP(ep8, fp8);
#endif /* EP_ADD == BASIC */
-#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
+#if EP_ADD == PROJC || !defined(STRIP)
/**
- * Doubles a point represented in affine coordinates on an ordinary prime
+ * Doubles a point represented in projective coordinates on an ordinary prime
* elliptic curve.
*
- * @param[out] r - the result.
- * @param[in] p - the point to double.
+ * @param r - the result.
+ * @param p - the point to double.
*/
-static void ep8_dbl_projc_imp(ep8_t r, const ep8_t p) {
- fp8_t t0, t1, t2, t3, t4, t5;
-
- fp8_null(t0);
- fp8_null(t1);
- fp8_null(t2);
- fp8_null(t3);
- fp8_null(t4);
- fp8_null(t5);
-
- RLC_TRY {
- fp8_new(t0);
- fp8_new(t1);
- fp8_new(t2);
- fp8_new(t3);
- fp8_new(t4);
- fp8_new(t5);
-
- if (ep_curve_opt_a() == RLC_ZERO) {
- fp8_sqr(t0, p->x);
- fp8_add(t2, t0, t0);
- fp8_add(t0, t2, t0);
-
- fp8_sqr(t3, p->y);
- fp8_mul(t1, t3, p->x);
- fp8_add(t1, t1, t1);
- fp8_add(t1, t1, t1);
- fp8_sqr(r->x, t0);
- fp8_add(t2, t1, t1);
- fp8_sub(r->x, r->x, t2);
- fp8_mul(r->z, p->z, p->y);
- fp8_add(r->z, r->z, r->z);
- fp8_add(t3, t3, t3);
-
- fp8_sqr(t3, t3);
- fp8_add(t3, t3, t3);
- fp8_sub(t1, t1, r->x);
- fp8_mul(r->y, t0, t1);
- fp8_sub(r->y, r->y, t3);
- } else {
- /* dbl-2007-bl formulas: 1M + 8S + 1*a + 10add + 1*8 + 2*2 + 1*3 */
- /* http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-2007-bl */
-
- /* t0 = x1^2, t1 = y1^2, t2 = y1^4. */
- fp8_sqr(t0, p->x);
- fp8_sqr(t1, p->y);
- fp8_sqr(t2, t1);
-
- if (p->coord != BASIC) {
- /* t3 = z1^2. */
- fp8_sqr(t3, p->z);
+TMPL_DBL_PROJC_IMP(ep8, fp8);
- if (ep_curve_get_a() == RLC_ZERO) {
- /* z3 = 2 * y1 * z1. */
- fp8_mul(r->z, p->y, p->z);
- fp8_dbl(r->z, r->z);
- } else {
- /* z3 = (y1 + z1)^2 - y1^2 - z1^2. */
- fp8_add(r->z, p->y, p->z);
- fp8_sqr(r->z, r->z);
- fp8_sub(r->z, r->z, t1);
- fp8_sub(r->z, r->z, t3);
- }
- } else {
- /* z3 = 2 * y1. */
- fp8_dbl(r->z, p->y);
- }
-
- /* t4 = S = 2*((x1 + y1^2)^2 - x1^2 - y1^4). */
- fp8_add(t4, p->x, t1);
- fp8_sqr(t4, t4);
- fp8_sub(t4, t4, t0);
- fp8_sub(t4, t4, t2);
- fp8_dbl(t4, t4);
-
- /* t5 = M = 3 * x1^2 + a * z1^4. */
- fp8_dbl(t5, t0);
- fp8_add(t5, t5, t0);
- if (p->coord != BASIC) {
- fp8_sqr(t3, t3);
- ep8_curve_get_a(t1);
- fp8_mul(t1, t3, t1);
- fp8_add(t5, t5, t1);
- } else {
- ep8_curve_get_a(t1);
- fp8_add(t5, t5, t1);
- }
-
- /* x3 = T = M^2 - 2 * S. */
- fp8_sqr(r->x, t5);
- fp8_dbl(t1, t4);
- fp8_sub(r->x, r->x, t1);
+#endif /* EP_ADD == PROJC */
- /* y3 = M * (S - T) - 8 * y1^4. */
- fp8_dbl(t2, t2);
- fp8_dbl(t2, t2);
- fp8_dbl(t2, t2);
- fp8_sub(t4, t4, r->x);
- fp8_mul(t5, t5, t4);
- fp8_sub(r->y, t5, t2);
- }
+#if EP_ADD == JACOB || !defined(STRIP)
- r->coord = PROJC;
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp8_free(t0);
- fp8_free(t1);
- fp8_free(t2);
- fp8_free(t3);
- fp8_free(t4);
- fp8_free(t5);
- }
-}
+/**
+ * Doubles a point represented in Jacobian coordinates on an ordinary prime
+ * elliptic curve.
+ *
+ * @param r - the result.
+ * @param p - the point to double.
+ */
+TMPL_DBL_JACOB_IMP(ep8, fp8);
-#endif /* EP_ADD == PROJC */
+#endif /* EP_ADD == JACOB */
/*============================================================================*/
- /* Public definitions */
+/* Public definitions */
/*============================================================================*/
#if EP_ADD == BASIC || !defined(STRIP)
@@ -247,7 +88,6 @@ void ep8_dbl_basic(ep8_t r, const ep8_t p) {
ep8_set_infty(r);
return;
}
-
ep8_dbl_basic_imp(r, NULL, p);
}
@@ -262,7 +102,7 @@ void ep8_dbl_slp_basic(ep8_t r, fp8_t s, const ep8_t p) {
#endif
-#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
+#if EP_ADD == PROJC || !defined(STRIP)
void ep8_dbl_projc(ep8_t r, const ep8_t p) {
if (ep8_is_infty(p)) {
@@ -274,3 +114,16 @@ void ep8_dbl_projc(ep8_t r, const ep8_t p) {
}
#endif
+
+#if EP_ADD == JACOB || !defined(STRIP)
+
+void ep8_dbl_jacob(ep8_t r, const ep8_t p) {
+ if (ep8_is_infty(p)) {
+ ep8_set_infty(r);
+ return;
+ }
+
+ ep8_dbl_jacob_imp(r, p);
+}
+
+#endif
diff --git a/src/epx/relic_ep8_frb.c b/src/epx/relic_ep8_frb.c
index 1cd8c4f72..4d3e4ed43 100644
--- a/src/epx/relic_ep8_frb.c
+++ b/src/epx/relic_ep8_frb.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of frobenius action on prime elliptic curves over
- * quartic extensions.
+ * Implementation of frobenius action on prime elliptic curves over an octic
+ * extension field.
*
* @ingroup epx
*/
diff --git a/src/epx/relic_ep8_map.c b/src/epx/relic_ep8_map.c
index ce8420a74..05f11180d 100644
--- a/src/epx/relic_ep8_map.c
+++ b/src/epx/relic_ep8_map.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of hashing to a prime elliptic curve over a quadratic
- * extension.
+ * Implementation of hashing to a prime elliptic curve over an octic extension
+ * field.
*
* @ingroup epx
*/
@@ -124,33 +124,17 @@ void ep8_map(ep8_t p, const uint8_t *msg, size_t len) {
fp8_sqr(z1, z1);
fp8_add(z1, z1, u);
- ep8_curve_get_b(w);
-
- fp8_sqr(t, x1);
- fp8_mul(t, t, x1);
- fp8_add(t, t, w);
-
- fp8_sqr(u, y1);
- fp8_mul(u, u, y1);
- fp8_add(u, u, w);
-
- fp8_sqr(v, z1);
- fp8_mul(v, v, z1);
- fp8_add(v, v, w);
+ ep8_rhs(t, x1);
+ ep8_rhs(u, y1);
+ ep8_rhs(v, z1);
c2 = fp8_is_sqr(u);
c3 = fp8_is_sqr(v);
- for (int i = 0; i < 2; i++) {
- for (int j = 0; j < 2; j++) {
- for (int l = 0; l < 2; l++) {
- dv_swap_cond(x1[i][j][l], y1[i][j][l], RLC_FP_DIGS, c2);
- dv_swap_cond(t[i][j][l], u[i][j][l], RLC_FP_DIGS, c2);
- dv_swap_cond(x1[i][j][l], z1[i][j][l], RLC_FP_DIGS, c3);
- dv_swap_cond(t[i][j][l], v[i][j][l], RLC_FP_DIGS, c3);
- }
- }
- }
+ fp8_copy_sec(t, u, c2);
+ fp8_copy_sec(x1, y1, c2);
+ fp8_copy_sec(t, v, c3);
+ fp8_copy_sec(x1, z1, c3);
if (!fp8_srt(t, t)) {
RLC_THROW(ERR_NO_VALID);
@@ -172,13 +156,7 @@ void ep8_map(ep8_t p, const uint8_t *msg, size_t len) {
}
fp8_neg(u, t);
- for (int i = 0; i < 2; i++) {
- for (int j = 0; j < 2; j++) {
- for (int l = 0; l < 2; l++) {
- dv_swap_cond(t[i][j][l], u[i][j][l], RLC_FP_DIGS, sign);
- }
- }
- }
+ fp8_copy_sec(t, u, sign);
fp8_copy(p->x, x1);
fp8_copy(p->y, t);
diff --git a/src/epx/relic_ep8_mul.c b/src/epx/relic_ep8_mul.c
index 8e0b0f60a..5300e8933 100644
--- a/src/epx/relic_ep8_mul.c
+++ b/src/epx/relic_ep8_mul.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of point multiplication on prime elliptic curves over
- * quadratic extensions.
+ * Implementation of point multiplication on prime elliptic curves over an
+ * octic extension field.
*
* @ingroup epx
*/
@@ -36,10 +36,10 @@
/* Private definitions */
/*============================================================================*/
-#if EP_MUL == LWNAF || !defined(STRIP)
-
#if defined(EP_ENDOM)
+#if EP_MUL == LWNAF || !defined(STRIP)
+
static void ep8_mul_glv_imp(ep8_t r, const ep8_t p, const bn_t k) {
size_t l, _l[16];
bn_t n, _k[16], u;
@@ -106,14 +106,136 @@ static void ep8_mul_glv_imp(ep8_t r, const ep8_t p, const bn_t k) {
bn_free(_k[i]);
ep8_free(q[i]);
}
+ }
+}
+
+#endif /* EP_MUL == LWNAF */
+
+#if EP_MUL == LWREG || !defined(STRIP)
+
+static void ep8_mul_reg_gls(ep8_t r, const ep8_t p, const bn_t k) {
+ int8_t reg[16][RLC_FP_BITS + 1], b[16], s[16], c0, n0;
+ ep8_t q, w, t[16][1 << (RLC_WIDTH - 2)];
+ bn_t n, _k[16], u;
+ size_t l, len, _l[16];
+
+ bn_null(n);
+ bn_null(u);
+ ep8_null(q);
+ ep8_null(w);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(u);
+ ep8_new(q);
+ ep8_new(w);
+ for (size_t i = 0; i < 16; i++) {
+ bn_null(_k[i]);
+ bn_new(_k[i]);
+ for (size_t j = 0; j < (1 << (RLC_WIDTH - 2)); j++) {
+ ep8_null(t[i][j]);
+ ep8_new(t[i][j]);
+ }
+ }
+
+ ep8_curve_get_ord(n);
+ fp_prime_get_par(u);
+ bn_mod(_k[0], k, n);
+ bn_rec_frb(_k, 16, _k[0], u, n, ep_curve_is_pairf() == EP_BN);
+
+ l = 0;
+ /* Make some extra room for BN curves that grow subscalars by 1. */
+ len = bn_bits(u) + (ep_curve_is_pairf() == EP_BN);
+ ep8_norm(t[0][0], p);
+ for (size_t i = 0; i < 16; i++) {
+ s[i] = bn_sign(_k[i]);
+ bn_abs(_k[i], _k[i]);
+ b[i] = bn_is_even(_k[i]);
+ _k[i]->dp[0] |= b[i];
+
+ _l[i] = RLC_FP_BITS + 1;
+ bn_rec_reg(reg[i], &_l[i], _k[i], len, RLC_WIDTH);
+ l = RLC_MAX(l, _l[i]);
+
+ /* Apply Frobenius before flipping sign to build table. */
+ if (i > 0) {
+ ep8_frb(t[i][0], t[i - 1][0], 1);
+ }
+ }
+
+ for (size_t i = 0; i < 16; i++) {
+ ep8_neg(q, t[i][0]);
+ fp8_copy_sec(q->y, t[i][0]->y, s[i] == RLC_POS);
+ ep8_tab(t[i], q, RLC_WIDTH);
+ }
+
+#if defined(EP_MIXED)
+ fp8_set_dig(w->z, 1);
+ w->coord = BASIC;
+#else
+ w->coord = = EP_ADD;
+#endif
+
+ ep8_set_infty(r);
+ for (int j = l - 1; j >= 0; j--) {
+ for (size_t i = 0; i < RLC_WIDTH - 1; i++) {
+ ep8_dbl(r, r);
+ }
+
+ for (size_t i = 0; i < 16; i++) {
+ n0 = reg[i][j];
+ c0 = (n0 >> 7);
+ n0 = ((n0 ^ c0) - c0) >> 1;
+
+ for (size_t m = 0; m < (1 << (RLC_WIDTH - 2)); m++) {
+ fp8_copy_sec(w->x, t[i][m]->x, m == n0);
+ fp8_copy_sec(w->y, t[i][m]->y, m == n0);
+ #if !defined(EP_MIXED)
+ fp8_copy_sec(w->z, t[i][m]->z, m == n0);
+ #endif
+ }
+
+ ep8_neg(q, w);
+ fp8_copy_sec(q->y, w->y, c0 == 0);
+ ep8_add(r, r, q);
+ }
+ }
+ for (size_t i = 0; i < 16; i++) {
+ /* Tables are built with points already negated, so no need here. */
+ ep8_sub(q, r, t[i][0]);
+ fp8_copy_sec(r->x, q->x, b[i]);
+ fp8_copy_sec(r->y, q->y, b[i]);
+ fp8_copy_sec(r->z, q->z, b[i]);
+ }
+
+ /* Convert r to affine coordinates. */
+ ep8_norm(r, r);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ bn_free(u);
+ ep8_free(q);
+ ep8_free(w);
+ for (int i = 0; i < 16; i++) {
+ bn_free(_k[i]);
+ for (size_t j = 0; j < (1 << (RLC_WIDTH - 2)); j++) {
+ ep8_free(t[i][j]);
+ }
+ }
}
}
+#endif /* EP_MUL == LWREG */
#endif /* EP_ENDOM */
#if defined(EP_PLAIN) || defined(EP_SUPER)
+#if EP_MUL == LWNAF || !defined(STRIP)
+
static void ep8_mul_naf_imp(ep8_t r, const ep8_t p, const bn_t k) {
int i, n;
int8_t naf[RLC_FP_BITS + 1];
@@ -162,9 +284,95 @@ static void ep8_mul_naf_imp(ep8_t r, const ep8_t p, const bn_t k) {
}
}
-#endif /* EP_PLAIN || EP_SUPER */
#endif /* EP_MUL == LWNAF */
+#if EP_MUL == LWREG || !defined(STRIP)
+
+static void ep8_mul_reg_imp(ep8_t r, const ep8_t p, const bn_t k) {
+ bn_t _k;
+ int8_t s, reg[1 + RLC_CEIL(RLC_FP_BITS + 1, RLC_WIDTH - 1)];
+ ep8_t t[1 << (RLC_WIDTH - 2)], u, v;
+ size_t l, n;
+
+ bn_null(_k);
+
+ RLC_TRY {
+ bn_new(_k);
+ ep8_new(u);
+ ep8_new(v);
+ /* Prepare the precomputation table. */
+ for (size_t i = 0; i < (1 << (RLC_WIDTH - 2)); i++) {
+ ep8_null(t[i]);
+ ep8_new(t[i]);
+ }
+ /* Compute the precomputation table. */
+ ep8_tab(t, p, RLC_WIDTH);
+
+ ep8_curve_get_ord(_k);
+ n = bn_bits(_k);
+
+ /* Make a copy of the scalar for processing. */
+ bn_abs(_k, k);
+ _k->dp[0] |= 1;
+
+ /* Compute the regular w-NAF representation of k. */
+ l = RLC_CEIL(n, RLC_WIDTH - 1) + 1;
+ bn_rec_reg(reg, &l, _k, n, RLC_WIDTH);
+
+#if defined(EP_MIXED)
+ fp8_set_dig(u->z, 1);
+ u->coord = BASIC;
+#else
+ u->coord = EP_ADD;
+#endif
+ ep8_set_infty(r);
+ for (int i = l - 1; i >= 0; i--) {
+ for (size_t j = 0; j < RLC_WIDTH - 1; j++) {
+ ep8_dbl(r, r);
+ }
+
+ n = reg[i];
+ s = (n >> 7);
+ n = ((n ^ s) - s) >> 1;
+
+ for (size_t j = 0; j < (1 << (RLC_WIDTH - 2)); j++) {
+ fp8_copy_sec(u->x, t[j]->x, j == n);
+ fp8_copy_sec(u->y, t[j]->y, j == n);
+#if !defined(EP_MIXED)
+ fp_copy_sec(u->z, t[j]->z, j == n);
+#endif
+ }
+ ep8_neg(v, u);
+ fp8_copy_sec(u->y, v->y, s != 0);
+ ep8_add(r, r, u);
+ }
+ /* t[0] has an unmodified copy of p. */
+ ep8_sub(u, r, t[0]);
+ fp8_copy_sec(r->x, u->x, bn_is_even(k));
+ fp8_copy_sec(r->y, u->y, bn_is_even(k));
+ fp8_copy_sec(r->z, u->z, bn_is_even(k));
+ /* Convert r to affine coordinates. */
+ ep8_norm(r, r);
+ ep8_neg(u, r);
+ fp8_copy_sec(r->y, u->y, bn_sign(k) == RLC_NEG);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ /* Free the precomputation table. */
+ for (size_t i = 0; i < (1 << (RLC_WIDTH - 2)); i++) {
+ ep8_free(t[i]);
+ }
+ bn_free(_k);
+ ep8_free(u);
+ ep8_free(v);
+ }
+}
+
+#endif /* EP_MUL == LWREG */
+#endif /* EP_PLAIN || EP_SUPER */
+
/*============================================================================*/
/* Public definitions */
/*============================================================================*/
@@ -327,7 +535,7 @@ void ep8_mul_monty(ep8_t r, const ep8_t p, const bn_t k) {
bn_abs(l, _k);
bn_add(l, l, n);
bn_add(n, l, n);
- dv_swap_cond(l->dp, n->dp, RLC_MAX(l->used, n->used),
+ dv_swap_sec(l->dp, n->dp, RLC_MAX(l->used, n->used),
bn_get_bit(l, bits) == 0);
l->used = RLC_SEL(l->used, n->used, bn_get_bit(l, bits) == 0);
@@ -343,9 +551,9 @@ void ep8_mul_monty(ep8_t r, const ep8_t p, const bn_t k) {
for (int l = 0; l < 2; l++) {
for (int m = 0; m < 2; m++) {
for (int n = 0; n < 2; n++) {
- dv_swap_cond(t[0]->x[l][m][n], t[1]->x[l][m][n], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y[l][m][n], t[1]->y[l][m][n], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z[l][m][n], t[1]->z[l][m][n], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x[l][m][n], t[1]->x[l][m][n], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y[l][m][n], t[1]->y[l][m][n], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z[l][m][n], t[1]->z[l][m][n], RLC_FP_DIGS, j ^ 1);
}
}
}
@@ -354,9 +562,9 @@ void ep8_mul_monty(ep8_t r, const ep8_t p, const bn_t k) {
for (int l = 0; l < 2; l++) {
for (int m = 0; m < 2; m++) {
for (int n = 0; n < 2; n++) {
- dv_swap_cond(t[0]->x[l][m][n], t[1]->x[l][m][n], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->y[l][m][n], t[1]->y[l][m][n], RLC_FP_DIGS, j ^ 1);
- dv_swap_cond(t[0]->z[l][m][n], t[1]->z[l][m][n], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->x[l][m][n], t[1]->x[l][m][n], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->y[l][m][n], t[1]->y[l][m][n], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0]->z[l][m][n], t[1]->z[l][m][n], RLC_FP_DIGS, j ^ 1);
}
}
}
@@ -399,6 +607,28 @@ void ep8_mul_lwnaf(ep8_t r, const ep8_t p, const bn_t k) {
#endif
+#if EP_MUL == LWREG || !defined(STRIP)
+
+void ep8_mul_lwreg(ep8_t r, const ep8_t p, const bn_t k) {
+ if (bn_is_zero(k) || ep8_is_infty(p)) {
+ ep8_set_infty(r);
+ return;
+ }
+
+#if defined(EP_ENDOM)
+ if (ep_curve_is_endom()) {
+ ep8_mul_reg_gls(r, p, k);
+ return;
+ }
+#endif
+
+#if defined(EP_PLAIN) || defined(EP_SUPER)
+ ep8_mul_reg_imp(r, p, k);
+#endif
+}
+
+#endif
+
void ep8_mul_gen(ep8_t r, const bn_t k) {
if (bn_is_zero(k)) {
ep8_set_infty(r);
diff --git a/src/epx/relic_ep8_mul_cof.c b/src/epx/relic_ep8_mul_cof.c
index 65f85a660..2d43beef6 100644
--- a/src/epx/relic_ep8_mul_cof.c
+++ b/src/epx/relic_ep8_mul_cof.c
@@ -25,14 +25,13 @@
* @file
*
* Implementation of point multiplication of a prime elliptic curve over an
- * octic extension by the curve cofactor.
+ * octic extension field by the curve cofactor.
*
* @ingroup epx
*/
#include "relic_core.h"
#include "relic_md.h"
-#include "relic_tmpl_map.h"
/*============================================================================*/
/* Public definitions */
diff --git a/src/epx/relic_ep8_mul_fix.c b/src/epx/relic_ep8_mul_fix.c
index 94e80748e..f11327a91 100644
--- a/src/epx/relic_ep8_mul_fix.c
+++ b/src/epx/relic_ep8_mul_fix.c
@@ -25,7 +25,7 @@
* @file
*
* Implementation of fixed point multiplication on a prime elliptic curve over
- * a quartic extension.
+ * an octic extension field.
*
* @ingroup epx
*/
diff --git a/src/epx/relic_ep8_mul_sim.c b/src/epx/relic_ep8_mul_sim.c
index db08c8cbc..e6febc105 100644
--- a/src/epx/relic_ep8_mul_sim.c
+++ b/src/epx/relic_ep8_mul_sim.c
@@ -25,7 +25,7 @@
* @file
*
* Implementation of simultaneous point multiplication on a prime elliptic
- * curve over a quartic extension.
+ * curve over an octic extension field.
*
* @ingroup epx
*/
diff --git a/src/epx/relic_ep8_neg.c b/src/epx/relic_ep8_neg.c
index 3f0f3061e..accaa0670 100644
--- a/src/epx/relic_ep8_neg.c
+++ b/src/epx/relic_ep8_neg.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of point negation on elliptic prime curves over quartic
- * extensions.
+ * Implementation of point negation on elliptic prime curves over an octic
+ * extension field.
*
* @ingroup epx
*/
diff --git a/src/epx/relic_ep8_norm.c b/src/epx/relic_ep8_norm.c
index a477299b2..a70382332 100644
--- a/src/epx/relic_ep8_norm.c
+++ b/src/epx/relic_ep8_norm.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of point normalization on prime elliptic curves over octic
- * extensions.
+ * Implementation of point normalization on prime elliptic curves over an octic
+ * extension field.
*
* @ingroup epx
*/
@@ -43,36 +43,45 @@
*
* @param r - the result.
* @param p - the point to normalize.
+ * @param inv - the flag to indicate if z is already inverted.
*/
-static void ep8_norm_imp(ep8_t r, const ep8_t p, int inverted) {
+static void ep8_norm_imp(ep8_t r, const ep8_t p, int inv) {
if (p->coord != BASIC) {
- fp8_t t0, t1;
+ fp8_t t;
- fp8_null(t0);
- fp8_null(t1);
+ fp8_null(t);
RLC_TRY {
+ fp8_new(t);
- fp8_new(t0);
- fp8_new(t1);
-
- if (inverted) {
- fp8_copy(t1, p->z);
+ if (inv) {
+ fp8_copy(r->z, p->z);
} else {
- fp8_inv(t1, p->z);
+ fp8_inv(r->z, p->z);
+ }
+
+ switch (p->coord) {
+ case PROJC:
+ fp8_mul(r->x, p->x, r->z);
+ fp8_mul(r->y, p->y, r->z);
+ break;
+ case JACOB:
+ fp8_sqr(t, r->z);
+ fp8_mul(r->x, p->x, t);
+ fp8_mul(t, t, r->z);
+ fp8_mul(r->y, p->y, t);
+ break;
+ default:
+ ep8_copy(r, p);
+ break;
}
- fp8_sqr(t0, t1);
- fp8_mul(r->x, p->x, t0);
- fp8_mul(t0, t0, t1);
- fp8_mul(r->y, p->y, t0);
fp8_set_dig(r->z, 1);
}
RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
}
RLC_FINALLY {
- fp8_free(t0);
- fp8_free(t1);
+ fp8_free(t);
}
}
@@ -92,17 +101,18 @@ void ep8_norm(ep8_t r, const ep8_t p) {
}
if (p->coord == BASIC) {
- /* If the point is represented in affine coordinates, we just copy it. */
+ /* If the point is represented in affine coordinates, just copy it. */
ep8_copy(r, p);
+ return;
}
-#if EP_ADD == PROJC || !defined(STRIP)
+#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
ep8_norm_imp(r, p, 0);
-#endif
+#endif /* EP_ADD == PROJC */
}
void ep8_norm_sim(ep8_t *r, const ep8_t *t, int n) {
int i;
- fp8_t *a = RLC_ALLOCA(fp8_t, n);
+ fp8_t* a = RLC_ALLOCA(fp8_t, n);
RLC_TRY {
if (a == NULL) {
@@ -114,17 +124,20 @@ void ep8_norm_sim(ep8_t *r, const ep8_t *t, int n) {
fp8_copy(a[i], t[i]->z);
}
- fp8_inv_sim(a, a, n);
+ fp8_inv_sim(a, (const fp8_t *)a, n);
for (i = 0; i < n; i++) {
fp8_copy(r[i]->x, t[i]->x);
fp8_copy(r[i]->y, t[i]->y);
- fp8_copy(r[i]->z, a[i]);
+ if (!ep8_is_infty(t[i])) {
+ fp8_copy(r[i]->z, a[i]);
+ }
}
-
+#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
for (i = 0; i < n; i++) {
ep8_norm_imp(r[i], r[i], 1);
}
+#endif /* EP_ADD == PROJC */
}
RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
diff --git a/src/epx/relic_ep8_util.c b/src/epx/relic_ep8_util.c
index 3b5e737f0..0c44ff045 100644
--- a/src/epx/relic_ep8_util.c
+++ b/src/epx/relic_ep8_util.c
@@ -24,8 +24,8 @@
/**
* @file
*
- * Implementation of comparison for points on prime elliptic curves over
- * quartic extensions.
+ * Implementation of comparison for points on prime elliptic curves over an
+ * octic extensions.
*
* @ingroup epx
*/
@@ -89,13 +89,18 @@ void ep8_blind(ep8_t r, const ep8_t p) {
#if EP_ADD == BASIC
(void)rand;
ep8_copy(r, p);
-#else
+#elif EP_ADD == PROJC
+ fp8_mul(r->x, p->x, rand);
+ fp8_mul(r->y, p->y, rand);
+ fp8_mul(r->z, p->z, rand);
+ r->coord = PROJC;
+#elif EP_ADD == JACOB
fp8_mul(r->z, p->z, rand);
fp8_mul(r->y, p->y, rand);
fp8_sqr(rand, rand);
fp8_mul(r->x, r->x, rand);
fp8_mul(r->y, r->y, rand);
- r->coord = EP_ADD;
+ r->coord = JACOB;
#endif
} RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
@@ -104,17 +109,15 @@ void ep8_blind(ep8_t r, const ep8_t p) {
}
}
-void ep8_rhs(fp8_t rhs, const ep8_t p) {
- fp8_t t0, t1;
+void ep8_rhs(fp8_t rhs, const fp8_t x) {
+ fp8_t t0;
fp8_null(t0);
- fp8_null(t1);
RLC_TRY {
fp8_new(t0);
- fp8_new(t1);
- fp8_sqr(t0, p->x); /* x1^2 */
+ fp8_sqr(t0, x);
switch (ep8_curve_opt_a()) {
case RLC_ZERO:
@@ -130,24 +133,16 @@ void ep8_rhs(fp8_t rhs, const ep8_t p) {
fp_add_dig(t0[0][0][0], t0[0][0][0], 2);
break;
case RLC_TINY:
- ep8_curve_get_a(t1);
- fp_mul_dig(t0[0][0][0], t0[0][0][0], t1[0][0][0][0]);
- fp_mul_dig(t0[0][0][1], t0[0][0][1], t1[0][0][0][0]);
- fp_mul_dig(t0[0][1][0], t0[0][1][0], t1[0][0][0][0]);
- fp_mul_dig(t0[0][1][1], t0[0][1][1], t1[0][0][0][0]);
- fp_mul_dig(t0[1][0][0], t0[1][0][0], t1[0][0][0][0]);
- fp_mul_dig(t0[1][0][1], t0[1][0][1], t1[0][0][0][0]);
- fp_mul_dig(t0[1][1][0], t0[1][1][0], t1[0][0][0][0]);
- fp_mul_dig(t0[1][1][1], t0[1][1][1], t1[0][0][0][0]);
+ fp_add_dig(t0[0][0][0], t0[0][0][0],
+ ep8_curve_get_a()[0][0][0][0]);
break;
#endif
default:
- ep8_curve_get_a(t1);
- fp8_add(t0, t0, t1);
+ fp8_add(t0, t0, ep8_curve_get_a());
break;
}
- fp8_mul(t0, t0, p->x); /* x1^3 + a * x */
+ fp8_mul(t0, t0, x);
switch (ep8_curve_opt_b()) {
case RLC_ZERO:
@@ -163,16 +158,12 @@ void ep8_rhs(fp8_t rhs, const ep8_t p) {
fp_add_dig(t0[0][0][0], t0[0][0][0], 2);
break;
case RLC_TINY:
- ep8_curve_get_b(t1);
- fp_mul_dig(t0[0][0][0], t0[0][0][0], t1[0][0][0][0]);
- fp_mul_dig(t0[0][1][0], t0[0][1][0], t1[0][0][0][0]);
- fp_mul_dig(t0[1][0][0], t0[0][0][0], t1[0][0][0][0]);
- fp_mul_dig(t0[1][1][0], t0[1][1][0], t1[0][0][0][0]);
+ fp_add_dig(t0[0][0][0], t0[0][0][0],
+ ep8_curve_get_b()[0][0][0][0]);
break;
#endif
default:
- ep8_curve_get_b(t1);
- fp8_add(t0, t0, t1);
+ fp8_add(t0, t0, ep8_curve_get_b());
break;
}
@@ -181,11 +172,9 @@ void ep8_rhs(fp8_t rhs, const ep8_t p) {
RLC_THROW(ERR_CAUGHT);
} RLC_FINALLY {
fp8_free(t0);
- fp8_free(t1);
}
}
-
int ep8_on_curve(const ep8_t p) {
ep8_t t;
int r = 0;
@@ -197,7 +186,7 @@ int ep8_on_curve(const ep8_t p) {
ep8_norm(t, p);
- ep8_rhs(t->x, t);
+ ep8_rhs(t->x, t->x);
fp8_sqr(t->y, t->y);
r = (fp8_cmp(t->x, t->y) == RLC_EQ) || ep8_is_infty(p);
@@ -321,8 +310,8 @@ void ep8_write_bin(uint8_t *bin, size_t len, const ep8_t a, int pack) {
RLC_THROW(ERR_NO_BUFFER);
} else {
bin[0] = 4;
- fp8_write_bin(bin + 1, 8 * RLC_FP_BYTES, t->x);
- fp8_write_bin(bin + 8 * RLC_FP_BYTES + 1, 8 * RLC_FP_BYTES, t->y);
+ fp8_write_bin(bin + 1, 8 * RLC_FP_BYTES, t->x, 0);
+ fp8_write_bin(bin + 8 * RLC_FP_BYTES + 1, 8 * RLC_FP_BYTES, t->y, 0);
}
} RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
diff --git a/src/fb/relic_fb_cmp.c b/src/fb/relic_fb_cmp.c
index 9e3dc2085..3eb0ef1b8 100644
--- a/src/fb/relic_fb_cmp.c
+++ b/src/fb/relic_fb_cmp.c
@@ -48,5 +48,5 @@ int fb_cmp_dig(const fb_t a, dig_t b) {
}
int fb_cmp(const fb_t a, const fb_t b) {
- return dv_cmp_const(a, b, RLC_FB_DIGS);
+ return dv_cmp_sec(a, b, RLC_FB_DIGS);
}
diff --git a/src/fb/relic_fb_exp.c b/src/fb/relic_fb_exp.c
index 600287306..b25d688a9 100644
--- a/src/fb/relic_fb_exp.c
+++ b/src/fb/relic_fb_exp.c
@@ -173,10 +173,10 @@ void fb_exp_monty(fb_t c, const fb_t a, const bn_t b) {
for (int i = bn_bits(b) - 1; i >= 0; i--) {
int j = bn_get_bit(b, i);
- dv_swap_cond(t[0], t[1], RLC_FB_DIGS, j ^ 1);
+ dv_swap_sec(t[0], t[1], RLC_FB_DIGS, j ^ 1);
fb_mul(t[0], t[0], t[1]);
fb_sqr(t[1], t[1]);
- dv_swap_cond(t[0], t[1], RLC_FB_DIGS, j ^ 1);
+ dv_swap_sec(t[0], t[1], RLC_FB_DIGS, j ^ 1);
}
if (bn_sign(b) == RLC_NEG) {
diff --git a/src/fp/relic_fp_crt.c b/src/fp/relic_fp_crt.c
index 140f64683..74e5326f3 100644
--- a/src/fp/relic_fp_crt.c
+++ b/src/fp/relic_fp_crt.c
@@ -157,7 +157,7 @@ int fp_crt(fp_t c, const fp_t a) {
fp_exp(t0, a, e);
/* Recover 3^f-root of unity, and continue algorithm. */
- fp_copy(t3, fp_prime_get_crt());
+ fp_copy(t3, (const dig_t *)fp_prime_get_crt());
fp_copy(c, t3);
for (int i = 0; i < f - 1; i++) {
diff --git a/src/fp/relic_fp_exp.c b/src/fp/relic_fp_exp.c
index de847ba78..715dc55dc 100644
--- a/src/fp/relic_fp_exp.c
+++ b/src/fp/relic_fp_exp.c
@@ -168,10 +168,10 @@ void fp_exp_monty(fp_t c, const fp_t a, const bn_t b) {
for (int i = bn_bits(b) - 1; i >= 0; i--) {
int j = bn_get_bit(b, i);
- dv_swap_cond(t[0], t[1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0], t[1], RLC_FP_DIGS, j ^ 1);
fp_mul(t[0], t[0], t[1]);
fp_sqr(t[1], t[1]);
- dv_swap_cond(t[0], t[1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_sec(t[0], t[1], RLC_FP_DIGS, j ^ 1);
}
if (bn_sign(b) == RLC_NEG) {
diff --git a/src/fp/relic_fp_inv.c b/src/fp/relic_fp_inv.c
index 91615ede3..4ca9b265b 100644
--- a/src/fp/relic_fp_inv.c
+++ b/src/fp/relic_fp_inv.c
@@ -512,10 +512,10 @@ void fp_inv_divst(fp_t c, const fp_t a) {
/* Conditionally negate delta if d0 is set. */
delta = (delta ^ -d0) + d0;
/* Conditionally swap based on d0. */
- dv_swap_cond(r, v, RLC_FP_DIGS, d0);
+ dv_swap_sec(r, v, RLC_FP_DIGS, d0);
fp_negm_low(t, r);
- dv_swap_cond(f, g, RLC_FP_DIGS, d0);
- dv_copy_cond(r, t, RLC_FP_DIGS, d0);
+ dv_swap_sec(f, g, RLC_FP_DIGS, d0);
+ dv_copy_sec(r, t, RLC_FP_DIGS, d0);
for (int j = 0; j < RLC_FP_DIGS; j++) {
g[j] = RLC_SEL(g[j], ~g[j], d0);
}
@@ -541,7 +541,7 @@ void fp_inv_divst(fp_t c, const fp_t a) {
g[RLC_FP_DIGS - 1] |= (dig_t)gs << (RLC_DIG - 1);
}
fp_neg(t, v);
- dv_copy_cond(v, t, RLC_FP_DIGS, fs);
+ fp_copy_sec(v, t, fs);
dv_copy(t, fp_prime_get(), RLC_FP_DIGS);
fp_add_dig(t, t, 1);
@@ -650,10 +650,10 @@ void fp_inv_jmpds(fp_t c, const fp_t a) {
/* Update column vector below. */
v1[0] = RLC_SEL(m[1], -m[1], RLC_SIGN(m[1]));
fp_negm_low(t, v1);
- dv_copy_cond(v1, t, RLC_FP_DIGS, RLC_SIGN(m[1]));
+ fp_copy_sec(v1, t, RLC_SIGN(m[1]));
u1[0] = RLC_SEL(m[3], -m[3], RLC_SIGN(m[3]));
fp_negm_low(t, u1);
- dv_copy_cond(u1, t, RLC_FP_DIGS, RLC_SIGN(m[3]));
+ fp_copy_sec(u1, t, RLC_SIGN(m[3]));
dv_copy(p01, v1, 2 * RLC_FP_DIGS);
dv_copy(p11, u1, 2 * RLC_FP_DIGS);
@@ -686,19 +686,19 @@ void fp_inv_jmpds(fp_t c, const fp_t a) {
/* Update column vector below. */
bn_mul2_low(v0, p01, m[0], RLC_FP_DIGS + j);
fp_subd_low(t, p, v0);
- dv_copy_cond(v0, t, RLC_FP_DIGS + j + 1, RLC_SIGN(m[0]));
+ dv_copy_sec(v0, t, RLC_FP_DIGS + j + 1, RLC_SIGN(m[0]));
bn_mul2_low(v1, p11, m[1], RLC_FP_DIGS + j);
fp_subd_low(t, p, v1);
- dv_copy_cond(v1, t, RLC_FP_DIGS + j + 1, RLC_SIGN(m[1]));
+ dv_copy_sec(v1, t, RLC_FP_DIGS + j + 1, RLC_SIGN(m[1]));
bn_mul2_low(u0, p01, m[2], RLC_FP_DIGS + j);
fp_subd_low(t, p, u0);
- dv_copy_cond(u0, t, RLC_FP_DIGS + j + 1, RLC_SIGN(m[2]));
+ dv_copy_sec(u0, t, RLC_FP_DIGS + j + 1, RLC_SIGN(m[2]));
bn_mul2_low(u1, p11, m[3], RLC_FP_DIGS + j);
fp_subd_low(t, p, u1);
- dv_copy_cond(u1, t, RLC_FP_DIGS + j + 1, RLC_SIGN(m[3]));
+ dv_copy_sec(u1, t, RLC_FP_DIGS + j + 1, RLC_SIGN(m[3]));
j = i % RLC_FP_DIGS;
if (j == 0) {
@@ -719,19 +719,19 @@ void fp_inv_jmpds(fp_t c, const fp_t a) {
/* Update column vector below. */
bn_mul2_low(v0, p01, m[0], 2 * RLC_FP_DIGS);
fp_subd_low(t, p, v0);
- dv_copy_cond(v0, t, 2 * RLC_FP_DIGS, RLC_SIGN(m[0]));
+ dv_copy_sec(v0, t, 2 * RLC_FP_DIGS, RLC_SIGN(m[0]));
bn_mul2_low(v1, p11, m[1], 2 * RLC_FP_DIGS);
fp_subd_low(t, p, v1);
- dv_copy_cond(v1, t, 2 * RLC_FP_DIGS, RLC_SIGN(m[1]));
+ dv_copy_sec(v1, t, 2 * RLC_FP_DIGS, RLC_SIGN(m[1]));
bn_mul2_low(u0, p01, m[2], 2 * RLC_FP_DIGS);
fp_subd_low(t, p, u0);
- dv_copy_cond(u0, t, 2 * RLC_FP_DIGS, RLC_SIGN(m[2]));
+ dv_copy_sec(u0, t, 2 * RLC_FP_DIGS, RLC_SIGN(m[2]));
bn_mul2_low(u1, p11, m[3], 2 * RLC_FP_DIGS);
fp_subd_low(t, p, u1);
- dv_copy_cond(u1, t, 2 * RLC_FP_DIGS, RLC_SIGN(m[3]));
+ dv_copy_sec(u1, t, 2 * RLC_FP_DIGS, RLC_SIGN(m[3]));
fp_addc_low(t, u0, u1);
fp_rdc(p11, t);
@@ -768,11 +768,11 @@ void fp_inv_jmpds(fp_t c, const fp_t a) {
/* Update column vector below. */
bn_mul2_low(v0, p01, m[0], RLC_FP_DIGS + j);
fp_subd_low(t, p, v0);
- dv_copy_cond(v0, t, RLC_FP_DIGS + j + 1, RLC_SIGN(m[0]));
+ dv_copy_sec(v0, t, RLC_FP_DIGS + j + 1, RLC_SIGN(m[0]));
bn_mul2_low(v1, p11, m[1], RLC_FP_DIGS + j);
fp_subd_low(t, p, v1);
- dv_copy_cond(v1, t, RLC_FP_DIGS + j + 1, RLC_SIGN(m[1]));
+ dv_copy_sec(v1, t, RLC_FP_DIGS + j + 1, RLC_SIGN(m[1]));
fp_addd_low(t, v0, v1);
fp_rdc(p01, t);
@@ -784,11 +784,11 @@ void fp_inv_jmpds(fp_t c, const fp_t a) {
/* Update column vector below. */
bn_mul2_low(v0, p01, m[0], 2 * RLC_FP_DIGS);
fp_subd_low(t, p, v0);
- dv_copy_cond(v0, t, 2 * RLC_FP_DIGS, RLC_SIGN(m[0]));
+ dv_copy_sec(v0, t, 2 * RLC_FP_DIGS, RLC_SIGN(m[0]));
bn_mul2_low(v1, p11, m[1], 2 * RLC_FP_DIGS);
fp_subd_low(t, p, v1);
- dv_copy_cond(v1, t, 2 * RLC_FP_DIGS, RLC_SIGN(m[1]));
+ dv_copy_sec(v1, t, 2 * RLC_FP_DIGS, RLC_SIGN(m[1]));
fp_addc_low(t, v0, v1);
fp_rdc(p01, t);
@@ -796,7 +796,7 @@ void fp_inv_jmpds(fp_t c, const fp_t a) {
/* Negate based on sign of f at the end. */
fp_negm_low(t, p01);
- dv_copy_cond(p01, t, RLC_FP_DIGS, f[RLC_FP_DIGS] >> (RLC_DIG - 1));
+ dv_copy_sec(p01, t, RLC_FP_DIGS, f[RLC_FP_DIGS] >> (RLC_DIG - 1));
/* Multiply by (precomp * R^j) % p, one for each iteration of the loop,
* one for the constant, one more to be removed by reduction. */
diff --git a/src/fp/relic_fp_param.c b/src/fp/relic_fp_param.c
index 674ffb3de..8ff841371 100644
--- a/src/fp/relic_fp_param.c
+++ b/src/fp/relic_fp_param.c
@@ -569,16 +569,6 @@ void fp_param_set(int param) {
fp_prime_set_pairf(t0, EP_SG18);
break;
#elif FP_PRIME == 765
- case N16_765:
- /* u = -(2^48 - 2^44 + 2^37) */
- bn_set_2b(t0, 48);
- bn_set_2b(t1, 44);
- bn_sub(t0, t0, t1);
- bn_set_2b(t1, 37);
- bn_add(t0, t0, t1);
- bn_neg(t0, t0);
- fp_prime_set_pairf(t0, EP_N16);
- break;
case FM16_765:
/* u = 2^48-2^44-2^38+2^31 */
bn_set_2b(t0, 48);
@@ -605,13 +595,13 @@ void fp_param_set(int param) {
fp_prime_set_pairf(t0, EP_K16);
break;
case N16_766:
- /* u = 2^48-2^20+2^15+2^5 */
+ /* u = 2^48-2^28-2^25+2^2 */
bn_set_2b(t0, 48);
- bn_set_2b(t1, 20);
+ bn_set_2b(t1, 28);
bn_sub(t0, t0, t1);
- bn_set_2b(t1, 15);
- bn_add(t0, t0, t1);
- bn_add_dig(t0, t0, 32);
+ bn_set_2b(t1, 25);
+ bn_sub(t0, t0, t1);
+ bn_add_dig(t0, t0, 4);
fp_prime_set_pairf(t0, EP_N16);
break;
#elif FP_PRIME == 768
@@ -633,6 +623,22 @@ void fp_param_set(int param) {
bn_read_str(p, STR_P1024, strlen(STR_P1024), 16);
fp_prime_set_dense(p);
break;
+#elif FP_PRIME == 1150
+ case B12_1150:
+ /* x = -(2^192 - 2^188 + 2^115 + 2^110 + 2^44 + 1 */
+ bn_set_2b(t0, 192);
+ bn_set_2b(t1, 188);
+ bn_sub(t0, t0, t1);
+ bn_set_2b(t1, 115);
+ bn_add(t0, t0, t1);
+ bn_set_2b(t1, 110);
+ bn_add(t0, t0, t1);
+ bn_set_2b(t1, 44);
+ bn_add(t0, t0, t1);
+ bn_add_dig(t0, t0, 1);
+ bn_neg(t0, t0);
+ fp_prime_set_pairf(t0, EP_B12);
+ break;
#elif FP_PRIME == 1536
case SS_1536:
/* x = 2^255 + 2^41 + 1. */
@@ -821,13 +827,14 @@ int fp_param_set_any_tower(void) {
//fp_param_set(SG18_638);
#endif
#elif FP_PRIME == 765
- fp_param_set(N16_765);
- //fp_param_set(FM16_765);
+ fp_param_set(FM16_765);
#elif FP_PRIME == 766
fp_param_set(N16_766);
//fp_param_set(K16_766);
#elif FP_PRIME == 768
fp_param_set(FM18_768);
+#elif FP_PRIME == 1150
+ fp_param_set(B12_1150);
#elif FP_PRIME == 1536
fp_param_set(SS_1536);
#elif FP_PRIME == 3072
diff --git a/src/fp/relic_fp_smb.c b/src/fp/relic_fp_smb.c
index be7973591..bdab95d3d 100644
--- a/src/fp/relic_fp_smb.c
+++ b/src/fp/relic_fp_smb.c
@@ -208,7 +208,7 @@ int fp_smb_divst(const fp_t a) {
#endif
r = dv_cmp(g, f, RLC_FP_DIGS);
fp_subn_low(t, g, f);
- dv_copy_cond(g, t, RLC_FP_DIGS, r != RLC_LT);
+ fp_copy_sec(g, t, r != RLC_LT);
fs = gs = RLC_POS;
@@ -251,9 +251,9 @@ int fp_smb_divst(const fp_t a) {
t[0] = 1;
bn_negs_low(f, f, fs, RLC_FP_DIGS);
- r = RLC_SEL(r, 1 - k, dv_cmp_const(f, t, RLC_FP_DIGS) == RLC_EQ);
+ r = RLC_SEL(r, 1 - k, dv_cmp_sec(f, t, RLC_FP_DIGS) == RLC_EQ);
bn_negs_low(t, t, 1, RLC_FP_DIGS);
- r = RLC_SEL(r, 1 - k, dv_cmp_const(f, t, RLC_FP_DIGS) == RLC_EQ);
+ r = RLC_SEL(r, 1 - k, dv_cmp_sec(f, t, RLC_FP_DIGS) == RLC_EQ);
r = RLC_SEL(r, 1 - k, fp_is_zero(f));
r = RLC_SEL(r, 0, fp_is_zero(a));
} RLC_CATCH_ANY {
@@ -350,11 +350,11 @@ int fp_smb_jmpds(const fp_t a) {
j = (j + (j & 1)) % 4;
fp_zero(t0);
- r = RLC_SEL(r, 1 - j, dv_cmp_const(f, t0, RLC_FP_DIGS) == RLC_EQ);
+ r = RLC_SEL(r, 1 - j, dv_cmp_sec(f, t0, RLC_FP_DIGS) == RLC_EQ);
t0[0] = 1;
- r = RLC_SEL(r, 1 - j, dv_cmp_const(f, t0, RLC_FP_DIGS) == RLC_EQ);
+ r = RLC_SEL(r, 1 - j, dv_cmp_sec(f, t0, RLC_FP_DIGS) == RLC_EQ);
bn_negs_low(t0, t0, 1, RLC_FP_DIGS);
- r = RLC_SEL(r, 1 - j, dv_cmp_const(f, t0, RLC_FP_DIGS) == RLC_EQ);
+ r = RLC_SEL(r, 1 - j, dv_cmp_sec(f, t0, RLC_FP_DIGS) == RLC_EQ);
}
RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
diff --git a/src/fp/relic_fp_srt.c b/src/fp/relic_fp_srt.c
index c5656be1c..693fd99a9 100644
--- a/src/fp/relic_fp_srt.c
+++ b/src/fp/relic_fp_srt.c
@@ -110,16 +110,14 @@ int fp_srt(fp_t c, const fp_t a) {
fp_sqr(t2, t2);
}
fp_mul(t0, c, t3);
- dv_copy_cond(c, t0, RLC_FP_DIGS,
- fp_cmp_dig(t2, 1) != RLC_EQ);
+ fp_copy_sec(c, t0, fp_cmp_dig(t2, 1) != RLC_EQ);
fp_sqr(t3, t3);
fp_mul(t0, t1, t3);
- dv_copy_cond(t1, t0, RLC_FP_DIGS,
- fp_cmp_dig(t2, 1) != RLC_EQ);
+ fp_copy_sec(t1, t0, fp_cmp_dig(t2, 1) != RLC_EQ);
}
fp_neg(t0, c);
- dv_copy_cond(c, t0, RLC_FP_DIGS, fp_is_even(c) == 0);
+ fp_copy_sec(c, t0, fp_is_even(c) == 0);
break;
}
}
diff --git a/src/fp/relic_fp_util.c b/src/fp/relic_fp_util.c
index 8866fbb43..9556a9fd8 100644
--- a/src/fp/relic_fp_util.c
+++ b/src/fp/relic_fp_util.c
@@ -40,6 +40,10 @@ void fp_copy(fp_t c, const fp_t a) {
dv_copy(c, a, RLC_FP_DIGS);
}
+void fp_copy_sec(fp_t c, const fp_t a, dig_t bit) {
+ dv_copy_sec(c, a, RLC_FP_DIGS, bit);
+}
+
void fp_zero(fp_t a) {
dv_zero(a, RLC_FP_DIGS);
}
diff --git a/src/fpx/relic_fp2_mul.c b/src/fpx/relic_fp2_mul.c
index 558f8b0f7..457e8724b 100644
--- a/src/fpx/relic_fp2_mul.c
+++ b/src/fpx/relic_fp2_mul.c
@@ -121,17 +121,20 @@ void fp2_mul_nor_basic(fp2_t c, const fp2_t a) {
int qnr = fp2_field_get_qnr();
switch (fp_prime_get_mod8()) {
- case 3:
- /* If p = 3 mod 8, (1 + i) is a QNR/CNR. */
- fp_neg(t[0], a[1]);
- fp_add(c[1], a[0], a[1]);
- fp_add(c[0], t[0], a[0]);
- break;
case 1:
case 5:
/* If p = 1,5 mod 8, (i) is a QNR/CNR. */
fp2_mul_art(c, a);
break;
+ case 3:
+ if (qnr == 1) {
+ /* If p = 3 mod 8, (1 + i) is a QNR/CNR. */
+ fp_neg(t[0], a[1]);
+ fp_add(c[1], a[0], a[1]);
+ fp_add(c[0], t[0], a[0]);
+ break;
+ }
+ /* Otherwise, fall back to next one. */
case 7:
/* If p = 7 mod 8, we choose (2^k + i) as a QNR/CNR. */
fp2_mul_art(t, a);
diff --git a/src/fpx/relic_fp8_mul.c b/src/fpx/relic_fp8_mul.c
index c2d0587da..878d2d7a3 100644
--- a/src/fpx/relic_fp8_mul.c
+++ b/src/fpx/relic_fp8_mul.c
@@ -298,3 +298,8 @@ void fp8_mul_frb(fp8_t c, const fp8_t a, int i, int j) {
fp4_free(t);
}
}
+
+void fp8_mul_dig(fp8_t c, const fp8_t a, dig_t b) {
+ fp4_mul_dig(c[0], a[0], b);
+ fp4_mul_dig(c[1], a[1], b);
+}
diff --git a/src/fpx/relic_fpx_cyc.c b/src/fpx/relic_fpx_cyc.c
index 02803b6c9..f1b9acbbf 100644
--- a/src/fpx/relic_fpx_cyc.c
+++ b/src/fpx/relic_fpx_cyc.c
@@ -368,6 +368,108 @@ void fp8_exp_cyc(fp8_t c, const fp8_t a, const bn_t b) {
}
}
+void fp8_exp_cyc_sim(fp8_t e, const fp8_t a, const bn_t b, const fp8_t c,
+ const bn_t d) {
+ int n0, n1;
+ int8_t naf0[RLC_FP_BITS + 1], naf1[RLC_FP_BITS + 1], *_k, *_m;
+ fp8_t r, t0[1 << (RLC_WIDTH - 2)];
+ fp8_t s, t1[1 << (RLC_WIDTH - 2)];
+ size_t l, l0, l1;
+
+ if (bn_is_zero(b)) {
+ return fp8_exp_cyc(e, c, d);
+ }
+
+ if (bn_is_zero(d)) {
+ return fp8_exp_cyc(e, a, b);
+ }
+
+ fp8_null(r);
+ fp8_null(s);
+
+ RLC_TRY {
+ fp8_new(r);
+ fp8_new(s);
+ for (int i = 0; i < (1 << (RLC_WIDTH - 2)); i ++) {
+ fp8_null(t0[i]);
+ fp8_null(t1[i]);
+ fp8_new(t0[i]);
+ fp8_new(t1[i]);
+ }
+
+#if RLC_WIDTH > 2
+ fp8_sqr(t0[0], a);
+ fp8_mul(t0[1], t0[0], a);
+ for (int i = 2; i < (1 << (RLC_WIDTH - 2)); i++) {
+ fp8_mul(t0[i], t0[i - 1], t0[0]);
+ }
+
+ fp8_sqr(t1[0], c);
+ fp8_mul(t1[1], t1[0], c);
+ for (int i = 2; i < (1 << (RLC_WIDTH - 2)); i++) {
+ fp8_mul(t1[i], t1[i - 1], t1[0]);
+ }
+#endif
+ fp8_copy(t0[0], a);
+ fp8_copy(t1[0], c);
+
+ l0 = l1 = RLC_FP_BITS + 1;
+ bn_rec_naf(naf0, &l0, b, RLC_WIDTH);
+ bn_rec_naf(naf1, &l1, d, RLC_WIDTH);
+
+ l = RLC_MAX(l0, l1);
+ if (bn_sign(b) == RLC_NEG) {
+ for (size_t i = 0; i < l0; i++) {
+ naf0[i] = -naf0[i];
+ }
+ }
+ if (bn_sign(d) == RLC_NEG) {
+ for (size_t i = 0; i < l1; i++) {
+ naf1[i] = -naf1[i];
+ }
+ }
+
+ _k = naf0 + l - 1;
+ _m = naf1 + l - 1;
+
+ fp8_set_dig(r, 1);
+ for (int i = l - 1; i >= 0; i--, _k--, _m--) {
+ fp8_sqr(r, r);
+
+ n0 = *_k;
+ n1 = *_m;
+
+ if (n0 > 0) {
+ fp8_mul(r, r, t0[n0 / 2]);
+ }
+ if (n0 < 0) {
+ fp8_inv_cyc(s, t0[-n0 / 2]);
+ fp8_mul(r, r, s);
+ }
+ if (n1 > 0) {
+ fp8_mul(r, r, t1[n1 / 2]);
+ }
+ if (n1 < 0) {
+ fp8_inv_cyc(s, t1[-n1 / 2]);
+ fp8_mul(r, r, s);
+ }
+ }
+
+ fp8_copy(e, r);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ fp8_free(r);
+ fp8_free(s);
+ for (int i = 0; i < (1 << (RLC_WIDTH - 2)); i++) {
+ fp8_free(t0[i]);
+ fp8_free(t1[i]);
+ }
+ }
+}
+
void fp12_conv_cyc(fp12_t c, const fp12_t a) {
fp12_t t;
@@ -443,13 +545,11 @@ void fp12_back_cyc(fp12_t c, const fp12_t a) {
int f = fp2_is_zero(a[1][0]);
/* If f, t0 = 2 * g4 * g5, t1 = g3. */
fp2_copy(t2, a[0][1]);
- dv_copy_cond(t2[0], a[1][2][0], RLC_FP_DIGS, f);
- dv_copy_cond(t2[1], a[1][2][1], RLC_FP_DIGS, f);
+ fp2_copy_sec(t2, a[1][2], f);
/* t0 = g4^2. */
fp2_mul(t0, a[0][1], t2);
fp2_dbl(t2, t0);
- dv_copy_cond(t0[0], t2[0], RLC_FP_DIGS, f);
- dv_copy_cond(t0[1], t2[1], RLC_FP_DIGS, f);
+ fp2_copy_sec(t0, t2, f);
/* t1 = 3 * g4^2 - 2 * g3. */
fp2_sub(t1, t0, a[0][2]);
fp2_dbl(t1, t1);
@@ -461,13 +561,11 @@ void fp12_back_cyc(fp12_t c, const fp12_t a) {
/* t1 = (4 * g2). */
fp2_dbl(t1, a[1][0]);
fp2_dbl(t1, t1);
- dv_copy_cond(t1[0], a[0][2][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[1], a[0][2][1], RLC_FP_DIGS, f);
+ fp2_copy_sec(t1, a[0][2], f);
/* If unity, decompress to unity as well. */
f = fp12_cmp_dig(a, 1) == RLC_EQ;
fp2_set_dig(t2, 1);
- dv_copy_cond(t1[0], t2[0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[1], t2[1], RLC_FP_DIGS, f);
+ fp2_copy_sec(t1, t2, f);
/* t1 = 1/g3 or 1/(4*g2), depending on the above. */
fp2_inv(t1, t1);
@@ -529,13 +627,11 @@ void fp12_back_cyc_sim(fp12_t c[], const fp12_t a[], int n) {
int f = fp2_is_zero(a[i][1][0]);
/* If f, t0 = 2 * g4 * g5, t1 = g3. */
fp2_copy(t2[i], a[i][0][1]);
- dv_copy_cond(t2[i][0], a[i][1][2][0], RLC_FP_DIGS, f);
- dv_copy_cond(t2[i][1], a[i][1][2][1], RLC_FP_DIGS, f);
+ fp2_copy_sec(t2[i], a[i][1][2], f);
/* t0 = g4^2. */
fp2_mul(t0[i], a[i][0][1], t2[i]);
fp2_dbl(t2[i], t0[i]);
- dv_copy_cond(t0[i][0], t2[i][0], RLC_FP_DIGS, f);
- dv_copy_cond(t0[i][1], t2[i][1], RLC_FP_DIGS, f);
+ fp2_copy_sec(t0[i], t2[i], f);
/* t1 = 3 * g4^2 - 2 * g3. */
fp2_sub(t1[i], t0[i], a[i][0][2]);
fp2_dbl(t1[i], t1[i]);
@@ -547,13 +643,11 @@ void fp12_back_cyc_sim(fp12_t c[], const fp12_t a[], int n) {
/* t1 = (4 * g2). */
fp2_dbl(t1[i], a[i][1][0]);
fp2_dbl(t1[i], t1[i]);
- dv_copy_cond(t1[i][0], a[i][0][2][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][1], a[i][0][2][1], RLC_FP_DIGS, f);
+ fp2_copy_sec(t1[i], a[i][0][2], f);
/* If unity, decompress to unity as well. */
f = (fp12_cmp_dig(a[i], 1) == RLC_EQ);
fp2_set_dig(t2[i], 1);
- dv_copy_cond(t1[i][0], t2[i][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][1], t2[i][1], RLC_FP_DIGS, f);
+ fp2_copy_sec(t1[i], t2[i], f);
}
/* t1 = 1 / t1. */
@@ -722,81 +816,6 @@ void fp12_exp_cyc(fp12_t c, const fp12_t a, const bn_t b) {
}
}
-void fp12_exp_cyc_gls(fp12_t c, const fp12_t a, const bn_t b) {
- size_t l, _l[4];
- int8_t naf[4][RLC_FP_BITS + 1];
- fp12_t t[4];
- bn_t _b[4], n, u;
-
- if (bn_is_zero(b)) {
- return fp12_set_dig(c, 1);
- }
-
- bn_null(n);
- bn_null(u);
-
- RLC_TRY {
- bn_new(n);
- bn_new(u);
- for (size_t i = 0; i < 4; i++) {
- bn_null(_b[i]);
- bn_new(_b[i]);
- fp12_null(t[i]);
- fp12_new(t[i]);
- }
-
- ep_curve_get_ord(n);
- fp_prime_get_par(u);
- bn_abs(_b[0], b);
- bn_mod(_b[0], _b[0], n);
- if (bn_sign(b) == RLC_NEG) {
- bn_neg(_b[0], _b[0]);
- }
- bn_rec_frb(_b, 4, _b[0], u, n, ep_curve_is_pairf() == EP_BN);
-
- fp12_copy(t[0], a);
- fp12_frb(t[1], t[0], 1);
- fp12_frb(t[2], t[1], 1);
- fp12_frb(t[3], t[2], 1);
-
- l = 0;
- for (size_t i = 0; i < 4; i++) {
- if (bn_sign(_b[i]) == RLC_NEG) {
- fp12_inv_cyc(t[i], t[i]);
- }
- _l[i] = RLC_FP_BITS + 1;
- bn_rec_naf(naf[i], &_l[i], _b[i], 2);
- l = RLC_MAX(l, _l[i]);
- }
-
- fp12_set_dig(c, 1);
- for (int i = l - 1; i >= 0; i--) {
- fp12_sqr_cyc(c, c);
- for (size_t j = 0; j < 4; j++) {
- if (naf[j][i] > 0) {
- fp12_mul(c, c, t[j]);
- }
- if (naf[j][i] < 0) {
- fp12_inv_cyc(t[j], t[j]);
- fp12_mul(c, c, t[j]);
- fp12_inv_cyc(t[j], t[j]);
- }
- }
- }
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- bn_free(n);
- bn_free(u);
- for (size_t i = 0; i < 4; i++) {
- bn_free(_b[i]);
- fp12_free(t[i]);
- }
- }
-}
-
void fp12_exp_cyc_sim(fp12_t e, const fp12_t a, const bn_t b, const fp12_t c,
const bn_t d) {
int i, j, l;
@@ -843,7 +862,7 @@ void fp12_exp_cyc_sim(fp12_t e, const fp12_t a, const bn_t b, const fp12_t c,
}
bn_rec_frb(_d, 4, _d[0], x, n, ep_curve_is_pairf() == EP_BN);
- if (ep_curve_is_pairf() && ep_param_embed() == 12) {
+ if (ep_curve_is_pairf() && ep_curve_embed() == 12) {
for (i = 0; i < 4; i++) {
fp12_frb(t[i], a, i);
fp12_frb(u[i], c, i);
@@ -1035,41 +1054,6 @@ int fp16_test_cyc(const fp16_t a) {
return result;
}
-static void fp16_gls(fp16_t c, const fp16_t a) {
- fp16_t b;
-
- fp16_null(b);
-
- RLC_TRY {
- fp16_new(b);
-
- switch (ep_curve_is_pairf()) {
- case EP_K16:
- /* u = (2*p^5 - p) mod r */
- fp16_frb(b, a, 1);
- fp16_frb(c, b, 4);
- fp16_sqr_cyc(c, c);
- fp16_inv_cyc(b, b);
- fp16_mul(c, c, b);
- break;
- case EP_N16:
- /* u = -p^5 mod r */
- fp16_frb(c, a, 5);
- fp16_inv_cyc(c, c);
- break;
- case EP_FM16:
- fp16_frb(c, a, 1);
- break;
- }
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp16_free(b);
- }
-}
-
void fp16_exp_cyc(fp16_t c, const fp16_t a, const bn_t b) {
size_t l, w = RLC_WIDTH;
fp16_t r, s, t[1 << (RLC_WIDTH - 2)];
@@ -1137,81 +1121,6 @@ void fp16_exp_cyc(fp16_t c, const fp16_t a, const bn_t b) {
}
}
-void fp16_exp_cyc_gls(fp16_t c, const fp16_t a, const bn_t b) {
- size_t i, l, _l[8];
- int8_t naf[8][RLC_FP_BITS + 1];
- fp16_t t[8];
- bn_t _b[8], n, x;
-
- if (bn_is_zero(b)) {
- return fp16_set_dig(c, 1);
- }
-
- bn_null(n);
- bn_null(x);
-
- RLC_TRY {
- bn_new(n);
- bn_new(x);
- for (i = 0; i < 8; i++) {
- bn_null(_b[i]);
- bn_new(_b[i]);
- fp16_null(t[i]);
- fp16_new(t[i]);
- }
-
- ep_curve_get_ord(n);
- fp_prime_get_par(x);
- bn_abs(_b[0], b);
- bn_mod(_b[0], _b[0], n);
- if (bn_sign(b) == RLC_NEG) {
- bn_neg(_b[0], _b[0]);
- }
- bn_rec_frb(_b, 8, _b[0], x, n, ep_curve_is_pairf() == EP_BN);
-
- fp16_copy(t[0], a);
- for (int i = 1; i < 8; i++) {
- fp16_gls(t[i], t[i - 1]);
- }
-
- l = 0;
- for (size_t i = 0; i < 8; i++) {
- if (bn_sign(_b[i]) == RLC_NEG) {
- fp16_inv_cyc(t[i], t[i]);
- }
- _l[i] = RLC_FP_BITS + 1;
- bn_rec_naf(naf[i], &_l[i], _b[i], 2);
- l = RLC_MAX(l, _l[i]);
- }
-
- fp16_set_dig(c, 1);
- for (int i = l - 1; i >= 0; i--) {
- fp16_sqr_cyc(c, c);
- for (size_t j = 0; j < 8; j++) {
- if (naf[j][i] > 0) {
- fp16_mul(c, c, t[j]);
- }
- if (naf[j][i] < 0) {
- fp16_inv_cyc(t[j], t[j]);
- fp16_mul(c, c, t[j]);
- fp16_inv_cyc(t[j], t[j]);
- }
- }
- }
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- bn_free(n);
- bn_free(x);
- for (size_t i = 0; i < 8; i++) {
- bn_free(_b[i]);
- fp16_free(t[i]);
- }
- }
-}
-
void fp16_exp_cyc_sim(fp16_t e, const fp16_t a, const bn_t b, const fp16_t c,
const bn_t d) {
int n0, n1;
@@ -1389,15 +1298,11 @@ void fp18_back_cyc(fp18_t c, const fp18_t a) {
int f = fp3_is_zero(a[1][0]);
/* If f, t0 = 2 * g4 * g5, t1 = g3. */
fp3_copy(t2, a[0][1]);
- dv_copy_cond(t2[0], a[1][2][0], RLC_FP_DIGS, f);
- dv_copy_cond(t2[1], a[1][2][1], RLC_FP_DIGS, f);
- dv_copy_cond(t2[2], a[1][2][2], RLC_FP_DIGS, f);
+ fp3_copy_sec(t2, a[1][2], f);
/* t0 = g4^2. */
fp3_mul(t0, a[0][1], t2);
fp3_dbl(t2, t0);
- dv_copy_cond(t0[0], t2[0], RLC_FP_DIGS, f);
- dv_copy_cond(t0[1], t2[1], RLC_FP_DIGS, f);
- dv_copy_cond(t0[2], t2[2], RLC_FP_DIGS, f);
+ fp3_copy_sec(t0, t2, f);
/* t1 = 3 * g4^2 - 2 * g3. */
fp3_sub(t1, t0, a[0][2]);
fp3_dbl(t1, t1);
@@ -1409,15 +1314,11 @@ void fp18_back_cyc(fp18_t c, const fp18_t a) {
/* t1 = (4 * g2). */
fp3_dbl(t1, a[1][0]);
fp3_dbl(t1, t1);
- dv_copy_cond(t1[0], a[0][2][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[1], a[0][2][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[2], a[0][2][2], RLC_FP_DIGS, f);
+ fp3_copy_sec(t1, a[0][2], f);
/* If unity, decompress to unity as well. */
f = fp18_cmp_dig(a, 1) == RLC_EQ;
fp3_set_dig(t2, 1);
- dv_copy_cond(t1[0], t2[0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[1], t2[1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[2], t2[2], RLC_FP_DIGS, f);
+ fp3_copy_sec(t1, t2, f);
/* t1 = 1/g3 or 1/(4 * g2), depending on the above. */
fp3_inv(t1, t1);
@@ -1479,15 +1380,11 @@ void fp18_back_cyc_sim(fp18_t c[], const fp18_t a[], int n) {
int f = fp3_is_zero(a[i][1][0]);
/* If f, t0 = 2 * g4 * g5, t1 = g3. */
fp3_copy(t2[i], a[i][0][1]);
- dv_copy_cond(t2[i][0], a[i][1][2][0], RLC_FP_DIGS, f);
- dv_copy_cond(t2[i][1], a[i][1][2][1], RLC_FP_DIGS, f);
- dv_copy_cond(t2[i][2], a[i][1][2][2], RLC_FP_DIGS, f);
+ fp3_copy_sec(t2[i], a[i][1][2], f);
/* t0 = g4^2. */
fp3_mul(t0[i], a[i][0][1], t2[i]);
fp3_dbl(t2[i], t0[i]);
- dv_copy_cond(t0[i][0], t2[i][0], RLC_FP_DIGS, f);
- dv_copy_cond(t0[i][1], t2[i][1], RLC_FP_DIGS, f);
- dv_copy_cond(t0[i][2], t2[i][2], RLC_FP_DIGS, f);
+ fp3_copy_sec(t0[i], t2[i], f);
/* t1 = 3 * g4^2 - 2 * g3. */
fp3_sub(t1[i], t0[i], a[i][0][2]);
fp3_dbl(t1[i], t1[i]);
@@ -1499,15 +1396,11 @@ void fp18_back_cyc_sim(fp18_t c[], const fp18_t a[], int n) {
/* t1 = (4 * g2). */
fp3_dbl(t1[i], a[i][1][0]);
fp3_dbl(t1[i], t1[i]);
- dv_copy_cond(t1[i][0], a[i][0][2][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][1], a[i][0][2][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][2], a[i][0][2][2], RLC_FP_DIGS, f);
+ fp3_copy_sec(t1[i], a[i][0][2], f);
/* If unity, decompress to unity as well. */
f = (fp18_cmp_dig(a[i], 1) == RLC_EQ);
fp3_set_dig(t2[i], 1);
- dv_copy_cond(t1[i][0], t2[i][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][1], t2[i][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][2], t2[i][2], RLC_FP_DIGS, f);
+ fp3_copy_sec(t1[i], t2[i], f);
}
/* t1 = 1 / t1. */
@@ -1548,50 +1441,6 @@ void fp18_back_cyc_sim(fp18_t c[], const fp18_t a[], int n) {
}
}
-static void fp18_gls(fp18_t c, const fp18_t a) {
- fp18_t b;
-
- fp18_null(b);
-
- RLC_TRY {
- fp18_new(b);
-
- switch (ep_curve_is_pairf()) {
- case EP_SG18:
- /* -3*u = (2*p^2 - p^5) mod r */
- fp18_frb(b, a, 5);
- fp18_inv_cyc(b, b);
- fp18_frb(c, a, 2);
- fp18_sqr_cyc(c, c);
- fp18_mul(c, c, b);
- break;
- case EP_K18:
- /* For KSS18, we have that x = p^4 - 3*p = (p^3 - 3)p mod n. */
- fp18_sqr_cyc(b, a);
- fp18_mul(b, b, a);
- fp18_frb(c, a, 3);
- fp18_inv_cyc(b, b);
- fp18_mul(c, c, b);
- fp18_frb(c, c, 1);
- break;
- case EP_FM18:
- /* For FM18, we have that u = (p^4-p) mod r. */
- fp18_frb(b, a, 3);
- fp18_inv_cyc(b, b);
- fp18_mul(c, a, b);
- fp18_frb(c, c, 1);
- fp18_inv_cyc(c, c);
- break;
- }
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp18_free(b);
- }
-}
-
void fp18_exp_cyc(fp18_t c, const fp18_t a, const bn_t b) {
size_t l, w = bn_ham(b);
@@ -1723,89 +1572,6 @@ void fp18_exp_cyc(fp18_t c, const fp18_t a, const bn_t b) {
}
}
-void fp18_exp_cyc_gls(fp18_t c, const fp18_t a, const bn_t b) {
- size_t l, _l[6];
- int8_t naf[6][RLC_FP_BITS + 1];
- fp18_t t[6];
- bn_t _b[6], n, x;
-
- if (bn_is_zero(b)) {
- return fp18_set_dig(c, 1);
- }
-
- bn_null(n);
- bn_null(x);
-
- RLC_TRY {
- bn_new(n);
- bn_new(x);
- for (size_t i = 0; i < 6; i++) {
- bn_null(_b[i]);
- bn_new(_b[i]);
- fp18_null(t[i]);
- fp18_new(t[i]);
- }
-
- fp_prime_get_par(x);
- if (ep_curve_is_pairf() == EP_SG18) {
- /* Compute base -3*u for the recoding below. */
- bn_dbl(n, x);
- bn_add(x, x, n);
- bn_neg(x, x);
- }
- ep_curve_get_ord(n);
- bn_abs(_b[0], b);
- bn_mod(_b[0], _b[0], n);
- if (bn_sign(b) == RLC_NEG) {
- bn_neg(_b[0], _b[0]);
- }
- bn_rec_frb(_b, 6, _b[0], x, n, ep_curve_is_pairf() == EP_BN);
-
- l = 0;
- fp18_copy(t[0], a);
- for (size_t i = 0; i < 6; i++) {
- _l[i] = RLC_FP_BITS + 1;
- bn_rec_naf(naf[i], &_l[i], _b[i], 2);
- l = RLC_MAX(l, _l[i]);
- if (i > 0) {
- fp18_gls(t[i], t[i - 1]);
- }
- }
-
- for (size_t i = 0; i < 6; i++) {
- if (bn_sign(_b[i]) == RLC_NEG) {
- fp18_inv_cyc(t[i], t[i]);
- }
- }
-
- fp18_set_dig(c, 1);
- for (int i = l - 1; i >= 0; i--) {
- fp18_sqr_cyc(c, c);
- for (int j = 0; j < 6; j++) {
- if (naf[j][i] > 0) {
- fp18_mul(c, c, t[j]);
- }
- if (naf[j][i] < 0) {
- fp18_inv_cyc(t[j], t[j]);
- fp18_mul(c, c, t[j]);
- fp18_inv_cyc(t[j], t[j]);
- }
- }
- }
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- bn_free(n);
- bn_free(x);
- for (size_t i = 0; i < 6; i++) {
- bn_free(_b[i]);
- fp18_free(t[i]);
- }
- }
-}
-
void fp18_exp_cyc_sim(fp18_t e, const fp18_t a, const bn_t b, const fp18_t c,
const bn_t d) {
int i, n0, n1;
@@ -2063,17 +1829,11 @@ void fp24_back_cyc(fp24_t c, const fp24_t a) {
int f = fp4_is_zero(a[1][0]);
/* If f, t0 = 2 * g4 * g5, t1 = g3. */
fp4_copy(t2, a[2][0]);
- dv_copy_cond(t2[0][0], a[2][1][0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t2[0][1], a[2][1][0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t2[1][0], a[2][1][1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t2[1][1], a[2][1][1][1], RLC_FP_DIGS, f);
+ fp4_copy_sec(t2, a[2][1], f);
/* t0 = g4^2. */
fp4_mul(t0, a[2][0], t2);
fp4_dbl(t2, t0);
- dv_copy_cond(t0[0][0], t2[0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t0[0][1], t2[0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t0[1][0], t2[1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t0[1][1], t2[1][1], RLC_FP_DIGS, f);
+ fp4_copy_sec(t0, t2, f);
/* t1 = 3 * g4^2 - 2 * g3. */
fp4_sub(t1, t0, a[1][1]);
fp4_dbl(t1, t1);
@@ -2085,17 +1845,11 @@ void fp24_back_cyc(fp24_t c, const fp24_t a) {
/* t1 = (4 * g2). */
fp4_dbl(t1, a[1][0]);
fp4_dbl(t1, t1);
- dv_copy_cond(t1[0][0], a[1][1][0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[0][1], a[1][1][0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[1][0], a[1][1][1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[1][1], a[1][1][1][1], RLC_FP_DIGS, f);
+ fp4_copy_sec(t1, a[1][1], f);
/* If unity, decompress to unity as well. */
f = fp24_cmp_dig(a, 1) == RLC_EQ;
fp4_set_dig(t2, 1);
- dv_copy_cond(t1[0][0], t2[0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[0][1], t2[0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[1][0], t2[1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[1][1], t2[1][1], RLC_FP_DIGS, f);
+ fp4_copy_sec(t1, t2, f);
fp4_inv(t1, t1);
/* c_1 = g1. */
@@ -2156,17 +1910,11 @@ void fp24_back_cyc_sim(fp24_t c[], const fp24_t a[], int n) {
int f = fp4_is_zero(a[i][1][0]);
/* If f, t0 = 2 * g4 * g5, t1 = g3. */
fp4_copy(t2[i], a[i][2][0]);
- dv_copy_cond(t2[i][0][0], a[i][2][1][0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t2[i][0][1], a[i][2][1][0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t2[i][1][0], a[i][2][1][1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t2[i][1][1], a[i][2][1][1][1], RLC_FP_DIGS, f);
+ fp4_copy_sec(t2[i], a[i][2][1], f);
/* t0 = g4^2. */
fp4_mul(t0[i], a[i][2][0], t2[i]);
fp4_dbl(t2[i], t0[i]);
- dv_copy_cond(t0[i][0][0], t2[i][0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t0[i][0][1], t2[i][0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t0[i][1][0], t2[i][1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t0[i][1][1], t2[i][1][1], RLC_FP_DIGS, f);
+ fp4_copy_sec(t0[i], t2[i], f);
/* t1 = 3 * g4^2 - 2 * g3. */
fp4_sub(t1[i], t0[i], a[i][1][1]);
fp4_dbl(t1[i], t1[i]);
@@ -2178,17 +1926,11 @@ void fp24_back_cyc_sim(fp24_t c[], const fp24_t a[], int n) {
/* t1 = (4 * g2). */
fp4_dbl(t1[i], a[i][1][0]);
fp4_dbl(t1[i], t1[i]);
- dv_copy_cond(t1[i][0][0], a[i][1][1][0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][0][1], a[i][1][1][0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][1][0], a[i][1][1][1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][1][1], a[i][1][1][1][1], RLC_FP_DIGS, f);
+ fp4_copy_sec(t1[i], a[i][1][1], f);
/* If unity, decompress to unity as well. */
f = fp24_cmp_dig(a[i], 1) == RLC_EQ;
fp4_set_dig(t2[i], 1);
- dv_copy_cond(t1[i][0][0], t2[i][0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][0][1], t2[i][0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][1][0], t2[i][1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][1][1], t2[i][1][1], RLC_FP_DIGS, f);
+ fp4_copy_sec(t1[i], t2[i], f);
}
/* t1 = 1 / t1. */
@@ -2360,81 +2102,6 @@ void fp24_exp_cyc(fp24_t c, const fp24_t a, const bn_t b) {
}
}
-void fp24_exp_cyc_gls(fp24_t c, const fp24_t a, const bn_t b) {
- size_t l, _l[8];
- int8_t naf[8][RLC_FP_BITS + 1];
- fp24_t t[8];
- bn_t _b[8], n, x;
-
- if (bn_is_zero(b)) {
- fp24_set_dig(c, 1);
- return;
- }
-
- bn_null(n);
- bn_null(x);
-
- RLC_TRY {
- bn_new(n);
- bn_new(x);
- for (int i = 0; i < 8; i++) {
- bn_null(_b[i]);
- bn_new(_b[i]);
- fp24_null(t[i]);
- fp24_new(t[i]);
- }
-
- ep_curve_get_ord(n);
- fp_prime_get_par(x);
- bn_abs(_b[0], b);
- bn_mod(_b[0], _b[0], n);
- if (bn_sign(b) == RLC_NEG) {
- bn_neg(_b[0], _b[0]);
- }
- bn_rec_frb(_b, 8, _b[0], x, n, ep_curve_is_pairf() == EP_BN);
-
- fp24_copy(t[0], a);
- for (size_t i = 1; i < 8; i++) {
- fp24_frb(t[i], t[i - 1], 1);
- }
-
- l = 0;
- for (size_t i = 0; i < 8; i++) {
- if (bn_sign(_b[i]) == RLC_NEG) {
- fp24_inv_cyc(t[i], t[i]);
- }
- _l[i] = RLC_FP_BITS + 1;
- bn_rec_naf(naf[i], &_l[i], _b[i], 2);
- l = RLC_MAX(l, _l[i]);
- }
-
- fp24_set_dig(c, 1);
- for (int i = l - 1; i >= 0; i--) {
- fp24_sqr_cyc(c, c);
- for (size_t j = 0; j < 8; j++) {
- if (naf[j][i] > 0) {
- fp24_mul(c, c, t[j]);
- }
- if (naf[j][i] < 0) {
- fp24_inv_cyc(t[j], t[j]);
- fp24_mul(c, c, t[j]);
- fp24_inv_cyc(t[j], t[j]);
- }
- }
- }
- } RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- bn_free(n);
- bn_free(x);
- for (size_t i = 0; i < 8; i++) {
- bn_free(_b[i]);
- fp24_free(t[i]);
- }
- }
-}
-
void fp24_exp_cyc_sim(fp24_t e, const fp24_t a, const bn_t b, const fp24_t c,
const bn_t d) {
int n0, n1;
@@ -2692,25 +2359,11 @@ void fp48_back_cyc(fp48_t c, const fp48_t a) {
int f = fp8_is_zero(a[1][0]);
/* If f, t0 = 2 * g4 * g5, t1 = g3. */
fp8_copy(t2, a[0][1]);
- dv_copy_cond(t2[0][0][0], a[1][2][0][0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t2[0][0][1], a[1][2][0][0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t2[0][1][0], a[1][2][0][1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t2[0][1][1], a[1][2][0][1][1], RLC_FP_DIGS, f);
- dv_copy_cond(t2[1][0][0], a[1][2][1][0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t2[1][0][1], a[1][2][1][0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t2[1][1][0], a[1][2][1][1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t2[1][1][1], a[1][2][1][1][1], RLC_FP_DIGS, f);
+ fp8_copy_sec(t2, a[1][2], f);
/* t0 = g4^2. */
fp8_mul(t0, a[0][1], t2);
fp8_dbl(t2, t0);
- dv_copy_cond(t0[0][0][0], t2[0][0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t0[0][0][1], t2[0][0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t0[0][1][0], t2[0][1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t0[0][1][1], t2[0][1][1], RLC_FP_DIGS, f);
- dv_copy_cond(t0[1][0][0], t2[1][0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t0[1][0][1], t2[1][0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t0[1][1][0], t2[1][1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t0[1][1][1], t2[1][1][1], RLC_FP_DIGS, f);
+ fp8_copy_sec(t0, t2, f);
/* t1 = 3 * g4^2 - 2 * g3. */
fp8_sub(t1, t0, a[0][2]);
fp8_dbl(t1, t1);
@@ -2722,25 +2375,11 @@ void fp48_back_cyc(fp48_t c, const fp48_t a) {
/* t1 = (4 * g2). */
fp8_dbl(t1, a[1][0]);
fp8_dbl(t1, t1);
- dv_copy_cond(t1[0][0][0], a[0][2][0][0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[0][0][1], a[0][2][0][0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[0][1][0], a[0][2][0][1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[0][1][1], a[0][2][0][1][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[1][0][0], a[0][2][1][0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[1][0][1], a[0][2][1][0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[1][1][0], a[0][2][1][1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[1][1][1], a[0][2][1][1][1], RLC_FP_DIGS, f);
+ fp8_copy_sec(t1, a[0][2], f);
/* If unity, decompress to unity as well. */
f = fp48_cmp_dig(a, 1) == RLC_EQ;
fp8_set_dig(t2, 1);
- dv_copy_cond(t1[0][0][0], t2[0][0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[0][0][1], t2[0][0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[0][1][0], t2[0][1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[0][1][1], t2[0][1][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[1][0][0], t2[1][0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[1][0][1], t2[1][0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[1][1][0], t2[1][1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[1][1][1], t2[1][1][1], RLC_FP_DIGS, f);
+ fp8_copy_sec(t1, t2, f);
/* t1 = 1/g3 or 1/(4 * g2), depending on the above. */
fp8_inv(t1, t1);
@@ -2802,25 +2441,11 @@ void fp48_back_cyc_sim(fp48_t c[], const fp48_t a[], int n) {
int f = fp8_is_zero(a[i][1][0]);
/* If f, t0[i] = 2 * g4 * g5, t1[i] = g3. */
fp8_copy(t2[i], a[i][0][1]);
- dv_copy_cond(t2[i][0][0][0], a[i][1][2][0][0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t2[i][0][0][1], a[i][1][2][0][0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t2[i][0][1][0], a[i][1][2][0][1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t2[i][0][1][1], a[i][1][2][0][1][1], RLC_FP_DIGS, f);
- dv_copy_cond(t2[i][1][0][0], a[i][1][2][1][0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t2[i][1][0][1], a[i][1][2][1][0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t2[i][1][1][0], a[i][1][2][1][1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t2[i][1][1][1], a[i][1][2][1][1][1], RLC_FP_DIGS, f);
+ fp8_copy_sec(t2[i], a[i][1][2], f);
/* t0[i] = g4^2. */
fp8_mul(t0[i], a[i][0][1], t2[i]);
fp8_dbl(t2[i], t0[i]);
- dv_copy_cond(t0[i][0][0][0], t2[i][0][0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t0[i][0][0][1], t2[i][0][0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t0[i][0][1][0], t2[i][0][1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t0[i][0][1][1], t2[i][0][1][1], RLC_FP_DIGS, f);
- dv_copy_cond(t0[i][1][0][0], t2[i][1][0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t0[i][1][0][1], t2[i][1][0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t0[i][1][1][0], t2[i][1][1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t0[i][1][1][1], t2[i][1][1][1], RLC_FP_DIGS, f);
+ fp8_copy_sec(t0[i], t2[i], f);
/* t1[i] = 3 * g4^2 - 2 * g3. */
fp8_sub(t1[i], t0[i], a[i][0][2]);
fp8_dbl(t1[i], t1[i]);
@@ -2832,25 +2457,11 @@ void fp48_back_cyc_sim(fp48_t c[], const fp48_t a[], int n) {
/* t1[i] = (4 * g2). */
fp8_dbl(t1[i], a[i][1][0]);
fp8_dbl(t1[i], t1[i]);
- dv_copy_cond(t1[i][0][0][0], a[i][0][2][0][0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][0][0][1], a[i][0][2][0][0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][0][1][0], a[i][0][2][0][1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][0][1][1], a[i][0][2][0][1][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][1][0][0], a[i][0][2][1][0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][1][0][1], a[i][0][2][1][0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][1][1][0], a[i][0][2][1][1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][1][1][1], a[i][0][2][1][1][1], RLC_FP_DIGS, f);
+ fp8_copy_sec(t1[i], a[i][0][2], f);
/* If unity, decompress to unity as well. */
f = fp48_cmp_dig(a[i], 1) == RLC_EQ;
fp8_set_dig(t2[i], 1);
- dv_copy_cond(t1[i][0][0][0], t2[i][0][0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][0][0][1], t2[i][0][0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][0][1][0], t2[i][0][1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][0][1][1], t2[i][0][1][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][1][0][0], t2[i][1][0][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][1][0][1], t2[i][1][0][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][1][1][0], t2[i][1][1][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][1][1][1], t2[i][1][1][1], RLC_FP_DIGS, f);
+ fp8_copy_sec(t1[i], t2[i], f);
}
/* t1 = 1 / t1. */
@@ -3022,81 +2633,6 @@ void fp48_exp_cyc(fp48_t c, const fp48_t a, const bn_t b) {
}
}
-void fp48_exp_cyc_gls(fp48_t c, const fp48_t a, const bn_t b) {
- size_t l, _l[16];
- int8_t naf[16][RLC_FP_BITS + 1];
- fp48_t t[16];
- bn_t _b[16], n, x;
-
- if (bn_is_zero(b)) {
- fp48_set_dig(c, 1);
- return;
- }
-
- bn_null(n);
- bn_null(x);
-
- RLC_TRY {
- bn_new(n);
- bn_new(x);
- for (int i = 0; i < 8; i++) {
- bn_null(_b[i]);
- bn_new(_b[i]);
- fp48_null(t[i]);
- fp48_new(t[i]);
- }
-
- ep_curve_get_ord(n);
- fp_prime_get_par(x);
- bn_abs(_b[0], b);
- bn_mod(_b[0], _b[0], n);
- if (bn_sign(b) == RLC_NEG) {
- bn_neg(_b[0], _b[0]);
- }
- bn_rec_frb(_b, 16, _b[0], x, n, ep_curve_is_pairf() == EP_BN);
-
- fp48_copy(t[0], a);
- for (size_t i = 1; i < 16; i++) {
- fp48_frb(t[i], t[i - 1], 1);
- }
-
- l = 0;
- for (size_t i = 0; i < 16; i++) {
- if (bn_sign(_b[i]) == RLC_NEG) {
- fp48_inv_cyc(t[i], t[i]);
- }
- _l[i] = RLC_FP_BITS + 1;
- bn_rec_naf(naf[i], &_l[i], _b[i], 2);
- l = RLC_MAX(l, _l[i]);
- }
-
- fp48_set_dig(c, 1);
- for (int i = l - 1; i >= 0; i--) {
- fp48_sqr_cyc(c, c);
- for (size_t j = 0; j < 16; j++) {
- if (naf[j][i] > 0) {
- fp48_mul(c, c, t[j]);
- }
- if (naf[j][i] < 0) {
- fp48_inv_cyc(t[j], t[j]);
- fp48_mul(c, c, t[j]);
- fp48_inv_cyc(t[j], t[j]);
- }
- }
- }
- } RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- bn_free(n);
- bn_free(x);
- for (size_t i = 0; i < 16; i++) {
- bn_free(_b[i]);
- fp48_free(t[i]);
- }
- }
-}
-
void fp48_exp_cyc_sim(fp48_t e, const fp48_t a, const bn_t b, const fp48_t c,
const bn_t d) {
int n0, n1;
@@ -3353,19 +2889,11 @@ void fp54_back_cyc(fp54_t c, const fp54_t a) {
int f = fp9_is_zero(a[1][0]);
/* If f, t0 = 2 * g4 * g5, t1 = g3. */
fp9_copy(t2, a[2][0]);
- for (int j = 0; j < 3; j++) {
- dv_copy_cond(t2[j][0], a[2][1][j][0], RLC_FP_DIGS, f);
- dv_copy_cond(t2[j][1], a[2][1][j][1], RLC_FP_DIGS, f);
- dv_copy_cond(t2[j][2], a[2][1][j][2], RLC_FP_DIGS, f);
- }
+ fp9_copy_sec(t2, a[2][1], f);
/* t0 = g4^2. */
fp9_mul(t0, a[2][0], t2);
fp9_dbl(t2, t0);
- for (int j = 0; j < 3; j++) {
- dv_copy_cond(t0[j][0], t2[j][0], RLC_FP_DIGS, f);
- dv_copy_cond(t0[j][1], t2[j][1], RLC_FP_DIGS, f);
- dv_copy_cond(t0[j][2], t2[j][2], RLC_FP_DIGS, f);
- }
+ fp9_copy_sec(t0, t2, f);
/* t1 = 3 * g4^2 - 2 * g3. */
fp9_sub(t1, t0, a[1][1]);
fp9_dbl(t1, t1);
@@ -3377,19 +2905,11 @@ void fp54_back_cyc(fp54_t c, const fp54_t a) {
/* t1 = (4 * g2). */
fp9_dbl(t1, a[1][0]);
fp9_dbl(t1, t1);
- for (int j = 0; j < 3; j++) {
- dv_copy_cond(t1[j][0], a[1][1][j][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[j][1], a[1][1][j][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[j][2], a[1][1][j][2], RLC_FP_DIGS, f);
- }
+ fp9_copy_sec(t1, a[1][1], f);
/* If unity, decompress to unity as well. */
f = fp54_cmp_dig(a, 1) == RLC_EQ;
fp9_set_dig(t2, 1);
- for (int j = 0; j < 3; j++) {
- dv_copy_cond(t1[j][0], t2[j][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[j][1], t2[j][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[j][2], t2[j][2], RLC_FP_DIGS, f);
- }
+ fp9_copy_sec(t1, t2, f);
/* t1 = 1/(4 * g2). */
fp9_dbl(t1, a[1][0]);
@@ -3453,19 +2973,11 @@ void fp54_back_cyc_sim(fp54_t c[], const fp54_t a[], int n) {
int f = fp9_is_zero(a[i][1][0]);
/* If f, t0[i] = 2 * g4 * g5, t1[i] = g3. */
fp9_copy(t2[i], a[i][2][0]);
- for (int j = 0; j < 3; j++) {
- dv_copy_cond(t2[i][j][0], a[i][2][1][j][0], RLC_FP_DIGS, f);
- dv_copy_cond(t2[i][j][1], a[i][2][1][j][1], RLC_FP_DIGS, f);
- dv_copy_cond(t2[i][j][2], a[i][2][1][j][2], RLC_FP_DIGS, f);
- }
+ fp9_copy_sec(t2[i], a[i][2][1], f);
/* t0[i] = g4^2. */
fp9_mul(t0[i], a[i][2][0], t2[i]);
fp9_dbl(t2[i], t0[i]);
- for (int j = 0; j < 3; j++) {
- dv_copy_cond(t0[i][j][0], t2[i][j][0], RLC_FP_DIGS, f);
- dv_copy_cond(t0[i][j][1], t2[i][j][1], RLC_FP_DIGS, f);
- dv_copy_cond(t0[i][j][2], t2[i][j][2], RLC_FP_DIGS, f);
- }
+ fp9_copy_sec(t0[i], t2[i], f);
/* t1[i] = 3 * g4^2 - 2 * g3. */
fp9_sub(t1[i], t0[i], a[i][1][1]);
fp9_dbl(t1[i], t1[i]);
@@ -3477,19 +2989,11 @@ void fp54_back_cyc_sim(fp54_t c[], const fp54_t a[], int n) {
/* t1[i] = (4 * g2). */
fp9_dbl(t1[i], a[i][1][0]);
fp9_dbl(t1[i], t1[i]);
- for (int j = 0; j < 3; j++) {
- dv_copy_cond(t1[i][j][0], a[i][1][1][j][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][j][1], a[i][1][1][j][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][j][2], a[i][1][1][j][2], RLC_FP_DIGS, f);
- }
+ fp9_copy_sec(t1[i], a[i][1][1], f);
/* If unity, decompress to unity as well. */
f = fp54_cmp_dig(a[i], 1) == RLC_EQ;
fp9_set_dig(t2[i], 1);
- for (int j = 0; j < 3; j++) {
- dv_copy_cond(t1[i][j][0], t2[i][j][0], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][j][1], t2[i][j][1], RLC_FP_DIGS, f);
- dv_copy_cond(t1[i][j][2], t2[i][j][2], RLC_FP_DIGS, f);
- }
+ fp9_copy_sec(t1[i], t2[i], f);
}
/* t1 = 1 / t1. */
diff --git a/src/fpx/relic_fpx_field.c b/src/fpx/relic_fpx_field.c
index fad2a4536..62096c0d1 100644
--- a/src/fpx/relic_fpx_field.c
+++ b/src/fpx/relic_fpx_field.c
@@ -38,9 +38,11 @@
int fp2_field_get_qnr() {
/* Override some of the results when cubic non-residue is also needed. */
-#if FP_PRIME == 158 || FP_PRIME == 256
+#if FP_PRIME == 1150
+ return 32;
+#elif FP_PRIME == 158 || FP_PRIME == 256
return 4;
-#elif FP_PRIME == 446
+#elif FP_PRIME == 446 && !defined(FP_QNRES)
return 16;
#else
return core_get()->qnr2;
diff --git a/src/fpx/relic_fpx_srt.c b/src/fpx/relic_fpx_srt.c
index 574e36825..3b4ec0f6e 100644
--- a/src/fpx/relic_fpx_srt.c
+++ b/src/fpx/relic_fpx_srt.c
@@ -126,7 +126,7 @@ int fp2_srt(fp2_t c, const fp2_t a) {
/* t1 = (a_0 - sqrt(t0)) / 2 */
fp_sub(t1, a[0], t1);
fp_hlv(t1, t1);
- dv_copy_cond(t0, t1, RLC_FP_DIGS, !fp_is_sqr(t0));
+ fp_copy_sec(t0, t1, !fp_is_sqr(t0));
/* Should always be a quadratic residue. */
fp_srt(t2, t0);
@@ -244,22 +244,12 @@ int fp3_srt(fp3_t c, const fp3_t a) {
fp_mul(t0[0], t3[0], root);
fp_mul(t0[1], t3[1], root);
fp_mul(t0[2], t3[2], root);
- dv_copy_cond(t3[0], t0[0], RLC_FP_DIGS,
- fp3_cmp_dig(t2, 1) != RLC_EQ);
- dv_copy_cond(t3[1], t0[1], RLC_FP_DIGS,
- fp3_cmp_dig(t2, 1) != RLC_EQ);
- dv_copy_cond(t3[2], t0[2], RLC_FP_DIGS,
- fp3_cmp_dig(t2, 1) != RLC_EQ);
+ fp3_copy_sec(t3, t0, fp3_cmp_dig(t2, 1) != RLC_EQ);
fp_sqr(root, root);
fp_mul(t0[0], t1[0], root);
fp_mul(t0[1], t1[1], root);
fp_mul(t0[2], t1[2], root);
- dv_copy_cond(t1[0], t0[0], RLC_FP_DIGS,
- fp3_cmp_dig(t2, 1) != RLC_EQ);
- dv_copy_cond(t1[1], t0[1], RLC_FP_DIGS,
- fp3_cmp_dig(t2, 1) != RLC_EQ);
- dv_copy_cond(t1[2], t0[2], RLC_FP_DIGS,
- fp3_cmp_dig(t2, 1) != RLC_EQ);
+ fp3_copy_sec(t1, t0, fp3_cmp_dig(t2, 1) != RLC_EQ);
fp3_copy(t2, t1);
}
break;
@@ -311,9 +301,7 @@ int fp3_srt(fp3_t c, const fp3_t a) {
fp3_sqr(t0, t3);
r = (fp3_cmp(t0, a) == RLC_EQ ? 1 : 0);
fp3_zero(c);
- dv_copy_cond(c[0], t3[0], RLC_FP_DIGS, r);
- dv_copy_cond(c[1], t3[1], RLC_FP_DIGS, r);
- dv_copy_cond(c[2], t3[2], RLC_FP_DIGS, r);
+ fp3_copy_sec(c, t3, r);
} RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
} RLC_FINALLY {
@@ -412,8 +400,7 @@ int fp4_srt(fp4_t c, const fp4_t a) {
fp2_sub(t1, a[0], t1);
fp_hlv(t1[0], t1[0]);
fp_hlv(t1[1], t1[1]);
- dv_copy_cond(t0[0], t1[0], RLC_FP_DIGS, !c0);
- dv_copy_cond(t0[1], t1[1], RLC_FP_DIGS, !c0);
+ fp2_copy_sec(t0, t1, !c0);
/* Should always be a quadratic residue. */
fp2_srt(t2, t0);
/* c_0 = sqrt(t0) */
@@ -523,10 +510,7 @@ int fp8_srt(fp8_t c, const fp8_t a) {
fp_hlv(t1[0][1], t1[0][1]);
fp_hlv(t1[1][0], t1[1][0]);
fp_hlv(t1[1][1], t1[1][1]);
- dv_copy_cond(t0[0][0], t1[0][0], RLC_FP_DIGS, !c0);
- dv_copy_cond(t0[0][1], t1[0][1], RLC_FP_DIGS, !c0);
- dv_copy_cond(t0[1][0], t1[1][0], RLC_FP_DIGS, !c0);
- dv_copy_cond(t0[1][1], t1[1][1], RLC_FP_DIGS, !c0);
+ fp4_copy_sec(t0, t1, !c0);
/* Should always be a quadratic residue. */
fp4_srt(t2, t0);
/* c_0 = sqrt(t0) */
@@ -640,8 +624,7 @@ int fp16_srt(fp16_t c, const fp16_t a) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
fp_hlv(t1[i][j][k], t1[i][j][k]);
- dv_copy_cond(t0[i][j][k], t1[i][j][k], RLC_FP_DIGS,
- !c0);
+ fp_copy_sec(t0[i][j][k], t1[i][j][k], !c0);
}
}
}
diff --git a/src/fpx/relic_fpx_util.c b/src/fpx/relic_fpx_util.c
index bbc946c41..925b2e937 100644
--- a/src/fpx/relic_fpx_util.c
+++ b/src/fpx/relic_fpx_util.c
@@ -41,6 +41,11 @@ void fp2_copy(fp2_t c, const fp2_t a) {
fp_copy(c[1], a[1]);
}
+void fp2_copy_sec(fp2_t c, const fp2_t a, dig_t bit) {
+ fp_copy_sec(c[0], a[0], bit);
+ fp_copy_sec(c[1], a[1], bit);
+}
+
void fp2_zero(fp2_t a) {
fp_zero(a[0]);
fp_zero(a[1]);
@@ -134,6 +139,12 @@ void fp3_copy(fp3_t c, const fp3_t a) {
fp_copy(c[2], a[2]);
}
+void fp3_copy_sec(fp3_t c, const fp3_t a, dig_t bit) {
+ fp_copy_sec(c[0], a[0], bit);
+ fp_copy_sec(c[1], a[1], bit);
+ fp_copy_sec(c[2], a[2], bit);
+}
+
void fp3_zero(fp3_t a) {
fp_zero(a[0]);
fp_zero(a[1]);
@@ -191,6 +202,11 @@ void fp4_copy(fp4_t c, const fp4_t a) {
fp2_copy(c[1], a[1]);
}
+void fp4_copy_sec(fp4_t c, const fp4_t a, dig_t bit) {
+ fp2_copy_sec(c[0], a[0], bit);
+ fp2_copy_sec(c[1], a[1], bit);
+}
+
void fp4_zero(fp4_t a) {
fp2_zero(a[0]);
fp2_zero(a[1]);
@@ -243,6 +259,12 @@ void fp6_copy(fp6_t c, const fp6_t a) {
fp2_copy(c[2], a[2]);
}
+void fp6_copy_sec(fp6_t c, const fp6_t a, dig_t bit) {
+ fp2_copy_sec(c[0], a[0], bit);
+ fp2_copy_sec(c[1], a[1], bit);
+ fp2_copy_sec(c[2], a[2], bit);
+}
+
void fp6_zero(fp6_t a) {
fp2_zero(a[0]);
fp2_zero(a[1]);
@@ -300,6 +322,11 @@ void fp8_copy(fp8_t c, const fp8_t a) {
fp4_copy(c[1], a[1]);
}
+void fp8_copy_sec(fp8_t c, const fp8_t a, dig_t bit) {
+ fp4_copy_sec(c[0], a[0], bit);
+ fp4_copy_sec(c[1], a[1], bit);
+}
+
void fp8_zero(fp8_t a) {
fp4_zero(a[0]);
fp4_zero(a[1]);
@@ -340,7 +367,7 @@ void fp8_read_bin(fp8_t a, const uint8_t *bin, size_t len) {
fp4_read_bin(a[1], bin + 4 * RLC_FP_BYTES, 4 * RLC_FP_BYTES);
}
-void fp8_write_bin(uint8_t *bin, size_t len, const fp8_t a) {
+void fp8_write_bin(uint8_t *bin, size_t len, const fp8_t a, int pack) {
if (len != 8 * RLC_FP_BYTES) {
RLC_THROW(ERR_NO_BUFFER);
return;
@@ -360,6 +387,12 @@ void fp9_copy(fp9_t c, const fp9_t a) {
fp3_copy(c[2], a[2]);
}
+void fp9_copy_sec(fp9_t c, const fp9_t a, dig_t bit) {
+ fp3_copy_sec(c[0], a[0], bit);
+ fp3_copy_sec(c[1], a[1], bit);
+ fp3_copy_sec(c[2], a[2], bit);
+}
+
void fp9_zero(fp9_t a) {
fp3_zero(a[0]);
fp3_zero(a[1]);
@@ -417,6 +450,11 @@ void fp12_copy(fp12_t c, const fp12_t a) {
fp6_copy(c[1], a[1]);
}
+void fp12_copy_sec(fp12_t c, const fp12_t a, dig_t bit) {
+ fp6_copy_sec(c[0], a[0], bit);
+ fp6_copy_sec(c[1], a[1], bit);
+}
+
void fp12_zero(fp12_t a) {
fp6_zero(a[0]);
fp6_zero(a[1]);
@@ -509,6 +547,11 @@ void fp16_copy(fp16_t c, const fp16_t a) {
fp8_copy(c[1], a[1]);
}
+void fp16_copy_sec(fp16_t c, const fp16_t a, dig_t bit) {
+ fp8_copy_sec(c[0], a[0], bit);
+ fp8_copy_sec(c[1], a[1], bit);
+}
+
void fp16_zero(fp16_t a) {
fp8_zero(a[0]);
fp8_zero(a[1]);
@@ -554,8 +597,8 @@ void fp16_write_bin(uint8_t *bin, size_t len, const fp16_t a, int pack) {
RLC_THROW(ERR_NO_BUFFER);
return;
}
- fp8_write_bin(bin, 8 * RLC_FP_BYTES, a[0]);
- fp8_write_bin(bin + 8 * RLC_FP_BYTES, 8 * RLC_FP_BYTES, a[1]);
+ fp8_write_bin(bin, 8 * RLC_FP_BYTES, a[0], 0);
+ fp8_write_bin(bin + 8 * RLC_FP_BYTES, 8 * RLC_FP_BYTES, a[1], 0);
}
void fp16_set_dig(fp16_t a, const dig_t b) {
@@ -568,6 +611,11 @@ void fp18_copy(fp18_t c, const fp18_t a) {
fp9_copy(c[1], a[1]);
}
+void fp18_copy_sec(fp18_t c, const fp18_t a, dig_t bit) {
+ fp9_copy_sec(c[0], a[0], bit);
+ fp9_copy_sec(c[1], a[1], bit);
+}
+
void fp18_zero(fp18_t a) {
fp9_zero(a[0]);
fp9_zero(a[1]);
@@ -661,6 +709,12 @@ void fp24_copy(fp24_t c, const fp24_t a) {
fp8_copy(c[2], a[2]);
}
+void fp24_copy_sec(fp24_t c, const fp24_t a, dig_t bit) {
+ fp8_copy_sec(c[0], a[0], bit);
+ fp8_copy_sec(c[1], a[1], bit);
+ fp8_copy_sec(c[2], a[2], bit);
+}
+
void fp24_zero(fp24_t a) {
fp8_zero(a[0]);
fp8_zero(a[1]);
@@ -737,9 +791,9 @@ void fp24_write_bin(uint8_t *bin, size_t len, const fp24_t a, int pack) {
if (len != 24 * RLC_FP_BYTES) {
RLC_THROW(ERR_NO_BUFFER);
}
- fp8_write_bin(bin, 8 * RLC_FP_BYTES, a[0]);
- fp8_write_bin(bin + 8 * RLC_FP_BYTES, 8 * RLC_FP_BYTES, a[1]);
- fp8_write_bin(bin + 16 * RLC_FP_BYTES, 8 * RLC_FP_BYTES, a[2]);
+ fp8_write_bin(bin, 8 * RLC_FP_BYTES, a[0], 0);
+ fp8_write_bin(bin + 8 * RLC_FP_BYTES, 8 * RLC_FP_BYTES, a[1], 0);
+ fp8_write_bin(bin + 16 * RLC_FP_BYTES, 8 * RLC_FP_BYTES, a[2], 0);
}
} RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
@@ -759,6 +813,11 @@ void fp48_copy(fp48_t c, const fp48_t a) {
fp24_copy(c[1], a[1]);
}
+void fp48_copy_sec(fp48_t c, const fp48_t a, dig_t bit) {
+ fp24_copy_sec(c[0], a[0], bit);
+ fp24_copy_sec(c[1], a[1], bit);
+}
+
void fp48_zero(fp48_t a) {
fp24_zero(a[0]);
fp24_zero(a[1]);
@@ -823,10 +882,10 @@ void fp48_write_bin(uint8_t *bin, size_t len, const fp48_t a, int pack) {
RLC_THROW(ERR_NO_BUFFER);
}
fp48_pck(t, a);
- fp8_write_bin(bin, 8 * RLC_FP_BYTES, a[0][1]);
- fp8_write_bin(bin + 8 * RLC_FP_BYTES, 8 * RLC_FP_BYTES, a[0][2]);
- fp8_write_bin(bin + 16 * RLC_FP_BYTES, 8 * RLC_FP_BYTES, a[1][0]);
- fp8_write_bin(bin + 24 * RLC_FP_BYTES, 8 * RLC_FP_BYTES, a[1][2]);
+ fp8_write_bin(bin, 8 * RLC_FP_BYTES, a[0][1], 0);
+ fp8_write_bin(bin + 8 * RLC_FP_BYTES, 8 * RLC_FP_BYTES, a[0][2], 0);
+ fp8_write_bin(bin + 16 * RLC_FP_BYTES, 8 * RLC_FP_BYTES, a[1][0], 0);
+ fp8_write_bin(bin + 24 * RLC_FP_BYTES, 8 * RLC_FP_BYTES, a[1][2], 0);
} else {
if (len != 48 * RLC_FP_BYTES) {
RLC_THROW(ERR_NO_BUFFER);
@@ -852,6 +911,12 @@ void fp54_copy(fp54_t c, const fp54_t a) {
fp18_copy(c[2], a[2]);
}
+void fp54_copy_sec(fp54_t c, const fp54_t a, dig_t bit) {
+ fp18_copy_sec(c[0], a[0], bit);
+ fp18_copy_sec(c[1], a[1], bit);
+ fp18_copy_sec(c[2], a[2], bit);
+}
+
void fp54_zero(fp54_t a) {
fp18_zero(a[0]);
fp18_zero(a[1]);
diff --git a/src/low/easy/relic_fpx_add_low.c b/src/low/easy/relic_fpx_add_low.c
index b0869e642..8954883f1 100755
--- a/src/low/easy/relic_fpx_add_low.c
+++ b/src/low/easy/relic_fpx_add_low.c
@@ -104,17 +104,19 @@ void fp2_norm_low(fp2_t c, fp2_t a) {
#else
int qnr = fp2_field_get_qnr();
switch (fp_prime_get_mod8()) {
- case 3:
- /* If p = 3 mod 8, (1 + i) is a QNR/CNR. */
- fp_neg(t[0], a[1]);
- fp_add(c[1], a[0], a[1]);
- fp_add(c[0], t[0], a[0]);
- break;
case 1:
case 5:
/* If p = 1,5 mod 8, (i) is a QNR/CNR. */
fp2_mul_art(c, a);
break;
+ case 3:
+ if (qnr == 1) {
+ fp_copy(t[0], a[1]);
+ fp_add(c[1], a[0], a[1]);
+ fp_sub(c[0], a[0], t[0]);
+ break;
+ }
+ /* Otherwise, fall back to next one. */
case 7:
/* If p = 7 mod 8, we choose (2^k + i) as QNR/CNR. */
fp2_mul_art(t, a);
@@ -153,13 +155,6 @@ void fp2_nord_low(dv2_t c, dv2_t a) {
#else
int qnr = fp2_field_get_qnr();
switch (fp_prime_get_mod8()) {
- case 3:
- /* If p = 3 mod 8, (1 + i) is a QNR, i^2 = -1. */
- /* (a_0 + a_1 * i) * (1 + i) = (a_0 - a_1) + (a_0 + a_1) * i. */
- dv_copy(t[0], a[1], 2 * RLC_FP_DIGS);
- fp_addc_low(c[1], a[0], a[1]);
- fp_subc_low(c[0], a[0], t[0]);
- break;
case 1:
case 5:
/* If p = 1,5 mod 8, (i) is a QNR. */
@@ -172,6 +167,16 @@ void fp2_nord_low(dv2_t c, dv2_t a) {
}
dv_copy(c[1], t[0], 2 * RLC_FP_DIGS);
break;
+ case 3:
+ if (qnr == 1) {
+ /* If p = 3 mod 8, (1 + i) is a QNR, i^2 = -1. */
+ /* (a_0 + a_1 * i) * (1 + i) = (a_0 - a_1) + (a_0 + a_1) * i. */
+ dv_copy(t[0], a[1], 2 * RLC_FP_DIGS);
+ fp_addc_low(c[1], a[0], a[1]);
+ fp_subc_low(c[0], a[0], t[0]);
+ break;
+ }
+ /* Otherwise, fall back to next one. */
case 7:
/* If p = 7 mod 8, (2^k + i) is a QNR/CNR. */
dv_copy(t[0], a[0], 2 * RLC_FP_DIGS);
diff --git a/src/low/x64-asm-12l/macro.s b/src/low/x64-asm-12l/macro.s
index 31cddde65..851ddcc76 100644
--- a/src/low/x64-asm-12l/macro.s
+++ b/src/low/x64-asm-12l/macro.s
@@ -61,35 +61,21 @@
#define U0 0xC18CA908C52344BB
*/
/* AFG16-766 */
-#define P0 0xD1C2DA3812080101
-#define P1 0x7C7B86E2E778F618
-#define P2 0xCBDEA14B5B88FF11
-#define P3 0xCC0258598794E74A
-#define P4 0x2C3C97E23451D33D
-#define P5 0xD865BA50F2687698
-#define P6 0x7FE816EA1FC66244
-#define P7 0x28B32989A8983A80
-#define P8 0xA388C01776314278
-#define P9 0x103F6BCC973EF5C3
-#define P10 0x0BB883B2C64AF7BD
-#define P11 0X3FFFFFC200801C27
-#define U0 0x30B120EB030700FF
+#define P0 0xF45D1E791E054605
+#define P1 0xFCBC4220020A6592
+#define P2 0x211730168CD3106C
+#define P3 0xC81A3A94170A2E5A
+#define P4 0x04A837318C7897B6
+#define P5 0xA2902CAC0A117EAD
+#define P6 0x4C8C62B406D882C8
+#define P7 0xDC0F8D8300A6748A
+#define P8 0x67D35D389C7BD43C
+#define P9 0x89F38FC6E7249EF1
+#define P10 0xC2E122127943E41E
+#define P11 0x3FFFB8002607F379
+#define U0 0xF282381A203F6933
#elif FP_PRIME == 765
-/* AFG16-765 */
-#define P0 0x0000000000000001
-#define P1 0x00000000384F0100
-#define P2 0x7D00000000000000
-#define P3 0xFFFEE92F0199280F
-#define P4 0xF10B013FFFFFFFFF
-#define P5 0x4AC04FAC4912BADA
-#define P6 0x6AC50E5A1A6AEAE4
-#define P7 0xEE9C1E7F21BD9E92
-#define P8 0x249F514A2A836FBF
-#define P9 0x8866F5670199231B
-#define P10 0xB2847B1232833CC3
-#define P11 0x16FAB993B0C96754
-#define U0 0xFFFFFFFFFFFFFFFF
-/* FM16-765
+/* FM16-765 */
#define P0 0x1000EFC080000001
#define P1 0x0000000038223FF0
#define P2 0x0000000000000000
@@ -103,7 +89,6 @@
#define P10 0xBC5664C6F237BCB4
#define P11 0x166A30BEAF4CE221
#define U0 0xD000EFC07FFFFFFF
-*/
#endif
#if defined(__APPLE__)
diff --git a/src/pc/relic_pc_exp.c b/src/pc/relic_pc_exp.c
index 61bd8ed89..87b8cdf8c 100644
--- a/src/pc/relic_pc_exp.c
+++ b/src/pc/relic_pc_exp.c
@@ -31,6 +31,361 @@
#include "relic_pc.h"
#include "relic_core.h"
+/*============================================================================*/
+/* Private definitions */
+/*============================================================================*/
+
+/**
+ * Apply Frobenius endomorphism in different pairing-friendly curve families.
+ *
+ * @param[in] c - the result.
+ * @param[in] a - the extension field element to exponentiate.
+ */
+static void gt_gls(gt_t c, const gt_t a) {
+ gt_t b;
+
+ gt_null(b);
+
+ RLC_TRY {
+ gt_new(b);
+
+ switch (ep_curve_is_pairf()) {
+ case EP_K16:
+ /* u = (2*p^5 - p) mod r */
+ gt_frb(b, a, 1);
+ gt_frb(c, b, 4);
+ gt_sqr(c, c);
+ gt_inv(b, b);
+ gt_mul(c, c, b);
+ break;
+ case EP_N16:
+ /* u = -p^5 mod r */
+ gt_frb(c, a, 5);
+ gt_inv(c, c);
+ break;
+ case EP_SG18:
+ /* -3*u = (2*p^2 - p^5) mod r */
+ gt_frb(b, a, 5);
+ gt_inv(b, b);
+ gt_frb(c, a, 2);
+ gt_sqr(c, c);
+ gt_mul(c, c, b);
+ break;
+ case EP_K18:
+ /* For KSS18, we have that x = p^4 - 3*p = (p^3 - 3)p mod n. */
+ gt_sqr(b, a);
+ gt_mul(b, b, a);
+ gt_frb(c, a, 3);
+ gt_inv(b, b);
+ gt_mul(c, c, b);
+ gt_frb(c, c, 1);
+ break;
+ case EP_FM18:
+ /* For FM18, we have that u = (p^4-p) mod r. */
+ gt_frb(b, a, 3);
+ gt_inv(b, b);
+ gt_mul(c, a, b);
+ gt_frb(c, c, 1);
+ gt_inv(c, c);
+ break;
+ default:
+ gt_frb(c, a, 1);
+ break;
+ }
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ gt_free(b);
+ }
+}
+
+/**
+ * Size of a precomputation table using the double-table comb method.
+ */
+#define RLC_GT_TABLE (1 << (RLC_WIDTH - 2))
+
+/**
+ * Exponentiates an element from G_T in constant time.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the element to exponentiate.
+ * @param[in] b - the exponent.
+ * @param[in] f - the maximum Frobenius power.
+ */
+void gt_exp_imp(gt_t c, const gt_t a, const bn_t b, size_t f) {
+ int8_t c0, n0, *reg = RLC_ALLOCA(int8_t, f * (RLC_FP_BITS + 1));
+ int8_t *e = RLC_ALLOCA(int8_t, f), *s = RLC_ALLOCA(int8_t, f);
+ gt_t q, w, *t = RLC_ALLOCA(gt_t, f * RLC_GT_TABLE);
+ bn_t n, u, *_b = RLC_ALLOCA(bn_t, f);
+ size_t l, len, *_l = RLC_ALLOCA(size_t, f);
+
+ if (reg == NULL || e == NULL || t == NULL || _b == NULL || _l == NULL) {
+ RLC_THROW(ERR_NO_MEMORY);
+ return;
+ }
+
+ if (bn_is_zero(b)) {
+ RLC_FREE(reg);
+ RLC_FREE(e);
+ RLC_FREE(s);
+ RLC_FREE(t);
+ RLC_FREE(_b);
+ RLC_FREE(_l);
+ return gt_set_unity(c);
+ }
+
+ bn_null(n);
+ bn_null(u);
+ gt_null(q);
+ gt_null(w);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(u);
+ gt_new(q);
+ gt_new(w);
+ for (size_t i = 0; i < f; i++) {
+ bn_null(_b[i]);
+ bn_new(_b[i]);
+ for (size_t j = 0; j < RLC_GT_TABLE; j++) {
+ gt_null(t[i * RLC_GT_TABLE + j]);
+ gt_new(t[i * RLC_GT_TABLE + j]);
+ }
+ }
+
+ fp_prime_get_par(u);
+ if (ep_curve_is_pairf() == EP_SG18) {
+ /* Compute base -3*u for the recoding below. */
+ bn_dbl(n, u);
+ bn_add(u, u, n);
+ bn_neg(u, u);
+ }
+ gt_get_ord(n);
+ bn_abs(_b[0], b);
+ bn_mod(_b[0], _b[0], n);
+ if (bn_sign(b) == RLC_NEG) {
+ bn_neg(_b[0], _b[0]);
+ }
+ bn_rec_frb(_b, f, _b[0], u, n, ep_curve_is_pairf() == EP_BN);
+
+ l = 0;
+ len = bn_bits(u) + (ep_curve_is_pairf() == EP_BN);
+ gt_copy(t[0], a);
+ for (size_t i = 0; i < f; i++) {
+ s[i] = bn_sign(_b[i]);
+ bn_abs(_b[i], _b[i]);
+ e[i] = bn_is_even(_b[i]);
+ _b[i]->dp[0] |= e[i];
+
+ _l[i] = RLC_FP_BITS + 1;
+ bn_rec_reg(reg + i * (RLC_FP_BITS + 1), &_l[i], _b[i], len, RLC_WIDTH);
+ l = RLC_MAX(l, _l[i]);
+ /* Apply Frobenius before flipping sign to build table. */
+ if (i > 0) {
+ gt_gls(t[i * RLC_GT_TABLE], t[(i - 1) * RLC_GT_TABLE]);
+ }
+ }
+
+ for (size_t i = 0; i < f; i++) {
+ gt_inv(q, t[i * RLC_GT_TABLE]);
+ gt_copy_sec(q, t[i * RLC_GT_TABLE], s[i] == RLC_POS);
+ if (RLC_WIDTH > 2) {
+ gt_sqr(t[i * RLC_GT_TABLE], q);
+ gt_mul(t[i * RLC_GT_TABLE + 1], t[i * RLC_GT_TABLE], q);
+ for (size_t j = 2; j < RLC_GT_TABLE; j++) {
+ gt_mul(t[i * RLC_GT_TABLE + j], t[i * RLC_GT_TABLE + j - 1],
+ t[i * (RLC_GT_TABLE)]);
+ }
+ }
+ gt_copy(t[i * RLC_GT_TABLE], q);
+ }
+
+ gt_set_unity(c);
+ for (int j = l - 1; j >= 0; j--) {
+ for (size_t i = 0; i < RLC_WIDTH - 1; i++) {
+ gt_sqr(c, c);
+ }
+
+ for (size_t i = 0; i < f; i++) {
+ n0 = reg[i * (RLC_FP_BITS + 1) + j];
+ c0 = (n0 >> 7);
+ n0 = ((n0 ^ c0) - c0) >> 1;
+
+ for (size_t m = 0; m < RLC_GT_TABLE; m++) {
+ gt_copy_sec(w, t[i * RLC_GT_TABLE + m], m == n0);
+ }
+
+ gt_inv(q, w);
+ gt_copy_sec(q, w, c0 == 0);
+ gt_mul(c, c, q);
+
+ }
+ }
+
+ for (size_t i = 0; i < f; i++) {
+ /* Tables are built with points already negated, so no need here. */
+ gt_inv(q, t[i * RLC_GT_TABLE]);
+ gt_mul(q, c, q);
+ gt_copy_sec(c, q, e[i]);
+ }
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ bn_free(u);
+ gt_free(q);
+ gt_free(w);
+ for (size_t i = 0; i < f; i++) {
+ bn_free(_b[i]);
+ for (size_t j = 0; j < RLC_GT_TABLE; j++) {
+ gt_free(t[i * RLC_GT_TABLE + j]);
+ }
+ }
+ RLC_FREE(reg);
+ RLC_FREE(e);
+ RLC_FREE(s);
+ RLC_FREE(t);
+ RLC_FREE(_b);
+ RLC_FREE(_l);
+ }
+}
+
+/**
+ * Size of a precomputation table using the double-table comb method.
+ */
+#define RLC_GT_TABLE (1 << (RLC_WIDTH - 2))
+
+/**
+ * Exponentiates an element from G_T in constant time.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the element to exponentiate.
+ * @param[in] b - the exponent.
+ * @param[in] f - the maximum Frobenius power.
+ */
+void gt_exp_gls_imp(gt_t c, const gt_t a, const bn_t b, size_t f) {
+ int8_t *naf = RLC_ALLOCA(int8_t, f * (RLC_FP_BITS + 1));
+ int8_t n0, *s = RLC_ALLOCA(int8_t, f);
+ gt_t q, *t = RLC_ALLOCA(gt_t, f * RLC_GT_TABLE);
+ bn_t n, u, *_b = RLC_ALLOCA(bn_t, f);
+ size_t l, *_l = RLC_ALLOCA(size_t, f);
+
+ if (naf == NULL || t == NULL || _b == NULL || _l == NULL) {
+ RLC_THROW(ERR_NO_MEMORY);
+ return;
+ }
+
+ if (bn_is_zero(b)) {
+ RLC_FREE(naf);
+ RLC_FREE(s);
+ RLC_FREE(t);
+ RLC_FREE(_b);
+ RLC_FREE(_l);
+ return gt_set_unity(c);
+ }
+
+ bn_null(n);
+ bn_null(u);
+ gt_null(q);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(u);
+ gt_new(q);
+ for (size_t i = 0; i < f; i++) {
+ bn_null(_b[i]);
+ bn_new(_b[i]);
+ for (size_t j = 0; j < RLC_GT_TABLE; j++) {
+ gt_null(t[i * RLC_GT_TABLE + j]);
+ gt_new(t[i * RLC_GT_TABLE + j]);
+ }
+ }
+
+ fp_prime_get_par(u);
+ if (ep_curve_is_pairf() == EP_SG18) {
+ /* Compute base -3*u for the recoding below. */
+ bn_dbl(n, u);
+ bn_add(u, u, n);
+ bn_neg(u, u);
+ }
+ gt_get_ord(n);
+ bn_abs(_b[0], b);
+ bn_mod(_b[0], _b[0], n);
+ if (bn_sign(b) == RLC_NEG) {
+ bn_neg(_b[0], _b[0]);
+ }
+ bn_rec_frb(_b, f, _b[0], u, n, ep_curve_is_pairf() == EP_BN);
+
+ l = 0;
+ gt_copy(t[0], a);
+ for (size_t i = 0; i < f; i++) {
+ s[i] = bn_sign(_b[i]);
+ bn_abs(_b[i], _b[i]);
+
+ _l[i] = RLC_FP_BITS + 1;
+ bn_rec_naf(naf + i * (RLC_FP_BITS + 1), &_l[i], _b[i], RLC_WIDTH);
+ l = RLC_MAX(l, _l[i]);
+ /* Apply Frobenius before flipping sign to build table. */
+ if (i > 0) {
+ gt_gls(t[i * RLC_GT_TABLE], t[(i - 1) * RLC_GT_TABLE]);
+ }
+ }
+
+ for (size_t i = 0; i < f; i++) {
+ gt_inv(q, t[i * RLC_GT_TABLE]);
+ gt_copy_sec(q, t[i * RLC_GT_TABLE], s[i] == RLC_POS);
+ if (RLC_WIDTH > 2) {
+ gt_sqr(t[i * RLC_GT_TABLE], q);
+ gt_mul(t[i * RLC_GT_TABLE + 1], t[i * RLC_GT_TABLE], q);
+ for (size_t j = 2; j < RLC_GT_TABLE; j++) {
+ gt_mul(t[i * RLC_GT_TABLE + j], t[i * RLC_GT_TABLE + j - 1],
+ t[i * (RLC_GT_TABLE)]);
+ }
+ }
+ gt_copy(t[i * RLC_GT_TABLE], q);
+ }
+
+ gt_set_unity(c);
+ for (int j = l - 1; j >= 0; j--) {
+ gt_sqr(c, c);
+
+ for (size_t i = 0; i < f; i++) {
+ n0 = naf[i * (RLC_FP_BITS + 1) + j];
+ if (n0 > 0) {
+ gt_mul(c, c, t[i * RLC_GT_TABLE + n0 / 2]);
+ }
+ if (n0 < 0) {
+ gt_inv(q, t[i * RLC_GT_TABLE - n0 / 2]);
+ gt_mul(c, c, q);
+ }
+ }
+ }
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ bn_free(u);
+ gt_free(q);
+ for (size_t i = 0; i < f; i++) {
+ bn_free(_b[i]);
+ for (size_t j = 0; j < RLC_GT_TABLE; j++) {
+ gt_free(t[i * RLC_GT_TABLE + j]);
+ }
+ }
+ RLC_FREE(naf);
+ RLC_FREE(s);
+ RLC_FREE(t);
+ RLC_FREE(_b);
+ RLC_FREE(_l);
+ }
+}
+
/*============================================================================*/
/* Public definitions */
/*============================================================================*/
@@ -148,15 +503,31 @@ void gt_exp(gt_t c, const gt_t a, const bn_t b) {
return;
}
-#if FP_PRIME < 1536
- RLC_CAT(RLC_GT_LOWER, exp_cyc_gls)(c, a, b);
-#elif FP_PRIME == 1536
+#if FP_PRIME == 1536 || FP_PRIME == 544
RLC_CAT(RLC_GT_LOWER, exp_cyc)(c, a, b);
+#elif FP_PRIME < 1536
+ gt_exp_gls_imp(c, a, b, ep_curve_frdim());
#else
RLC_CAT(RLC_GT_LOWER, exp)(c, a, b);
#endif
}
+void gt_exp_sec(gt_t c, const gt_t a, const bn_t b) {
+ if (bn_bits(b) <= RLC_DIG) {
+ gt_exp_dig(c, a, b->dp[0]);
+ if (bn_sign(b) == RLC_NEG) {
+ gt_inv(c, c);
+ }
+ return;
+ }
+
+#if FP_PRIME <= 1536
+ gt_exp_imp(c, a, b, ep_curve_frdim());
+#else
+ RLC_CAT(RLC_GT_LOWER, exp_monty)(c, a, b);
+#endif
+}
+
void gt_exp_dig(gt_t c, const gt_t a, dig_t b) {
gt_t s, t;
bn_t _b;
diff --git a/src/pc/relic_pc_util.c b/src/pc/relic_pc_util.c
index c6072137a..cbee2cf96 100644
--- a/src/pc/relic_pc_util.c
+++ b/src/pc/relic_pc_util.c
@@ -58,6 +58,8 @@ void gt_rand(gt_t a) {
pp_exp_k16(a, a);
#elif FP_PRIME == 508 || FP_PRIME == 768 || FP_PRIME == 638 && !defined(FP_QNRES)
pp_exp_k18(a, a);
+#elif FP_PRIME == 544
+ pp_exp_k8(a, a);
#else
pp_exp_k12(a, a);
#endif
@@ -264,15 +266,14 @@ int g1_is_valid(const g1_t a) {
}
int g2_is_valid(const g2_t a) {
+#if FP_PRIME >= 1536
+ return g1_is_valid(a);
+#else
g2_t s, t, u, v, w;
bn_t n;
dig_t rem;
int r = 0;
-#if FP_PRIME >= 1536
- return g1_is_valid(a);
-#else
-
if (g2_is_infty(a)) {
return 0;
}
diff --git a/src/pp/relic_pp_dbl_k16.c b/src/pp/relic_pp_dbl_k16.c
index 61992eebb..26803c0dd 100644
--- a/src/pp/relic_pp_dbl_k16.c
+++ b/src/pp/relic_pp_dbl_k16.c
@@ -113,29 +113,7 @@ void pp_dbl_k16_projc_basic(fp16_t l, ep4_t r, const ep4_t q, const ep_t p) {
fp4_sqr(t0, q->x);
fp4_sqr(t1, q->y);
fp4_sqr(t2, q->z);
- switch (ep_curve_opt_a()) {
- case RLC_ZERO:
- fp4_zero(t3);
- break;
- case RLC_ONE:
- fp4_copy(t3, t2);
- break;
-#if FP_RDC != MONTY
- case RLC_TINY:
- fp_mul_dig(t3[0][0], t2[0][0], ep_curve_get_a()[0]);
- fp_mul_dig(t3[0][1], t2[0][1], ep_curve_get_a()[0]);
- fp_mul_dig(t3[1][0], t2[1][0], ep_curve_get_a()[0]);
- fp_mul_dig(t3[1][1], t2[1][1], ep_curve_get_a()[0]);
- break;
-#endif
- default:
- fp_mul(t3[0][0], t2[0][0], ep_curve_get_a());
- fp_mul(t3[0][1], t2[0][1], ep_curve_get_a());
- fp_mul(t3[1][0], t2[1][0], ep_curve_get_a());
- fp_mul(t3[1][1], t2[1][1], ep_curve_get_a());
- break;
- }
- fp4_mul_art(t3, t3);
+ ep4_curve_mul_a(t3, t2);
/* x3 = (A - D)^2, l11 = (A - D + x1)^2 - x3 - A. */
fp4_sub(t5, t0, t3);
@@ -236,29 +214,7 @@ void pp_dbl_k16_projc_lazyr(fp16_t l, ep4_t r, const ep4_t q, const ep_t p) {
fp4_sqr(t0, q->x);
fp4_sqr(t1, q->y);
fp4_sqr(t2, q->z);
- switch (ep_curve_opt_a()) {
- case RLC_ZERO:
- fp4_zero(t3);
- break;
- case RLC_ONE:
- fp4_copy(t3, t2);
- break;
-#if FP_RDC != MONTY
- case RLC_TINY:
- fp_mul_dig(t3[0][0], t2[0][0], ep_curve_get_a()[0]);
- fp_mul_dig(t3[0][1], t2[0][1], ep_curve_get_a()[0]);
- fp_mul_dig(t3[1][0], t2[1][0], ep_curve_get_a()[0]);
- fp_mul_dig(t3[1][1], t2[1][1], ep_curve_get_a()[0]);
- break;
-#endif
- default:
- fp_mul(t3[0][0], t2[0][0], ep_curve_get_a());
- fp_mul(t3[0][1], t2[0][1], ep_curve_get_a());
- fp_mul(t3[1][0], t2[1][0], ep_curve_get_a());
- fp_mul(t3[1][1], t2[1][1], ep_curve_get_a());
- break;
- }
- fp4_mul_art(t3, t3);
+ ep4_curve_mul_a(t3, t2);
/* x3 = (A - D)^2, l11 = (A - D + x1)^2 - x3 - A. */
fp4_sub(t5, t0, t3);
diff --git a/src/pp/relic_pp_dbl_k18.c b/src/pp/relic_pp_dbl_k18.c
index 2837eed99..a7e477c5a 100644
--- a/src/pp/relic_pp_dbl_k18.c
+++ b/src/pp/relic_pp_dbl_k18.c
@@ -117,8 +117,7 @@ void pp_dbl_k18_projc_basic(fp18_t l, ep3_t r, const ep3_t q, const ep_t p) {
/* D = 3bC, general b. */
fp3_dbl(t3, t2);
fp3_add(t3, t3, t2);
- ep3_curve_get_b(t4);
- fp3_mul(t3, t3, t4);
+ fp3_mul(t3, t3, ep3_curve_get_b());
/* E = (x1 + y1)^2 - A - B. */
fp3_add(t4, q->x, q->y);
fp3_sqr(t4, t4);
@@ -227,8 +226,7 @@ void pp_dbl_k18_projc_lazyr(fp18_t l, ep3_t r, const ep3_t q, const ep_t p) {
/* D = 3bC, for general b. */
fp3_dbl(t3, t2);
fp3_add(t3, t3, t2);
- ep3_curve_get_b(t4);
- fp3_mul(t3, t3, t4);
+ fp3_mul(t3, t3, ep3_curve_get_b());
/* E = (x1 + y1)^2 - A - B. */
fp3_add(t4, q->x, q->y);
fp3_sqr(t4, t4);
diff --git a/src/pp/relic_pp_dbl_k24.c b/src/pp/relic_pp_dbl_k24.c
index c85e56303..c1c33a79d 100644
--- a/src/pp/relic_pp_dbl_k24.c
+++ b/src/pp/relic_pp_dbl_k24.c
@@ -121,8 +121,7 @@ void pp_dbl_k24_projc(fp24_t l, ep4_t r, const ep4_t q, const ep_t p) {
/* D = 3bC, general b. */
fp4_dbl(t3, t2);
fp4_add(t3, t3, t2);
- ep4_curve_get_b(t4);
- fp4_mul(t3, t3, t4);
+ fp4_mul(t3, t3, ep4_curve_get_b());
/* E = (x1 + y1)^2 - A - B. */
fp4_add(t4, q->x, q->y);
diff --git a/src/pp/relic_pp_dbl_k48.c b/src/pp/relic_pp_dbl_k48.c
index a58c9155f..f80fd4f55 100644
--- a/src/pp/relic_pp_dbl_k48.c
+++ b/src/pp/relic_pp_dbl_k48.c
@@ -109,8 +109,7 @@ void pp_dbl_k48_projc(fp48_t l, ep8_t r, const ep8_t q, const ep_t p) {
/* D = 3bC, general b. */
fp8_dbl(t3, t2);
fp8_add(t3, t3, t2);
- ep8_curve_get_b(t4);
- fp8_mul(t3, t3, t4);
+ fp8_mul(t3, t3, ep8_curve_get_b());
/* E = (x1 + y1)^2 - A - B. */
fp8_add(t4, q->x, q->y);
diff --git a/src/pp/relic_pp_dbl_k8.c b/src/pp/relic_pp_dbl_k8.c
index 1153f3d04..72db1ce90 100644
--- a/src/pp/relic_pp_dbl_k8.c
+++ b/src/pp/relic_pp_dbl_k8.c
@@ -180,25 +180,7 @@ void pp_dbl_k8_projc_basic(fp8_t l, ep2_t r, const ep2_t q, const ep_t p) {
fp2_sqr(t0, q->x);
fp2_sqr(t1, q->y);
fp2_sqr(t2, q->z);
- switch (ep_curve_opt_a()) {
- case RLC_ZERO:
- fp2_zero(t3);
- break;
- case RLC_ONE:
- fp2_copy(t3, t2);
- break;
-#if FP_RDC != MONTY
- case RLC_TINY:
- fp_mul_dig(t3[0], t2[0], ep_curve_get_a()[0]);
- fp_mul_dig(t3[1], t2[1], ep_curve_get_a()[0]);
- break;
-#endif
- default:
- fp_mul(t3[0], t2[0], ep_curve_get_a());
- fp_mul(t3[1], t2[1], ep_curve_get_a());
- break;
- }
- fp2_mul_art(t3, t3);
+ ep2_curve_mul_a(t3, t2);
/* x3 = (A - D)^2, l11 = (A - D + x1)^2 - x3 - A. */
fp2_sub(t5, t0, t3);
@@ -293,28 +275,7 @@ void pp_dbl_k8_projc_lazyr(fp8_t l, ep2_t r, const ep2_t q, const ep_t p) {
fp2_sqr(t0, q->x);
fp2_sqr(t1, q->y);
fp2_sqr(t2, q->z);
- switch (ep_curve_opt_a()) {
- case RLC_ZERO:
- fp2_zero(t3);
- break;
- case RLC_ONE:
- fp2_copy(t3, t2);
- break;
- case RLC_TWO:
- fp2_dbl(t3, t2);
- break;
-#if FP_RDC != MONTY
- case RLC_TINY:
- fp_mul_dig(t3[0], t2[0], ep_curve_get_a()[0]);
- fp_mul_dig(t3[1], t2[1], ep_curve_get_a()[0]);
- break;
-#endif
- default:
- fp_mul(t3[0], t2[0], ep_curve_get_a());
- fp_mul(t3[1], t2[1], ep_curve_get_a());
- break;
- }
- fp2_mul_art(t3, t3);
+ ep2_curve_mul_a(t3, t2);
/* x3 = (A - D)^2, l11 = (A - D + x1)^2 - x3 - A. */
fp2_sub(t5, t0, t3);
diff --git a/src/pp/relic_pp_map_k12.c b/src/pp/relic_pp_map_k12.c
index 2446a083f..f82af9438 100644
--- a/src/pp/relic_pp_map_k12.c
+++ b/src/pp/relic_pp_map_k12.c
@@ -195,9 +195,8 @@ static void pp_mil_lit_k12(fp12_t r, ep_t *t, ep_t *p, ep2_t *q, int m, bn_t a)
* @param[out] t - the resulting point.
* @param[in] q - the first point of the pairing, in G_2.
* @param[in] p - the second point of the pairing, in G_1.
- * @param[in] a - the loop parameter.
*/
-static void pp_fin_k12_oatep(fp12_t r, ep2_t t, ep2_t q, ep_t p) {
+static void pp_fin_k12_oatep(fp12_t r, ep2_t t, const ep2_t q, const ep_t p) {
ep2_t q1, q2;
fp12_t tmp;
diff --git a/src/pp/relic_pp_map_k16.c b/src/pp/relic_pp_map_k16.c
index 837076802..6ab261f85 100644
--- a/src/pp/relic_pp_map_k16.c
+++ b/src/pp/relic_pp_map_k16.c
@@ -198,29 +198,37 @@ static void pp_mil_lit_k16(fp16_t r, ep_t *t, ep_t *p, ep4_t *q, int m, bn_t a)
* @param[in] p - the second point of the pairing, in G_1.
* @param[in] a - the loop parameter.
*/
-static void pp_fin_k16_oatep(fp16_t r, ep4_t t, ep4_t q, ep_t p) {
+static void pp_fin_k16_oatep(fp16_t r, ep4_t t, const ep4_t q, const ep_t p) {
ep4_t q1, q2;
fp16_t tmp;
+ ep_t _p;
fp16_null(tmp);
ep4_null(q1);
ep4_null(q2);
+ ep_null(_p);
RLC_TRY {
ep4_new(q1);
ep4_new(q2);
fp16_new(tmp);
- fp16_zero(tmp);
+ ep_new(_p);
-#if EP_ADD == PROJC || EP_ADD == JACOB
- fp_neg(p->x, p->x);
+#if EP_ADD == BASIC
+ ep_neg(_p, p);
+#else
+ fp_neg(_p->x, p->x);
+ fp_copy(_p->y, p->y);
#endif
+
+ fp16_zero(tmp);
ep4_frb(q1, q, 1);
- pp_add_k16(tmp, t, q1, p);
+ pp_add_k16(tmp, t, q1, _p);
fp16_frb(tmp, tmp, 3);
fp16_mul_dxs(r, r, tmp);
- pp_dbl_k16(tmp, q2, q, p);
+ fp16_zero(tmp);
+ pp_dbl_k16(tmp, q2, q, _p);
fp16_mul_dxs(r, r, tmp);
} RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
@@ -228,6 +236,7 @@ static void pp_fin_k16_oatep(fp16_t r, ep4_t t, ep4_t q, ep_t p) {
fp16_free(tmp);
ep4_free(q1);
ep4_free(q2);
+ ep_free(_p);
}
}
diff --git a/src/pp/relic_pp_map_k18.c b/src/pp/relic_pp_map_k18.c
index 99f733ed9..083775443 100644
--- a/src/pp/relic_pp_map_k18.c
+++ b/src/pp/relic_pp_map_k18.c
@@ -196,9 +196,10 @@ static void pp_mil_lit_k18(fp18_t r, ep_t *t, ep_t *p, ep3_t *q, int m, bn_t a)
* @param[out] t - the resulting point.
* @param[in] q - the first point of the pairing, in G_2.
* @param[in] p - the second point of the pairing, in G_1.
- * @param[in] a - the loop parameter.
+ * @param[in] f - the flag to correct for the curve family.
*/
-static void pp_fin_k18_oatep(fp18_t r, ep3_t t, ep3_t q, ep_t p, int f) {
+static void pp_fin_k18_oatep(fp18_t r, ep3_t t, const ep3_t q, const ep_t p,
+ int f) {
fp18_t u, v;
ep3_t _q;
ep_t _p;
diff --git a/src/pp/relic_pp_map_k54.c b/src/pp/relic_pp_map_k54.c
index 5860fa94a..17b2b0181 100644
--- a/src/pp/relic_pp_map_k54.c
+++ b/src/pp/relic_pp_map_k54.c
@@ -181,6 +181,7 @@ void pp_map_k54(fp54_t r, const ep_t p, const fp9_t qx, const fp9_t qy) {
if (bn_sign(a) == RLC_NEG) {
fp54_inv_cyc(r, r);
}
+ fp18_print(r[0]);
pp_exp_k54(r, r);
break;
}
diff --git a/src/pp/relic_pp_map_k8.c b/src/pp/relic_pp_map_k8.c
index 0d5e2ee8f..bf2b9682a 100644
--- a/src/pp/relic_pp_map_k8.c
+++ b/src/pp/relic_pp_map_k8.c
@@ -163,3 +163,61 @@ void pp_map_oatep_k8(fp8_t r, const ep_t p, const ep2_t q) {
bn_free(a);
}
}
+
+void pp_map_sim_oatep_k8(fp8_t r, const ep_t *p, const ep2_t *q, int m) {
+ ep_t *_p = RLC_ALLOCA(ep_t, m);
+ ep2_t *t = RLC_ALLOCA(ep2_t, m), *_q = RLC_ALLOCA(ep2_t, m);
+ bn_t a;
+ int i, j;
+
+ RLC_TRY {
+ bn_null(a);
+ bn_new(a);
+ if (_p == NULL || _q == NULL || t == NULL) {
+ RLC_THROW(ERR_NO_MEMORY);
+ }
+ 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]);
+ }
+ }
+
+ fp_prime_get_par(a);
+ fp8_set_dig(r, 1);
+
+ if (j > 0) {
+ /* r = f_{|a|,Q}(P). */
+ pp_mil_k8(r, t, _q, _p, j, a);
+ if (bn_sign(a) == RLC_NEG) {
+ fp8_inv_cyc(r, r);
+ ep2_neg(t[i], t[i]);
+ }
+ pp_exp_k8(r, r);
+ }
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(a);
+ for (i = 0; i < m; i++) {
+ ep_free(_p[i]);
+ ep4_free(_q[i]);
+ ep4_free(t[i]);
+ }
+ RLC_FREE(_p);
+ RLC_FREE(_q);
+ RLC_FREE(t);
+ }
+}
diff --git a/src/relic_util.c b/src/relic_util.c
index 161084893..c69fb5cca 100644
--- a/src/relic_util.c
+++ b/src/relic_util.c
@@ -138,7 +138,7 @@ size_t util_bits_dig(dig_t a) {
return RLC_DIG - arch_lzcnt(a);
}
-int util_cmp_const(const void *a, const void *b, size_t size) {
+int util_cmp_sec(const void *a, const void *b, size_t size) {
const uint8_t *_a = (const uint8_t *)a;
const uint8_t *_b = (const uint8_t *)b;
uint8_t result = 0;
diff --git a/src/tmpl/relic_ep_add_tmpl.h b/src/tmpl/relic_ep_add_tmpl.h
new file mode 100644
index 000000000..c847eb554
--- /dev/null
+++ b/src/tmpl/relic_ep_add_tmpl.h
@@ -0,0 +1,704 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2024 RELIC Authors
+ *
+ * This file is part of RELIC. RELIC is legal property of its developers,
+ * whose names are not listed here. Please refer to the COPYRIGHT file
+ * for contact information.
+ *
+ * RELIC is free software; you can redistribute it and/or modify it under the
+ * terms of the version 2.1 (or later) of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; or version 2.0 of the Apache
+ * License as published by the Apache Software Foundation. See the LICENSE files
+ * for more details.
+ *
+ * RELIC is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the LICENSE files for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public or the
+ * Apache License along with RELIC. If not, see
+ * or .
+ */
+
+/**
+ * @file
+ *
+ * Template for point addition on prime elliptic curves.
+ *
+ * @ingroup tmpl
+ */
+
+#include "relic_core.h"
+
+/*============================================================================*/
+/* Private definitions */
+/*============================================================================*/
+
+/**
+ * Defines a template for point addition in affine coordinates.
+ *
+ * @param[in] C - the curve.
+ * @param[in] F - the field prefix.
+ */
+#define TMPL_ADD_BASIC_IMP(C, F) \
+ static void C##_add_basic_imp(C##_t r, F##_t s, const C##_t p, \
+ const C##_t q) { \
+ F##_t t0, t1, t2; \
+ \
+ F##_null(t0); \
+ F##_null(t1); \
+ F##_null(t2); \
+ \
+ RLC_TRY { \
+ F##_new(t0); \
+ F##_new(t1); \
+ F##_new(t2); \
+ \
+ /* t0 = x2 - x1. */ \
+ F##_sub(t0, q->x, p->x); \
+ /* t1 = y2 - y1. */ \
+ F##_sub(t1, q->y, p->y); \
+ \
+ /* If t0 is zero. */ \
+ if (F##_is_zero(t0)) { \
+ if (F##_is_zero(t1)) { \
+ /* If t1 is zero, q = p, should have doubled. */ \
+ C##_dbl_basic(r, p); \
+ } else { \
+ /* If t1 != 0 and t0 == 0, q = -p and r = infinity. */ \
+ C##_set_infty(r); \
+ } \
+ } else { \
+ /* t2 = 1/(x2 - x1). */ \
+ F##_inv(t2, t0); \
+ /* t2 = lambda = (y2 - y1)/(x2 - x1). */ \
+ F##_mul(t2, t1, t2); \
+ \
+ /* x3 = lambda^2 - x2 - x1. */ \
+ F##_sqr(t1, t2); \
+ F##_sub(t0, t1, p->x); \
+ F##_sub(t0, t0, q->x); \
+ \
+ /* y3 = lambda * (x1 - x3) - y1. */ \
+ F##_sub(t1, p->x, t0); \
+ F##_mul(t1, t2, t1); \
+ F##_sub(r->y, t1, p->y); \
+ \
+ F##_copy(r->x, t0); \
+ F##_copy(r->z, p->z); \
+ \
+ if (s != NULL) { \
+ F##_copy(s, t2); \
+ } \
+ \
+ r->coord = BASIC; \
+ } \
+ F##_free(t0); \
+ F##_free(t1); \
+ F##_free(t2); \
+ } RLC_CATCH_ANY { \
+ RLC_THROW(ERR_CAUGHT); \
+ } RLC_FINALLY { \
+ F##_free(t0); \
+ F##_free(t1); \
+ F##_free(t2); \
+ } \
+ } \
+
+/**
+ * Defines a template for mixed point addition in homogeneous projective
+ * coordinates.
+ *
+ * Formulas for mixed addition from
+ * "Complete addition formulas for prime order elliptic curves"
+ * by Joost Renes, Craig Costello, and Lejla Batina
+ * https://eprint.iacr.org/2015/1060.pdf
+ *
+ * @param[in] C - the curve.
+ * @param[in] F - the field prefix.
+ */
+#define TMPL_ADD_PROJC_MIX(C, F) \
+ static void C##_add_projc_mix(C##_t r, const C##_t p, const C##_t q) { \
+ F##_t t0, t1, t2, t3, t4, t5; \
+ \
+ F##_null(t0); \
+ F##_null(t1); \
+ F##_null(t2); \
+ F##_null(t3); \
+ F##_null(t4); \
+ F##_null(t5); \
+ \
+ RLC_TRY { \
+ F##_new(t0); \
+ F##_new(t1); \
+ F##_new(t2); \
+ F##_new(t3); \
+ F##_new(t4); \
+ F##_new(t5); \
+ \
+ F##_mul(t0, p->x, q->x); \
+ F##_mul(t1, p->y, q->y); \
+ F##_add(t3, q->x, q->y); \
+ F##_add(t4, p->x, p->y); \
+ F##_mul(t3, t3, t4); \
+ F##_add(t4, t0, t1); \
+ F##_sub(t3, t3, t4); \
+ \
+ if (C##_curve_opt_a() == RLC_ZERO) { \
+ /* Cost of 11M + 2m_3b + 13a. */ \
+ if (p->coord == BASIC) { \
+ /* Save 1M + 1m_3b if z1 = 1. */ \
+ F##_add(t4, q->y, p->y); \
+ F##_add(r->y, q->x, p->x); \
+ F##_dbl(t5, C##_curve_get_b()); \
+ F##_add(t5, t5, C##_curve_get_b()); \
+ F##_add(r->z, t1, t5); \
+ F##_sub(t1, t1, t5); \
+ } else { \
+ F##_mul(t4, q->y, p->z); \
+ F##_add(t4, t4, p->y); \
+ F##_mul(r->y, q->x, p->z); \
+ F##_add(r->y, r->y, p->x); \
+ F##_dbl(t2, p->z); \
+ F##_add(t2, t2, p->z); \
+ C##_curve_mul_b(t2, t2); \
+ F##_add(r->z, t1, t2); \
+ F##_sub(t1, t1, t2); \
+ } \
+ F##_dbl(r->x, t0); \
+ F##_add(t0, t0, r->x); \
+ F##_dbl(t5, r->y); \
+ F##_add(r->y, r->y, t5); \
+ C##_curve_mul_b(r->y, r->y); \
+ F##_mul(r->x, t4, r->y); \
+ F##_mul(t2, t3, t1); \
+ F##_sub(r->x, t2, r->x); \
+ F##_mul(r->y, t0, r->y); \
+ F##_mul(t1, t1, r->z); \
+ F##_add(r->y, t1, r->y); \
+ F##_mul(t0, t0, t3); \
+ F##_mul(r->z, r->z, t4); \
+ F##_add(r->z, r->z, t0); \
+ } else if (C##_curve_opt_a() == RLC_MIN3) { \
+ /* Cost of 11M + 2m_b + 23a. */ \
+ if (p->coord == BASIC) { \
+ /* Save 2M + 3a if z1 = 1. */ \
+ F##_set_dig(t2, 3); \
+ F##_add(t4, q->y, p->y); \
+ F##_add(r->y, q->x, p->x); \
+ F##_sub(r->x, r->y, C##_curve_get_b()); \
+ } else { \
+ F##_dbl(t2, p->z); \
+ F##_add(t2, t2, p->z); \
+ F##_mul(t4, q->y, p->z); \
+ F##_add(t4, t4, p->y); \
+ F##_mul(r->y, q->x, p->z); \
+ F##_add(r->y, r->y, p->x); \
+ C##_curve_mul_b(r->z, p->z); \
+ F##_sub(r->x, r->y, r->z); \
+ } \
+ F##_dbl(r->z, r->x); \
+ F##_add(r->x, r->x, r->z); \
+ F##_sub(r->z, t1, r->x); \
+ F##_add(r->x, t1, r->x); \
+ C##_curve_mul_b(r->y, r->y); \
+ F##_sub(r->y, r->y, t2); \
+ F##_sub(r->y, r->y, t0); \
+ F##_dbl(t1, r->y); \
+ F##_add(r->y, t1, r->y); \
+ F##_dbl(t1, t0); \
+ F##_add(t0, t1, t0); \
+ F##_sub(t0, t0, t2); \
+ F##_mul(t1, t4, r->y); \
+ F##_mul(t2, t0, r->y); \
+ F##_mul(r->y, r->x, r->z); \
+ F##_add(r->y, r->y, t2); \
+ F##_mul(r->x, t3, r->x); \
+ F##_sub(r->x, r->x, t1); \
+ F##_mul(r->z, t4, r->z); \
+ F##_mul(t1, t3, t0); \
+ F##_add(r->z, r->z, t1); \
+ } else { \
+ /* Cost of 11M + 3m_a + 2m_3b + 17a. */ \
+ if (p->coord == BASIC) { \
+ /* Save 1M + 1m_a + 1m_3b if z1 = 1. */ \
+ F##_copy(t2, C##_curve_get_a()); \
+ F##_add(t4, q->x, p->x); \
+ F##_add(t5, q->y, p->y); \
+ C##_curve_mul_a(r->z, t4); \
+ F##_dbl(r->y, C##_curve_get_b()); \
+ F##_add(r->y, r->y, C##_curve_get_b()); \
+ F##_add(r->z, r->z, r->y); \
+ } else { \
+ C##_curve_mul_a(t2, p->z); \
+ F##_mul(t4, q->x, p->z); \
+ F##_add(t4, t4, p->x); \
+ F##_mul(t5, q->y, p->z); \
+ F##_add(t5, t5, p->y); \
+ F##_dbl(r->x, p->z); \
+ F##_add(r->x, r->x, p->z); \
+ C##_curve_mul_b(r->x, r->x); \
+ C##_curve_mul_a(r->z, t4); \
+ F##_add(r->z, r->x, r->z); \
+ } \
+ F##_sub(r->x, t1, r->z); \
+ F##_add(r->z, t1, r->z); \
+ F##_mul(r->y, r->x, r->z); \
+ F##_dbl(t1, t4); \
+ F##_add(t1, t1, t4); \
+ C##_curve_mul_b(t4, t1); \
+ F##_dbl(t1, t0); \
+ F##_add(t1, t1, t0); \
+ F##_add(t1, t1, t2); \
+ F##_sub(t2, t0, t2); \
+ C##_curve_mul_a(t2, t2); \
+ F##_add(t4, t4, t2); \
+ F##_mul(t0, t1, t4); \
+ F##_add(r->y, r->y, t0); \
+ F##_mul(t0, t5, t4); \
+ F##_mul(r->x, t3, r->x); \
+ F##_sub(r->x, r->x, t0); \
+ F##_mul(t0, t3, t1); \
+ F##_mul(r->z, t5, r->z); \
+ F##_add(r->z, r->z, t0); \
+ } \
+ \
+ r->coord = PROJC; \
+ } \
+ RLC_CATCH_ANY { \
+ RLC_THROW(ERR_CAUGHT); \
+ } \
+ RLC_FINALLY { \
+ F##_free(t0); \
+ F##_free(t1); \
+ F##_free(t2); \
+ F##_free(t3); \
+ F##_free(t4); \
+ F##_free(t5); \
+ } \
+ } \
+
+/**
+ * Defines a template for point addition in homogeneous projective
+ * coordinates.
+ *
+ * Formulas for mixed addition from
+ * "Complete addition formulas for prime order elliptic curves"
+ * by Joost Renes, Craig Costello, and Lejla Batina
+ * https://eprint.iacr.org/2015/1060.pdf
+ *
+ * @param[in] C - the curve.
+ * @param[in] F - the field prefix.
+ */
+#if defined(EP_MIXED) && defined(STRIP)
+
+#define TMPL_ADD_PROJC_IMP(C, F) \
+ static void C##_add_projc_imp(C##_t r, const C##_t p, const C##_t q) { \
+ /* If code size is a problem, leave only the mixed version. */ \
+ C##_add_projc_mix(r, p, q); \
+ } \
+
+#else
+
+#define TMPL_ADD_PROJC_IMP(C, F) \
+ static void C##_add_projc_imp(C##_t r, const C##_t p, const C##_t q) { \
+ F##_t t0, t1, t2, t3, t4, t5; \
+ \
+ if (q->coord == BASIC) { \
+ C##_add_projc_mix(r, p, q); \
+ return; \
+ } \
+ \
+ F##_null(t0); \
+ F##_null(t1); \
+ F##_null(t2); \
+ F##_null(t3); \
+ F##_null(t4); \
+ F##_null(t5); \
+ \
+ RLC_TRY { \
+ F##_new(t0); \
+ F##_new(t1); \
+ F##_new(t2); \
+ F##_new(t3); \
+ F##_new(t4); \
+ F##_new(t5); \
+ \
+ F##_mul(t0, p->x, q->x); \
+ F##_mul(t1, p->y, q->y); \
+ F##_mul(t2, p->z, q->z); \
+ F##_add(t3, p->x, p->y); \
+ F##_add(t4, q->x, q->y); \
+ F##_mul(t3, t3, t4); \
+ F##_add(t4, t0, t1); \
+ F##_sub(t3, t3, t4); \
+ if (C##_curve_opt_a() == RLC_ZERO) { \
+ /* Cost of 12M + 2m_3b + 19a. */ \
+ F##_add(t4, p->y, p->z); \
+ F##_add(t5, q->y, q->z); \
+ F##_mul(t4, t4, t5); \
+ F##_add(t5, t1, t2); \
+ F##_sub(t4, t4, t5); \
+ F##_add(r->y, q->x, q->z); \
+ F##_add(r->x, p->x, p->z); \
+ F##_mul(r->x, r->x, r->y); \
+ F##_add(r->y, t0, t2); \
+ F##_sub(r->y, r->x, r->y); \
+ F##_dbl(r->x, t0); \
+ F##_add(t0, t0, r->x); \
+ F##_dbl(t5, t2); \
+ F##_add(t2, t2, t5); \
+ C##_curve_mul_b(t2, t2); \
+ F##_add(r->z, t1, t2); \
+ F##_sub(t1, t1, t2); \
+ F##_dbl(t5, r->y); \
+ F##_add(r->y, r->y, t5); \
+ C##_curve_mul_b(r->y, r->y); \
+ F##_mul(r->x, t4, r->y); \
+ F##_mul(t2, t3, t1); \
+ F##_sub(r->x, t2, r->x); \
+ F##_mul(r->y, t0, r->y); \
+ F##_mul(t1, t1, r->z); \
+ F##_add(r->y, t1, r->y); \
+ F##_mul(t0, t0, t3); \
+ F##_mul(r->z, r->z, t4); \
+ F##_add(r->z, r->z, t0); \
+ } else if (C##_curve_opt_a() == RLC_MIN3) { \
+ /* Cost of 12M + 2m_b + 29a. */ \
+ F##_add(t4, p->y, p->z); \
+ F##_add(t5, q->y, q->z); \
+ F##_mul(t4, t4, t5); \
+ F##_add(t5, t1, t2); \
+ F##_sub(t4, t4, t5); \
+ F##_add(r->x, p->x, p->z); \
+ F##_add(r->y, q->x, q->z); \
+ F##_mul(r->x, r->x, r->y); \
+ F##_add(r->y, t0, t2); \
+ F##_sub(r->y, r->x, r->y); \
+ C##_curve_mul_b(r->z, t2); \
+ F##_sub(r->x, r->y, r->z); \
+ F##_dbl(r->z, r->x); \
+ F##_add(r->x, r->x, r->z); \
+ F##_sub(r->z, t1, r->x); \
+ F##_add(r->x, t1, r->x); \
+ C##_curve_mul_b(r->y, r->y); \
+ F##_dbl(t1, t2); \
+ F##_add(t2, t1, t2); \
+ F##_sub(r->y, r->y, t2); \
+ F##_sub(r->y, r->y, t0); \
+ F##_dbl(t1, r->y); \
+ F##_add(r->y, t1, r->y); \
+ F##_dbl(t1, t0); \
+ F##_add(t0, t1, t0); \
+ F##_sub(t0, t0, t2); \
+ F##_mul(t1, t4, r->y); \
+ F##_mul(t2, t0, r->y); \
+ F##_mul(r->y, r->x, r->z); \
+ F##_add(r->y, r->y, t2); \
+ F##_mul(r->x, t3, r->x); \
+ F##_sub(r->x, r->x, t1); \
+ F##_mul(r->z, t4, r->z); \
+ F##_mul(t1, t3, t0); \
+ F##_add(r->z, r->z, t1); \
+ } else { \
+ /* Cost of 12M + 3m_a + 2_m3b + 23a. */ \
+ F##_add(t4, p->x, p->z); \
+ F##_add(t5, q->x, q->z); \
+ F##_mul(t4, t4, t5); \
+ F##_add(t5, t0, t2); \
+ F##_sub(t4, t4, t5); \
+ F##_add(t5, p->y, p->z); \
+ F##_add(r->x, q->y, q->z); \
+ F##_mul(t5, t5, r->x); \
+ F##_add(r->x, t1, t2); \
+ F##_sub(t5, t5, r->x); \
+ C##_curve_mul_a(r->z, t4); \
+ F##_dbl(r->x, t2); \
+ F##_add(r->x, r->x, t2); \
+ C##_curve_mul_b(r->x, r->x); \
+ F##_add(r->z, r->x, r->z); \
+ F##_sub(r->x, t1, r->z); \
+ F##_add(r->z, t1, r->z); \
+ F##_mul(r->y, r->x, r->z); \
+ F##_dbl(t1, t4); \
+ F##_add(t1, t1, t4); \
+ C##_curve_mul_b(t4, t1); \
+ F##_dbl(t1, t0); \
+ F##_add(t1, t1, t0); \
+ C##_curve_mul_a(t2, t2); \
+ F##_add(t1, t1, t2); \
+ F##_sub(t2, t0, t2); \
+ C##_curve_mul_a(t2, t2); \
+ F##_add(t4, t4, t2); \
+ F##_mul(t0, t1, t4); \
+ F##_add(r->y, r->y, t0); \
+ F##_mul(t0, t5, t4); \
+ F##_mul(r->x, t3, r->x); \
+ F##_sub(r->x, r->x, t0); \
+ F##_mul(t0, t3, t1); \
+ F##_mul(r->z, t5, r->z); \
+ F##_add(r->z, r->z, t0); \
+ } \
+ r->coord = PROJC; \
+ } RLC_CATCH_ANY { \
+ RLC_THROW(ERR_CAUGHT); \
+ } RLC_FINALLY { \
+ F##_free(t0); \
+ F##_free(t1); \
+ F##_free(t2); \
+ F##_free(t3); \
+ F##_free(t4); \
+ F##_free(t5); \
+ } \
+ } \
+
+#endif
+
+/**
+ * Defines a template for mixed point addition in Jacobian coordinates.
+ *
+ * madd-2007-bl formulas: 7M + 4S + 9add + 1*4 + 3*2.
+ * http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-madd-2007-bl
+ *
+ * @param[in] C - the curve.
+ * @param[in] F - the field prefix.
+ */
+#define TMPL_ADD_JACOB_MIX(C, F) \
+ static void C##_add_jacob_mix(C##_t r, const C##_t p, const C##_t q) { \
+ F##_t t0, t1, t2, t3, t4, t5, t6; \
+ \
+ F##_null(t0); \
+ F##_null(t1); \
+ F##_null(t2); \
+ F##_null(t3); \
+ F##_null(t4); \
+ F##_null(t5); \
+ F##_null(t6); \
+ \
+ RLC_TRY { \
+ F##_new(t0); \
+ F##_new(t1); \
+ F##_new(t2); \
+ F##_new(t3); \
+ F##_new(t4); \
+ F##_new(t5); \
+ F##_new(t6); \
+ \
+ if (p->coord != BASIC) { \
+ /* t0 = z1^2. */ \
+ F##_sqr(t0, p->z); \
+ \
+ /* t3 = U2 = x2 * z1^2. */ \
+ F##_mul(t3, q->x, t0); \
+ \
+ /* t1 = S2 = y2 * z1^3. */ \
+ F##_mul(t1, t0, p->z); \
+ F##_mul(t1, t1, q->y); \
+ \
+ /* t3 = H = U2 - x1. */ \
+ F##_sub(t3, t3, p->x); \
+ \
+ /* t1 = R = 2 * (S2 - y1). */ \
+ F##_sub(t1, t1, p->y); \
+ F##_dbl(t1, t1); \
+ } else { \
+ /* H = x2 - x1. */ \
+ F##_sub(t3, q->x, p->x); \
+ \
+ /* t1 = R = 2 * (y2 - y1). */ \
+ F##_sub(t1, q->y, p->y); \
+ F##_dbl(t1, t1); \
+ } \
+ \
+ /* t2 = HH = H^2. */ \
+ F##_sqr(t2, t3); \
+ \
+ /* If H is zero. */ \
+ if (F##_is_zero(t3)) { \
+ if (F##_is_zero(t1)) { \
+ /* If I is zero, p = q, should have doubled. */ \
+ C##_dbl_jacob(r, p); \
+ } else { \
+ /* If I is not zero, q = -p, r = infinity. */ \
+ C##_set_infty(r); \
+ } \
+ } else { \
+ /* t4 = I = 4*HH. */ \
+ F##_dbl(t4, t2); \
+ F##_dbl(t4, t4); \
+ \
+ /* t5 = J = H * I. */ \
+ F##_mul(t5, t3, t4); \
+ \
+ /* t4 = V = x1 * I. */ \
+ F##_mul(t4, p->x, t4); \
+ \
+ /* x3 = R^2 - J - 2 * V. */ \
+ F##_sqr(r->x, t1); \
+ F##_sub(r->x, r->x, t5); \
+ F##_dbl(t6, t4); \
+ F##_sub(r->x, r->x, t6); \
+ \
+ /* y3 = R * (V - x3) - 2 * Y1 * J. */ \
+ F##_sub(t4, t4, r->x); \
+ F##_mul(t4, t4, t1); \
+ F##_mul(t1, p->y, t5); \
+ F##_dbl(t1, t1); \
+ F##_sub(r->y, t4, t1); \
+ \
+ if (p->coord != BASIC) { \
+ /* z3 = (z1 + H)^2 - z1^2 - HH. */ \
+ F##_add(r->z, p->z, t3); \
+ F##_sqr(r->z, r->z); \
+ F##_sub(r->z, r->z, t0); \
+ F##_sub(r->z, r->z, t2); \
+ } else { \
+ /* z3 = 2 * H. */ \
+ F##_dbl(r->z, t3); \
+ } \
+ } \
+ r->coord = JACOB; \
+ } RLC_CATCH_ANY { \
+ RLC_THROW(ERR_CAUGHT); \
+ } \
+ RLC_FINALLY { \
+ F##_free(t0); \
+ F##_free(t1); \
+ F##_free(t2); \
+ F##_free(t3); \
+ F##_free(t4); \
+ F##_free(t5); \
+ F##_free(t6); \
+ } \
+ } \
+
+/**
+ * Defines a template for point addition in Jacobian coordinates.
+ *
+ * add-2007-bl formulas: 11M + 5S + 9add + 4*2
+ * http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
+ *
+ * @param[in] C - the curve.
+ * @param[in] F - the field prefix.
+ */
+#if defined(EP_MIXED) && defined(STRIP)
+
+#define TMPL_ADD_JACOB_IMP(C, F) \
+ static void C##_add_jacob_imp(C##_t r, const C##_t p, const C##_t q) { \
+ /* If code size is a problem, leave only the mixed version. */ \
+ C##_add_jacob_mix(r, p, q); \
+ } \
+
+#else
+
+#define TMPL_ADD_JACOB_IMP(C, F) \
+ static void C##_add_jacob_imp(C##_t r, const C##_t p, const C##_t q) { \
+ F##_t t0, t1, t2, t3, t4, t5, t6; \
+ \
+ if (q->coord == BASIC) { \
+ C##_add_jacob_mix(r, p, q); \
+ return; \
+ } \
+ \
+ F##_null(t0); \
+ F##_null(t1); \
+ F##_null(t2); \
+ F##_null(t3); \
+ F##_null(t4); \
+ F##_null(t5); \
+ F##_null(t6); \
+ \
+ RLC_TRY { \
+ F##_new(t0); \
+ F##_new(t1); \
+ F##_new(t2); \
+ F##_new(t3); \
+ F##_new(t4); \
+ F##_new(t5); \
+ F##_new(t6); \
+ \
+ /* t0 = z1^2. */ \
+ F##_sqr(t0, p->z); \
+ \
+ /* t1 = z2^2. */ \
+ F##_sqr(t1, q->z); \
+ \
+ /* t2 = U1 = x1 * z2^2. */ \
+ F##_mul(t2, p->x, t1); \
+ \
+ /* t3 = U2 = x2 * z1^2. */ \
+ F##_mul(t3, q->x, t0); \
+ \
+ /* t6 = z1^2 + z2^2. */ \
+ F##_add(t6, t0, t1); \
+ \
+ /* t0 = S2 = y2 * z1^3. */ \
+ F##_mul(t0, t0, p->z); \
+ F##_mul(t0, t0, q->y); \
+ \
+ /* t1 = S1 = y1 * z2^3. */ \
+ F##_mul(t1, t1, q->z); \
+ F##_mul(t1, t1, p->y); \
+ \
+ /* t3 = H = U2 - U1. */ \
+ F##_sub(t3, t3, t2); \
+ \
+ /* t0 = R = 2 * (S2 - S1). */ \
+ F##_sub(t0, t0, t1); \
+ F##_dbl(t0, t0); \
+ \
+ /* If E is zero. */ \
+ if (F##_is_zero(t3)) { \
+ if (F##_is_zero(t0)) { \
+ /* If I is zero, p = q, should have doubled. */ \
+ C##_dbl_jacob(r, p); \
+ } else { \
+ /* If I is not zero, q = -p, r = infinity. */ \
+ C##_set_infty(r); \
+ } \
+ } else { \
+ /* t4 = I = (2*H)^2. */ \
+ F##_dbl(t4, t3); \
+ F##_sqr(t4, t4); \
+ \
+ /* t5 = J = H * I. */ \
+ F##_mul(t5, t3, t4); \
+ \
+ /* t4 = V = U1 * I. */ \
+ F##_mul(t4, t2, t4); \
+ \
+ /* x3 = R^2 - J - 2 * V. */ \
+ F##_sqr(r->x, t0); \
+ F##_sub(r->x, r->x, t5); \
+ F##_dbl(t2, t4); \
+ F##_sub(r->x, r->x, t2); \
+ \
+ /* y3 = R * (V - x3) - 2 * S1 * J. */ \
+ F##_sub(t4, t4, r->x); \
+ F##_mul(t4, t4, t0); \
+ F##_mul(t1, t1, t5); \
+ F##_dbl(t1, t1); \
+ F##_sub(r->y, t4, t1); \
+ \
+ /* z3 = ((z1 + z2)^2 - z1^2 - z2^2) * H. */ \
+ F##_add(r->z, p->z, q->z); \
+ F##_sqr(r->z, r->z); \
+ F##_sub(r->z, r->z, t6); \
+ F##_mul(r->z, r->z, t3); \
+ } \
+ r->coord = JACOB; \
+ } RLC_CATCH_ANY { \
+ RLC_THROW(ERR_CAUGHT); \
+ } RLC_FINALLY { \
+ F##_free(t0); \
+ F##_free(t1); \
+ F##_free(t2); \
+ F##_free(t3); \
+ F##_free(t4); \
+ F##_free(t5); \
+ F##_free(t6); \
+ } \
+ } \
+
+#endif
\ No newline at end of file
diff --git a/src/tmpl/relic_ep_dbl_tmpl.h b/src/tmpl/relic_ep_dbl_tmpl.h
new file mode 100644
index 000000000..12918e277
--- /dev/null
+++ b/src/tmpl/relic_ep_dbl_tmpl.h
@@ -0,0 +1,430 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2024 RELIC Authors
+ *
+ * This file is part of RELIC. RELIC is legal property of its developers,
+ * whose names are not listed here. Please refer to the COPYRIGHT file
+ * for contact information.
+ *
+ * RELIC is free software; you can redistribute it and/or modify it under the
+ * terms of the version 2.1 (or later) of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; or version 2.0 of the Apache
+ * License as published by the Apache Software Foundation. See the LICENSE files
+ * for more details.
+ *
+ * RELIC is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the LICENSE files for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public or the
+ * Apache License along with RELIC. If not, see
+ * or .
+ */
+
+/**
+ * @file
+ *
+ * Template for point doubling on prime elliptic curves.
+ *
+ * @ingroup tmpl
+ */
+
+#include "relic_core.h"
+
+/*============================================================================*/
+/* Private definitions */
+/*============================================================================*/
+
+/**
+ * Defines a template for point addition in affine coordinates.
+ *
+ * @param[in] C - the curve.
+ * @param[in] F - the field prefix.
+ */
+#define TMPL_DBL_BASIC_IMP(C, F) \
+ static void C##_dbl_basic_imp(C##_t r, F##_t s, const C##_t p) { \
+ F##_t t0, t1, t2; \
+ \
+ F##_null(t0); \
+ F##_null(t1); \
+ F##_null(t2); \
+ \
+ RLC_TRY { \
+ F##_new(t0); \
+ F##_new(t1); \
+ F##_new(t2); \
+ \
+ /* t0 = 1/2 * y1. */ \
+ F##_dbl(t0, p->y); \
+ F##_inv(t0, t0); \
+ \
+ /* t1 = 3 * x1^2 + a. */ \
+ F##_sqr(t1, p->x); \
+ F##_copy(t2, t1); \
+ F##_dbl(t1, t1); \
+ F##_add(t1, t1, t2); \
+ F##_add(t1, t1, C##_curve_get_a()); \
+ \
+ /* t1 = (3 * x1^2 + a)/(2 * y1). */ \
+ F##_mul(t1, t1, t0); \
+ \
+ if (s != NULL) { \
+ F##_copy(s, t1); \
+ } \
+ \
+ /* t2 = t1^2. */ \
+ F##_sqr(t2, t1); \
+ \
+ /* x3 = t1^2 - 2 * x1. */ \
+ F##_dbl(t0, p->x); \
+ F##_sub(t0, t2, t0); \
+ \
+ /* y3 = t1 * (x1 - x3) - y1. */ \
+ F##_sub(t2, p->x, t0); \
+ F##_mul(t1, t1, t2); \
+ F##_sub(r->y, t1, p->y); \
+ \
+ F##_copy(r->x, t0); \
+ F##_copy(r->z, p->z); \
+ \
+ r->coord = BASIC; \
+ } RLC_CATCH_ANY { \
+ RLC_THROW(ERR_CAUGHT); \
+ } RLC_FINALLY { \
+ F##_free(t0); \
+ F##_free(t1); \
+ F##_free(t2); \
+ } \
+ } \
+
+/**
+ * Defines a template for point addition in affine coordinates.
+ *
+ * Formulas for point doubling from
+ * "Complete addition formulas for prime order elliptic curves"
+ * by Joost Renes, Craig Costello, and Lejla Batina
+ * https://eprint.iacr.org/2015/1060.pdf
+ *
+ * @param[in] C - the curve.
+ * @param[in] F - the field prefix.
+ */
+#define TMPL_DBL_PROJC_IMP(C, F) \
+ static void C##_dbl_projc_imp(C##_t r, const C##_t p) { \
+ F##_t t0, t1, t2, t3, t4, t5; \
+ \
+ F##_null(t0); \
+ F##_null(t1); \
+ F##_null(t2); \
+ F##_null(t3); \
+ F##_null(t4); \
+ F##_null(t5); \
+ \
+ RLC_TRY { \
+ F##_new(t0); \
+ F##_new(t1); \
+ F##_new(t2); \
+ F##_new(t3); \
+ F##_new(t4); \
+ F##_new(t5); \
+ \
+ if (C##_curve_opt_a() == RLC_ZERO) { \
+ /* Cost of 6M + 2S + 1m_3b + 9a. */ \
+ F##_sqr(t0, p->y); \
+ F##_mul(t3, p->x, p->y); \
+ \
+ if (p->coord == BASIC) { \
+ /* Save 1M + 1S + 1m_b3 if z1 = 1. */ \
+ F##_copy(t1, p->y); \
+ F##_dbl(t2, C##_curve_get_b()); \
+ F##_add(t2, t2, C##_curve_get_b()); \
+ } else { \
+ F##_mul(t1, p->y, p->z); \
+ F##_sqr(t2, p->z); \
+ F##_dbl(t5, t2); \
+ F##_add(t5, t5, t2); \
+ C##_curve_mul_b(t2, t5); \
+ } \
+ F##_dbl(r->z, t0); \
+ F##_dbl(r->z, r->z); \
+ F##_dbl(r->z, r->z); \
+ F##_mul(r->x, t2, r->z); \
+ F##_add(r->y, t0, t2); \
+ F##_mul(r->z, t1, r->z); \
+ F##_dbl(t1, t2); \
+ F##_add(t2, t1, t2); \
+ F##_sub(t0, t0, t2); \
+ F##_mul(r->y, t0, r->y); \
+ F##_add(r->y, r->x, r->y); \
+ F##_mul(r->x, t0, t3); \
+ F##_dbl(r->x, r->x); \
+ } else { \
+ F##_sqr(t0, p->x); \
+ F##_sqr(t1, p->y); \
+ F##_mul(t3, p->x, p->y); \
+ F##_dbl(t3, t3); \
+ F##_mul(t4, p->y, p->z); \
+ \
+ if (C##_curve_opt_a() == RLC_MIN3) { \
+ /* Cost of 8M + 3S + 2mb + 21a. */ \
+ if (p->coord == BASIC) { \
+ /* Save 1S + 1m_b + 2a if z1 = 1. */ \
+ F##_set_dig(t2, 3); \
+ F##_copy(r->y, C##_curve_get_b()); \
+ } else { \
+ F##_sqr(t2, p->z); \
+ C##_curve_mul_b(r->y, t2); \
+ F##_dbl(t5, t2); \
+ F##_add(t2, t2, t5); \
+ } \
+ F##_mul(r->z, p->x, p->z); \
+ F##_dbl(r->z, r->z); \
+ F##_sub(r->y, r->y, r->z); \
+ F##_dbl(r->x, r->y); \
+ F##_add(r->y, r->x, r->y); \
+ F##_sub(r->x, t1, r->y); \
+ F##_add(r->y, t1, r->y); \
+ F##_mul(r->y, r->x, r->y); \
+ F##_mul(r->x, t3, r->x); \
+ C##_curve_mul_b(r->z, r->z); \
+ F##_sub(t3, r->z, t2); \
+ F##_sub(t3, t3, t0); \
+ F##_dbl(r->z, t3); \
+ F##_add(t3, t3, r->z); \
+ F##_dbl(r->z, t0); \
+ F##_add(t0, t0, r->z); \
+ F##_sub(t0, t0, t2); \
+ } else { \
+ /* Common cost of 8M + 3S + 3m_a + 2m_3b + 15a. */ \
+ if (p->coord == BASIC) { \
+ /* Save 1S + 1m_b + 1m_a if z1 = 1. */ \
+ F##_dbl(r->y, C##_curve_get_b()); \
+ F##_add(r->y, r->y, C##_curve_get_b()); \
+ F##_copy(t2, C##_curve_get_a()); \
+ } else { \
+ F##_sqr(t2, p->z); \
+ F##_dbl(t5, t2); \
+ F##_add(t5, t5, t2); \
+ C##_curve_mul_b(r->y, t5); \
+ C##_curve_mul_a(t2, t2); \
+ } \
+ F##_mul(r->z, p->x, p->z); \
+ F##_dbl(r->z, r->z); \
+ C##_curve_mul_a(r->x, r->z); \
+ F##_add(r->y, r->x, r->y); \
+ F##_sub(r->x, t1, r->y); \
+ F##_add(r->y, t1, r->y); \
+ F##_mul(r->y, r->x, r->y); \
+ F##_mul(r->x, t3, r->x); \
+ F##_dbl(t5, r->z); \
+ F##_add(t5, t5, r->z); \
+ C##_curve_mul_b(r->z, t5); \
+ F##_sub(t3, t0, t2); \
+ C##_curve_mul_a(t3, t3); \
+ F##_add(t3, t3, r->z); \
+ F##_dbl(r->z, t0); \
+ F##_add(t0, t0, r->z); \
+ F##_add(t0, t0, t2); \
+ } \
+ /* Common part with renamed variables. */ \
+ F##_mul(t0, t0, t3); \
+ F##_add(r->y, r->y, t0); \
+ F##_dbl(t2, t4); \
+ F##_mul(t0, t2, t3); \
+ F##_sub(r->x, r->x, t0); \
+ F##_mul(r->z, t2, t1); \
+ F##_dbl(r->z, r->z); \
+ F##_dbl(r->z, r->z); \
+ } \
+ r->coord = PROJC; \
+ } RLC_CATCH_ANY { \
+ RLC_THROW(ERR_CAUGHT); \
+ } RLC_FINALLY { \
+ F##_free(t0); \
+ F##_free(t1); \
+ F##_free(t2); \
+ F##_free(t3); \
+ F##_free(t4); \
+ F##_free(t5); \
+ } \
+ } \
+
+/**
+ * Defines a template for point addition in Jacobian coordinates.
+ *
+ * Formulas from http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html
+ *
+ * @param[in] C - the curve.
+ * @param[in] F - the field prefix.
+ */
+#define TMPL_DBL_JACOB_IMP(C, F) \
+ static void C##_dbl_jacob_imp(C##_t r, const C##_t p) { \
+ F##_t t0, t1, t2, t3, t4, t5; \
+ \
+ F##_null(t1); \
+ F##_null(t2); \
+ F##_null(t3); \
+ F##_null(t4); \
+ F##_null(t5); \
+ \
+ RLC_TRY { \
+ F##_new(t0); \
+ F##_new(t1); \
+ F##_new(t2); \
+ F##_new(t3); \
+ F##_new(t4); \
+ F##_new(t5); \
+ \
+ if (p->coord != BASIC && C##_curve_opt_a() == RLC_MIN3) { \
+ /* dbl-2001-b formulas: 3M + 5S + 8add + 1*4 + 2*8 + 1*3 */ \
+ \
+ /* t0 = delta = z1^2. */ \
+ F##_sqr(t0, p->z); \
+ \
+ /* t1 = gamma = y1^2. */ \
+ F##_sqr(t1, p->y); \
+ \
+ /* t2 = beta = x1 * y1^2. */ \
+ F##_mul(t2, p->x, t1); \
+ \
+ /* t3 = alpha = 3 * (x1 - z1^2) * (x1 + z1^2). */ \
+ F##_sub(t3, p->x, t0); \
+ F##_add(t4, p->x, t0); \
+ F##_mul(t4, t3, t4); \
+ F##_dbl(t3, t4); \
+ F##_add(t3, t3, t4); \
+ \
+ /* x3 = alpha^2 - 8 * beta. */ \
+ F##_dbl(t2, t2); \
+ F##_dbl(t2, t2); \
+ F##_dbl(t5, t2); \
+ F##_sqr(r->x, t3); \
+ F##_sub(r->x, r->x, t5); \
+ \
+ /* z3 = (y1 + z1)^2 - gamma - delta. */ \
+ F##_add(r->z, p->y, p->z); \
+ F##_sqr(r->z, r->z); \
+ F##_sub(r->z, r->z, t1); \
+ F##_sub(r->z, r->z, t0); \
+ \
+ /* y3 = alpha * (4 * beta - x3) - 8 * gamma^2. */ \
+ F##_dbl(t1, t1); \
+ F##_sqr(t1, t1); \
+ F##_dbl(t1, t1); \
+ F##_sub(r->y, t2, r->x); \
+ F##_mul(r->y, r->y, t3); \
+ F##_sub(r->y, r->y, t1); \
+ } else if (C##_curve_opt_a() == RLC_ZERO) { \
+ /* dbl-2009-l formulas: 2M + 5S + 6add + 1*8 + 3*2 + 1*3.*/ \
+ \
+ /* A = X1^2 */ \
+ F##_sqr(t0, p->x); \
+ \
+ /* B = Y1^2 */ \
+ F##_sqr(t1, p->y); \
+ \
+ /* C = B^2 */ \
+ F##_sqr(t2, t1); \
+ \
+ /* D = 2*((X1+B)^2-A-C) */ \
+ F##_add(t1, t1, p->x); \
+ F##_sqr(t1, t1); \
+ F##_sub(t1, t1, t0); \
+ F##_sub(t1, t1, t2); \
+ F##_dbl(t1, t1); \
+ \
+ /* E = 3*A */ \
+ F##_dbl(t3, t0); \
+ F##_add(t0, t3, t0); \
+ \
+ /* F = E^2 */ \
+ F##_sqr(t3, t0); \
+ \
+ /* Z3 = 2*Y1*Z1 */ \
+ F##_mul(r->z, p->y, p->z); \
+ F##_dbl(r->z, r->z); \
+ \
+ /* X3 = F-2*D */ \
+ F##_sub(r->x, t3, t1); \
+ F##_sub(r->x, r->x, t1); \
+ \
+ /* Y3 = E*(D-X3)-8*C */ \
+ F##_sub(r->y, t1, r->x); \
+ F##_mul(r->y, r->y, t0); \
+ F##_dbl(t2, t2); \
+ F##_dbl(t2, t2); \
+ F##_dbl(t2, t2); \
+ F##_sub(r->y, r->y, t2); \
+ } else { \
+ /* dbl-2007-bl: 1M + 8S + 1*a + 10add + 1*8 + 2*2 + 1*3 */ \
+ \
+ /* t0 = x1^2, t1 = y1^2, t2 = y1^4. */ \
+ F##_sqr(t0, p->x); \
+ F##_sqr(t1, p->y); \
+ F##_sqr(t2, t1); \
+ \
+ if (p->coord != BASIC) { \
+ /* t3 = z1^2. */ \
+ F##_sqr(t3, p->z); \
+ \
+ if (C##_curve_opt_a() == RLC_ZERO) { \
+ /* z3 = 2 * y1 * z1. */ \
+ F##_mul(r->z, p->y, p->z); \
+ F##_dbl(r->z, r->z); \
+ } else { \
+ /* z3 = (y1 + z1)^2 - y1^2 - z1^2. */ \
+ F##_add(r->z, p->y, p->z); \
+ F##_sqr(r->z, r->z); \
+ F##_sub(r->z, r->z, t1); \
+ F##_sub(r->z, r->z, t3); \
+ } \
+ } else { \
+ /* z3 = 2 * y1. */ \
+ F##_dbl(r->z, p->y); \
+ } \
+ \
+ /* t4 = S = 2*((x1 + y1^2)^2 - x1^2 - y1^4). */ \
+ F##_add(t4, p->x, t1); \
+ F##_sqr(t4, t4); \
+ F##_sub(t4, t4, t0); \
+ F##_sub(t4, t4, t2); \
+ F##_dbl(t4, t4); \
+ \
+ /* t5 = M = 3 * x1^2 + a * z1^4. */ \
+ F##_dbl(t5, t0); \
+ F##_add(t5, t5, t0); \
+ if (p->coord != BASIC) { \
+ F##_sqr(t3, t3); \
+ C##_curve_mul_a(t1, t3); \
+ F##_add(t5, t5, t1); \
+ } else { \
+ F##_add(t5, t5, C##_curve_get_a()); \
+ } \
+ /* x3 = T = M^2 - 2 * S. */ \
+ F##_sqr(r->x, t5); \
+ F##_dbl(t1, t4); \
+ F##_sub(r->x, r->x, t1); \
+ \
+ /* y3 = M * (S - T) - 8 * y1^4. */ \
+ F##_dbl(t2, t2); \
+ F##_dbl(t2, t2); \
+ F##_dbl(t2, t2); \
+ F##_sub(t4, t4, r->x); \
+ F##_mul(t5, t5, t4); \
+ F##_sub(r->y, t5, t2); \
+ } \
+ \
+ r->coord = JACOB; \
+ } \
+ RLC_CATCH_ANY { \
+ RLC_THROW(ERR_CAUGHT); \
+ } \
+ RLC_FINALLY { \
+ F##_free(t0); \
+ F##_free(t1); \
+ F##_free(t2); \
+ F##_free(t3); \
+ F##_free(t4); \
+ F##_free(t5); \
+ } \
+ } \
+
diff --git a/src/tmpl/relic_tmpl_map.h b/src/tmpl/relic_ep_map_tmpl.h
similarity index 88%
rename from src/tmpl/relic_tmpl_map.h
rename to src/tmpl/relic_ep_map_tmpl.h
index 2caaef1f7..7e31f88c7 100644
--- a/src/tmpl/relic_tmpl_map.h
+++ b/src/tmpl/relic_ep_map_tmpl.h
@@ -24,7 +24,7 @@
/**
* @file
*
- * Templates for hashing to elliptic curves.
+ * Template for hashing to prime elliptic curves.
*
* @ingroup tmpl
*/
@@ -34,7 +34,7 @@
/*============================================================================*/
/**
- * Evaluate a polynomial represented by its coefficients over a using Horner's
+ * Evaluates a polynomial represented by its coefficients over a using Horner's
* rule. Might promove to an API if needed elsewhere in the future.
*/
#define TMPL_MAP_HORNER(PFX, IN) \
@@ -46,9 +46,9 @@
} \
}
-/* TODO: remove the ugly hack due to lack of support for JACOB in ep2. */
/* conditionally normalize result of isogeny map when not using projective coords */
#if EP_ADD == JACOB
+
#define TMPL_MAP_ISOMAP_NORM(PFX) \
do { \
/* Y = Ny * Dx * Z^2. */ \
@@ -62,22 +62,11 @@
PFX##_mul(q->x, t0, t2); \
PFX##_mul(q->x, q->x, q->z); \
q->coord = JACOB; \
- } while (0)
+ } while (0) \
+
#elif EP_ADD == PROJC
+
#define TMPL_MAP_ISOMAP_NORM(PFX) \
- if (#PFX[2] == '2') { \
- /* Y = Ny * Dx * Z^2. */ \
- PFX##_mul(q->y, p->y, t1); \
- PFX##_mul(q->y, q->y, t3); \
- /* Z = Dx * Dy, t1 = Z^2. */ \
- PFX##_mul(q->z, t2, t3); \
- PFX##_sqr(t1, q->z); \
- PFX##_mul(q->y, q->y, t1); \
- /* X = Nx * Dy * Z. */ \
- PFX##_mul(q->x, t0, t2); \
- PFX##_mul(q->x, q->x, q->z); \
- q->coord = PROJC; \
- } else { \
/* Z = Dx * Dy. */ \
PFX##_mul(q->z, t2, t3); \
/* X = Nx * Dy. */ \
@@ -86,8 +75,9 @@
PFX##_mul(q->y, p->y, t1); \
PFX##_mul(q->y, q->y, t3); \
q->coord = PROJC; \
- }
+
#else
+
#define TMPL_MAP_ISOMAP_NORM(PFX) \
do { \
/* when working with affine coordinates, clear denominator */ \
@@ -103,7 +93,8 @@
/* z coord == 1 */ \
PFX##_set_dig(q->z, 1); \
q->coord = BASIC; \
- } while (0)
+ } while (0) \
+
#endif
/**
@@ -153,7 +144,7 @@
PFX##_free(t2); \
PFX##_free(t3); \
} \
- }
+ } \
/* Conditionally call isogeny mapping function depending on whether EP_CTMAP is defined */
#ifdef EP_CTMAP
@@ -162,16 +153,19 @@
if (CUR##_curve_is_ctmap()) { \
CUR##_iso(PT, PT); \
} \
- } while (0)
+ } while (0) \
+
#else
+
#define TMPL_MAP_CALL_ISOMAP(CUR, PT) /* No isogeny map call in this case. */
+
#endif
/**
* Simplified SWU mapping from Section 4 of
* "Fast and simple constant-time hashing to the BLS12-381 Elliptic Curve"
*/
-#define TMPL_MAP_SSWU(CUR, PFX, PTR_TY, COPY_COND) \
+#define TMPL_MAP_SSWU(CUR, PFX, PTR_TY) \
static void CUR##_map_sswu(CUR##_t p, const PFX##_t t) { \
PFX##_t t0, t1, t2, t3; \
ctx_t *ctx = core_get(); \
@@ -203,11 +197,11 @@
const int e1 = PFX##_is_zero(t2); \
PFX##_neg(t3, u); /* t3 = -u */ \
/* exception: -u instead of u^2t^4 + ut^2 */ \
- COPY_COND(t2, t3, e1); \
+ PFX##_copy_sec(t2, t3, e1); \
/* t2 = -1/u or 1/(u^2 * t^4 + u*t^2) */ \
PFX##_inv(t2, t2); \
PFX##_add_dig(t3, t2, 1); /* t3 = 1 + t2 */ \
- COPY_COND(t2, t3, e1 == 0); /* only add 1 if t2 != -1/u */ \
+ PFX##_copy_sec(t2, t3, e1 == 0); /* add 1 if t2 != -1/u */ \
} \
/* e1 goes out of scope */ \
/* compute x1, g(x1) */ \
@@ -225,8 +219,8 @@
{ \
/* try x2, g(x2) */ \
const int e1 = PFX##_is_sqr(p->y); \
- COPY_COND(p->x, t2, e1 == 0); \
- COPY_COND(p->y, t3, e1 == 0); \
+ PFX##_copy_sec(p->x, t2, e1 == 0); \
+ PFX##_copy_sec(p->y, t3, e1 == 0); \
} \
if (!PFX##_srt(p->y, p->y)) { \
RLC_THROW(ERR_NO_VALID); \
@@ -241,13 +235,13 @@
PFX##_free(t2); \
PFX##_free(t3); \
} \
- }
+ } \
/**
* Shallue--van de Woestijne map, based on the definition from
* draft-irtf-cfrg-hash-to-curve-06, Section 6.6.1
*/
-#define TMPL_MAP_SVDW(CUR, PFX, PTR_TY, COPY_COND) \
+#define TMPL_MAP_SVDW(CUR, PFX, PTR_TY) \
static void CUR##_map_svdw(CUR##_t p, const PFX##_t t) { \
PFX##_t t1, t2, t3, t4; \
ctx_t *ctx = core_get(); \
@@ -280,10 +274,10 @@
{ \
/* compute inv0(t3), i.e., 0 if t3 == 0, 1/t3 otherwise */ \
const int e0 = PFX##_is_zero(t3); \
- COPY_COND(t3, gU, e0); /* g(u) is nonzero */ \
+ PFX##_copy_sec(t3, gU, e0); /* g(u) is nonzero */ \
PFX##_inv(t3, t3); \
PFX##_zero(t4); \
- COPY_COND(t3, t4, e0); \
+ PFX##_copy_sec(t3, t4, e0); \
} \
/* e0 goes out of scope */ \
PFX##_mul(t4, t, t1); \
@@ -292,14 +286,14 @@
\
/* compute x1 and g(x1) */ \
PFX##_sub(p->x, mUover2, t4); \
- CUR##_rhs(p->y, p); \
+ CUR##_rhs(p->y, p->x); \
{ \
const int e0 = PFX##_is_sqr(p->y); \
/* compute x2 and g(x2) */ \
PFX##_add(t4, mUover2, t4); \
- COPY_COND(p->x, t4, e0 == 0); \
- CUR##_rhs(t1, p); \
- COPY_COND(p->y, t1, e0 == 0); \
+ PFX##_copy_sec(p->x, t4, e0 == 0); \
+ CUR##_rhs(t1, p->x); \
+ PFX##_copy_sec(p->y, t1, e0 == 0); \
} \
{ \
const int e1 = PFX##_is_sqr(p->y); \
@@ -309,9 +303,9 @@
PFX##_sqr(t1, t1); \
PFX##_mul(t1, t1, c4); \
PFX##_add(t1, t1, u); \
- COPY_COND(p->x, t1, e1 == 0); \
- CUR##_rhs(t2, p); \
- COPY_COND(p->y, t2, e1 == 0); \
+ PFX##_copy_sec(p->x, t1, e1 == 0); \
+ CUR##_rhs(t2, p->x); \
+ PFX##_copy_sec(p->y, t2, e1 == 0); \
} \
if (!PFX##_srt(p->y, p->y)) { \
RLC_THROW(ERR_NO_VALID); \
@@ -326,4 +320,5 @@
PFX##_free(t3); \
PFX##_free(t4); \
} \
- }
+ } \
+
diff --git a/test/test_dv.c b/test/test_dv.c
index c272f33c5..29d4182e0 100644
--- a/test/test_dv.c
+++ b/test/test_dv.c
@@ -81,17 +81,17 @@ static int copy(void) {
}
}
dv_copy(a, b, RLC_DV_DIGS);
- TEST_ASSERT(dv_cmp_const(a, b, RLC_DV_DIGS) == RLC_EQ, end);
+ TEST_ASSERT(dv_cmp_sec(a, b, RLC_DV_DIGS) == RLC_EQ, end);
}
TEST_END;
TEST_CASE("conditional copy and comparison are consistent") {
rand_bytes((uint8_t *)a, RLC_DV_DIGS * sizeof(dig_t));
rand_bytes((uint8_t *)b, RLC_DV_DIGS * sizeof(dig_t));
- dv_copy_cond(a, b, RLC_DV_DIGS, 0);
- TEST_ASSERT(dv_cmp_const(a, b, RLC_DV_DIGS) == RLC_NE, end);
- dv_copy_cond(a, b, RLC_DV_DIGS, 1);
- TEST_ASSERT(dv_cmp_const(a, b, RLC_DV_DIGS) == RLC_EQ, end);
+ dv_copy_sec(a, b, RLC_DV_DIGS, 0);
+ TEST_ASSERT(dv_cmp_sec(a, b, RLC_DV_DIGS) == RLC_NE, end);
+ dv_copy_sec(a, b, RLC_DV_DIGS, 1);
+ TEST_ASSERT(dv_cmp_sec(a, b, RLC_DV_DIGS) == RLC_EQ, end);
}
TEST_END;
} RLC_CATCH_ANY {
@@ -123,8 +123,8 @@ static int swap(void) {
rand_bytes((uint8_t *)a, RLC_DV_DIGS * sizeof(dig_t));
rand_bytes((uint8_t *)b, RLC_DV_DIGS * sizeof(dig_t));
dv_copy(c, a, RLC_DV_DIGS);
- dv_swap_cond(a, b, RLC_DV_DIGS, 1);
- TEST_ASSERT(dv_cmp_const(c, b, RLC_DV_DIGS) == RLC_EQ, end);
+ dv_swap_sec(a, b, RLC_DV_DIGS, 1);
+ TEST_ASSERT(dv_cmp_sec(c, b, RLC_DV_DIGS) == RLC_EQ, end);
}
TEST_END;
@@ -133,16 +133,16 @@ static int swap(void) {
rand_bytes((uint8_t *)b, RLC_DV_DIGS * sizeof(dig_t));
dv_copy(c, a, RLC_DV_DIGS);
dv_copy(d, b, RLC_DV_DIGS);
- dv_swap_cond(a, b, RLC_DV_DIGS, 0);
- TEST_ASSERT(dv_cmp_const(c, a, RLC_DV_DIGS) == RLC_EQ, end);
- TEST_ASSERT(dv_cmp_const(d, b, RLC_DV_DIGS) == RLC_EQ, end);
- TEST_ASSERT(dv_cmp_const(c, b, RLC_DV_DIGS) == RLC_NE, end);
- TEST_ASSERT(dv_cmp_const(d, a, RLC_DV_DIGS) == RLC_NE, end);
- dv_swap_cond(a, b, RLC_DV_DIGS, 1);
- TEST_ASSERT(dv_cmp_const(c, b, RLC_DV_DIGS) == RLC_EQ, end);
- TEST_ASSERT(dv_cmp_const(d, a, RLC_DV_DIGS) == RLC_EQ, end);
- TEST_ASSERT(dv_cmp_const(c, a, RLC_DV_DIGS) == RLC_NE, end);
- TEST_ASSERT(dv_cmp_const(d, b, RLC_DV_DIGS) == RLC_NE, end);
+ dv_swap_sec(a, b, RLC_DV_DIGS, 0);
+ TEST_ASSERT(dv_cmp_sec(c, a, RLC_DV_DIGS) == RLC_EQ, end);
+ TEST_ASSERT(dv_cmp_sec(d, b, RLC_DV_DIGS) == RLC_EQ, end);
+ TEST_ASSERT(dv_cmp_sec(c, b, RLC_DV_DIGS) == RLC_NE, end);
+ TEST_ASSERT(dv_cmp_sec(d, a, RLC_DV_DIGS) == RLC_NE, end);
+ dv_swap_sec(a, b, RLC_DV_DIGS, 1);
+ TEST_ASSERT(dv_cmp_sec(c, b, RLC_DV_DIGS) == RLC_EQ, end);
+ TEST_ASSERT(dv_cmp_sec(d, a, RLC_DV_DIGS) == RLC_EQ, end);
+ TEST_ASSERT(dv_cmp_sec(c, a, RLC_DV_DIGS) == RLC_NE, end);
+ TEST_ASSERT(dv_cmp_sec(d, b, RLC_DV_DIGS) == RLC_NE, end);
}
TEST_END;
} RLC_CATCH_ANY {
diff --git a/test/test_ep.c b/test/test_ep.c
index 5c60e2560..5484a4ede 100644
--- a/test/test_ep.c
+++ b/test/test_ep.c
@@ -1394,15 +1394,17 @@ static int hashing(void) {
#endif
#if EP_MAP == SWIFT || !defined(STRIP)
- if (ep_curve_opt_a() == RLC_ZERO || ep_curve_opt_b() == RLC_ZERO) {
- TEST_CASE("swift point hashing is correct") {
- rand_bytes(msg, sizeof(msg));
- ep_map_swift(a, msg, sizeof(msg));
- TEST_ASSERT(ep_on_curve(a) && ep_is_infty(a) == 0, end);
- ep_mul(a, a, n);
- TEST_ASSERT(ep_on_curve(a) && ep_is_infty(a) == 1, end);
+ if (!ep_curve_is_super()) {
+ if (ep_curve_opt_a() == RLC_ZERO || ep_curve_opt_b() == RLC_ZERO) {
+ TEST_CASE("swift point hashing is correct") {
+ rand_bytes(msg, sizeof(msg));
+ ep_map_swift(a, msg, sizeof(msg));
+ TEST_ASSERT(ep_on_curve(a) && ep_is_infty(a) == 0, end);
+ ep_mul(a, a, n);
+ TEST_ASSERT(ep_on_curve(a) && ep_is_infty(a) == 1, end);
+ }
+ TEST_END;
}
- TEST_END;
}
#endif
}
diff --git a/test/test_epx.c b/test/test_epx.c
index d975bfdfc..5dda4c52f 100644
--- a/test/test_epx.c
+++ b/test/test_epx.c
@@ -219,9 +219,9 @@ static int addition2(void) {
ep2_rand(a);
ep2_set_infty(d);
ep2_add(e, a, d);
- TEST_ASSERT(ep2_cmp(e, a) == RLC_EQ, end);
+ TEST_ASSERT(ep2_cmp(a, e) == RLC_EQ, end);
ep2_add(e, d, a);
- TEST_ASSERT(ep2_cmp(e, a) == RLC_EQ, end);
+ TEST_ASSERT(ep2_cmp(a, e) == RLC_EQ, end);
} TEST_END;
TEST_CASE("point addition has inverse") {
@@ -237,7 +237,7 @@ static int addition2(void) {
ep2_rand(b);
ep2_add(d, a, b);
ep2_add_basic(e, a, b);
- TEST_ASSERT(ep2_cmp(e, d) == RLC_EQ, end);
+ TEST_ASSERT(ep2_cmp(d, e) == RLC_EQ, end);
} TEST_END;
#endif
@@ -281,6 +281,46 @@ static int addition2(void) {
} TEST_END;
#endif
+#if EP_ADD == JACOB || !defined(STRIP)
+#if !defined(EP_MIXED) || !defined(STRIP)
+ TEST_CASE("point addition in jacobian coordinates is correct") {
+ ep2_rand(a);
+ ep2_rand(b);
+ ep2_rand(c);
+ ep2_add_jacob(a, a, b);
+ ep2_add_jacob(b, b, c);
+ /* a and b in projective coordinates. */
+ ep2_add_jacob(d, a, b);
+ ep2_norm(a, a);
+ ep2_norm(b, b);
+ ep2_add(e, a, b);
+ TEST_ASSERT(ep2_cmp(d, e) == RLC_EQ, end);
+ } TEST_END;
+#endif
+
+ TEST_CASE("point addition in mixed coordinates (z2 = 1) is correct") {
+ ep2_rand(a);
+ ep2_rand(b);
+ /* a in projective, b in affine coordinates. */
+ ep2_add_jacob(a, a, b);
+ ep2_add_jacob(d, a, b);
+ /* a in affine coordinates. */
+ ep2_norm(a, a);
+ ep2_add(e, a, b);
+ TEST_ASSERT(ep2_cmp(d, e) == RLC_EQ, end);
+ } TEST_END;
+
+ TEST_CASE("point addition in mixed coordinates (z1,z2 = 1) is correct") {
+ ep2_rand(a);
+ ep2_rand(b);
+ ep2_norm(a, a);
+ ep2_norm(b, b);
+ /* a and b in affine coordinates. */
+ ep2_add(d, a, b);
+ ep2_add_jacob(e, a, b);
+ TEST_ASSERT(ep2_cmp(d, e) == RLC_EQ, end);
+ } TEST_END;
+#endif
}
RLC_CATCH_ANY {
RLC_ERROR(end);
@@ -395,6 +435,26 @@ static int doubling2(void) {
TEST_ASSERT(ep2_cmp(b, c) == RLC_EQ, end);
} TEST_END;
#endif
+
+#if EP_ADD == JACOB || !defined(STRIP)
+ TEST_CASE("point doubling in jacobian coordinates is correct") {
+ ep2_rand(a);
+ /* a in projective coordinates. */
+ ep2_dbl_jacob(a, a);
+ ep2_dbl_jacob(b, a);
+ ep2_norm(a, a);
+ ep2_dbl(c, a);
+ TEST_ASSERT(ep2_cmp(b, c) == RLC_EQ, end);
+ } TEST_END;
+
+ TEST_CASE("point doubling in mixed coordinates (z1 = 1) is correct") {
+ ep2_rand(a);
+ ep2_dbl_jacob(b, a);
+ ep2_norm(b, b);
+ ep2_dbl(c, a);
+ TEST_ASSERT(ep2_cmp(b, c) == RLC_EQ, end);
+ } TEST_END;
+#endif
}
RLC_CATCH_ANY {
RLC_ERROR(end);
@@ -567,6 +627,34 @@ static int multiplication2(void) {
TEST_END;
#endif
+#if EP_MUL == LWREG || !defined(STRIP)
+ TEST_CASE("left-to-right regular point multiplication is correct") {
+ bn_zero(k);
+ ep2_mul_lwreg(r, p, k);
+ TEST_ASSERT(ep2_is_infty(r), end);
+ bn_set_dig(k, 1);
+ ep2_mul_lwreg(r, p, k);
+ TEST_ASSERT(ep2_cmp(p, r) == RLC_EQ, end);
+ ep2_rand(p);
+ ep2_mul_lwreg(r, p, n);
+ TEST_ASSERT(ep2_is_infty(r), end);
+ bn_rand_mod(k, n);
+ ep2_mul(q, p, k);
+ ep2_mul_lwreg(r, p, k);
+ TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
+ bn_neg(k, k);
+ ep2_mul_lwreg(r, p, k);
+ ep2_neg(r, r);
+ TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
+ bn_rand_mod(k, n);
+ ep2_mul_lwreg(q, p, k);
+ bn_add(k, k, n);
+ ep2_mul_lwreg(r, p, k);
+ TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
+ }
+ TEST_END;
+#endif
+
TEST_CASE("point multiplication by digit is correct") {
ep2_mul_dig(r, p, 0);
TEST_ASSERT(ep2_is_infty(r), end);
@@ -1390,9 +1478,9 @@ static int addition3(void) {
ep3_rand(a);
ep3_set_infty(d);
ep3_add(e, a, d);
- TEST_ASSERT(ep3_cmp(e, a) == RLC_EQ, end);
+ TEST_ASSERT(ep3_cmp(a, e) == RLC_EQ, end);
ep3_add(e, d, a);
- TEST_ASSERT(ep3_cmp(e, a) == RLC_EQ, end);
+ TEST_ASSERT(ep3_cmp(a, e) == RLC_EQ, end);
} TEST_END;
TEST_CASE("point addition has inverse") {
@@ -1408,7 +1496,7 @@ static int addition3(void) {
ep3_rand(b);
ep3_add(d, a, b);
ep3_add_basic(e, a, b);
- TEST_ASSERT(ep3_cmp(e, d) == RLC_EQ, end);
+ TEST_ASSERT(ep3_cmp(d, e) == RLC_EQ, end);
} TEST_END;
#endif
@@ -1452,6 +1540,46 @@ static int addition3(void) {
} TEST_END;
#endif
+#if EP_ADD == JACOB || !defined(STRIP)
+#if !defined(EP_MIXED) || !defined(STRIP)
+ TEST_CASE("point addition in jacobian coordinates is correct") {
+ ep3_rand(a);
+ ep3_rand(b);
+ ep3_rand(c);
+ ep3_add_jacob(a, a, b);
+ ep3_add_jacob(b, b, c);
+ /* a and b in projective coordinates. */
+ ep3_add_jacob(d, a, b);
+ ep3_norm(a, a);
+ ep3_norm(b, b);
+ ep3_add(e, a, b);
+ TEST_ASSERT(ep3_cmp(d, e) == RLC_EQ, end);
+ } TEST_END;
+#endif
+
+ TEST_CASE("point addition in mixed coordinates (z2 = 1) is correct") {
+ ep3_rand(a);
+ ep3_rand(b);
+ /* a in projective, b in affine coordinates. */
+ ep3_add_jacob(a, a, b);
+ ep3_add_jacob(d, a, b);
+ /* a in affine coordinates. */
+ ep3_norm(a, a);
+ ep3_add(e, a, b);
+ TEST_ASSERT(ep3_cmp(d, e) == RLC_EQ, end);
+ } TEST_END;
+
+ TEST_CASE("point addition in mixed coordinates (z1,z2 = 1) is correct") {
+ ep3_rand(a);
+ ep3_rand(b);
+ ep3_norm(a, a);
+ ep3_norm(b, b);
+ /* a and b in affine coordinates. */
+ ep3_add(d, a, b);
+ ep3_add_jacob(e, a, b);
+ TEST_ASSERT(ep3_cmp(d, e) == RLC_EQ, end);
+ } TEST_END;
+#endif
}
RLC_CATCH_ANY {
RLC_ERROR(end);
@@ -1566,6 +1694,26 @@ static int doubling3(void) {
TEST_ASSERT(ep3_cmp(b, c) == RLC_EQ, end);
} TEST_END;
#endif
+
+#if EP_ADD == JACOB || !defined(STRIP)
+ TEST_CASE("point doubling in jacobian coordinates is correct") {
+ ep3_rand(a);
+ /* a in projective coordinates. */
+ ep3_dbl_jacob(a, a);
+ ep3_dbl_jacob(b, a);
+ ep3_norm(a, a);
+ ep3_dbl(c, a);
+ TEST_ASSERT(ep3_cmp(b, c) == RLC_EQ, end);
+ } TEST_END;
+
+ TEST_CASE("point doubling in mixed coordinates (z1 = 1) is correct") {
+ ep3_rand(a);
+ ep3_dbl_jacob(b, a);
+ ep3_norm(b, b);
+ ep3_dbl(c, a);
+ TEST_ASSERT(ep3_cmp(b, c) == RLC_EQ, end);
+ } TEST_END;
+#endif
}
RLC_CATCH_ANY {
RLC_ERROR(end);
@@ -1718,6 +1866,34 @@ static int multiplication3(void) {
TEST_END;
#endif
+#if EP_MUL == LWREG || !defined(STRIP)
+ TEST_CASE("left-to-right regular point multiplication is correct") {
+ bn_zero(k);
+ ep3_mul_lwreg(r, p, k);
+ TEST_ASSERT(ep3_is_infty(r), end);
+ bn_set_dig(k, 1);
+ ep3_mul_lwreg(r, p, k);
+ TEST_ASSERT(ep3_cmp(p, r) == RLC_EQ, end);
+ ep3_rand(p);
+ ep3_mul_lwreg(r, p, n);
+ TEST_ASSERT(ep3_is_infty(r), end);
+ bn_rand_mod(k, n);
+ ep3_mul(q, p, k);
+ ep3_mul_lwreg(r, p, k);
+ TEST_ASSERT(ep3_cmp(q, r) == RLC_EQ, end);
+ bn_neg(k, k);
+ ep3_mul_lwreg(r, p, k);
+ ep3_neg(r, r);
+ TEST_ASSERT(ep3_cmp(q, r) == RLC_EQ, end);
+ bn_rand_mod(k, n);
+ ep3_mul_lwreg(q, p, k);
+ bn_add(k, k, n);
+ ep3_mul_lwreg(r, p, k);
+ TEST_ASSERT(ep3_cmp(q, r) == RLC_EQ, end);
+ }
+ TEST_END;
+#endif
+
TEST_CASE("multiplication by digit is correct") {
ep3_mul_dig(r, p, 0);
TEST_ASSERT(ep3_is_infty(r), end);
@@ -2419,9 +2595,9 @@ static int addition4(void) {
ep4_rand(a);
ep4_set_infty(d);
ep4_add(e, a, d);
- TEST_ASSERT(ep4_cmp(e, a) == RLC_EQ, end);
+ TEST_ASSERT(ep4_cmp(a, e) == RLC_EQ, end);
ep4_add(e, d, a);
- TEST_ASSERT(ep4_cmp(e, a) == RLC_EQ, end);
+ TEST_ASSERT(ep4_cmp(a, e) == RLC_EQ, end);
} TEST_END;
TEST_CASE("point addition has inverse") {
@@ -2437,7 +2613,7 @@ static int addition4(void) {
ep4_rand(b);
ep4_add(d, a, b);
ep4_add_basic(e, a, b);
- TEST_ASSERT(ep4_cmp(e, d) == RLC_EQ, end);
+ TEST_ASSERT(ep4_cmp(d, e) == RLC_EQ, end);
} TEST_END;
#endif
@@ -2481,6 +2657,46 @@ static int addition4(void) {
} TEST_END;
#endif
+#if EP_ADD == JACOB || !defined(STRIP)
+#if !defined(EP_MIXED) || !defined(STRIP)
+ TEST_CASE("point addition in jacobian coordinates is correct") {
+ ep4_rand(a);
+ ep4_rand(b);
+ ep4_rand(c);
+ ep4_add_jacob(a, a, b);
+ ep4_add_jacob(b, b, c);
+ /* a and b in projective coordinates. */
+ ep4_add_jacob(d, a, b);
+ ep4_norm(a, a);
+ ep4_norm(b, b);
+ ep4_add(e, a, b);
+ TEST_ASSERT(ep4_cmp(d, e) == RLC_EQ, end);
+ } TEST_END;
+#endif
+
+ TEST_CASE("point addition in mixed coordinates (z2 = 1) is correct") {
+ ep4_rand(a);
+ ep4_rand(b);
+ /* a in projective, b in affine coordinates. */
+ ep4_add_jacob(a, a, b);
+ ep4_add_jacob(d, a, b);
+ /* a in affine coordinates. */
+ ep4_norm(a, a);
+ ep4_add(e, a, b);
+ TEST_ASSERT(ep4_cmp(d, e) == RLC_EQ, end);
+ } TEST_END;
+
+ TEST_CASE("point addition in mixed coordinates (z1,z2 = 1) is correct") {
+ ep4_rand(a);
+ ep4_rand(b);
+ ep4_norm(a, a);
+ ep4_norm(b, b);
+ /* a and b in affine coordinates. */
+ ep4_add(d, a, b);
+ ep4_add_jacob(e, a, b);
+ TEST_ASSERT(ep4_cmp(d, e) == RLC_EQ, end);
+ } TEST_END;
+#endif
}
RLC_CATCH_ANY {
RLC_ERROR(end);
@@ -2595,6 +2811,26 @@ static int doubling4(void) {
TEST_ASSERT(ep4_cmp(b, c) == RLC_EQ, end);
} TEST_END;
#endif
+
+#if EP_ADD == JACOB || !defined(STRIP)
+ TEST_CASE("point doubling in jacobian coordinates is correct") {
+ ep4_rand(a);
+ /* a in projective coordinates. */
+ ep4_dbl_jacob(a, a);
+ ep4_dbl_jacob(b, a);
+ ep4_norm(a, a);
+ ep4_dbl(c, a);
+ TEST_ASSERT(ep4_cmp(b, c) == RLC_EQ, end);
+ } TEST_END;
+
+ TEST_CASE("point doubling in mixed coordinates (z1 = 1) is correct") {
+ ep4_rand(a);
+ ep4_dbl_jacob(b, a);
+ ep4_norm(b, b);
+ ep4_dbl(c, a);
+ TEST_ASSERT(ep4_cmp(b, c) == RLC_EQ, end);
+ } TEST_END;
+#endif
}
RLC_CATCH_ANY {
RLC_ERROR(end);
@@ -2747,6 +2983,34 @@ static int multiplication4(void) {
TEST_END;
#endif
+#if EP_MUL == LWREG || !defined(STRIP)
+ TEST_CASE("left-to-right regular point multiplication is correct") {
+ bn_zero(k);
+ ep4_mul_lwreg(r, p, k);
+ TEST_ASSERT(ep4_is_infty(r), end);
+ bn_set_dig(k, 1);
+ ep4_mul_lwreg(r, p, k);
+ TEST_ASSERT(ep4_cmp(p, r) == RLC_EQ, end);
+ ep4_rand(p);
+ ep4_mul_lwreg(r, p, n);
+ TEST_ASSERT(ep4_is_infty(r), end);
+ bn_rand_mod(k, n);
+ ep4_mul(q, p, k);
+ ep4_mul_lwreg(r, p, k);
+ TEST_ASSERT(ep4_cmp(q, r) == RLC_EQ, end);
+ bn_neg(k, k);
+ ep4_mul_lwreg(r, p, k);
+ ep4_neg(r, r);
+ TEST_ASSERT(ep4_cmp(q, r) == RLC_EQ, end);
+ bn_rand_mod(k, n);
+ ep4_mul_lwreg(q, p, k);
+ bn_add(k, k, n);
+ ep4_mul_lwreg(r, p, k);
+ TEST_ASSERT(ep4_cmp(q, r) == RLC_EQ, end);
+ }
+ TEST_END;
+#endif
+
TEST_CASE("multiplication by digit is correct") {
ep4_mul_dig(r, p, 0);
TEST_ASSERT(ep4_is_infty(r), end);
@@ -3448,9 +3712,9 @@ static int addition8(void) {
ep8_rand(a);
ep8_set_infty(d);
ep8_add(e, a, d);
- TEST_ASSERT(ep8_cmp(e, a) == RLC_EQ, end);
+ TEST_ASSERT(ep8_cmp(a, e) == RLC_EQ, end);
ep8_add(e, d, a);
- TEST_ASSERT(ep8_cmp(e, a) == RLC_EQ, end);
+ TEST_ASSERT(ep8_cmp(a, e) == RLC_EQ, end);
} TEST_END;
TEST_CASE("point addition has inverse") {
@@ -3466,7 +3730,7 @@ static int addition8(void) {
ep8_rand(b);
ep8_add(d, a, b);
ep8_add_basic(e, a, b);
- TEST_ASSERT(ep8_cmp(e, d) == RLC_EQ, end);
+ TEST_ASSERT(ep8_cmp(d, e) == RLC_EQ, end);
} TEST_END;
#endif
@@ -3510,6 +3774,46 @@ static int addition8(void) {
} TEST_END;
#endif
+#if EP_ADD == JACOB || !defined(STRIP)
+#if !defined(EP_MIXED) || !defined(STRIP)
+ TEST_CASE("point addition in jacobian coordinates is correct") {
+ ep8_rand(a);
+ ep8_rand(b);
+ ep8_rand(c);
+ ep8_add_jacob(a, a, b);
+ ep8_add_jacob(b, b, c);
+ /* a and b in projective coordinates. */
+ ep8_add_jacob(d, a, b);
+ ep8_norm(a, a);
+ ep8_norm(b, b);
+ ep8_add(e, a, b);
+ TEST_ASSERT(ep8_cmp(d, e) == RLC_EQ, end);
+ } TEST_END;
+#endif
+
+ TEST_CASE("point addition in mixed coordinates (z2 = 1) is correct") {
+ ep8_rand(a);
+ ep8_rand(b);
+ /* a in projective, b in affine coordinates. */
+ ep8_add_jacob(a, a, b);
+ ep8_add_jacob(d, a, b);
+ /* a in affine coordinates. */
+ ep8_norm(a, a);
+ ep8_add(e, a, b);
+ TEST_ASSERT(ep8_cmp(d, e) == RLC_EQ, end);
+ } TEST_END;
+
+ TEST_CASE("point addition in mixed coordinates (z1,z2 = 1) is correct") {
+ ep8_rand(a);
+ ep8_rand(b);
+ ep8_norm(a, a);
+ ep8_norm(b, b);
+ /* a and b in affine coordinates. */
+ ep8_add(d, a, b);
+ ep8_add_jacob(e, a, b);
+ TEST_ASSERT(ep8_cmp(d, e) == RLC_EQ, end);
+ } TEST_END;
+#endif
}
RLC_CATCH_ANY {
RLC_ERROR(end);
@@ -3624,6 +3928,26 @@ static int doubling8(void) {
TEST_ASSERT(ep8_cmp(b, c) == RLC_EQ, end);
} TEST_END;
#endif
+
+#if EP_ADD == JACOB || !defined(STRIP)
+ TEST_CASE("point doubling in jacobian coordinates is correct") {
+ ep8_rand(a);
+ /* a in projective coordinates. */
+ ep8_dbl_jacob(a, a);
+ ep8_dbl_jacob(b, a);
+ ep8_norm(a, a);
+ ep8_dbl(c, a);
+ TEST_ASSERT(ep8_cmp(b, c) == RLC_EQ, end);
+ } TEST_END;
+
+ TEST_CASE("point doubling in mixed coordinates (z1 = 1) is correct") {
+ ep8_rand(a);
+ ep8_dbl_jacob(b, a);
+ ep8_norm(b, b);
+ ep8_dbl(c, a);
+ TEST_ASSERT(ep8_cmp(b, c) == RLC_EQ, end);
+ } TEST_END;
+#endif
}
RLC_CATCH_ANY {
RLC_ERROR(end);
@@ -3776,6 +4100,34 @@ static int multiplication8(void) {
TEST_END;
#endif
+#if EP_MUL == LWREG || !defined(STRIP)
+ TEST_CASE("left-to-right regular point multiplication is correct") {
+ bn_zero(k);
+ ep8_mul_lwreg(r, p, k);
+ TEST_ASSERT(ep8_is_infty(r), end);
+ bn_set_dig(k, 1);
+ ep8_mul_lwreg(r, p, k);
+ TEST_ASSERT(ep8_cmp(p, r) == RLC_EQ, end);
+ ep8_rand(p);
+ ep8_mul_lwreg(r, p, n);
+ TEST_ASSERT(ep8_is_infty(r), end);
+ bn_rand_mod(k, n);
+ ep8_mul(q, p, k);
+ ep8_mul_lwreg(r, p, k);
+ TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end);
+ bn_neg(k, k);
+ ep8_mul_lwreg(r, p, k);
+ ep8_neg(r, r);
+ TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end);
+ bn_rand_mod(k, n);
+ ep8_mul_lwreg(q, p, k);
+ bn_add(k, k, n);
+ ep8_mul_lwreg(r, p, k);
+ TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end);
+ }
+ TEST_END;
+#endif
+
TEST_CASE("multiplication by digit is correct") {
ep8_mul_dig(r, p, 0);
TEST_ASSERT(ep8_is_infty(r), end);
diff --git a/test/test_fp.c b/test/test_fp.c
index a25936fc5..49fa961a3 100644
--- a/test/test_fp.c
+++ b/test/test_fp.c
@@ -87,6 +87,14 @@ static int util(void) {
fp_copy(b, a);
TEST_ASSERT(fp_cmp(a, b) == RLC_EQ, end);
}
+ fp_rand(a);
+ fp_rand(b);
+ if (fp_cmp(a, b) != RLC_EQ) {
+ fp_copy_sec(b, a, 0);
+ TEST_ASSERT(fp_cmp(a, b) != RLC_EQ, end);
+ fp_copy_sec(b, a, 1);
+ TEST_ASSERT(fp_cmp(a, b) == RLC_EQ, end);
+ }
}
TEST_END;
@@ -1145,7 +1153,7 @@ static int cube_root(void) {
fp_mul(c, c, a);
TEST_ASSERT(fp_crt(b, c), end);
if (fp_prime_get_cnr()) {
- fp_copy(d, fp_prime_get_crt());
+ fp_copy(d, (const dig_t *)fp_prime_get_crt());
while (fp_cmp_dig(d, 1) != RLC_EQ) {
fp_copy(c, d);
fp_sqr(d, d);
diff --git a/test/test_fpx.c b/test/test_fpx.c
index aa922c2c4..45da38fb6 100644
--- a/test/test_fpx.c
+++ b/test/test_fpx.c
@@ -476,10 +476,6 @@ static int multiplication2(void) {
fp2_mul_art(c, a);
break;
case 3:
- fp_set_dig(c[0], 1);
- fp_set_dig(c[1], 1);
- fp2_mul(c, a, c);
- break;
case 7:
fp_set_dig(c[0], fp2_field_get_qnr());
fp_set_dig(c[1], 1);
@@ -2953,7 +2949,7 @@ static int util8(void) {
TEST_CASE("reading and writing a finite field element are consistent") {
fp8_rand(a);
- fp8_write_bin(bin, sizeof(bin), a);
+ fp8_write_bin(bin, sizeof(bin), a, 0);
fp8_read_bin(b, bin, sizeof(bin));
TEST_ASSERT(fp8_cmp(a, b) == RLC_EQ, end);
}
@@ -4681,29 +4677,6 @@ static int cyclotomic12(void) {
TEST_ASSERT(fp12_cmp(b, c) == RLC_EQ, end);
} TEST_END;
- if (ep_curve_is_pairf() && ep_param_embed() == 12) {
- TEST_CASE("cyclotomic exponentiation in subgroup is correct") {
- fp12_rand(a);
- pp_exp_k12(a, a);
- bn_zero(f);
- fp12_exp_cyc_gls(c, a, f);
- TEST_ASSERT(fp12_cmp_dig(c, 1) == RLC_EQ, end);
- bn_set_dig(f, 1);
- fp12_exp_cyc_gls(c, a, f);
- TEST_ASSERT(fp12_cmp(c, a) == RLC_EQ, end);
- bn_rand(f, RLC_POS, RLC_FP_BITS);
- fp12_exp(b, a, f);
- fp12_exp_cyc_gls(c, a, f);
- TEST_ASSERT(fp12_cmp(b, c) == RLC_EQ, end);
- bn_rand(f, RLC_POS, RLC_FP_BITS);
- fp12_exp_cyc_gls(b, a, f);
- bn_neg(f, f);
- fp12_exp_cyc_gls(c, a, f);
- fp12_inv_cyc(c, c);
- TEST_ASSERT(fp12_cmp(b, c) == RLC_EQ, end);
- } TEST_END;
- }
-
TEST_CASE("sparse cyclotomic exponentiation is correct") {
int g[3] = {0, 0, RLC_FP_BITS - 1};
do {
@@ -5411,7 +5384,7 @@ static int cyclotomic16(void) {
TEST_ASSERT(fp16_cmp(b, c) == RLC_EQ, end);
} TEST_END;
- if (ep_curve_is_pairf() && ep_param_embed() == 16) {
+ if (ep_curve_is_pairf() && ep_curve_embed() == 16) {
TEST_CASE("cyclotomic exponentiation in subgroup is correct") {
fp16_rand(a);
pp_exp_k16(a, a);
@@ -6181,29 +6154,6 @@ static int cyclotomic18(void) {
TEST_ASSERT(fp18_cmp(b, c) == RLC_EQ, end);
} TEST_END;
- if (ep_curve_is_pairf() && ep_param_embed() == 18) {
- TEST_CASE("cyclotomic exponentiation in subgroup is correct") {
- fp18_rand(a);
- pp_exp_k18(a, a);
- bn_zero(f);
- fp18_exp_cyc_gls(c, a, f);
- TEST_ASSERT(fp18_cmp_dig(c, 1) == RLC_EQ, end);
- bn_set_dig(f, 1);
- fp18_exp_cyc_gls(c, a, f);
- TEST_ASSERT(fp18_cmp(c, a) == RLC_EQ, end);
- bn_rand(f, RLC_POS, RLC_FP_BITS);
- fp18_exp(b, a, f);
- fp18_exp_cyc_gls(c, a, f);
- TEST_ASSERT(fp18_cmp(b, c) == RLC_EQ, end);
- bn_rand(f, RLC_POS, RLC_FP_BITS);
- fp18_exp_cyc_gls(b, a, f);
- bn_neg(f, f);
- fp18_exp_cyc_gls(c, a, f);
- fp18_inv_cyc(c, c);
- TEST_ASSERT(fp18_cmp(b, c) == RLC_EQ, end);
- } TEST_END;
- }
-
TEST_CASE("sparse cyclotomic exponentiation is correct") {
int g[3] = {0, 0, RLC_FP_BITS - 1};
do {
@@ -6957,29 +6907,6 @@ static int cyclotomic24(void) {
TEST_ASSERT(fp24_cmp(b, c) == RLC_EQ, end);
} TEST_END;
- if (ep_curve_is_pairf() && ep_param_embed() == 24) {
- TEST_CASE("cyclotomic exponentiation in subgroup is correct") {
- fp24_rand(a);
- pp_exp_k24(a, a);
- bn_zero(f);
- fp24_exp_cyc_gls(c, a, f);
- TEST_ASSERT(fp24_cmp_dig(c, 1) == RLC_EQ, end);
- bn_set_dig(f, 1);
- fp24_exp_cyc_gls(c, a, f);
- TEST_ASSERT(fp24_cmp(c, a) == RLC_EQ, end);
- bn_rand(f, RLC_POS, RLC_DIG);
- fp24_exp(b, a, f);
- fp24_exp_cyc_gls(c, a, f);
- TEST_ASSERT(fp24_cmp(b, c) == RLC_EQ, end);
- bn_rand(f, RLC_POS, RLC_FP_BITS);
- fp24_exp_cyc_gls(b, a, f);
- bn_neg(f, f);
- fp24_exp_cyc_gls(c, a, f);
- fp24_inv_cyc(c, c);
- TEST_ASSERT(fp24_cmp(b, c) == RLC_EQ, end);
- } TEST_END;
- }
-
TEST_CASE("sparse cyclotomic exponentiation is correct") {
int g[3] = {0, 0, RLC_FP_BITS - 1};
do {
@@ -7772,29 +7699,6 @@ static int cyclotomic48(void) {
TEST_ASSERT(fp48_cmp(b, c) == RLC_EQ, end);
} TEST_END;
- if (ep_curve_is_pairf() && ep_param_embed() == 48) {
- TEST_CASE("cyclotomic exponentiation in subgroup is correct") {
- fp48_rand(a);
- pp_exp_k48(a, a);
- bn_zero(f);
- fp48_exp_cyc_gls(c, a, f);
- TEST_ASSERT(fp48_cmp_dig(c, 1) == RLC_EQ, end);
- bn_set_dig(f, 1);
- fp48_exp_cyc_gls(c, a, f);
- TEST_ASSERT(fp48_cmp(c, a) == RLC_EQ, end);
- bn_rand(f, RLC_POS, RLC_DIG);
- fp48_exp(b, a, f);
- fp48_exp_cyc_gls(c, a, f);
- TEST_ASSERT(fp48_cmp(b, c) == RLC_EQ, end);
- bn_rand(f, RLC_POS, RLC_FP_BITS);
- fp48_exp_cyc_gls(b, a, f);
- bn_neg(f, f);
- fp48_exp_cyc_gls(c, a, f);
- fp48_inv_cyc(c, c);
- TEST_ASSERT(fp48_cmp(b, c) == RLC_EQ, end);
- } TEST_END;
- }
-
TEST_CASE("sparse cyclotomic exponentiation is correct") {
int g[3] = {0, 0, RLC_FP_BITS - 1};
do {
@@ -8615,7 +8519,9 @@ static int inversion54(void) {
fp54_conv_cyc(a, a);
fp54_inv(b, a);
fp54_inv_cyc(c, a);
- TEST_ASSERT(fp54_cmp(b, c) == RLC_EQ, end);
+ fp18_print(b[0]);
+ fp18_print(c[0]);
+ TEST_ASSERT(fp18_cmp(b[0], c[0]) == RLC_EQ, end);
} TEST_END;
}
RLC_CATCH_ANY {
@@ -8783,7 +8689,7 @@ int main(void) {
}
/* Only execute these if there is an assigned cubic non-residue. */
- if (fp_prime_get_cnr()) {
+ if (fp_prime_get_cnr() && (ep_curve_embed() >= 3)) {
util_print("\n-- Cubic extension: %d as CNR\n", fp_prime_get_cnr());
util_banner("Utilities:", 1);
@@ -8846,7 +8752,7 @@ int main(void) {
}
/* Fp^4 is defined as a quadratic extension of Fp^2. */
- if (fp_prime_get_qnr()) {
+ if (fp_prime_get_qnr() && (ep_curve_embed() >= 4)) {
util_print("\n-- Quartic extension: (i + %d) as QNR\n",
fp2_field_get_qnr());
util_banner("Utilities:", 1);
@@ -8910,7 +8816,7 @@ int main(void) {
}
/* Fp^6 is defined as a cubic extension of Fp^2. */
- if (fp_prime_get_qnr() && fp_prime_get_cnr()) {
+ if (fp_prime_get_qnr() && fp_prime_get_cnr() && (ep_curve_embed() >= 6)) {
util_print("\n-- Sextic extension: (i + %d) as CNR\n",
fp2_field_get_qnr());
util_banner("Utilities:", 1);
@@ -8963,7 +8869,7 @@ int main(void) {
}
}
- if (fp_prime_get_qnr() && (ep_param_embed() >= 8)) {
+ if (fp_prime_get_qnr() && (ep_curve_embed() >= 8)) {
util_banner("Octic extension: (j) as CNR", 0);
util_banner("Utilities:", 1);
@@ -9026,7 +8932,7 @@ int main(void) {
}
/* Only execute these if there is an assigned cubic non-residue. */
- if (fp_prime_get_cnr() && (ep_param_embed() >= 9)) {
+ if (fp_prime_get_cnr() && (ep_curve_embed() >= 9)) {
util_print("\n-- Nonic extension: (j + %d) as CNR\n",
fp3_field_get_cnr());
util_banner("Utilities:", 1);
@@ -9080,7 +8986,7 @@ int main(void) {
}
if (fp_prime_get_qnr() && fp_prime_get_cnr() &&
- (ep_param_embed() >= 12) && (ep_param_embed() != 16)) {
+ (ep_curve_embed() >= 12) && (ep_curve_embed() != 16)) {
util_banner("Dodecic extension:", 0);
util_banner("Utilities:", 1);
@@ -9137,7 +9043,7 @@ int main(void) {
}
}
- if (fp_prime_get_qnr() && (ep_param_embed() >= 16)) {
+ if (fp_prime_get_qnr() && (ep_curve_embed() >= 16)) {
util_banner("Sextadecic extension:", 0);
util_banner("Utilities:", 1);
@@ -9199,7 +9105,7 @@ int main(void) {
}
}
- if (fp_prime_get_cnr() && (ep_param_embed() >= 18)) {
+ if (fp_prime_get_cnr() && (ep_curve_embed() >= 18)) {
util_banner("Octdecic extension:", 0);
util_banner("Utilities:", 1);
@@ -9256,7 +9162,7 @@ int main(void) {
}
}
- if (fp_prime_get_qnr() && (ep_param_embed() >= 24)) {
+ if (fp_prime_get_qnr() && (ep_curve_embed() >= 24)) {
util_banner("Extension of degree 24:", 0);
util_banner("Utilities:", 1);
@@ -9313,7 +9219,7 @@ int main(void) {
}
}
- if (fp_prime_get_qnr() && (ep_param_embed() >= 48)) {
+ if (fp_prime_get_qnr() && (ep_curve_embed() >= 48)) {
util_banner("Extension of degree 48:", 0);
util_banner("Utilities:", 1);
@@ -9370,7 +9276,7 @@ int main(void) {
}
}
- if (fp_prime_get_cnr() && (ep_param_embed() == 54)) {
+ if (fp_prime_get_cnr() && (ep_curve_embed() == 54)) {
util_banner("Extension of degree 54:", 0);
util_banner("Utilities:", 1);
diff --git a/test/test_pc.c b/test/test_pc.c
index cf06c9300..53bfb9e18 100644
--- a/test/test_pc.c
+++ b/test/test_pc.c
@@ -1488,18 +1488,31 @@ int exponentiation(void) {
TEST_CASE("exponentiation is correct") {
gt_rand(a);
- gt_rand(b);
+ bn_set_dig(d, 0);
+ gt_exp(b, a, d);
+ TEST_ASSERT(gt_is_unity(b), end);
+ bn_set_dig(d, 1);
+ gt_exp(b, a, d);
+ TEST_ASSERT(gt_cmp(a, b) == RLC_EQ, end);
+ bn_rand_mod(d, n);
+ RLC_CAT(RLC_GT_LOWER, exp)(b, a, d);
+ gt_exp(c, a, d);
+ TEST_ASSERT(gt_cmp(b, c) == RLC_EQ, end);
bn_rand_mod(d, n);
+ gt_exp(b, a, d);
+ gt_exp_sec(c, a, d);
+ TEST_ASSERT(gt_cmp(b, c) == RLC_EQ, end);
+ bn_neg(d, d);
+ gt_exp(b, a, d);
+ gt_exp_sec(c, a, d);
+ TEST_ASSERT(gt_cmp(b, c) == RLC_EQ, end);
+ gt_rand(b);
bn_rand_mod(e, n);
gt_exp_sim(c, a, d, b, e);
gt_exp(a, a, d);
gt_exp(b, b, e);
gt_mul(b, a, b);
TEST_ASSERT(gt_cmp(b, c) == RLC_EQ, end);
- gt_exp_dig(b, a, 0);
- TEST_ASSERT(gt_is_unity(b), end);
- gt_exp_dig(b, a, 1);
- TEST_ASSERT(gt_cmp(a, b) == RLC_EQ, end);
bn_rand(d, RLC_POS, RLC_DIG);
gt_exp(b, a, d);
gt_exp_dig(c, a, d->dp[0]);
diff --git a/test/test_pp.c b/test/test_pp.c
index 6af9e2bab..56e2cd695 100644
--- a/test/test_pp.c
+++ b/test/test_pp.c
@@ -3927,7 +3927,7 @@ int main(void) {
util_banner("Arithmetic", 1);
- if (ep_param_embed() == 1) {
+ if (ep_curve_embed() == 1) {
if (doubling1() != RLC_OK) {
core_clean();
return 1;
@@ -3944,7 +3944,7 @@ int main(void) {
}
}
- if (ep_param_embed() == 2) {
+ if (ep_curve_embed() == 2) {
if (doubling2() != RLC_OK) {
core_clean();
return 1;
@@ -3961,7 +3961,7 @@ int main(void) {
}
}
- if (ep_param_embed() == 8) {
+ if (ep_curve_embed() == 8) {
if (doubling8() != RLC_OK) {
core_clean();
return 1;
@@ -3978,7 +3978,7 @@ int main(void) {
}
}
- if (ep_param_embed() == 12) {
+ if (ep_curve_embed() == 12) {
if (doubling12() != RLC_OK) {
core_clean();
return 1;
@@ -3995,7 +3995,7 @@ int main(void) {
}
}
- if (ep_param_embed() == 16) {
+ if (ep_curve_embed() == 16) {
if (doubling16() != RLC_OK) {
core_clean();
return 1;
@@ -4012,7 +4012,7 @@ int main(void) {
}
}
- if (ep_param_embed() == 18) {
+ if (ep_curve_embed() == 18) {
if (doubling18() != RLC_OK) {
core_clean();
return 1;
@@ -4029,7 +4029,7 @@ int main(void) {
}
}
- if (ep_param_embed() == 24) {
+ if (ep_curve_embed() == 24) {
if (doubling24() != RLC_OK) {
core_clean();
return 1;
@@ -4046,7 +4046,7 @@ int main(void) {
}
}
- if (ep_param_embed() == 48) {
+ if (ep_curve_embed() == 48) {
if (doubling48() != RLC_OK) {
core_clean();
return 1;
@@ -4063,7 +4063,7 @@ int main(void) {
}
}
- if (ep_param_embed() == 54) {
+ if (ep_curve_embed() == 54) {
if (doubling54() != RLC_OK) {
core_clean();
return 1;
diff --git a/tools/run-pairings.sh b/tools/run-pairings.sh
index 0f091790f..39a659e24 100755
--- a/tools/run-pairings.sh
+++ b/tools/run-pairings.sh
@@ -1,17 +1,33 @@
set -e
for script in preset/x64-pbc-*; do
- file=${script##*/}
- file=${file%.sh}
- echo target-$file
- mkdir -p target-$file
- cd target-$file
- ../$script ../
- make
- ./bin/test_fpx && ./bin/test_pc
- if [ $? -ne 0 ]; then
- echo "FAILED: target-$file"
- exit 1
- fi
- cd ..
+ file=${script##*/}
+ file=${file%.sh}
+ echo target-$file
+ mkdir -p target-$file
+ cd target-$file
+ ../$script ../
+ make
+ ./bin/test_fpx && ./bin/test_pc
+ if [ $? -ne 0 ]; then
+ echo "FAILED: target-$file"
+ exit 1
+ fi
+ cd ..
+done
+
+for script in preset/gmp-pbc-*; do
+ file=${script##*/}
+ file=${file%.sh}
+ echo target-$file
+ mkdir -p target-$file
+ cd target-$file
+ ../$script ../
+ make
+ ./bin/test_fpx && ./bin/test_pc
+ if [ $? -ne 0 ]; then
+ echo "FAILED: target-$file"
+ exit 1
+ fi
+ cd ..
done