diff --git a/CMakeLists.txt b/CMakeLists.txt index 96431d56b..dc41cbc8d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.1) +cmake_minimum_required(VERSION 3.5) if(NOT ${CMAKE_VERSION} VERSION_LESS "3.1") cmake_policy(SET CMP0054 NEW) endif() diff --git a/bench/bench_ep.c b/bench/bench_ep.c index 04ccdfc83..54b36f890 100644 --- a/bench/bench_ep.c +++ b/bench/bench_ep.c @@ -394,6 +394,11 @@ static void arith(void) { BENCH_ADD(ep_mul_gen(q, k)); } BENCH_END; + BENCH_RUN("ep_mul_cof") { + ep_rand(p); + BENCH_ADD(ep_mul_cof(q, p)); + } BENCH_END; + BENCH_RUN("ep_mul_dig") { bn_rand(k, RLC_POS, RLC_DIG); bn_rand_mod(k, n); @@ -575,6 +580,32 @@ static void arith(void) { BENCH_ADD(ep_map(p, msg, 5)); } BENCH_END; +#if EP_MAP == BASIC || !defined(STRIP) + BENCH_RUN("ep_map_basic") { + uint8_t msg[5]; + rand_bytes(msg, 5); + BENCH_ADD(ep_map_basic(p, msg, 5)); + } BENCH_END; +#endif + +#if EP_MAP == SSWUM || !defined(STRIP) + BENCH_RUN("ep_map_sswum") { + uint8_t msg[5]; + rand_bytes(msg, 5); + BENCH_ADD(ep_map_sswum(p, msg, 5)); + } BENCH_END; +#endif + +#if EP_MAP == SWIFT || !defined(STRIP) + if (ep_curve_opt_a() == RLC_ZERO || ep_curve_opt_b() == RLC_ZERO) { + BENCH_RUN("ep_map_swift") { + uint8_t msg[5]; + rand_bytes(msg, 5); + BENCH_ADD(ep_map_swift(p, msg, 5)); + } BENCH_END; + } +#endif + BENCH_RUN("ep_pck") { ep_rand(p); BENCH_ADD(ep_pck(q, p)); diff --git a/bench/bench_epx.c b/bench/bench_epx.c index 9df560f20..46e054db7 100644 --- a/bench/bench_epx.c +++ b/bench/bench_epx.c @@ -362,10 +362,15 @@ static void arith2(void) { BENCH_ADD(ep2_mul_gen(q, k)); } BENCH_END; + BENCH_RUN("ep2_mul_cof") { + ep2_rand(p); + BENCH_ADD(ep2_mul_cof(q, p)); + } BENCH_END; + BENCH_RUN("ep2_mul_dig") { bn_rand(k, RLC_POS, RLC_DIG); - bn_rand_mod(k, n); - BENCH_ADD(ep2_mul_dig(p, q, k->dp[0])); + ep2_rand(p); + BENCH_ADD(ep2_mul_dig(q, p, k->dp[0])); } BENCH_END; @@ -549,6 +554,24 @@ static void arith2(void) { BENCH_ADD(ep2_map(p, msg, 5)); } BENCH_END; + BENCH_RUN("ep2_map_basic") { + uint8_t msg[5]; + rand_bytes(msg, 5); + BENCH_ADD(ep2_map_basic(p, msg, 5)); + } BENCH_END; + + BENCH_RUN("ep2_map_sswum") { + uint8_t msg[5]; + rand_bytes(msg, 5); + BENCH_ADD(ep2_map_sswum(p, msg, 5)); + } BENCH_END; + + BENCH_RUN("ep2_map_swift") { + uint8_t msg[5]; + rand_bytes(msg, 5); + BENCH_ADD(ep2_map_swift(p, msg, 5)); + } BENCH_END; + BENCH_RUN("ep2_pck") { ep2_rand(p); BENCH_ADD(ep2_pck(q, p)); @@ -569,464 +592,963 @@ static void arith2(void) { fp2_free(s); } -static void memory4(void) { - ep4_t a[BENCH]; +static void memory3(void) { + ep3_t a[BENCH]; - BENCH_FEW("ep4_null", ep4_null(a[i]), 1); + BENCH_FEW("ep3_null", ep3_null(a[i]), 1); - BENCH_FEW("ep4_new", ep4_new(a[i]), 1); + BENCH_FEW("ep3_new", ep3_new(a[i]), 1); for (int i = 0; i < BENCH; i++) { - ep4_free(a[i]); + ep3_free(a[i]); } for (int i = 0; i < BENCH; i++) { - ep4_new(a[i]); + ep3_new(a[i]); } - BENCH_FEW("ep4_free", ep4_free(a[i]), 1); + BENCH_FEW("ep3_free", ep3_free(a[i]), 1); (void)a; } -static void util4(void) { - ep4_t p, q, t[2]; +static void util3(void) { + ep3_t p, q, t[2]; uint8_t bin[8 * RLC_FP_BYTES + 1]; int l; - ep4_null(p); - ep4_null(q); - ep4_null(t[0]); - ep4_null(t[1]); + ep3_null(p); + ep3_null(q); + ep3_null(t[0]); + ep3_null(t[1]); - ep4_new(p); - ep4_new(q); - ep4_new(t[0]); - ep4_new(t[1]); + ep3_new(p); + ep3_new(q); + ep3_new(t[0]); + ep3_new(t[1]); - BENCH_RUN("ep4_is_infty") { - ep4_rand(p); - BENCH_ADD(ep4_is_infty(p)); + BENCH_RUN("ep3_is_infty") { + ep3_rand(p); + BENCH_ADD(ep3_is_infty(p)); } BENCH_END; - BENCH_RUN("ep4_set_infty") { - ep4_rand(p); - BENCH_ADD(ep4_set_infty(p)); + BENCH_RUN("ep3_set_infty") { + ep3_rand(p); + BENCH_ADD(ep3_set_infty(p)); } BENCH_END; - BENCH_RUN("ep4_copy") { - ep4_rand(p); - ep4_rand(q); - BENCH_ADD(ep4_copy(p, q)); + BENCH_RUN("ep3_copy") { + ep3_rand(p); + ep3_rand(q); + BENCH_ADD(ep3_copy(p, q)); } BENCH_END; - BENCH_RUN("ep4_cmp") { - ep4_rand(p); - ep4_dbl(p, p); - ep4_rand(q); - ep4_dbl(q, q); - BENCH_ADD(ep4_cmp(p, q)); + BENCH_RUN("ep3_cmp") { + ep3_rand(p); + ep3_dbl(p, p); + ep3_rand(q); + ep3_dbl(q, q); + BENCH_ADD(ep3_cmp(p, q)); } BENCH_END; - BENCH_RUN("ep4_norm") { - ep4_rand(p); - ep4_dbl(p, p); - BENCH_ADD(ep4_norm(p, p)); + BENCH_RUN("ep3_norm") { + ep3_rand(p); + ep3_dbl(p, p); + BENCH_ADD(ep3_norm(p, p)); } BENCH_END; - BENCH_RUN("ep4_norm_sim (2)") { - ep4_rand(t[0]); - ep4_rand(t[1]); - ep4_dbl(t[0], t[0]); - ep4_dbl(t[1], t[1]); - BENCH_ADD(ep4_norm_sim(t, t, 2)); + BENCH_RUN("ep3_norm_sim (2)") { + ep3_rand(t[0]); + ep3_rand(t[1]); + ep3_dbl(t[0], t[0]); + ep3_dbl(t[1], t[1]); + BENCH_ADD(ep3_norm_sim(t, t, 2)); } BENCH_END; - BENCH_RUN("ep4_cmp (1 norm)") { - ep4_rand(p); - ep4_dbl(p, p); - ep4_rand(q); - BENCH_ADD(ep4_cmp(p, q)); + BENCH_RUN("ep3_cmp (1 norm)") { + ep3_rand(p); + ep3_dbl(p, p); + ep3_rand(q); + BENCH_ADD(ep3_cmp(p, q)); } BENCH_END; - BENCH_RUN("ep4_cmp (2 norm)") { - ep4_rand(p); - ep4_rand(q); - BENCH_ADD(ep4_cmp(p, q)); + BENCH_RUN("ep3_cmp (2 norm)") { + ep3_rand(p); + ep3_rand(q); + BENCH_ADD(ep3_cmp(p, q)); } BENCH_END; - BENCH_RUN("ep4_rand") { - BENCH_ADD(ep4_rand(p)); + BENCH_RUN("ep3_rand") { + BENCH_ADD(ep3_rand(p)); } BENCH_END; - BENCH_RUN("ep4_blind") { - BENCH_ADD(ep4_blind(p, p)); + BENCH_RUN("ep3_blind") { + BENCH_ADD(ep3_blind(p, p)); } BENCH_END; - BENCH_RUN("ep4_on_curve") { - ep4_rand(p); - BENCH_ADD(ep4_on_curve(p)); + BENCH_RUN("ep3_on_curve") { + ep3_rand(p); + BENCH_ADD(ep3_on_curve(p)); } BENCH_END; - BENCH_RUN("ep4_size_bin") { - ep4_rand(p); - BENCH_ADD(ep4_size_bin(p, 0)); + BENCH_RUN("ep3_size_bin") { + ep3_rand(p); + BENCH_ADD(ep3_size_bin(p, 0)); } BENCH_END; - BENCH_RUN("ep4_write_bin") { - ep4_rand(p); - l = ep4_size_bin(p, 0); - BENCH_ADD(ep4_write_bin(bin, l, p, 0)); + BENCH_RUN("ep3_write_bin") { + ep3_rand(p); + l = ep3_size_bin(p, 0); + BENCH_ADD(ep3_write_bin(bin, l, p, 0)); } BENCH_END; - BENCH_RUN("ep4_read_bin") { - ep4_rand(p); - l = ep4_size_bin(p, 0); - ep4_write_bin(bin, l, p, 0); - BENCH_ADD(ep4_read_bin(p, bin, l)); + BENCH_RUN("ep3_read_bin") { + ep3_rand(p); + l = ep3_size_bin(p, 0); + ep3_write_bin(bin, l, p, 0); + BENCH_ADD(ep3_read_bin(p, bin, l)); } BENCH_END; - ep4_free(p); - ep4_free(q); - ep4_free(t[0]); - ep4_free(t[1]); + ep3_free(p); + ep3_free(q); + ep3_free(t[0]); + ep3_free(t[1]); } -static void arith4(void) { - ep4_t p, q, r, t[RLC_EPX_TABLE_MAX]; +static void arith3(void) { + ep3_t p, q, r, t[RLC_EPX_TABLE_MAX]; bn_t k, n, l; - fp4_t s; + fp3_t s; - ep4_null(p); - ep4_null(q); - ep4_null(r); + ep3_null(p); + ep3_null(q); + ep3_null(r); bn_null(k); bn_null(n); - fp4_null(s); + fp3_null(s); for (int i = 0; i < RLC_EPX_TABLE_MAX; i++) { - ep4_null(t[i]); + ep3_null(t[i]); } - ep4_new(p); - ep4_new(q); - ep4_new(r); + ep3_new(p); + ep3_new(q); + ep3_new(r); bn_new(k); bn_new(n); bn_new(l); - fp4_new(s); + fp3_new(s); - ep4_curve_get_ord(n); + ep3_curve_get_ord(n); - BENCH_RUN("ep4_add") { - ep4_rand(p); - ep4_rand(q); - ep4_add(p, p, q); - ep4_rand(q); - ep4_rand(p); - ep4_add(q, q, p); - BENCH_ADD(ep4_add(r, p, q)); + BENCH_RUN("ep3_add") { + ep3_rand(p); + ep3_rand(q); + ep3_add(p, p, q); + ep3_rand(q); + ep3_rand(p); + ep3_add(q, q, p); + BENCH_ADD(ep3_add(r, p, q)); } BENCH_END; #if EP_ADD == BASIC || !defined(STRIP) - BENCH_RUN("ep4_add_basic") { - ep4_rand(p); - ep4_rand(q); - BENCH_ADD(ep4_add_basic(r, p, q)); + BENCH_RUN("ep3_add_basic") { + ep3_rand(p); + ep3_rand(q); + BENCH_ADD(ep3_add_basic(r, p, q)); } BENCH_END; - BENCH_RUN("ep4_add_slp_basic") { - ep4_rand(p); - ep4_rand(q); - BENCH_ADD(ep4_add_slp_basic(r, s, p, q)); + BENCH_RUN("ep3_add_slp_basic") { + ep3_rand(p); + ep3_rand(q); + BENCH_ADD(ep3_add_slp_basic(r, s, p, q)); } BENCH_END; #endif #if EP_ADD == PROJC || !defined(STRIP) - BENCH_RUN("ep4_add_projc") { - ep4_rand(p); - ep4_rand(q); - ep4_add_projc(p, p, q); - ep4_rand(q); - ep4_rand(p); - ep4_add_projc(q, q, p); - BENCH_ADD(ep4_add_projc(r, p, q)); + BENCH_RUN("ep3_add_projc") { + ep3_rand(p); + ep3_rand(q); + ep3_add_projc(p, p, q); + ep3_rand(q); + ep3_rand(p); + ep3_add_projc(q, q, p); + BENCH_ADD(ep3_add_projc(r, p, q)); } BENCH_END; - BENCH_RUN("ep4_add_projc (z2 = 1)") { - ep4_rand(p); - ep4_rand(q); - ep4_add_projc(p, p, q); - ep4_rand(q); - ep4_norm(q, q); - BENCH_ADD(ep4_add_projc(r, p, q)); + BENCH_RUN("ep3_add_projc (z2 = 1)") { + ep3_rand(p); + ep3_rand(q); + ep3_add_projc(p, p, q); + ep3_rand(q); + ep3_norm(q, q); + BENCH_ADD(ep3_add_projc(r, p, q)); } BENCH_END; - BENCH_RUN("ep4_add_projc (z1,z2 = 1)") { - ep4_rand(p); - ep4_norm(p, p); - ep4_rand(q); - ep4_norm(q, q); - BENCH_ADD(ep4_add_projc(r, p, q)); + BENCH_RUN("ep3_add_projc (z1,z2 = 1)") { + ep3_rand(p); + ep3_norm(p, p); + ep3_rand(q); + ep3_norm(q, q); + BENCH_ADD(ep3_add_projc(r, p, q)); } BENCH_END; #endif - BENCH_RUN("ep4_sub") { - ep4_rand(p); - ep4_rand(q); - ep4_add(p, p, q); - ep4_rand(q); - ep4_rand(p); - ep4_add(q, q, p); - BENCH_ADD(ep4_sub(r, p, q)); + BENCH_RUN("ep3_sub") { + ep3_rand(p); + ep3_rand(q); + ep3_add(p, p, q); + ep3_rand(q); + ep3_rand(p); + ep3_add(q, q, p); + BENCH_ADD(ep3_sub(r, p, q)); } BENCH_END; - BENCH_RUN("ep4_dbl") { - ep4_rand(p); - ep4_rand(q); - ep4_add(p, p, q); - BENCH_ADD(ep4_dbl(r, p)); + BENCH_RUN("ep3_dbl") { + ep3_rand(p); + ep3_rand(q); + ep3_add(p, p, q); + BENCH_ADD(ep3_dbl(r, p)); } BENCH_END; #if EP_ADD == BASIC || !defined(STRIP) - BENCH_RUN("ep4_dbl_basic") { - ep4_rand(p); - BENCH_ADD(ep4_dbl_basic(r, p)); + BENCH_RUN("ep3_dbl_basic") { + ep3_rand(p); + BENCH_ADD(ep3_dbl_basic(r, p)); } BENCH_END; - BENCH_RUN("ep4_dbl_slp_basic") { - ep4_rand(p); - BENCH_ADD(ep4_dbl_slp_basic(r, s, p)); + BENCH_RUN("ep3_dbl_slp_basic") { + ep3_rand(p); + BENCH_ADD(ep3_dbl_slp_basic(r, s, p)); } BENCH_END; #endif #if EP_ADD == PROJC || !defined(STRIP) - BENCH_RUN("ep4_dbl_projc") { - ep4_rand(p); - ep4_rand(q); - ep4_add_projc(p, p, q); - BENCH_ADD(ep4_dbl_projc(r, p)); + BENCH_RUN("ep3_dbl_projc") { + ep3_rand(p); + ep3_rand(q); + ep3_add_projc(p, p, q); + BENCH_ADD(ep3_dbl_projc(r, p)); } BENCH_END; - BENCH_RUN("ep4_dbl_projc (z1 = 1)") { - ep4_rand(p); - ep4_norm(p, p); - BENCH_ADD(ep4_dbl_projc(r, p)); + BENCH_RUN("ep3_dbl_projc (z1 = 1)") { + ep3_rand(p); + ep3_norm(p, p); + BENCH_ADD(ep3_dbl_projc(r, p)); } BENCH_END; #endif - BENCH_RUN("ep4_neg") { - ep4_rand(p); - ep4_rand(q); - ep4_add(p, p, q); - BENCH_ADD(ep4_neg(r, p)); + BENCH_RUN("ep3_neg") { + ep3_rand(p); + ep3_rand(q); + ep3_add(p, p, q); + BENCH_ADD(ep3_neg(r, p)); } BENCH_END; - BENCH_RUN("ep4_mul") { + BENCH_RUN("ep3_mul") { bn_rand_mod(k, n); - BENCH_ADD(ep4_mul(q, p, k)); + BENCH_ADD(ep3_mul(q, p, k)); } BENCH_END; #if EP_MUL == BASIC || !defined(STRIP) - BENCH_RUN("ep4_mul_basic") { + BENCH_RUN("ep3_mul_basic") { bn_rand_mod(k, n); - BENCH_ADD(ep4_mul_basic(q, p, k)); + BENCH_ADD(ep3_mul_basic(q, p, k)); } BENCH_END; #endif #if EP_MUL == SLIDE || !defined(STRIP) - BENCH_RUN("ep4_mul_slide") { + BENCH_RUN("ep3_mul_slide") { bn_rand_mod(k, n); - ep4_rand(p); - BENCH_ADD(ep4_mul_slide(q, p, k)); + ep3_rand(p); + BENCH_ADD(ep3_mul_slide(q, p, k)); } BENCH_END; #endif #if EP_MUL == MONTY || !defined(STRIP) - BENCH_RUN("ep4_mul_monty") { + BENCH_RUN("ep3_mul_monty") { bn_rand_mod(k, n); - ep4_rand(p); - BENCH_ADD(ep4_mul_monty(q, p, k)); + ep3_rand(p); + BENCH_ADD(ep3_mul_monty(q, p, k)); } BENCH_END; #endif #if EP_MUL == LWNAF || !defined(STRIP) - BENCH_RUN("ep4_mul_lwnaf") { + BENCH_RUN("ep3_mul_lwnaf") { bn_rand_mod(k, n); - ep4_rand(p); - BENCH_ADD(ep4_mul_lwnaf(q, p, k)); + ep3_rand(p); + BENCH_ADD(ep3_mul_lwnaf(q, p, k)); } BENCH_END; #endif - BENCH_RUN("ep4_mul_gen") { + BENCH_RUN("ep3_mul_gen") { bn_rand_mod(k, n); - BENCH_ADD(ep4_mul_gen(q, k)); + BENCH_ADD(ep3_mul_gen(q, k)); } BENCH_END; - BENCH_RUN("ep4_mul_dig") { + BENCH_RUN("ep3_mul_cof") { + ep3_rand(p); + BENCH_ADD(ep3_mul_cof(q, p)); + } BENCH_END; + + BENCH_RUN("ep3_mul_dig") { bn_rand(k, RLC_POS, RLC_DIG); - bn_rand_mod(k, n); - BENCH_ADD(ep4_mul_dig(p, q, k->dp[0])); + ep3_rand(p); + BENCH_ADD(ep3_mul_dig(q, p, k->dp[0])); } BENCH_END; for (int i = 0; i < RLC_EPX_TABLE_MAX; i++) { - ep4_new(t[i]); + ep3_new(t[i]); } - BENCH_RUN("ep4_mul_pre") { - ep4_rand(p); - BENCH_ADD(ep4_mul_pre(t, p)); + BENCH_RUN("ep3_mul_pre") { + ep3_rand(p); + BENCH_ADD(ep3_mul_pre(t, p)); } BENCH_END; - BENCH_RUN("ep4_mul_fix") { + BENCH_RUN("ep3_mul_fix") { bn_rand_mod(k, n); - ep4_rand(p); - ep4_mul_pre(t, p); - BENCH_ADD(ep4_mul_fix(q, t, k)); + ep3_rand(p); + ep3_mul_pre(t, p); + BENCH_ADD(ep3_mul_fix(q, t, k)); } BENCH_END; for (int i = 0; i < RLC_EPX_TABLE_MAX; i++) { - ep4_free(t[i]); + ep3_free(t[i]); } #if EP_FIX == BASIC || !defined(STRIP) for (int i = 0; i < RLC_EPX_TABLE_BASIC; i++) { - ep4_new(t[i]); + ep3_new(t[i]); } - BENCH_RUN("ep4_mul_pre_basic") { - ep4_rand(p); - BENCH_ADD(ep4_mul_pre_basic(t, p)); + BENCH_RUN("ep3_mul_pre_basic") { + ep3_rand(p); + BENCH_ADD(ep3_mul_pre_basic(t, p)); } BENCH_END; - BENCH_RUN("ep4_mul_fix_basic") { + BENCH_RUN("ep3_mul_fix_basic") { bn_rand_mod(k, n); - ep4_rand(p); - ep4_mul_pre_basic(t, p); - BENCH_ADD(ep4_mul_fix_basic(q, t, k)); + ep3_rand(p); + ep3_mul_pre_basic(t, p); + BENCH_ADD(ep3_mul_fix_basic(q, t, k)); } BENCH_END; for (int i = 0; i < RLC_EPX_TABLE_BASIC; i++) { - ep4_free(t[i]); + ep3_free(t[i]); } #endif #if EP_FIX == COMBS || !defined(STRIP) for (int i = 0; i < RLC_EPX_TABLE_COMBS; i++) { - ep4_new(t[i]); + ep3_new(t[i]); } - BENCH_RUN("ep4_mul_pre_combs") { - ep4_rand(p); - BENCH_ADD(ep4_mul_pre_combs(t, p)); + BENCH_RUN("ep3_mul_pre_combs") { + ep3_rand(p); + BENCH_ADD(ep3_mul_pre_combs(t, p)); } BENCH_END; - BENCH_RUN("ep4_mul_fix_combs") { + BENCH_RUN("ep3_mul_fix_combs") { bn_rand_mod(k, n); - ep4_rand(p); - ep4_mul_pre_combs(t, p); - BENCH_ADD(ep4_mul_fix_combs(q, t, k)); + ep3_rand(p); + ep3_mul_pre_combs(t, p); + BENCH_ADD(ep3_mul_fix_combs(q, t, k)); } BENCH_END; for (int i = 0; i < RLC_EPX_TABLE_COMBS; i++) { - ep4_free(t[i]); + ep3_free(t[i]); } #endif #if EP_FIX == COMBD || !defined(STRIP) for (int i = 0; i < RLC_EPX_TABLE_COMBD; i++) { - ep4_new(t[i]); + ep3_new(t[i]); } - BENCH_RUN("ep4_mul_pre_combd") { - BENCH_ADD(ep4_mul_pre_combd(t, p)); + BENCH_RUN("ep3_mul_pre_combd") { + BENCH_ADD(ep3_mul_pre_combd(t, p)); } BENCH_END; - BENCH_RUN("ep4_mul_fix_combd") { + BENCH_RUN("ep3_mul_fix_combd") { bn_rand_mod(k, n); - ep4_mul_pre_combd(t, p); - BENCH_ADD(ep4_mul_fix_combd(q, t, k)); + ep3_mul_pre_combd(t, p); + BENCH_ADD(ep3_mul_fix_combd(q, t, k)); } BENCH_END; for (int i = 0; i < RLC_EPX_TABLE_COMBD; i++) { - ep4_free(t[i]); + ep3_free(t[i]); } #endif #if EP_FIX == LWNAF || !defined(STRIP) for (int i = 0; i < RLC_EPX_TABLE_LWNAF; i++) { - ep4_new(t[i]); + ep3_new(t[i]); } - BENCH_RUN("ep4_mul_pre_lwnaf") { - ep4_rand(p); - BENCH_ADD(ep4_mul_pre_lwnaf(t, p)); + BENCH_RUN("ep3_mul_pre_lwnaf") { + ep3_rand(p); + BENCH_ADD(ep3_mul_pre_lwnaf(t, p)); } BENCH_END; - BENCH_RUN("ep4_mul_fix_lwnaf") { + BENCH_RUN("ep3_mul_fix_lwnaf") { bn_rand_mod(k, n); - ep4_rand(p); - ep4_mul_pre_lwnaf(t, p); - BENCH_ADD(ep4_mul_fix_lwnaf(q, t, k)); + ep3_rand(p); + ep3_mul_pre_lwnaf(t, p); + BENCH_ADD(ep3_mul_fix_lwnaf(q, t, k)); } BENCH_END; for (int i = 0; i < RLC_EPX_TABLE_LWNAF; i++) { - ep4_free(t[i]); + ep3_free(t[i]); } #endif - BENCH_RUN("ep4_mul_sim") { + BENCH_RUN("ep3_mul_sim") { bn_rand_mod(k, n); bn_rand_mod(l, n); - ep4_rand(p); - ep4_rand(q); - BENCH_ADD(ep4_mul_sim(r, p, k, q, l)); + ep3_rand(p); + ep3_rand(q); + BENCH_ADD(ep3_mul_sim(r, p, k, q, l)); } BENCH_END; #if EP_SIM == BASIC || !defined(STRIP) - BENCH_RUN("ep4_mul_sim_basic") { + BENCH_RUN("ep3_mul_sim_basic") { bn_rand_mod(k, n); bn_rand_mod(l, n); - ep4_rand(p); - ep4_rand(q); - BENCH_ADD(ep4_mul_sim_basic(r, p, k, q, l)); + ep3_rand(p); + ep3_rand(q); + BENCH_ADD(ep3_mul_sim_basic(r, p, k, q, l)); } BENCH_END; #endif #if EP_SIM == TRICK || !defined(STRIP) - BENCH_RUN("ep4_mul_sim_trick") { + BENCH_RUN("ep3_mul_sim_trick") { bn_rand_mod(k, n); bn_rand_mod(l, n); - ep4_rand(p); - ep4_rand(q); - BENCH_ADD(ep4_mul_sim_trick(r, p, k, q, l)); + ep3_rand(p); + ep3_rand(q); + BENCH_ADD(ep3_mul_sim_trick(r, p, k, q, l)); } BENCH_END; #endif #if EP_SIM == INTER || !defined(STRIP) - BENCH_RUN("ep4_mul_sim_inter") { + BENCH_RUN("ep3_mul_sim_inter") { bn_rand_mod(k, n); bn_rand_mod(l, n); - ep4_rand(p); - ep4_rand(q); - BENCH_ADD(ep4_mul_sim_inter(r, p, k, q, l)); + ep3_rand(p); + ep3_rand(q); + BENCH_ADD(ep3_mul_sim_inter(r, p, k, q, l)); } BENCH_END; #endif #if EP_SIM == JOINT || !defined(STRIP) - BENCH_RUN("ep4_mul_sim_joint") { + BENCH_RUN("ep3_mul_sim_joint") { bn_rand_mod(k, n); bn_rand_mod(l, n); - ep4_rand(p); - ep4_rand(q); + ep3_rand(p); + ep3_rand(q); + BENCH_ADD(ep3_mul_sim_joint(r, p, k, q, l)); + } BENCH_END; +#endif + + BENCH_RUN("ep3_mul_sim_gen") { + bn_rand_mod(k, n); + bn_rand_mod(l, n); + ep3_rand(q); + BENCH_ADD(ep3_mul_sim_gen(r, k, q, l)); + } BENCH_END; + + BENCH_RUN("ep3_frb") { + ep3_rand(q); + BENCH_ADD(ep3_frb(r, q, 1)); + } BENCH_END; + + BENCH_RUN("ep3_map") { + uint8_t msg[5]; + rand_bytes(msg, 5); + BENCH_ADD(ep3_map(p, msg, 5)); + } BENCH_END; + + ep3_free(p); + ep3_free(q); + ep3_free(r); + bn_free(k); + bn_free(n); + bn_free(l); + fp3_free(s); +} + +static void memory4(void) { + ep4_t a[BENCH]; + + BENCH_FEW("ep4_null", ep4_null(a[i]), 1); + + BENCH_FEW("ep4_new", ep4_new(a[i]), 1); + for (int i = 0; i < BENCH; i++) { + ep4_free(a[i]); + } + + for (int i = 0; i < BENCH; i++) { + ep4_new(a[i]); + } + BENCH_FEW("ep4_free", ep4_free(a[i]), 1); + + (void)a; +} + +static void util4(void) { + ep4_t p, q, t[2]; + uint8_t bin[8 * RLC_FP_BYTES + 1]; + int l; + + ep4_null(p); + ep4_null(q); + ep4_null(t[0]); + ep4_null(t[1]); + + ep4_new(p); + ep4_new(q); + ep4_new(t[0]); + ep4_new(t[1]); + + BENCH_RUN("ep4_is_infty") { + ep4_rand(p); + BENCH_ADD(ep4_is_infty(p)); + } + BENCH_END; + + BENCH_RUN("ep4_set_infty") { + ep4_rand(p); + BENCH_ADD(ep4_set_infty(p)); + } + BENCH_END; + + BENCH_RUN("ep4_copy") { + ep4_rand(p); + ep4_rand(q); + BENCH_ADD(ep4_copy(p, q)); + } + BENCH_END; + + BENCH_RUN("ep4_cmp") { + ep4_rand(p); + ep4_dbl(p, p); + ep4_rand(q); + ep4_dbl(q, q); + BENCH_ADD(ep4_cmp(p, q)); + } BENCH_END; + + BENCH_RUN("ep4_norm") { + ep4_rand(p); + ep4_dbl(p, p); + BENCH_ADD(ep4_norm(p, p)); + } BENCH_END; + + BENCH_RUN("ep4_norm_sim (2)") { + ep4_rand(t[0]); + ep4_rand(t[1]); + ep4_dbl(t[0], t[0]); + ep4_dbl(t[1], t[1]); + BENCH_ADD(ep4_norm_sim(t, t, 2)); + } BENCH_END; + + BENCH_RUN("ep4_cmp (1 norm)") { + ep4_rand(p); + ep4_dbl(p, p); + ep4_rand(q); + BENCH_ADD(ep4_cmp(p, q)); + } BENCH_END; + + BENCH_RUN("ep4_cmp (2 norm)") { + ep4_rand(p); + ep4_rand(q); + BENCH_ADD(ep4_cmp(p, q)); + } BENCH_END; + + BENCH_RUN("ep4_rand") { + BENCH_ADD(ep4_rand(p)); + } + BENCH_END; + + BENCH_RUN("ep4_blind") { + BENCH_ADD(ep4_blind(p, p)); + } + BENCH_END; + + BENCH_RUN("ep4_on_curve") { + ep4_rand(p); + BENCH_ADD(ep4_on_curve(p)); + } BENCH_END; + + BENCH_RUN("ep4_size_bin") { + ep4_rand(p); + BENCH_ADD(ep4_size_bin(p, 0)); + } BENCH_END; + + BENCH_RUN("ep4_write_bin") { + ep4_rand(p); + l = ep4_size_bin(p, 0); + BENCH_ADD(ep4_write_bin(bin, l, p, 0)); + } BENCH_END; + + BENCH_RUN("ep4_read_bin") { + ep4_rand(p); + l = ep4_size_bin(p, 0); + ep4_write_bin(bin, l, p, 0); + BENCH_ADD(ep4_read_bin(p, bin, l)); + } BENCH_END; + + ep4_free(p); + ep4_free(q); + ep4_free(t[0]); + ep4_free(t[1]); +} + +static void arith4(void) { + ep4_t p, q, r, t[RLC_EPX_TABLE_MAX]; + bn_t k, n, l; + fp4_t s; + + ep4_null(p); + ep4_null(q); + ep4_null(r); + bn_null(k); + bn_null(n); + fp4_null(s); + for (int i = 0; i < RLC_EPX_TABLE_MAX; i++) { + ep4_null(t[i]); + } + + ep4_new(p); + ep4_new(q); + ep4_new(r); + bn_new(k); + bn_new(n); + bn_new(l); + fp4_new(s); + + ep4_curve_get_ord(n); + + BENCH_RUN("ep4_add") { + ep4_rand(p); + ep4_rand(q); + ep4_add(p, p, q); + ep4_rand(q); + ep4_rand(p); + ep4_add(q, q, p); + BENCH_ADD(ep4_add(r, p, q)); + } + BENCH_END; + +#if EP_ADD == BASIC || !defined(STRIP) + BENCH_RUN("ep4_add_basic") { + ep4_rand(p); + ep4_rand(q); + BENCH_ADD(ep4_add_basic(r, p, q)); + } + BENCH_END; + + BENCH_RUN("ep4_add_slp_basic") { + ep4_rand(p); + ep4_rand(q); + BENCH_ADD(ep4_add_slp_basic(r, s, p, q)); + } + BENCH_END; +#endif + +#if EP_ADD == PROJC || !defined(STRIP) + BENCH_RUN("ep4_add_projc") { + ep4_rand(p); + ep4_rand(q); + ep4_add_projc(p, p, q); + ep4_rand(q); + ep4_rand(p); + ep4_add_projc(q, q, p); + BENCH_ADD(ep4_add_projc(r, p, q)); + } + BENCH_END; + + BENCH_RUN("ep4_add_projc (z2 = 1)") { + ep4_rand(p); + ep4_rand(q); + ep4_add_projc(p, p, q); + ep4_rand(q); + ep4_norm(q, q); + BENCH_ADD(ep4_add_projc(r, p, q)); + } + BENCH_END; + + BENCH_RUN("ep4_add_projc (z1,z2 = 1)") { + ep4_rand(p); + ep4_norm(p, p); + ep4_rand(q); + ep4_norm(q, q); + BENCH_ADD(ep4_add_projc(r, p, q)); + } + BENCH_END; +#endif + + BENCH_RUN("ep4_sub") { + ep4_rand(p); + ep4_rand(q); + ep4_add(p, p, q); + ep4_rand(q); + ep4_rand(p); + ep4_add(q, q, p); + BENCH_ADD(ep4_sub(r, p, q)); + } + BENCH_END; + + BENCH_RUN("ep4_dbl") { + ep4_rand(p); + ep4_rand(q); + ep4_add(p, p, q); + BENCH_ADD(ep4_dbl(r, p)); + } + BENCH_END; + +#if EP_ADD == BASIC || !defined(STRIP) + BENCH_RUN("ep4_dbl_basic") { + ep4_rand(p); + BENCH_ADD(ep4_dbl_basic(r, p)); + } + BENCH_END; + + BENCH_RUN("ep4_dbl_slp_basic") { + ep4_rand(p); + BENCH_ADD(ep4_dbl_slp_basic(r, s, p)); + } + BENCH_END; +#endif + +#if EP_ADD == PROJC || !defined(STRIP) + BENCH_RUN("ep4_dbl_projc") { + ep4_rand(p); + ep4_rand(q); + ep4_add_projc(p, p, q); + BENCH_ADD(ep4_dbl_projc(r, p)); + } + BENCH_END; + + BENCH_RUN("ep4_dbl_projc (z1 = 1)") { + ep4_rand(p); + ep4_norm(p, p); + BENCH_ADD(ep4_dbl_projc(r, p)); + } + BENCH_END; +#endif + + BENCH_RUN("ep4_neg") { + ep4_rand(p); + ep4_rand(q); + ep4_add(p, p, q); + BENCH_ADD(ep4_neg(r, p)); + } + BENCH_END; + + BENCH_RUN("ep4_mul") { + bn_rand_mod(k, n); + BENCH_ADD(ep4_mul(q, p, k)); + } BENCH_END; + +#if EP_MUL == BASIC || !defined(STRIP) + BENCH_RUN("ep4_mul_basic") { + bn_rand_mod(k, n); + BENCH_ADD(ep4_mul_basic(q, p, k)); + } BENCH_END; +#endif + +#if EP_MUL == SLIDE || !defined(STRIP) + BENCH_RUN("ep4_mul_slide") { + bn_rand_mod(k, n); + ep4_rand(p); + BENCH_ADD(ep4_mul_slide(q, p, k)); + } BENCH_END; +#endif + +#if EP_MUL == MONTY || !defined(STRIP) + BENCH_RUN("ep4_mul_monty") { + bn_rand_mod(k, n); + ep4_rand(p); + BENCH_ADD(ep4_mul_monty(q, p, k)); + } BENCH_END; +#endif + +#if EP_MUL == LWNAF || !defined(STRIP) + BENCH_RUN("ep4_mul_lwnaf") { + bn_rand_mod(k, n); + ep4_rand(p); + BENCH_ADD(ep4_mul_lwnaf(q, p, k)); + } BENCH_END; +#endif + + BENCH_RUN("ep4_mul_gen") { + bn_rand_mod(k, n); + BENCH_ADD(ep4_mul_gen(q, k)); + } BENCH_END; + + BENCH_RUN("ep4_mul_cof") { + ep4_rand(p); + BENCH_ADD(ep4_mul_cof(q, p)); + } BENCH_END; + + BENCH_RUN("ep4_mul_dig") { + bn_rand(k, RLC_POS, RLC_DIG); + ep4_rand(p); + BENCH_ADD(ep4_mul_dig(q, p, k->dp[0])); + } + BENCH_END; + + for (int i = 0; i < RLC_EPX_TABLE_MAX; i++) { + ep4_new(t[i]); + } + + BENCH_RUN("ep4_mul_pre") { + ep4_rand(p); + BENCH_ADD(ep4_mul_pre(t, p)); + } BENCH_END; + + BENCH_RUN("ep4_mul_fix") { + bn_rand_mod(k, n); + ep4_rand(p); + ep4_mul_pre(t, p); + BENCH_ADD(ep4_mul_fix(q, t, k)); + } BENCH_END; + + for (int i = 0; i < RLC_EPX_TABLE_MAX; i++) { + ep4_free(t[i]); + } + +#if EP_FIX == BASIC || !defined(STRIP) + for (int i = 0; i < RLC_EPX_TABLE_BASIC; i++) { + ep4_new(t[i]); + } + BENCH_RUN("ep4_mul_pre_basic") { + ep4_rand(p); + BENCH_ADD(ep4_mul_pre_basic(t, p)); + } BENCH_END; + + BENCH_RUN("ep4_mul_fix_basic") { + bn_rand_mod(k, n); + ep4_rand(p); + ep4_mul_pre_basic(t, p); + BENCH_ADD(ep4_mul_fix_basic(q, t, k)); + } BENCH_END; + for (int i = 0; i < RLC_EPX_TABLE_BASIC; i++) { + ep4_free(t[i]); + } +#endif + +#if EP_FIX == COMBS || !defined(STRIP) + for (int i = 0; i < RLC_EPX_TABLE_COMBS; i++) { + ep4_new(t[i]); + } + BENCH_RUN("ep4_mul_pre_combs") { + ep4_rand(p); + BENCH_ADD(ep4_mul_pre_combs(t, p)); + } BENCH_END; + + BENCH_RUN("ep4_mul_fix_combs") { + bn_rand_mod(k, n); + ep4_rand(p); + ep4_mul_pre_combs(t, p); + BENCH_ADD(ep4_mul_fix_combs(q, t, k)); + } BENCH_END; + for (int i = 0; i < RLC_EPX_TABLE_COMBS; i++) { + ep4_free(t[i]); + } +#endif + +#if EP_FIX == COMBD || !defined(STRIP) + for (int i = 0; i < RLC_EPX_TABLE_COMBD; i++) { + ep4_new(t[i]); + } + BENCH_RUN("ep4_mul_pre_combd") { + BENCH_ADD(ep4_mul_pre_combd(t, p)); + } BENCH_END; + + BENCH_RUN("ep4_mul_fix_combd") { + bn_rand_mod(k, n); + ep4_mul_pre_combd(t, p); + BENCH_ADD(ep4_mul_fix_combd(q, t, k)); + } BENCH_END; + for (int i = 0; i < RLC_EPX_TABLE_COMBD; i++) { + ep4_free(t[i]); + } +#endif + +#if EP_FIX == LWNAF || !defined(STRIP) + for (int i = 0; i < RLC_EPX_TABLE_LWNAF; i++) { + ep4_new(t[i]); + } + BENCH_RUN("ep4_mul_pre_lwnaf") { + ep4_rand(p); + BENCH_ADD(ep4_mul_pre_lwnaf(t, p)); + } BENCH_END; + + BENCH_RUN("ep4_mul_fix_lwnaf") { + bn_rand_mod(k, n); + ep4_rand(p); + ep4_mul_pre_lwnaf(t, p); + BENCH_ADD(ep4_mul_fix_lwnaf(q, t, k)); + } BENCH_END; + for (int i = 0; i < RLC_EPX_TABLE_LWNAF; i++) { + ep4_free(t[i]); + } +#endif + + BENCH_RUN("ep4_mul_sim") { + bn_rand_mod(k, n); + bn_rand_mod(l, n); + ep4_rand(p); + ep4_rand(q); + BENCH_ADD(ep4_mul_sim(r, p, k, q, l)); + } BENCH_END; + +#if EP_SIM == BASIC || !defined(STRIP) + BENCH_RUN("ep4_mul_sim_basic") { + bn_rand_mod(k, n); + bn_rand_mod(l, n); + ep4_rand(p); + ep4_rand(q); + BENCH_ADD(ep4_mul_sim_basic(r, p, k, q, l)); + } BENCH_END; +#endif + +#if EP_SIM == TRICK || !defined(STRIP) + BENCH_RUN("ep4_mul_sim_trick") { + bn_rand_mod(k, n); + bn_rand_mod(l, n); + ep4_rand(p); + ep4_rand(q); + BENCH_ADD(ep4_mul_sim_trick(r, p, k, q, l)); + } BENCH_END; +#endif + +#if EP_SIM == INTER || !defined(STRIP) + BENCH_RUN("ep4_mul_sim_inter") { + bn_rand_mod(k, n); + bn_rand_mod(l, n); + ep4_rand(p); + ep4_rand(q); + BENCH_ADD(ep4_mul_sim_inter(r, p, k, q, l)); + } BENCH_END; +#endif + +#if EP_SIM == JOINT || !defined(STRIP) + BENCH_RUN("ep4_mul_sim_joint") { + bn_rand_mod(k, n); + bn_rand_mod(l, n); + ep4_rand(p); + ep4_rand(q); BENCH_ADD(ep4_mul_sim_joint(r, p, k, q, l)); } BENCH_END; #endif @@ -1058,8 +1580,502 @@ static void arith4(void) { fp4_free(s); } +static void memory8(void) { + ep8_t a[BENCH]; + + BENCH_FEW("ep8_null", ep8_null(a[i]), 1); + + BENCH_FEW("ep8_new", ep8_new(a[i]), 1); + for (int i = 0; i < BENCH; i++) { + ep8_free(a[i]); + } + + for (int i = 0; i < BENCH; i++) { + ep8_new(a[i]); + } + BENCH_FEW("ep8_free", ep8_free(a[i]), 1); + + (void)a; +} + +static void util8(void) { + ep8_t p, q, t[2]; + uint8_t bin[16 * RLC_FP_BYTES + 1]; + int l; + + ep8_null(p); + ep8_null(q); + ep8_null(t[0]); + ep8_null(t[1]); + + ep8_new(p); + ep8_new(q); + ep8_new(t[0]); + ep8_new(t[1]); + + BENCH_RUN("ep8_is_infty") { + ep8_rand(p); + BENCH_ADD(ep8_is_infty(p)); + } + BENCH_END; + + BENCH_RUN("ep8_set_infty") { + ep8_rand(p); + BENCH_ADD(ep8_set_infty(p)); + } + BENCH_END; + + BENCH_RUN("ep8_copy") { + ep8_rand(p); + ep8_rand(q); + BENCH_ADD(ep8_copy(p, q)); + } + BENCH_END; + + BENCH_RUN("ep8_cmp") { + ep8_rand(p); + ep8_dbl(p, p); + ep8_rand(q); + ep8_dbl(q, q); + BENCH_ADD(ep8_cmp(p, q)); + } BENCH_END; + + BENCH_RUN("ep8_norm") { + ep8_rand(p); + ep8_dbl(p, p); + BENCH_ADD(ep8_norm(p, p)); + } BENCH_END; + + BENCH_RUN("ep8_norm_sim (2)") { + ep8_rand(t[0]); + ep8_rand(t[1]); + ep8_dbl(t[0], t[0]); + ep8_dbl(t[1], t[1]); + BENCH_ADD(ep8_norm_sim(t, t, 2)); + } BENCH_END; + + BENCH_RUN("ep8_cmp (1 norm)") { + ep8_rand(p); + ep8_dbl(p, p); + ep8_rand(q); + BENCH_ADD(ep8_cmp(p, q)); + } BENCH_END; + + BENCH_RUN("ep8_cmp (2 norm)") { + ep8_rand(p); + ep8_rand(q); + BENCH_ADD(ep8_cmp(p, q)); + } BENCH_END; + + BENCH_RUN("ep8_rand") { + BENCH_ADD(ep8_rand(p)); + } + BENCH_END; + + BENCH_RUN("ep8_blind") { + BENCH_ADD(ep8_blind(p, p)); + } + BENCH_END; + + BENCH_RUN("ep8_on_curve") { + ep8_rand(p); + BENCH_ADD(ep8_on_curve(p)); + } BENCH_END; + + BENCH_RUN("ep8_size_bin") { + ep8_rand(p); + BENCH_ADD(ep8_size_bin(p, 0)); + } BENCH_END; + + BENCH_RUN("ep8_write_bin") { + ep8_rand(p); + l = ep8_size_bin(p, 0); + BENCH_ADD(ep8_write_bin(bin, l, p, 0)); + } BENCH_END; + + BENCH_RUN("ep8_read_bin") { + ep8_rand(p); + l = ep8_size_bin(p, 0); + ep8_write_bin(bin, l, p, 0); + BENCH_ADD(ep8_read_bin(p, bin, l)); + } BENCH_END; + + ep8_free(p); + ep8_free(q); + ep8_free(t[0]); + ep8_free(t[1]); +} + +static void arith8(void) { + ep8_t p, q, r, t[RLC_EPX_TABLE_MAX]; + bn_t k, n, l; + fp8_t s; + + ep8_null(p); + ep8_null(q); + ep8_null(r); + bn_null(k); + bn_null(n); + fp8_null(s); + for (int i = 0; i < RLC_EPX_TABLE_MAX; i++) { + ep8_null(t[i]); + } + + ep8_new(p); + ep8_new(q); + ep8_new(r); + bn_new(k); + bn_new(n); + bn_new(l); + fp8_new(s); + + ep8_curve_get_ord(n); + + BENCH_RUN("ep8_add") { + ep8_rand(p); + ep8_rand(q); + ep8_add(p, p, q); + ep8_rand(q); + ep8_rand(p); + ep8_add(q, q, p); + BENCH_ADD(ep8_add(r, p, q)); + } + BENCH_END; + +#if EP_ADD == BASIC || !defined(STRIP) + BENCH_RUN("ep8_add_basic") { + ep8_rand(p); + ep8_rand(q); + BENCH_ADD(ep8_add_basic(r, p, q)); + } + BENCH_END; + + BENCH_RUN("ep8_add_slp_basic") { + ep8_rand(p); + ep8_rand(q); + BENCH_ADD(ep8_add_slp_basic(r, s, p, q)); + } + BENCH_END; +#endif + +#if EP_ADD == PROJC || !defined(STRIP) + BENCH_RUN("ep8_add_projc") { + ep8_rand(p); + ep8_rand(q); + ep8_add_projc(p, p, q); + ep8_rand(q); + ep8_rand(p); + ep8_add_projc(q, q, p); + BENCH_ADD(ep8_add_projc(r, p, q)); + } + BENCH_END; + + BENCH_RUN("ep8_add_projc (z2 = 1)") { + ep8_rand(p); + ep8_rand(q); + ep8_add_projc(p, p, q); + ep8_rand(q); + ep8_norm(q, q); + BENCH_ADD(ep8_add_projc(r, p, q)); + } + BENCH_END; + + BENCH_RUN("ep8_add_projc (z1,z2 = 1)") { + ep8_rand(p); + ep8_norm(p, p); + ep8_rand(q); + ep8_norm(q, q); + BENCH_ADD(ep8_add_projc(r, p, q)); + } + BENCH_END; +#endif + + BENCH_RUN("ep8_sub") { + ep8_rand(p); + ep8_rand(q); + ep8_add(p, p, q); + ep8_rand(q); + ep8_rand(p); + ep8_add(q, q, p); + BENCH_ADD(ep8_sub(r, p, q)); + } + BENCH_END; + + BENCH_RUN("ep8_dbl") { + ep8_rand(p); + ep8_rand(q); + ep8_add(p, p, q); + BENCH_ADD(ep8_dbl(r, p)); + } + BENCH_END; + +#if EP_ADD == BASIC || !defined(STRIP) + BENCH_RUN("ep8_dbl_basic") { + ep8_rand(p); + BENCH_ADD(ep8_dbl_basic(r, p)); + } + BENCH_END; + + BENCH_RUN("ep8_dbl_slp_basic") { + ep8_rand(p); + BENCH_ADD(ep8_dbl_slp_basic(r, s, p)); + } + BENCH_END; +#endif + +#if EP_ADD == PROJC || !defined(STRIP) + BENCH_RUN("ep8_dbl_projc") { + ep8_rand(p); + ep8_rand(q); + ep8_add_projc(p, p, q); + BENCH_ADD(ep8_dbl_projc(r, p)); + } + BENCH_END; + + BENCH_RUN("ep8_dbl_projc (z1 = 1)") { + ep8_rand(p); + ep8_norm(p, p); + BENCH_ADD(ep8_dbl_projc(r, p)); + } + BENCH_END; +#endif + + BENCH_RUN("ep8_neg") { + ep8_rand(p); + ep8_rand(q); + ep8_add(p, p, q); + BENCH_ADD(ep8_neg(r, p)); + } + BENCH_END; + + BENCH_RUN("ep8_mul") { + bn_rand_mod(k, n); + BENCH_ADD(ep8_mul(q, p, k)); + } BENCH_END; + +#if EP_MUL == BASIC || !defined(STRIP) + BENCH_RUN("ep8_mul_basic") { + bn_rand_mod(k, n); + BENCH_ADD(ep8_mul_basic(q, p, k)); + } BENCH_END; +#endif + +#if EP_MUL == SLIDE || !defined(STRIP) + BENCH_RUN("ep8_mul_slide") { + bn_rand_mod(k, n); + ep8_rand(p); + BENCH_ADD(ep8_mul_slide(q, p, k)); + } BENCH_END; +#endif + +#if EP_MUL == MONTY || !defined(STRIP) + BENCH_RUN("ep8_mul_monty") { + bn_rand_mod(k, n); + ep8_rand(p); + BENCH_ADD(ep8_mul_monty(q, p, k)); + } BENCH_END; +#endif + +#if EP_MUL == LWNAF || !defined(STRIP) + BENCH_RUN("ep8_mul_lwnaf") { + bn_rand_mod(k, n); + ep8_rand(p); + BENCH_ADD(ep8_mul_lwnaf(q, p, k)); + } BENCH_END; +#endif + + BENCH_RUN("ep8_mul_gen") { + bn_rand_mod(k, n); + BENCH_ADD(ep8_mul_gen(q, k)); + } BENCH_END; + + BENCH_RUN("ep8_mul_cof") { + ep8_rand(p); + BENCH_ADD(ep8_mul_cof(q, p)); + } BENCH_END; + + BENCH_RUN("ep8_mul_dig") { + bn_rand(k, RLC_POS, RLC_DIG); + ep8_rand(p); + BENCH_ADD(ep8_mul_dig(q, p, k->dp[0])); + } + BENCH_END; + + for (int i = 0; i < RLC_EPX_TABLE_MAX; i++) { + ep8_new(t[i]); + } + + BENCH_RUN("ep8_mul_pre") { + ep8_rand(p); + BENCH_ADD(ep8_mul_pre(t, p)); + } BENCH_END; + + BENCH_RUN("ep8_mul_fix") { + bn_rand_mod(k, n); + ep8_rand(p); + ep8_mul_pre(t, p); + BENCH_ADD(ep8_mul_fix(q, t, k)); + } BENCH_END; + + for (int i = 0; i < RLC_EPX_TABLE_MAX; i++) { + ep8_free(t[i]); + } + +#if EP_FIX == BASIC || !defined(STRIP) + for (int i = 0; i < RLC_EPX_TABLE_BASIC; i++) { + ep8_new(t[i]); + } + BENCH_RUN("ep8_mul_pre_basic") { + ep8_rand(p); + BENCH_ADD(ep8_mul_pre_basic(t, p)); + } BENCH_END; + + BENCH_RUN("ep8_mul_fix_basic") { + bn_rand_mod(k, n); + ep8_rand(p); + ep8_mul_pre_basic(t, p); + BENCH_ADD(ep8_mul_fix_basic(q, t, k)); + } BENCH_END; + for (int i = 0; i < RLC_EPX_TABLE_BASIC; i++) { + ep8_free(t[i]); + } +#endif + +#if EP_FIX == COMBS || !defined(STRIP) + for (int i = 0; i < RLC_EPX_TABLE_COMBS; i++) { + ep8_new(t[i]); + } + BENCH_RUN("ep8_mul_pre_combs") { + ep8_rand(p); + BENCH_ADD(ep8_mul_pre_combs(t, p)); + } BENCH_END; + + BENCH_RUN("ep8_mul_fix_combs") { + bn_rand_mod(k, n); + ep8_rand(p); + ep8_mul_pre_combs(t, p); + BENCH_ADD(ep8_mul_fix_combs(q, t, k)); + } BENCH_END; + for (int i = 0; i < RLC_EPX_TABLE_COMBS; i++) { + ep8_free(t[i]); + } +#endif + +#if EP_FIX == COMBD || !defined(STRIP) + for (int i = 0; i < RLC_EPX_TABLE_COMBD; i++) { + ep8_new(t[i]); + } + BENCH_RUN("ep8_mul_pre_combd") { + BENCH_ADD(ep8_mul_pre_combd(t, p)); + } BENCH_END; + + BENCH_RUN("ep8_mul_fix_combd") { + bn_rand_mod(k, n); + ep8_mul_pre_combd(t, p); + BENCH_ADD(ep8_mul_fix_combd(q, t, k)); + } BENCH_END; + for (int i = 0; i < RLC_EPX_TABLE_COMBD; i++) { + ep8_free(t[i]); + } +#endif + +#if EP_FIX == LWNAF || !defined(STRIP) + for (int i = 0; i < RLC_EPX_TABLE_LWNAF; i++) { + ep8_new(t[i]); + } + BENCH_RUN("ep8_mul_pre_lwnaf") { + ep8_rand(p); + BENCH_ADD(ep8_mul_pre_lwnaf(t, p)); + } BENCH_END; + + BENCH_RUN("ep8_mul_fix_lwnaf") { + bn_rand_mod(k, n); + ep8_rand(p); + ep8_mul_pre_lwnaf(t, p); + BENCH_ADD(ep8_mul_fix_lwnaf(q, t, k)); + } BENCH_END; + for (int i = 0; i < RLC_EPX_TABLE_LWNAF; i++) { + ep8_free(t[i]); + } +#endif + + BENCH_RUN("ep8_mul_sim") { + bn_rand_mod(k, n); + bn_rand_mod(l, n); + ep8_rand(p); + ep8_rand(q); + BENCH_ADD(ep8_mul_sim(r, p, k, q, l)); + } BENCH_END; + +#if EP_SIM == BASIC || !defined(STRIP) + BENCH_RUN("ep8_mul_sim_basic") { + bn_rand_mod(k, n); + bn_rand_mod(l, n); + ep8_rand(p); + ep8_rand(q); + BENCH_ADD(ep8_mul_sim_basic(r, p, k, q, l)); + } BENCH_END; +#endif + +#if EP_SIM == TRICK || !defined(STRIP) + BENCH_RUN("ep8_mul_sim_trick") { + bn_rand_mod(k, n); + bn_rand_mod(l, n); + ep8_rand(p); + ep8_rand(q); + BENCH_ADD(ep8_mul_sim_trick(r, p, k, q, l)); + } BENCH_END; +#endif + +#if EP_SIM == INTER || !defined(STRIP) + BENCH_RUN("ep8_mul_sim_inter") { + bn_rand_mod(k, n); + bn_rand_mod(l, n); + ep8_rand(p); + ep8_rand(q); + BENCH_ADD(ep8_mul_sim_inter(r, p, k, q, l)); + } BENCH_END; +#endif + +#if EP_SIM == JOINT || !defined(STRIP) + BENCH_RUN("ep8_mul_sim_joint") { + bn_rand_mod(k, n); + bn_rand_mod(l, n); + ep8_rand(p); + ep8_rand(q); + BENCH_ADD(ep8_mul_sim_joint(r, p, k, q, l)); + } BENCH_END; +#endif + + BENCH_RUN("ep8_mul_sim_gen") { + bn_rand_mod(k, n); + bn_rand_mod(l, n); + ep8_rand(q); + BENCH_ADD(ep8_mul_sim_gen(r, k, q, l)); + } BENCH_END; + + BENCH_RUN("ep8_frb") { + ep8_rand(q); + BENCH_ADD(ep8_frb(r, q, 1)); + } BENCH_END; + + BENCH_RUN("ep8_map") { + uint8_t msg[5]; + rand_bytes(msg, 5); + BENCH_ADD(ep8_map(p, msg, 5)); + } BENCH_END; + + ep8_free(p); + ep8_free(q); + ep8_free(r); + bn_free(k); + bn_free(n); + bn_free(l); + fp8_free(s); +} + int main(void) { - int r0, r1; + int r0, r1, r2, r3; if (core_init() != RLC_OK) { core_clean(); return 1; @@ -1086,7 +2102,18 @@ int main(void) { arith2(); } - if ((r1 = ep4_curve_is_twist())) { + if ((r1 = ep3_curve_is_twist())) { + ep_param_print(); + + util_banner("Utilities:", 1); + memory3(); + util3(); + + util_banner("Arithmetic:", 1); + arith3(); + } + + if ((r2 = ep4_curve_is_twist())) { ep_param_print(); util_banner("Utilities:", 1); @@ -1097,7 +2124,18 @@ int main(void) { arith4(); } - if (!r0 && !r1) { + if ((r3 = ep8_curve_is_twist())) { + ep_param_print(); + + util_banner("Utilities:", 1); + memory8(); + util8(); + + util_banner("Arithmetic:", 1); + arith8(); + } + + if (!r0 && !r2 && !r1 && !r3) { RLC_THROW(ERR_NO_CURVE); core_clean(); return 0; diff --git a/bench/bench_fp.c b/bench/bench_fp.c index 39204de2f..ea3f576c2 100644 --- a/bench/bench_fp.c +++ b/bench/bench_fp.c @@ -81,6 +81,12 @@ static void util(void) { } BENCH_END; + BENCH_RUN("fp_is_even") { + fp_rand(a); + BENCH_ADD(fp_is_even(a)); + } + BENCH_END; + BENCH_RUN("fp_get_bit") { fp_rand(a); BENCH_ADD(fp_get_bit(a, RLC_DIG / 2)); @@ -626,6 +632,19 @@ static void arith(void) { BENCH_END; #endif + BENCH_RUN("fp_exp_dig") { + fp_rand(a); + bn_rand(e, RLC_POS, RLC_DIG); + BENCH_ADD(fp_exp_dig(b, a, e->dp[0])); + } + BENCH_END; + + BENCH_RUN("fp_is_sqr") { + fp_rand(a); + BENCH_ADD(fp_is_sqr(a)); + } + BENCH_END; + BENCH_RUN("fp_srt") { fp_rand(a); fp_sqr(a, a); @@ -633,6 +652,20 @@ static void arith(void) { } BENCH_END; + BENCH_RUN("fp_is_cub") { + fp_rand(a); + BENCH_ADD(fp_is_cub(a)); + } + BENCH_END; + + BENCH_RUN("fp_crt") { + fp_rand(a); + fp_sqr(b, a); + fp_mul(b, b, a); + BENCH_ADD(fp_crt(c, a)); + } + BENCH_END; + BENCH_RUN("fp_prime_conv") { bn_rand(e, RLC_POS, RLC_FP_BITS); BENCH_ADD(fp_prime_conv(a, e)); diff --git a/bench/bench_fpx.c b/bench/bench_fpx.c index 1ee0c9830..18ad1e8e3 100644 --- a/bench/bench_fpx.c +++ b/bench/bench_fpx.c @@ -380,13 +380,18 @@ static void arith2(void) { BENCH_RUN("fp2_mul_frb") { fp2_rand(a); - BENCH_ADD(fp2_mul_frb(c, a, 1, 0)); + BENCH_ADD(fp2_mul_frb(c, a, 1, 1)); + } + BENCH_END; + + BENCH_RUN("fp2_is_sqr") { + fp2_rand(a); + BENCH_ADD(fp2_is_sqr(a)); } BENCH_END; BENCH_RUN("fp2_srt") { fp2_rand(a); - fp2_sqr(a, a); BENCH_ADD(fp2_srt(c, a)); } BENCH_END; @@ -694,6 +699,18 @@ static void arith3(void) { } BENCH_END; + BENCH_RUN("fp3_is_sqr") { + fp3_rand(a); + BENCH_ADD(fp3_is_sqr(a)); + } + BENCH_END; + + BENCH_RUN("fp3_srt") { + fp2_rand(a); + BENCH_ADD(fp3_srt(c, a)); + } + BENCH_END; + fp3_free(a); fp3_free(b); fp3_free(c); @@ -909,6 +926,12 @@ static void arith4(void) { } BENCH_END; + BENCH_RUN("fp4_is_sqr") { + fp4_rand(a); + BENCH_ADD(fp4_is_sqr(a)); + } + BENCH_END; + BENCH_RUN("fp4_srt") { fp4_rand(a); fp4_sqr(a, a); @@ -1405,6 +1428,19 @@ static void arith8(void) { } BENCH_END; + BENCH_RUN("fp8_is_sqr") { + fp8_rand(a); + BENCH_ADD(fp8_is_sqr(a)); + } + BENCH_END; + + BENCH_RUN("fp8_srt") { + fp8_rand(a); + fp8_sqr(a, a); + BENCH_ADD(fp8_srt(c, a)); + } + BENCH_END; + fp8_free(a); fp8_free(b); fp8_free(c); @@ -2014,6 +2050,230 @@ static void arith12(void) { bn_free(e); } +static void memory16(void) { + fp16_t a[BENCH]; + + BENCH_FEW("fp16_null", fp16_null(a[i]), 1); + + BENCH_FEW("fp16_new", fp16_new(a[i]), 1); + for (int i = 0; i < BENCH; i++) { + fp16_free(a[i]); + } + + for (int i = 0; i < BENCH; i++) { + fp16_new(a[i]); + } + BENCH_FEW("fp16_free", fp16_free(a[i]), 1); + + (void)a; +} + +static void util16(void) { + fp16_t a, b; + + fp16_null(a); + fp16_null(b); + + fp16_new(a); + fp16_new(b); + + BENCH_RUN("fp16_copy") { + fp16_rand(a); + BENCH_ADD(fp16_copy(b, a)); + } + BENCH_END; + + BENCH_RUN("fp16_neg") { + fp16_rand(a); + BENCH_ADD(fp16_neg(b, a)); + } + BENCH_END; + + BENCH_RUN("fp16_zero") { + fp16_rand(a); + BENCH_ADD(fp16_zero(a)); + } + BENCH_END; + + BENCH_RUN("fp16_is_zero") { + fp16_rand(a); + BENCH_ADD((void)fp16_is_zero(a)); + } + BENCH_END; + + BENCH_RUN("fp16_set_dig (1)") { + fp16_rand(a); + BENCH_ADD(fp16_set_dig(a, 1)); + } + BENCH_END; + + BENCH_RUN("fp16_set_dig") { + fp16_rand(a); + BENCH_ADD(fp16_set_dig(a, a[0][0][0][0][0])); + } + BENCH_END; + + BENCH_RUN("fp16_rand") { + BENCH_ADD(fp16_rand(a)); + } + BENCH_END; + + BENCH_RUN("fp16_cmp") { + fp16_rand(a); + fp16_rand(b); + BENCH_ADD(fp16_cmp(b, a)); + } + BENCH_END; + + BENCH_RUN("fp16_cmp_dig") { + fp16_rand(a); + BENCH_ADD(fp16_cmp_dig(a, (dig_t)0)); + } + BENCH_END; + + fp16_free(a); + fp16_free(b); +} + +static void arith16(void) { + fp16_t a, b, c; + bn_t e; + + fp16_new(a); + fp16_new(b); + fp16_new(c); + bn_new(e); + + BENCH_RUN("fp16_add") { + fp16_rand(a); + fp16_rand(b); + BENCH_ADD(fp16_add(c, a, b)); + } + BENCH_END; + + BENCH_RUN("fp16_sub") { + fp16_rand(a); + fp16_rand(b); + BENCH_ADD(fp16_sub(c, a, b)); + } + BENCH_END; + + BENCH_RUN("fp16_mul") { + fp16_rand(a); + fp16_rand(b); + BENCH_ADD(fp16_mul(c, a, b)); + } + BENCH_END; + +#if FPX_RDC == BASIC || !defined(STRIP) + BENCH_RUN("fp16_mul_basic") { + fp16_rand(a); + fp16_rand(b); + BENCH_ADD(fp16_mul_basic(c, a, b)); + } + BENCH_END; +#endif + +#if FPX_RDC == LAZYR || !defined(STRIP) + BENCH_RUN("fp16_mul_lazyr") { + fp16_rand(a); + fp16_rand(b); + BENCH_ADD(fp16_mul_lazyr(c, a, b)); + } + BENCH_END; +#endif + + BENCH_RUN("fp16_sqr") { + fp16_rand(a); + BENCH_ADD(fp16_sqr(c, a)); + } + BENCH_END; + + BENCH_RUN("fp16_sqr_cyc") { + fp16_rand(a); + BENCH_ADD(fp16_sqr_cyc(c, a)); + } + BENCH_END; + + BENCH_RUN("fp16_test_cyc") { + fp16_rand(a); + fp16_conv_cyc(a, a); + BENCH_ADD(fp16_test_cyc(a)); + } + BENCH_END; + + BENCH_RUN("fp16_conv_cyc") { + fp16_rand(a); + BENCH_ADD(fp16_conv_cyc(c, a)); + } + BENCH_END; + + BENCH_RUN("fp16_conv_cyc") { + fp16_rand(a); + BENCH_ADD(fp16_conv_cyc(c, a)); + } + BENCH_END; + + BENCH_RUN("fp16_inv") { + fp16_rand(a); + BENCH_ADD(fp16_inv(c, a)); + } + BENCH_END; + + BENCH_RUN("fp16_inv_cyc") { + fp16_rand(a); + BENCH_ADD(fp16_inv_cyc(c, a)); + } + BENCH_END; + + BENCH_RUN("fp16_exp") { + fp16_rand(a); + bn_rand(e, RLC_POS, RLC_FP_BITS); + BENCH_ADD(fp16_exp(c, a, e)); + } + BENCH_END; + + BENCH_RUN("fp16_exp (cyc)") { + fp16_rand(a); + fp16_conv_cyc(a, a); + bn_rand(e, RLC_POS, RLC_FP_BITS); + BENCH_ADD(fp16_exp(c, a, e)); + } + BENCH_END; + + BENCH_RUN("fp16_exp_cyc (param or sparse)") { + fp16_rand(a); + fp16_conv_cyc(a, a); + bn_zero(e); + fp_prime_get_par(e); + if (bn_is_zero(e)) { + bn_set_2b(e, RLC_FP_BITS - 1); + bn_set_bit(e, RLC_FP_BITS / 2, 1); + bn_set_bit(e, 0, 1); + } + BENCH_ADD(fp16_exp_cyc(c, a, e)); + } + BENCH_END; + + BENCH_RUN("fp16_exp_dig") { + fp16_rand(a); + bn_rand(e, RLC_POS, RLC_DIG); + BENCH_ADD(fp16_exp_dig(c, a, e->dp[0])); + } + BENCH_END; + + BENCH_RUN("fp16_frb") { + fp16_rand(a); + BENCH_ADD(fp16_frb(c, a, 1)); + } + BENCH_END; + + fp16_free(a); + fp16_free(b); + fp16_free(c); + bn_free(e); +} + static void memory18(void) { fp18_t a[BENCH]; @@ -2034,6 +2294,7 @@ static void memory18(void) { static void util18(void) { fp18_t a, b; + uint8_t bin[18 * RLC_FP_BYTES]; fp18_null(a); fp18_null(b); @@ -2082,6 +2343,47 @@ static void util18(void) { } BENCH_END; + BENCH_RUN("fp18_size_bin (0)") { + fp18_rand(a); + BENCH_ADD(fp18_size_bin(a, 0)); + } + BENCH_END; + + BENCH_RUN("fp18_size_bin (1)") { + fp18_rand(a); + fp18_conv_cyc(a, a); + BENCH_ADD(fp18_size_bin(a, 1)); + } + BENCH_END; + + BENCH_RUN("fp18_write_bin (0)") { + fp18_rand(a); + BENCH_ADD(fp18_write_bin(bin, sizeof(bin), a, 0)); + } + BENCH_END; + + BENCH_RUN("fp18_write_bin (1)") { + fp18_rand(a); + fp18_conv_cyc(a, a); + BENCH_ADD(fp18_write_bin(bin, 8 * RLC_FP_BYTES, a, 1)); + } + BENCH_END; + + BENCH_RUN("fp18_read_bin (0)") { + fp18_rand(a); + fp18_write_bin(bin, sizeof(bin), a, 0); + BENCH_ADD(fp18_read_bin(a, bin, sizeof(bin))); + } + BENCH_END; + + BENCH_RUN("fp18_read_bin (1)") { + fp18_rand(a); + fp18_conv_cyc(a, a); + fp18_write_bin(bin, fp18_size_bin(a, 1), a, 1); + BENCH_ADD(fp18_read_bin(a, bin, 8 * RLC_FP_BYTES)); + } + BENCH_END; + BENCH_RUN("fp18_cmp") { fp18_rand(a); fp18_rand(b); @@ -2100,12 +2402,14 @@ static void util18(void) { } static void arith18(void) { - fp18_t a, b, c; + fp18_t a, b, c, d[2]; bn_t e; fp18_new(a); fp18_new(b); fp18_new(c); + fp18_new(d[0]); + fp18_new(d[1]); bn_new(e); BENCH_RUN("fp18_add") { @@ -2147,51 +2451,200 @@ static void arith18(void) { BENCH_END; #endif + BENCH_RUN("fp18_mul_dxs") { + fp18_rand(a); + fp18_rand(b); + BENCH_ADD(fp18_mul_dxs(c, a, b)); + } + BENCH_END; + +#if FPX_RDC == BASIC || !defined(STRIP) + BENCH_RUN("fp18_mul_dxs_basic") { + fp18_rand(a); + fp18_rand(b); + BENCH_ADD(fp18_mul_dxs_basic(c, a, b)); + } + BENCH_END; +#endif + +#if FPX_RDC == LAZYR || !defined(STRIP) + BENCH_RUN("fp18_mul_dxs_lazyr") { + fp18_rand(a); + fp18_rand(b); + BENCH_ADD(fp18_mul_dxs_lazyr(c, a, b)); + } + BENCH_END; +#endif + BENCH_RUN("fp18_sqr") { fp18_rand(a); BENCH_ADD(fp18_sqr(c, a)); } BENCH_END; + BENCH_RUN("fp18_sqr_cyc") { + fp18_rand(a); + BENCH_ADD(fp18_sqr_cyc(c, a)); + } + BENCH_END; + +#if FPX_RDC == BASIC || !defined(STRIP) + BENCH_RUN("fp18_sqr_cyc_basic") { + fp18_rand(a); + fp18_rand(b); + BENCH_ADD(fp18_sqr_cyc_basic(c, a)); + } + BENCH_END; +#endif + +#if FPX_RDC == LAZYR || !defined(STRIP) + BENCH_RUN("fp18_sqr_cyc_lazyr") { + fp18_rand(a); + fp18_rand(b); + BENCH_ADD(fp18_sqr_cyc_lazyr(c, a)); + } + BENCH_END; +#endif + + BENCH_RUN("fp18_sqr_pck") { + fp18_rand(a); + BENCH_ADD(fp18_sqr_pck(c, a)); + } + BENCH_END; + #if FPX_RDC == BASIC || !defined(STRIP) - BENCH_RUN("fp18_sqr_basic") { + BENCH_RUN("fp18_sqr_pck_basic") { fp18_rand(a); - BENCH_ADD(fp18_sqr_basic(c, a)); + fp18_rand(b); + BENCH_ADD(fp18_sqr_pck_basic(c, a)); } BENCH_END; #endif #if FPX_RDC == LAZYR || !defined(STRIP) - BENCH_RUN("fp18_sqr_lazyr") { + BENCH_RUN("fp18_sqr_pck_lazyr") { fp18_rand(a); - BENCH_ADD(fp18_sqr_lazyr(c, a)); + fp18_rand(b); + BENCH_ADD(fp18_sqr_pck_lazyr(c, a)); } BENCH_END; #endif + BENCH_RUN("fp18_test_cyc") { + fp18_rand(a); + fp18_conv_cyc(a, a); + BENCH_ADD(fp18_test_cyc(a)); + } + BENCH_END; + + BENCH_RUN("fp18_conv_cyc") { + fp18_rand(a); + BENCH_ADD(fp18_conv_cyc(c, a)); + } + BENCH_END; + + BENCH_RUN("fp18_back_cyc") { + fp18_rand(a); + BENCH_ADD(fp18_back_cyc(c, a)); + } + BENCH_END; + + BENCH_RUN("fp18_back_cyc (2)") { + fp18_rand(d[0]); + fp18_rand(d[1]); + BENCH_ADD(fp18_back_cyc_sim(d, d, 2)); + } + BENCH_END; + + BENCH_RUN("fp18_conv_cyc") { + fp18_rand(a); + BENCH_ADD(fp18_conv_cyc(c, a)); + } + BENCH_END; + BENCH_RUN("fp18_inv") { fp18_rand(a); BENCH_ADD(fp18_inv(c, a)); } BENCH_END; + BENCH_RUN("fp18_inv_cyc") { + fp18_rand(a); + BENCH_ADD(fp18_inv_cyc(c, a)); + } + BENCH_END; + BENCH_RUN("fp18_exp") { fp18_rand(a); - e->used = RLC_FP_DIGS; - dv_copy(e->dp, fp_prime_get(), RLC_FP_DIGS); + bn_rand(e, RLC_POS, RLC_FP_BITS); BENCH_ADD(fp18_exp(c, a, e)); } BENCH_END; + BENCH_RUN("fp18_exp (cyc)") { + fp18_rand(a); + fp18_conv_cyc(a, a); + bn_rand(e, RLC_POS, RLC_FP_BITS); + BENCH_ADD(fp18_exp(c, a, e)); + } + BENCH_END; + + BENCH_RUN("fp18_exp_cyc (param or sparse)") { + fp18_rand(a); + fp18_conv_cyc(a, a); + bn_zero(e); + fp_prime_get_par(e); + if (bn_is_zero(e)) { + bn_set_2b(e, RLC_FP_BITS - 1); + bn_set_bit(e, RLC_FP_BITS / 2, 1); + bn_set_bit(e, 0, 1); + } + BENCH_ADD(fp18_exp_cyc(c, a, e)); + } + BENCH_END; + + BENCH_RUN("fp18_exp_cyc_sps (param)") { + const int *k; + int l; + k = fp_prime_get_par_sps(&l); + fp18_rand(a); + BENCH_ADD(fp18_exp_cyc_sps(c, a, k, l, RLC_POS)); + } + BENCH_END; + + BENCH_RUN("fp18_exp_dig") { + fp18_rand(a); + bn_rand(e, RLC_POS, RLC_DIG); + BENCH_ADD(fp18_exp_dig(c, a, e->dp[0])); + } + BENCH_END; + BENCH_RUN("fp18_frb") { fp18_rand(a); BENCH_ADD(fp18_frb(c, a, 1)); } BENCH_END; + BENCH_RUN("fp18_pck") { + fp18_rand(a); + fp18_conv_cyc(a, a); + BENCH_ADD(fp18_pck(c, a)); + } + BENCH_END; + + BENCH_RUN("fp18_upk") { + fp18_rand(a); + fp18_conv_cyc(a, a); + fp18_pck(a, a); + BENCH_ADD(fp18_upk(c, a)); + } + BENCH_END; + fp18_free(a); fp18_free(b); fp18_free(c); + fp18_free(d[0]); + fp18_free(d[1]); bn_free(e); } @@ -3293,7 +3746,7 @@ int main(void) { arith9(); } - if (fp_prime_get_qnr() && (ep_param_embed() >= 12)) { + if (fp_prime_get_qnr() && fp_prime_get_cnr() && (ep_param_embed() >= 12)) { util_banner("Dodecic extension:", 0); util_banner("Utilities:", 1); memory12(); @@ -3302,6 +3755,16 @@ int main(void) { arith12(); } + if (fp_prime_get_qnr() && (ep_param_embed() >= 16)) { + util_banner("Sextadecic extension:", 0); + util_banner("Utilities:", 1); + memory16(); + util16(); + + util_banner("Arithmetic:", 1); + arith16(); + } + if (fp_prime_get_cnr() && (ep_param_embed() >= 18)) { util_banner("Octdecic extension:", 0); util_banner("Utilities:", 1); diff --git a/bench/bench_pc.c b/bench/bench_pc.c index cb5bebf45..b161cb91a 100755 --- a/bench/bench_pc.c +++ b/bench/bench_pc.c @@ -303,7 +303,7 @@ static void memory2(void) { static void util2(void) { g2_t p, q; - uint8_t bin[8 * RLC_PC_BYTES + 1]; + uint8_t bin[16 * RLC_PC_BYTES + 1]; int l; g2_null(p); @@ -519,13 +519,11 @@ static void arith2(void) { } BENCH_END; -#if FP_PRIME != 509 BENCH_RUN("g2_map") { uint8_t msg[5]; rand_bytes(msg, 5); BENCH_ADD(g2_map(p, msg, 5)); } BENCH_END; -#endif g2_free(p); g2_free(q); @@ -557,7 +555,7 @@ static void memory(void) { static void util(void) { gt_t a, b; - uint8_t bin[24 * RLC_PC_BYTES]; + uint8_t bin[48 * RLC_PC_BYTES]; int l; gt_null(a); @@ -602,11 +600,6 @@ static void util(void) { } BENCH_END; - BENCH_RUN("gt_size_bin (0)") { - gt_rand(a); - BENCH_ADD(gt_size_bin(a, 0)); - } BENCH_END; - BENCH_RUN("gt_write_bin (0)") { gt_rand(a); l = gt_size_bin(a, 0); @@ -621,11 +614,6 @@ static void util(void) { } BENCH_END; if (ep_param_embed() == 12) { - BENCH_RUN("gt_size_bin (1)") { - gt_rand(a); - BENCH_ADD(gt_size_bin(a, 1)); - } BENCH_END; - BENCH_RUN("gt_write_bin (1)") { gt_rand(a); l = gt_size_bin(a, 1); diff --git a/bench/bench_pp.c b/bench/bench_pp.c index 01bb27e77..47b55c2d5 100644 --- a/bench/bench_pp.c +++ b/bench/bench_pp.c @@ -550,83 +550,214 @@ static void pairing12(void) { } } +static void pairing24(void) { + bn_t k, n, l; + ep4_t p[2], r; + ep_t q[2]; + fp24_t e; + int j; + + bn_null(k); + bn_null(n); + bn_null(l); + ep4_null(r); + fp24_null(e); + + bn_new(k); + bn_new(n); + bn_new(l); + ep4_new(r); + fp24_new(e); + + for (j = 0; j < 2; j++) { + ep4_null(p[j]); + ep_null(q[j]); + ep4_new(p[j]); + ep_new(q[j]); + } + + ep4_curve_get_ord(n); + + BENCH_RUN("pp_add_k24") { + ep4_rand(p[0]); + ep4_dbl(r, p[0]); + ep4_norm(r, r); + ep_rand(q[0]); + BENCH_ADD(pp_add_k24(e, r, p[0], q[0])); + } + BENCH_END; + +#if EP_ADD == BASIC || !defined(STRIP) + BENCH_RUN("pp_add_k24_basic") { + ep4_rand(p[0]); + ep4_dbl(r, p[0]); + ep4_norm(r, r); + ep_rand(q[0]); + BENCH_ADD(pp_add_k24_basic(e, r, p[0], q[0])); + } + BENCH_END; +#endif + +#if EP_ADD == PROJC || !defined(STRIP) + + BENCH_RUN("pp_add_k24_projc") { + ep4_rand(p[0]); + ep4_dbl(r, p[0]); + ep4_norm(r, r); + ep_rand(q[0]); + BENCH_ADD(pp_add_k24_projc(e, r, p[0], q[0])); + } + BENCH_END; + +#endif + + BENCH_RUN("pp_dbl_k24") { + ep4_rand(p[0]); + ep_rand(q[0]); + BENCH_ADD(pp_dbl_k24(e, p[0], p[0], q[0])); + } + BENCH_END; + +#if EP_ADD == BASIC || !defined(STRIP) + BENCH_RUN("pp_dbl_k24_basic") { + ep4_rand(p[0]); + ep_rand(q[0]); + BENCH_ADD(pp_dbl_k24_basic(e, p[0], p[0], q[0])); + } + BENCH_END; +#endif + +#if EP_ADD == PROJC || !defined(STRIP) + + BENCH_RUN("pp_dbl_k24_projc") { + ep4_rand(p[0]); + ep_rand(q[0]); + BENCH_ADD(pp_dbl_k24_projc(e, p[0], p[0], q[0])); + } + BENCH_END; + +#endif + + BENCH_RUN("pp_exp_k24") { + fp24_rand(e); + BENCH_ADD(pp_exp_k24(e, e)); + } + BENCH_END; + + BENCH_RUN("pp_map_k24") { + ep4_rand(p[0]); + ep_rand(q[0]); + BENCH_ADD(pp_map_k24(e, q[0], p[0])); + } + BENCH_END; + + BENCH_RUN("pp_map_sim_k24 (2)") { + ep4_rand(p[0]); + ep_rand(q[0]); + ep4_rand(p[1]); + ep_rand(q[1]); + BENCH_ADD(pp_map_sim_k24(e, q, p, 2)); + } + BENCH_END; + + bn_free(k); + bn_free(n); + bn_free(l); + fp24_free(e); + ep4_free(r); + for (j = 0; j < 2; j++) { + ep4_free(p[j]); + ep_free(q[j]); + } +} + static void pairing48(void) { - ep_t p; - fp8_t qx, qy, qz; + bn_t k, n, l; + ep8_t p[2], r; + ep_t q[2]; fp48_t e; + int j; - ep_null(p); - fp8_null(qx); - fp8_null(qy); - fp8_null(qz); + bn_null(k); + bn_null(n); + bn_null(l); + ep8_null(r); fp48_null(e); - ep_new(p); - fp8_new(qx); - fp8_new(qy); - fp8_new(qz); + bn_new(k); + bn_new(n); + bn_new(l); + ep8_new(r); fp48_new(e); + for (j = 0; j < 2; j++) { + ep8_null(p[j]); + ep_null(q[j]); + ep8_new(p[j]); + ep_new(q[j]); + } + + ep8_curve_get_ord(n); + BENCH_RUN("pp_add_k48") { - fp8_rand(qx); - fp8_rand(qy); - fp8_rand(qz); - ep_rand(p); - BENCH_ADD(pp_add_k48(e, qx, qy, qz, qy, qx, p)); + ep8_rand(p[0]); + ep8_dbl(r, p[0]); + ep8_norm(r, r); + ep_rand(q[0]); + BENCH_ADD(pp_add_k48(e, r, p[0], q[0])); } BENCH_END; #if EP_ADD == BASIC || !defined(STRIP) BENCH_RUN("pp_add_k48_basic") { - fp8_rand(qx); - fp8_rand(qy); - fp8_rand(qz); - ep_rand(p); - BENCH_ADD(pp_add_k48_basic(e, qx, qy, qy, qx, p)); + ep8_rand(p[0]); + ep8_dbl(r, p[0]); + ep8_norm(r, r); + ep_rand(q[0]); + BENCH_ADD(pp_add_k48_basic(e, r, p[0], q[0])); } BENCH_END; #endif #if EP_ADD == PROJC || !defined(STRIP) + BENCH_RUN("pp_add_k48_projc") { - fp8_rand(qx); - fp8_rand(qy); - fp8_rand(qz); - ep_rand(p); - BENCH_ADD(pp_add_k48_projc(e, qx, qy, qz, qx, qy, p)); + ep8_rand(p[0]); + ep8_dbl(r, p[0]); + ep8_norm(r, r); + ep_rand(q[0]); + BENCH_ADD(pp_add_k48_projc(e, r, p[0], q[0])); } BENCH_END; + #endif BENCH_RUN("pp_dbl_k48") { - fp8_rand(qx); - fp8_rand(qy); - fp8_rand(qz); - ep_rand(p); - BENCH_ADD(pp_dbl_k48(e, qx, qy, qz, p)); + ep8_rand(p[0]); + ep_rand(q[0]); + BENCH_ADD(pp_dbl_k48(e, p[0], p[0], q[0])); } BENCH_END; - #if EP_ADD == BASIC || !defined(STRIP) - BENCH_RUN("pp_dbl_k48_basic") { - fp8_rand(qx); - fp8_rand(qy); - ep_rand(p); - BENCH_ADD(pp_dbl_k48_basic(e, qx, qy, p)); - } - BENCH_END; - #endif +#if EP_ADD == BASIC || !defined(STRIP) + BENCH_RUN("pp_dbl_k48_basic") { + ep8_rand(p[0]); + ep_rand(q[0]); + BENCH_ADD(pp_dbl_k48_basic(e, p[0], p[0], q[0])); + } + BENCH_END; +#endif - #if EP_ADD == PROJC || !defined(STRIP) - BENCH_RUN("pp_dbl_k48_projc") { - fp8_rand(qx); - fp8_rand(qy); - fp8_rand(qz); - ep_rand(p); - BENCH_ADD(pp_dbl_k48_projc(e, qx, qy, qz, p)); - } - BENCH_END; - #endif +#if EP_ADD == PROJC || !defined(STRIP) + + BENCH_RUN("pp_dbl_k48_projc") { + ep8_rand(p[0]); + ep_rand(q[0]); + BENCH_ADD(pp_dbl_k48_projc(e, p[0], p[0], q[0])); + } + BENCH_END; + +#endif BENCH_RUN("pp_exp_k48") { fp48_rand(e); @@ -635,19 +766,30 @@ static void pairing48(void) { BENCH_END; BENCH_RUN("pp_map_k48") { - fp8_rand(qx); - fp8_rand(qy); - fp8_rand(qz); - ep_rand(p); - BENCH_ADD(pp_map_k48(e, p, qx, qy)); + ep8_rand(p[0]); + ep_rand(q[0]); + BENCH_ADD(pp_map_k48(e, q[0], p[0])); } BENCH_END; - ep_free(p); - fp8_free(qx); - fp8_free(qy); - fp8_free(qz); + BENCH_RUN("pp_map_sim_k48 (2)") { + ep8_rand(p[0]); + ep_rand(q[0]); + ep8_rand(p[1]); + ep_rand(q[1]); + BENCH_ADD(pp_map_sim_k48(e, q, p, 2)); + } + BENCH_END; + + bn_free(k); + bn_free(n); + bn_free(l); fp48_free(e); + ep8_free(r); + for (j = 0; j < 2; j++) { + ep8_free(p[j]); + ep_free(q[j]); + } } static void pairing54(void) { @@ -781,6 +923,10 @@ int main(void) { pairing12(); } + if (ep_param_embed() == 48) { + pairing24(); + } + if (ep_param_embed() == 48) { pairing48(); } diff --git a/cmake/ep.cmake b/cmake/ep.cmake index d0cd6deb7..14a36921f 100644 --- a/cmake/ep.cmake +++ b/cmake/ep.cmake @@ -11,7 +11,7 @@ message(" EP_CTMAP=[off|on] Use contant-time SSWU and isogeny map for hashi message(" EP_PRECO=[off|on] Build precomputation table for generator.") message(" RLC_DEPTH=w Width w in [2,8] of precomputation table for fixed point methods.") -message(" ** Available prime elliptic curve methods (default = PROJC;LWNAF;COMBS;INTER):\n") +message(" ** Available prime elliptic curve methods (default = PROJC;LWNAF;COMBS;INTER;SSWUM):\n") message(" Point representation:") message(" EP_METHD=BASIC Affine coordinates.") @@ -19,6 +19,7 @@ message(" EP_METHD=PROJC Homogeneous projective coordinates (complete fo message(" EP_METHD=JACOB Jacobian projective coordinates.\n") message(" Variable-base scalar multiplication:") +message(" EB_METHD=BASIC Binary double-and-add method.") message(" EP_METHD=SLIDE Sliding window method.") message(" EP_METHD=MONTY Montgomery ladder method.") message(" EP_METHD=LWNAF Left-to-right window NAF method.") @@ -36,6 +37,11 @@ message(" EP_METHD=TRICK Shamir's trick for simultaneous multiplication. message(" EP_METHD=INTER Interleaving of window NAFs (GLV for Koblitz curves).") message(" EP_METHD=JOINT Joint sparse form.\n") +message(" Hash to point on the elliptic curve:") +message(" EP_METHD=BASIC Hash to x-coordinate and increment.") +message(" EP_METHD=SSWUM Simplified Shallue-van de Woestijne-Ulas method.") +message(" EP_METHD=SWIFT SwiftEC hashing method.\n") + option(EP_PLAIN "Support for ordinary curves without endomorphisms" on) option(EP_SUPER "Support for supersingular curves" on) option(EP_MIXED "Use mixed coordinates" on) @@ -45,15 +51,16 @@ option(EP_CTMAP "Use contant-time SSWU and isogeny map for hashing" on) # Choose the arithmetic methods. if (NOT EP_METHD) - set(EP_METHD "PROJC;LWNAF;COMBS;INTER") + set(EP_METHD "PROJC;LWNAF;COMBS;INTER;SSWUM") endif(NOT EP_METHD) list(LENGTH EP_METHD EP_LEN) -if (EP_LEN LESS 4) +if (EP_LEN LESS 5) message(FATAL_ERROR "Incomplete EP_METHD specification: ${EP_METHD}") -endif(EP_LEN LESS 4) +endif(EP_LEN LESS 5) list(GET EP_METHD 0 EP_ADD) list(GET EP_METHD 1 EP_MUL) list(GET EP_METHD 2 EP_FIX) list(GET EP_METHD 3 EP_SIM) +list(GET EP_METHD 4 EP_MAP) set(EP_METHD ${EP_METHD} CACHE STRING "Method for prime elliptic curve arithmetic.") diff --git a/cmake/fp.cmake b/cmake/fp.cmake index 4636a948a..44648fb2c 100644 --- a/cmake/fp.cmake +++ b/cmake/fp.cmake @@ -39,7 +39,6 @@ message(" FP_METHD=LOWER Pass inversion to the lower level.\n") message(" Legendre symbol:") message(" FP_METHD=BASIC Computation by Fermat's Little Theorem.") -message(" FP_METHD=BINAR Binary algorithm.") message(" FP_METHD=DIVST Constant-time method by division steps.") message(" FP_METHD=JMPDS Constant-time method by jump division steps.") message(" FP_METHD=LOWER Pass call to the lower level.\n") diff --git a/demo/cert-input/Makefile b/demo/cert-input/Makefile index 25f24241c..acad9b177 100644 --- a/demo/cert-input/Makefile +++ b/demo/cert-input/Makefile @@ -7,7 +7,7 @@ all: lib lib: mkdir -p target - cd target; ${RELIC_ROOT}/../preset/x64-pbc-bls12-381.sh ${RELIC_ROOT}/../; cmake -DEP_METHD='JACOB;LWNAF;COMBS;INTER' .; make + cd target; ${RELIC_ROOT}/../preset/x64-pbc-bls12-381.sh ${RELIC_ROOT}/../; cmake -DEP_METHD='JACOB;LWNAF;COMBS;INTER;SSWUM' .; make clean: rm -rf target *.o test-bench diff --git a/demo/ers-etrs/Makefile b/demo/ers-etrs/Makefile index 16d60bad2..af1dca7e7 100644 --- a/demo/ers-etrs/Makefile +++ b/demo/ers-etrs/Makefile @@ -7,7 +7,7 @@ all: lib lib: mkdir -p target - cd target; ${RELIC_ROOT}/../preset/x64-ecc-128.sh ${RELIC_ROOT}/../; cmake -DED_METHD='EXTND;LWNAF;COMBS;INTER' -DEP_ENDOM=off -DBN_METHD='COMBA;COMBA;MONTY;SLIDE;LEHME;BASIC' -DWITH="MD;BC;DV;BN;FP;EP;ED;EC;CP" .; make + cd target; ${RELIC_ROOT}/../preset/x64-ecc-128.sh ${RELIC_ROOT}/../; cmake -DEP_METHD='JACOB;LWNAF;COMBS;INTER;SSWUM' -DEP_ENDOM=off -DBN_METHD=' COMBA;COMBA;MONTY;SLIDE;LEHME;BASIC' -DWITH="MD;BC;DV;BN;FP;EP;ED;EC;CP" .; make clean: rm -rf target *.o test-bench diff --git a/demo/psi-client-server/Makefile b/demo/psi-client-server/Makefile index 1b3fc7f1a..4c1ea6c27 100644 --- a/demo/psi-client-server/Makefile +++ b/demo/psi-client-server/Makefile @@ -9,7 +9,7 @@ all: lib lib: mkdir -p target - cd target; ${RELIC_ROOT}/../preset/x64-pbc-bls12-381.sh ${RELIC_ROOT}/../; cmake -DTIMER=HREAL -DBN_PRECI=3072 -DBENCH=1 -DMULTI=PTHREAD -DEP_METHD='JACOB;LWNAF;COMBS;INTER' .; make + cd target; ${RELIC_ROOT}/../preset/x64-pbc-bls12-381.sh ${RELIC_ROOT}/../; cmake -DTIMER=HREAL -DBN_PRECI=3072 -DBENCH=1 -DMULTI=PTHREAD -DEP_METHD='JACOB;LWNAF;COMBS;INTER;SSWUM' .; make clean: rm -rf target *.o test-bench receiver sender diff --git a/demo/public-stats/Makefile b/demo/public-stats/Makefile index f52bd9ab9..0fcc9bc36 100644 --- a/demo/public-stats/Makefile +++ b/demo/public-stats/Makefile @@ -8,7 +8,7 @@ all: lib data.csv lib: mkdir -p target - cd target; ${RELIC_ROOT}/../preset/x64-pbc-bls12-381.sh ${RELIC_ROOT}/../; cmake -DEP_METHD='JACOB;LWNAF;COMBS;INTER' .; make + cd target; ${RELIC_ROOT}/../preset/x64-pbc-bls12-381.sh ${RELIC_ROOT}/../; cmake -DEP_METHD='JACOB;LWNAF;COMBS;INTER;SSWUM' .; make data.csv: wget -c https://raw.githubusercontent.com/TheEconomist/covid-19-excess-deaths-tracker/master/source-data/spain/archive/spain_total_source_2020_04_13.csv diff --git a/demo/tweedledum/Makefile b/demo/tweedledum/Makefile index c5e31f030..f7a1fb08c 100644 --- a/demo/tweedledum/Makefile +++ b/demo/tweedledum/Makefile @@ -7,7 +7,7 @@ all: lib lib: mkdir -p target - cd target; ${RELIC_ROOT}/../preset/gmp-ecc-tweedledum.sh ${RELIC_ROOT}/../; cmake -DEP_METHD='JACOB;LWNAF;COMBS;INTER' .; make + cd target; ${RELIC_ROOT}/../preset/gmp-ecc-tweedledum.sh ${RELIC_ROOT}/../; cmake -DEP_METHD='JACOB;LWNAF;COMBS;INTER;SSWUM' .; make clean: rm -rf target *.o main diff --git a/include/relic_conf.h.in b/include/relic_conf.h.in index b865495c8..e11eb7a44 100644 --- a/include/relic_conf.h.in +++ b/include/relic_conf.h.in @@ -266,8 +266,6 @@ /** Legendre by Fermat's Little Theorem. */ #define BASIC 1 -/** Binary method. */ -#define BINAR 2 /** Constant-time inversion by Bernstein-Yang division steps. */ #define DIVST 5 /** Constant-time inversion by Bernstein-Yang jump division steps. */ @@ -465,6 +463,15 @@ /** Chosen prime elliptic curve simulteanous point multiplication method. */ #define EP_SIM @EP_SIM@ +/** Basic hash to x-coordinate and increment. */ +#define BASIC 1 +/** (Simplified) Shallue-van de Woestijne-Ulas map. */ +#define SSWUM 2 +/** SwiftEC method. */ +#define SWIFT 3 +/** Chosen prime elliptic curve hashing method. */ +#define EP_MAP @EP_MAP@ + /** Prime elliptic curve arithmetic method. */ #define EP_METHD "@EP_METHD@" diff --git a/include/relic_core.h b/include/relic_core.h index 4b7c92152..5ad5b357f 100644 --- a/include/relic_core.h +++ b/include/relic_core.h @@ -232,9 +232,13 @@ typedef struct _ctx_t { /** Value of constant for divstep-based inversion. */ bn_st inv; #endif /* FP_INV */ + /** Square root of unity for square root extraction. */ + bn_st srt; + /** Cube root of unity for square root extraction. */ + bn_st crt; /** Prime modulus modulo 8. */ dig_t mod8; - /** Prime modulus modulo 8. */ + /** Prime modulus modulo 18. */ dig_t mod18; /** Value derived from the prime used for modular reduction. */ dig_t u; @@ -270,7 +274,7 @@ typedef struct _ctx_t { /** The distinguished non-square used by the mapping function */ fp_st ep_map_u; /** Precomputed constants for hashing. */ - fp_st ep_map_c[4]; + fp_st ep_map_c[7]; #ifdef EP_ENDOM #if EP_MUL == LWNAF || EP_FIX == COMBS || EP_FIX == LWNAF || EP_SIM == INTER || !defined(STRIP) /** Parameters required by the GLV method. @{ */ @@ -386,6 +390,28 @@ typedef struct _ctx_t { ep4_st ep4_pre[RLC_EP_TABLE]; /** Array of pointers to the precomputation table. */ ep4_st *ep4_ptr[RLC_EP_TABLE]; +#endif /* EP_PRECO */ + /** The generator of the elliptic curve. */ + ep8_t ep8_g; + /** The 'a' coefficient of the curve. */ + fp8_t ep8_a; + /** The 'b' coefficient of the curve. */ + fp8_t ep8_b; + /** The order of the group of points in the elliptic curve. */ + bn_st ep8_r; + /** The cofactor of the group order in the elliptic curve. */ + bn_st ep8_h; + /** Optimization identifier for the a-coefficient. */ + int ep8_opt_a; + /** Optimization identifier for the b-coefficient. */ + int ep8_opt_b; + /** Flag that stores if the prime curve is a twist. */ + int ep8_is_twist; +#ifdef EP_PRECO + /** Precomputation table for generator multiplication.*/ + ep8_st ep8_pre[RLC_EP_TABLE]; + /** Array of pointers to the precomputation table. */ + ep8_st *ep8_ptr[RLC_EP_TABLE]; #endif /* EP_PRECO */ #endif /* WITH_EPX */ @@ -414,19 +440,21 @@ typedef struct _ctx_t { #endif #if defined(WITH_FPX) || defined(WITH_PP) - /** Integer part of the quadratic non-residue. */ + /** Integer part of the quadratic non-residue in the quadratic extension. */ dis_t qnr2; /** Constants for computing Frobenius maps in higher extensions. @{ */ fp2_st fp2_p1[5]; - fp2_st fp2_p2[3]; - int frb4; - fp2_st fp4_p1; - /** @} */ - /** Constants for computing Frobenius maps in higher extensions. @{ */ + fp2_st fp2_p2[4]; int frb3[3]; + /** Integer part of the cubic non-residue in the cubic extension. */ + dis_t cnr3; fp_st fp3_p0[2]; fp3_st fp3_p1[5]; fp3_st fp3_p2[2]; + int frb4; + fp2_st fp4_p1; + int frb8; + fp2_st fp8_p1; /** @} */ #endif /* WITH_PP */ diff --git a/include/relic_ep.h b/include/relic_ep.h index 8bbb06bf2..d4a1416d6 100644 --- a/include/relic_ep.h +++ b/include/relic_ep.h @@ -53,20 +53,18 @@ * Pairing-friendly elliptic curve identifiers. */ enum { - /** Supersingular curves with embedding degree 1. */ - EP_SS1 = 1, + /** Ordinary curves with embedding degree 1. */ + EP_K1 = 1, /** Supersingular curves with embedding degree 2. */ EP_SS2, /** Barreto-Naehrig. */ EP_BN, - /* Optimal TNFS-secure. */ - EP_OT8, /* Cocks-Pinch family discovered by Guillevic, Masson and Thomé (GMT). */ EP_GMT8, /* Barreto-Lynn-Scott family with embedding degree 12. */ EP_B12, - /* Fotiadis-Martindale family with embedding degree 16. */ - EP_FM16, + /* New family from Fotiadis-Martindale family with embedding degree 16. */ + EP_N16, /* Kachisa-Schaefer-Scott family with embedding degree 16. */ EP_K16, /* Fotiadis-Martindale family with embedding degree 18. */ @@ -139,6 +137,8 @@ enum { B24_P315, /** Barreto-Lynn-Scott curve with embedding degree 24 (SNARK curve). */ B24_P317, + /** Kachisa-Schaefer-Scott with embedding degree 16. */ + K16_P330, /** Barreto-Lynn-Scott curve with embedding degree 12 (SNARK curve). */ B12_P377, /** Barreto-Lynn-Scott curve with embedding degree 12 (ZCash curve). */ @@ -154,7 +154,7 @@ enum { /** Barreto-Lynn-Scott curve with embedding degree 12. */ B12_P455, /** Kachisa-Schaefer-Scott with negative x. */ - KSS_P508, + K18_P508, /** Barreto-Lynn-Scott curve with embedding degree 24. */ B24_P509, /** Optimal TNFS-secure curve with embedding degree 8. */ @@ -173,10 +173,14 @@ enum { K18_P638, /** Scott-Guillevic curve with embedding degree 18. */ SG18_P638, + /** New family with embeeding degree 16. */ + N16_P765, + /** Kachisa-Schaefer-Scott with embedding degree 16. */ + K16_P766, /** 1536-bit supersingular curve. */ SS_P1536, /** 3072-bit supersingular curve. */ - SS_P3072, + K1_P3072, }; /*============================================================================*/ @@ -455,6 +459,22 @@ typedef iso_st *iso_t; #define ep_mul_sim(R, P, K, Q, M) ep_mul_sim_joint(R, P, K, Q, M) #endif +/** + * Hashes a byte string to a prime elliptic point or the right order. + * Computes R = H(s). + * + * @param[out] R - the result. + * @param[in] S - the string to hash. + * @param[in] L - the string length. + */ +#if EP_MAP == BASIC +#define ep_map(R, S, L) ep_map_basic(R, S, L) +#elif EP_MAP == SSWUM +#define ep_map(R, S, L) ep_map_sswum(R, S, L) +#elif EP_MAP == SWIFT +#define ep_map(R, S, L) ep_map_swift(R, S, L) +#endif + /*============================================================================*/ /* Function prototypes */ /*============================================================================*/ @@ -620,11 +640,10 @@ iso_t ep_curve_get_iso(void); * @param[in] g - the generator. * @param[in] r - the order of the group of points. * @param[in] h - the cofactor of the group order. - * @param[in] u - the non-square used for hashing to this curve. * @param[in] ctmap - true if this curve will use an isogeny for mapping. */ void ep_curve_set_plain(const fp_t a, const fp_t b, const ep_t g, const bn_t r, - const bn_t h, const fp_t u, int ctmap); + const bn_t h, int ctmap); /** * Configures a supersingular prime elliptic curve by its coefficients and @@ -635,11 +654,10 @@ void ep_curve_set_plain(const fp_t a, const fp_t b, const ep_t g, const bn_t r, * @param[in] g - the generator. * @param[in] r - the order of the group of points. * @param[in] h - the cofactor of the group order. - * @param[in] u - the non-square used for hashing to this curve. * @param[in] ctmap - true if this curve will use an isogeny for mapping. */ void ep_curve_set_super(const fp_t a, const fp_t b, const ep_t g, const bn_t r, - const bn_t h, const fp_t u, int ctmap); + const bn_t h, int ctmap); /** * Configures a prime elliptic curve with endomorphisms by its coefficients and @@ -652,11 +670,10 @@ void ep_curve_set_super(const fp_t a, const fp_t b, const ep_t g, const bn_t r, * @param[in] beta - the constant associated with the endomorphism. * @param[in] l - the exponent corresponding to the endomorphism. * @param[in] h - the cofactor of the group order. - * @param[in] u - the non-square used for hashing to this curve. * @param[in] ctmap - true if this curve will use an isogeny for mapping. */ 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, const fp_t u, int ctmap); + const bn_t h, const fp_t beta, const bn_t l, int ctmap); /** * Configures a prime elliptic curve by its parameter identifier. @@ -1001,6 +1018,15 @@ void ep_mul_gen(ep_t r, const bn_t k); */ void ep_mul_dig(ep_t r, const ep_t p, dig_t k); +/** + * Multiplies a point in an elliptic curve over by the curve cofactor. + * In short, it takes a point in the curve to the large prime-order subgroup. + * + * @param[out] R - the result. + * @param[in] P - the point to multiply. + */ +void ep_mul_cof(ep_t r, const ep_t p); + /** * Builds a precomputation table for multiplying a fixed prime elliptic point * using the binary method. @@ -1218,38 +1244,33 @@ void ep_norm(ep_t r, const ep_t p); void ep_norm_sim(ep_t *r, const ep_t *t, int n); /** - * Maps an array of uniformly random bytes to a point in a prime elliptic - * curve. - * That array is expected to have a length suitable for two field elements plus - * extra bytes for uniformity. - * + * Maps a byte array to a point in a prime elliptic curve using the hash and + * increment approach. * @param[out] p - the result. - * @param[in] uniform_bytes - the array of uniform bytes to map. + * @param[in] msg - the byte array to map. * @param[in] len - the array length in bytes. */ -void ep_map_from_field(ep_t p, const uint8_t *uniform_bytes, size_t len); +void ep_map_basic(ep_t p, const uint8_t *msg, size_t len); /** - * Maps a byte array to a point in a prime elliptic curve. + * Maps a byte array to a point in a prime elliptic curve using the + * (Simplified) Shallue-van de Woestijne-Ulas map. * * @param[out] p - the result. * @param[in] msg - the byte array to map. * @param[in] len - the array length in bytes. */ -void ep_map(ep_t p, const uint8_t *msg, size_t len); +void ep_map_sswum(ep_t p, const uint8_t *msg, size_t len); /** - * Maps a byte array to a point in a prime elliptic curve with specified - * domain separation tag (aka personalization string). + * Maps a byte array to a point in a prime elliptic curve using the + * SwiftEC approach. * * @param[out] p - the result. * @param[in] msg - the byte array to map. * @param[in] len - the array length in bytes. - * @param[in] dst - the domain separation tag. - * @param[in] dst_len - the domain separation tag length in bytes. */ -void ep_map_dst(ep_t p, const uint8_t *msg, size_t len, const uint8_t *dst, - size_t dst_len); +void ep_map_swift(ep_t p, const uint8_t *msg, size_t len); /** * Compresses a point. diff --git a/include/relic_epx.h b/include/relic_epx.h index 72436397b..17177b4fa 100644 --- a/include/relic_epx.h +++ b/include/relic_epx.h @@ -117,7 +117,7 @@ typedef struct { } ep2_st; /** - * Pointer to an elliptic curve point. + * Pointer to an elliptic curve point over a quadratic extension field. */ #if ALLOC == AUTO typedef ep2_st ep2_t[1]; @@ -141,7 +141,7 @@ typedef struct { } ep3_st; /** - * Pointer to an elliptic curve point. + * Pointer to an elliptic curve point over a cubic extension field. */ #if ALLOC == AUTO typedef ep3_st ep3_t[1]; @@ -150,7 +150,7 @@ typedef ep3_st *ep3_t; #endif /** - * Represents an elliptic curve point over a quartic extension over a prime + * Represents an elliptic curve point over a octic extension over a prime * field. */ typedef struct { @@ -165,7 +165,7 @@ typedef struct { } ep4_st; /** - * Pointer to an elliptic curve point. + * Pointer to an elliptic curve point over a octic extension field. */ #if ALLOC == AUTO typedef ep4_st ep4_t[1]; @@ -173,6 +173,30 @@ typedef ep4_st ep4_t[1]; typedef ep4_st *ep4_t; #endif +/** + * Represents an elliptic curve point over an octic extension over a prime + * field. + */ +typedef struct { + /** The first coordinate. */ + fp8_t x; + /** The second coordinate. */ + fp8_t y; + /** The third coordinate (projective representation). */ + fp8_t z; + /** Flag to indicate the coordinate system of this point. */ + int coord; +} ep8_st; + +/** + * Pointer to an elliptic curve point over an octic extension field. + */ +#if ALLOC == AUTO +typedef ep8_st ep8_t[1]; +#else +typedef ep8_st *ep8_t; +#endif + /** * Coefficients of an isogeny map for a curve over a quadratic extension. */ @@ -358,6 +382,56 @@ typedef iso2_st *iso2_t; #define ep4_free(A) /* empty */ #endif +/** + * Initializes a point on an elliptic curve with a null value. + * + * @param[out] A - the point to initialize. + */ +#define ep8_null(A) RLC_NULL(A) + +/** + * Calls a function to allocate a point on an elliptic curve. + * + * @param[out] A - the new point. + * @throw ERR_NO_MEMORY - if there is no available memory. + */ +#if ALLOC == DYNAMIC +#define ep8_new(A) \ + A = (ep8_t)calloc(1, sizeof(ep8_st)); \ + if (A == NULL) { \ + RLC_THROW(ERR_NO_MEMORY); \ + } \ + fp8_null((A)->x); \ + fp8_null((A)->y); \ + fp8_null((A)->z); \ + fp8_new((A)->x); \ + fp8_new((A)->y); \ + fp8_new((A)->z); \ + +#elif ALLOC == AUTO +#define ep8_new(A) /* empty */ + +#endif + +/** + * Calls a function to clean and free a point on an elliptic curve. + * + * @param[out] A - the point to free. + */ +#if ALLOC == DYNAMIC +#define ep8_free(A) \ + if (A != NULL) { \ + fp8_free((A)->x); \ + fp8_free((A)->y); \ + fp8_free((A)->z); \ + free(A); \ + A = NULL; \ + } \ + +#elif ALLOC == AUTO +#define ep8_free(A) /* empty */ +#endif + /** * Adds two points in an elliptic curve over a quadratic extension field. * Computes R = P + Q. @@ -470,6 +544,22 @@ typedef iso2_st *iso2_t; #define ep2_mul_sim(R, P, K, Q, M) ep2_mul_sim_joint(R, P, K, Q, M) #endif +/** + * Hashes a byte string to a prime elliptic point or the right order. + * Computes R = H(s). + * + * @param[out] R - the result. + * @param[in] S - the string to hash. + * @param[in] L - the string length. + */ +#if EP_MAP == BASIC +#define ep2_map(R, S, L) ep2_map_basic(R, S, L) +#elif EP_MAP == SSWUM +#define ep2_map(R, S, L) ep2_map_sswum(R, S, L) +#elif EP_MAP == SWIFT +#define ep2_map(R, S, L) ep2_map_swift(R, S, L) +#endif + /** * Adds two points in an elliptic curve over a cubic extension field. * Computes R = P + Q. @@ -497,16 +587,6 @@ typedef iso2_st *iso2_t; #define ep3_dbl(R, P) ep3_dbl_projc(R, P); #endif -/** - * 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) - /** * Multiplies a point in an elliptic curve over a cubic extension field. * Computes R = [k]P. @@ -583,7 +663,7 @@ typedef iso2_st *iso2_t; #endif /** - * Adds two points in an elliptic curve over a quadratic extension field. + * Adds two points in an elliptic curve over a octic extension field. * Computes R = P + Q. * * @param[out] R - the result. @@ -597,7 +677,7 @@ typedef iso2_st *iso2_t; #endif /** - * Doubles a point in an elliptic curve over a quadratic extension field. + * Doubles a point in an elliptic curve over a octic extension field. * Computes R = 2P. * * @param[out] R - the result. @@ -610,7 +690,7 @@ typedef iso2_st *iso2_t; #endif /** - * Multiplies a point in an elliptic curve over a quadratic extension field by + * 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. @@ -620,7 +700,7 @@ typedef iso2_st *iso2_t; #define ep4_mul_big(R, P, K) ep4_mul_basic(R, P, K) /** - * Multiplies a point in an elliptic curve over a quadratic extension field. + * Multiplies a point in an elliptic curve over a octic extension field. * Computes R = [k]P. * * @param[out] R - the result. @@ -639,7 +719,7 @@ typedef iso2_st *iso2_t; /** * Builds a precomputation table for multiplying a fixed prime elliptic point - * over a quadratic extension. + * over a octic extension. * * @param[out] T - the precomputation table. * @param[in] P - the point to multiply. @@ -656,7 +736,7 @@ typedef iso2_st *iso2_t; #endif /** - * Multiplies a fixed prime elliptic point over a quadratic extension using a + * Multiplies a fixed prime elliptic point over a octic extension using a * precomputation table. Computes R = [k]P. * * @param[out] R - the result. @@ -694,6 +774,118 @@ typedef iso2_st *iso2_t; #define ep4_mul_sim(R, P, K, Q, M) ep4_mul_sim_joint(R, P, K, Q, M) #endif +/** + * Adds two points in an elliptic curve over a octic extension field. + * Computes R = P + Q. + * + * @param[out] R - the result. + * @param[in] P - the first point to add. + * @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); +#endif + +/** + * Doubles a point in an elliptic curve over a 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); +#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. + * Computes R = [k]P. + * + * @param[out] R - the result. + * @param[in] P - the point to multiply. + * @param[in] K - the integer. + */ +#if EP_MUL == BASIC +#define ep8_mul(R, P, K) ep8_mul_basic(R, P, K) +#elif EP_MUL == SLIDE +#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 +#define ep8_mul(R, P, K) ep8_mul_lwnaf(R, P, K) +#endif + +/** + * Builds a precomputation table for multiplying a fixed prime elliptic point + * over a octic extension. + * + * @param[out] T - the precomputation table. + * @param[in] P - the point to multiply. + */ +#if EP_FIX == BASIC +#define ep8_mul_pre(T, P) ep8_mul_pre_basic(T, P) +#elif EP_FIX == COMBS +#define ep8_mul_pre(T, P) ep8_mul_pre_combs(T, P) +#elif EP_FIX == COMBD +#define ep8_mul_pre(T, P) ep8_mul_pre_combd(T, P) +#elif EP_FIX == LWNAF +//TODO: implement ep8_mul_pre_glv +#define ep8_mul_pre(T, P) ep8_mul_pre_lwnaf(T, P) +#endif + +/** + * Multiplies a fixed prime elliptic point over a octic extension using a + * precomputation table. Computes R = [k]P. + * + * @param[out] R - the result. + * @param[in] T - the precomputation table. + * @param[in] K - the integer. + */ +#if EP_FIX == BASIC +#define ep8_mul_fix(R, T, K) ep8_mul_fix_basic(R, T, K) +#elif EP_FIX == COMBS +#define ep8_mul_fix(R, T, K) ep8_mul_fix_combs(R, T, K) +#elif EP_FIX == COMBD +#define ep8_mul_fix(R, T, K) ep8_mul_fix_combd(R, T, K) +#elif EP_FIX == LWNAF +//TODO: implement ep8_mul_fix_glv +#define ep8_mul_fix(R, T, K) ep8_mul_fix_lwnaf(R, T, K) +#endif + +/** + * Multiplies and adds two prime elliptic curve points simultaneously. Computes + * R = [k]P + [l]Q. + * + * @param[out] R - the result. + * @param[in] P - the first point to multiply. + * @param[in] K - the first integer. + * @param[in] Q - the second point to multiply. + * @param[in] M - the second integer, + */ +#if EP_SIM == BASIC +#define ep8_mul_sim(R, P, K, Q, M) ep8_mul_sim_basic(R, P, K, Q, M) +#elif EP_SIM == TRICK +#define ep8_mul_sim(R, P, K, Q, M) ep8_mul_sim_trick(R, P, K, Q, M) +#elif EP_SIM == INTER +#define ep8_mul_sim(R, P, K, Q, M) ep8_mul_sim_inter(R, P, K, Q, M) +#elif EP_SIM == JOINT +#define ep8_mul_sim(R, P, K, Q, M) ep8_mul_sim_joint(R, P, K, Q, M) +#endif + /*============================================================================*/ /* Function prototypes */ /*============================================================================*/ @@ -722,13 +914,6 @@ fp_t *ep2_curve_get_a(void); */ fp_t *ep2_curve_get_b(void); -/** - * Returns the vector of coefficients required to perform GLV method. - * - * @param[out] b - the vector of coefficients. - */ -void ep2_curve_get_vs(bn_t *v); - /** * Returns a optimization identifier based on the 'a' coefficient of the curve. * @@ -799,7 +984,8 @@ iso2_t ep2_curve_get_iso(void); * @param[in] r - the order of the group of points. * @param[in] h - the cofactor of the group order. */ -void ep2_curve_set(const fp2_t a, const fp2_t b, const ep2_t g, const bn_t r, const bn_t h); +void ep2_curve_set(const fp2_t a, const fp2_t b, const ep2_t g, const bn_t r, + const bn_t h); /** * Configures an elliptic curve by twisting the curve over the base prime field. @@ -962,7 +1148,7 @@ 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); /** - * Subtracts a point i an elliptic curve over a quadratic extension from + * Subtracts a point in an elliptic curve over a quadratic extension from * another. * * @param[out] r - the result. @@ -1289,38 +1475,33 @@ void ep2_norm(ep2_t r, const ep2_t p); void ep2_norm_sim(ep2_t *r, const ep2_t *t, int n); /** - * Maps an array of uniformly random bytes to a point in a prime elliptic - * curve. - * That array is expected to have a length suitable for four field elements plus - * extra bytes for uniformity. - * + * Maps a byte array to a point in a prime elliptic curve using the hash and + * increment approach. * @param[out] p - the result. - * @param[in] uniform_bytes - the array of uniform bytes to map. + * @param[in] msg - the byte array to map. * @param[in] len - the array length in bytes. */ -void ep2_map_from_field(ep2_t p, const uint8_t *uniform_bytes, size_t len); +void ep2_map_basic(ep2_t p, const uint8_t *msg, size_t len); /** - * Maps a byte array to a point in an elliptic curve over a quadratic extension. + * Maps a byte array to a point in a prime elliptic curve using the + * (Simplified) Shallue-van de Woestijne-Ulas map. * * @param[out] p - the result. * @param[in] msg - the byte array to map. * @param[in] len - the array length in bytes. */ -void ep2_map(ep2_t p, const uint8_t *msg, size_t len); +void ep2_map_sswum(ep2_t p, const uint8_t *msg, size_t len); /** - * Maps a byte array to a point in an elliptic curve over a quadratic extension - * using an explicit domain separation tag. + * Maps a byte array to a point in a prime elliptic curve using the + * SwiftEC approach. * * @param[out] p - the result. * @param[in] msg - the byte array to map. * @param[in] len - the array length in bytes. - * @param[in] dst - the domain separatoin tag. - * @param[in] dst_len - the domain separation tag length in bytes. */ -void ep2_map_dst(ep2_t p, const uint8_t *msg, size_t len, const uint8_t *dst, - size_t dst_len); +void ep2_map_swift(ep2_t p, const uint8_t *msg, size_t len); /** * Computes a power of the Gailbraith-Lin-Scott homomorphism of a point @@ -1354,12 +1535,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 quartic extension. + * Initializes the elliptic curve over octic extension. */ void ep3_curve_init(void); /** - * Finalizes the elliptic curve over quartic extension. + * Finalizes the elliptic curve over octic extension. */ void ep3_curve_clean(void); @@ -1377,13 +1558,6 @@ void ep3_curve_get_a(fp3_t a); */ void ep3_curve_get_b(fp3_t b); -/** - * Returns the vector of coefficients required to perform GLV method. - * - * @param[out] b - the vector of coefficients. - */ -void ep3_curve_get_vs(bn_t *v); - /** * Returns a optimization identifier based on the 'a' coefficient of the curve. * @@ -1434,7 +1608,7 @@ void ep3_curve_get_ord(bn_t n); void ep3_curve_get_cof(bn_t h); /** - * Configures an elliptic curve over a quartic extension by its coefficients. + * Configures an elliptic curve over a octic extension by its coefficients. * * @param[in] a - the 'a' coefficient of the curve. * @param[in] b - the 'b' coefficient of the curve. @@ -1442,7 +1616,8 @@ void ep3_curve_get_cof(bn_t h); * @param[in] r - the order of the group of points. * @param[in] h - the cofactor of the group order. */ -void ep3_curve_set(const fp3_t a, const fp3_t b, const ep3_t g, const bn_t r, const bn_t h); +void ep3_curve_set(const fp3_t a, const fp3_t b, const ep3_t g, const bn_t r, + const bn_t h); /** * Configures an elliptic curve by twisting the curve over the base prime field. @@ -1532,7 +1707,7 @@ void ep3_print(const ep3_t p); /** * Returns the number of bytes necessary to store a prime elliptic curve point - * over a quartic extension with optional point compression. + * over a octic extension with optional point compression. * * @param[in] a - the prime field element. * @param[in] pack - the flag to indicate compression. @@ -1541,7 +1716,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 quartic extension from a byte + * Reads a prime elliptic curve point over a octic extension from a byte * vector in big-endian format. * * @param[out] a - the result. @@ -1550,10 +1725,10 @@ int ep3_size_bin(const ep3_t a, int pack); * @throw ERR_NO_VALID - if the encoded point is invalid. * @throw ERR_NO_BUFFER - if the buffer capacity is invalid. */ -void ep3_read_bin(ep3_t a, const uint8_t *bin, int len); +void ep3_read_bin(ep3_t a, const uint8_t *bin, size_t len); /** - * Writes a prime elliptic curve pointer over a quartic extension to a byte + * Writes a prime elliptic curve pointer over a octic extension to a byte * vector in big-endian format with optional point compression. * * @param[out] bin - the byte vector. @@ -1562,11 +1737,11 @@ void ep3_read_bin(ep3_t a, const uint8_t *bin, int len); * @param[in] pack - the flag to indicate compression. * @throw ERR_NO_BUFFER - if the buffer capacity is invalid. */ -void ep3_write_bin(uint8_t *bin, int len, const ep3_t a, int pack); +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 quartic extension. + * a octic extension. * * @param[out] r - the result. * @param[out] p - the point to negate. @@ -1575,7 +1750,7 @@ void ep3_neg(ep3_t r, const ep3_t p); /** * Adds to points represented in affine coordinates in an elliptic curve over a - * quartic extension. + * octic extension. * * @param[out] r - the result. * @param[in] p - the first point to add. @@ -1585,7 +1760,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 - * quartic extension and returns the computed slope. + * octic extension and returns the computed slope. * * @param[out] r - the result. * @param[out] s - the slope. @@ -1596,7 +1771,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 quartic extension. + * over a octic extension. * * @param[out] r - the result. * @param[in] p - the first point to add. @@ -1605,7 +1780,7 @@ 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); /** - * Subtracts a point i an elliptic curve over a quartic extension from + * Subtracts a point in an elliptic curve over a octic extension from * another. * * @param[out] r - the result. @@ -1616,7 +1791,7 @@ 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 quartic extension. + * a octic extension. * * @param[out] r - the result. * @param[int] p - the point to double. @@ -1625,7 +1800,7 @@ void ep3_dbl_basic(ep3_t r, const ep3_t p); /** * Doubles a points represented in affine coordinates in an elliptic curve over - * a quartic extension and returns the computed slope. + * a octic extension and returns the computed slope. * * @param[out] r - the result. * @param[out] s - the slope. @@ -1635,7 +1810,7 @@ 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 quartic extension. + * over a octic extension. * * @param[out] r - the result. * @param[in] p - the point to double. @@ -1706,9 +1881,8 @@ 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 quartic extension field by + * Multiplies a point in an elliptic curve over a 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. * @@ -1910,7 +2084,7 @@ void ep3_mul_sim_gen(ep3_t r, const bn_t k, const ep3_t q, const bn_t m); * @param[in] k - the small scalars. * @param[in] len - the number of points to multiply. */ -void ep3_mul_sim_dig(ep3_t r, const ep3_t p[], const dig_t k[], int len); +void ep3_mul_sim_dig(ep3_t r, const ep3_t p[], const dig_t k[], size_t len); /** * Converts a point to affine coordinates. @@ -1930,33 +2104,21 @@ void ep3_norm(ep3_t r, const ep3_t p); void ep3_norm_sim(ep3_t *r, const ep3_t *t, int n); /** - * 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. - * @param[in] len - the array length in bytes. - */ -void ep3_map(ep3_t p, const uint8_t *msg, int len); - -/** - * Maps a byte array to a point in an elliptic curve over a quartic extension - * using an explicit domain separation tag. + * Maps a byte array to a point in an elliptic curve over a cubic extension. * * @param[out] p - the result. * @param[in] msg - the byte array to map. * @param[in] len - the array length in bytes. - * @param[in] dst - the domain separatoin tag. - * @param[in] dst_len - the domain separation tag length in bytes. */ -void ep3_map_dst(ep3_t p, const uint8_t *msg, int len, const uint8_t *dst, int dst_len); +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 - * 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 + * 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 * Frobenius map of a point represented in affine coordinates in an elliptic - * curve over a quartic exension. Computes Frob^i(P) = (p^i)P. + * curve over a 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. @@ -1965,7 +2127,7 @@ void ep3_map_dst(ep3_t p, const uint8_t *msg, int len, const uint8_t *dst, int d void ep3_frb(ep3_t r, const ep3_t p, int i); /** - * Compresses a point in an elliptic curve over a quartic extension. + * Compresses a point in an elliptic curve over a octic extension. * * @param[out] r - the result. * @param[in] p - the point to compress. @@ -1973,7 +2135,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 quartic extension. + * Decompresses a point in an elliptic curve over a octic extension. * * @param[out] r - the result. * @param[in] p - the point to decompress. @@ -1982,12 +2144,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 quartic extension. + * Initializes the elliptic curve over octic extension. */ void ep4_curve_init(void); /** - * Finalizes the elliptic curve over quartic extension. + * Finalizes the elliptic curve over octic extension. */ void ep4_curve_clean(void); @@ -2005,13 +2167,6 @@ void ep4_curve_get_a(fp4_t a); */ void ep4_curve_get_b(fp4_t b); -/** - * Returns the vector of coefficients required to perform GLV method. - * - * @param[out] b - the vector of coefficients. - */ -void ep4_curve_get_vs(bn_t *v); - /** * Returns a optimization identifier based on the 'a' coefficient of the curve. * @@ -2062,7 +2217,7 @@ void ep4_curve_get_ord(bn_t n); void ep4_curve_get_cof(bn_t h); /** - * Configures an elliptic curve over a quartic extension by its coefficients. + * Configures an elliptic curve over a octic extension by its coefficients. * * @param[in] a - the 'a' coefficient of the curve. * @param[in] b - the 'b' coefficient of the curve. @@ -2070,7 +2225,8 @@ void ep4_curve_get_cof(bn_t h); * @param[in] r - the order of the group of points. * @param[in] h - the cofactor of the group order. */ -void ep4_curve_set(const fp4_t a, const fp4_t b, const ep4_t g, const bn_t r, const bn_t h); +void ep4_curve_set(const fp4_t a, const fp4_t b, const ep4_t g, const bn_t r, + const bn_t h); /** * Configures an elliptic curve by twisting the curve over the base prime field. @@ -2160,7 +2316,7 @@ void ep4_print(const ep4_t p); /** * Returns the number of bytes necessary to store a prime elliptic curve point - * over a quartic extension with optional point compression. + * over a octic extension with optional point compression. * * @param[in] a - the prime field element. * @param[in] pack - the flag to indicate compression. @@ -2169,7 +2325,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 quartic extension from a byte + * Reads a prime elliptic curve point over a octic extension from a byte * vector in big-endian format. * * @param[out] a - the result. @@ -2181,7 +2337,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 quartic extension to a byte + * Writes a prime elliptic curve pointer over a octic extension to a byte * vector in big-endian format with optional point compression. * * @param[out] bin - the byte vector. @@ -2194,7 +2350,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 quartic extension. + * a octic extension. * * @param[out] r - the result. * @param[out] p - the point to negate. @@ -2203,7 +2359,7 @@ void ep4_neg(ep4_t r, const ep4_t p); /** * Adds to points represented in affine coordinates in an elliptic curve over a - * quartic extension. + * octic extension. * * @param[out] r - the result. * @param[in] p - the first point to add. @@ -2213,7 +2369,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 - * quartic extension and returns the computed slope. + * octic extension and returns the computed slope. * * @param[out] r - the result. * @param[out] s - the slope. @@ -2224,7 +2380,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 quartic extension. + * over a octic extension. * * @param[out] r - the result. * @param[in] p - the first point to add. @@ -2233,7 +2389,7 @@ 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); /** - * Subtracts a point i an elliptic curve over a quartic extension from + * Subtracts a point in an elliptic curve over a octic extension from * another. * * @param[out] r - the result. @@ -2244,7 +2400,7 @@ 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 quartic extension. + * a octic extension. * * @param[out] r - the result. * @param[int] p - the point to double. @@ -2253,7 +2409,7 @@ void ep4_dbl_basic(ep4_t r, const ep4_t p); /** * Doubles a points represented in affine coordinates in an elliptic curve over - * a quartic extension and returns the computed slope. + * a octic extension and returns the computed slope. * * @param[out] r - the result. * @param[out] s - the slope. @@ -2263,7 +2419,7 @@ 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 quartic extension. + * over a octic extension. * * @param[out] r - the result. * @param[in] p - the point to double. @@ -2336,7 +2492,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 quartic extension field by + * Multiplies a point in an elliptic curve over a 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. * @@ -2558,7 +2714,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 quartic extension. + * Maps a byte array to a point in an elliptic curve over a octic extension. * * @param[out] p - the result. * @param[in] msg - the byte array to map. @@ -2566,26 +2722,13 @@ void ep4_norm_sim(ep4_t *r, const ep4_t *t, int n); */ void ep4_map(ep4_t p, const uint8_t *msg, size_t len); -/** - * Maps a byte array to a point in an elliptic curve over a quartic extension - * using an explicit domain separation tag. - * - * @param[out] p - the result. - * @param[in] msg - the byte array to map. - * @param[in] len - the array length in bytes. - * @param[in] dst - the domain separatoin tag. - * @param[in] dst_len - the domain separation tag length in bytes. - */ -void ep4_map_dst(ep4_t p, const uint8_t *msg, size_t len, const uint8_t *dst, - size_t dst_len); - /** * Computes a power of the Gailbraith-Lin-Scott homomorphism of a point * represented in affine coordinates on a twisted elliptic curve over a - * 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 + * 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 * Frobenius map of a point represented in affine coordinates in an elliptic - * curve over a quartic exension. Computes Frob^i(P) = (p^i)P. + * curve over a 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. @@ -2594,7 +2737,7 @@ void ep4_map_dst(ep4_t p, const uint8_t *msg, size_t len, const uint8_t *dst, void ep4_frb(ep4_t r, const ep4_t p, int i); /** - * Compresses a point in an elliptic curve over a quartic extension. + * Compresses a point in an elliptic curve over a octic extension. * * @param[out] r - the result. * @param[in] p - the point to compress. @@ -2602,7 +2745,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 quartic extension. + * Decompresses a point in an elliptic curve over a octic extension. * * @param[out] r - the result. * @param[in] p - the point to decompress. @@ -2610,4 +2753,614 @@ void ep4_pck(ep4_t r, const ep4_t p); */ int ep4_upk(ep4_t r, const ep4_t p); +/** + * Initializes the elliptic curve over octic extension. + */ +void ep8_curve_init(void); + +/** + * Finalizes the elliptic curve over octic extension. + */ +void ep8_curve_clean(void); + +/** + * Returns the 'a' coefficient of the currently configured elliptic curve. + * + * @return the 'a' coefficient of the elliptic curve. + */ +void ep8_curve_get_a(fp8_t a); + +/** + * 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); + +/** + * Returns a optimization identifier based on the 'a' coefficient of the curve. + * + * @return the optimization identifier. + */ +int ep8_curve_opt_a(void); + +/** + * Returns b optimization identifier based on the 'b' coefficient of the curve. + * + * @return the optimization identifier. + */ +int ep8_curve_opt_b(void); + +/** + * Tests if the configured elliptic curve is a twist. + * + * @return the type of the elliptic curve twist, 0 if non-twisted curve. + */ +int ep8_curve_is_twist(void); + +/** + * Returns the generator of the group of points in the elliptic curve. + * + * @param[out] g - the returned generator. + */ +void ep8_curve_get_gen(ep8_t g); + +/** + * Returns the precomputation table for the generator. + * + * @return the table. + */ +ep8_t *ep8_curve_get_tab(void); + +/** + * Returns the order of the group of points in the elliptic curve. + * + * @param[out] n - the returned order. + */ +void ep8_curve_get_ord(bn_t n); + +/** + * Returns the cofactor of the group order in the elliptic curve. + * + * @param[out] h - the returned cofactor. + */ +void ep8_curve_get_cof(bn_t h); + +/** + * Configures an elliptic curve over a octic extension by its coefficients. + * + * @param[in] a - the 'a' coefficient of the curve. + * @param[in] b - the 'b' coefficient of the curve. + * @param[in] g - the generator. + * @param[in] r - the order of the group of points. + * @param[in] h - the cofactor of the group order. + */ +void ep8_curve_set(const fp8_t a, const fp8_t b, const ep8_t g, const bn_t r, + const bn_t h); + +/** + * Configures an elliptic curve by twisting the curve over the base prime field. + * + * @param - the type of twist (multiplicative or divisive) + */ +void ep8_curve_set_twist(int type); + +/** + * Tests if a point on an elliptic curve is at the infinity. + * + * @param[in] p - the point to test. + * @return 1 if the point is at infinity, 0 otherise. + */ +int ep8_is_infty(const ep8_t p); + +/** + * Assigns an elliptic curve point to the point at infinity. + * + * @param[out] p - the point to assign. + */ +void ep8_set_infty(ep8_t p); + +/** + * Copies the second argument to the first argument. + * + * @param[out] q - the result. + * @param[in] p - the elliptic curve point to copy. + */ +void ep8_copy(ep8_t r, const ep8_t p); + +/** + * Compares two elliptic curve points. + * + * @param[in] p - the first elliptic curve point. + * @param[in] q - the second elliptic curve point. + * @return RLC_EQ if p == q and RLC_NE if p != q. + */ +int ep8_cmp(const ep8_t p, const ep8_t q); + +/** + * Assigns a random value to an elliptic curve point. + * + * @param[out] p - the elliptic curve point to assign. + */ +void ep8_rand(ep8_t p); + +/** + * Randomizes coordinates of an elliptic curve point. + * + * @param[out] r - the blinded prime elliptic curve point. + * @param[in] p - the prime elliptic curve point to blind. + */ +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. + * + * @param[out] rhs - the result. + * @param[in] p - the point. + */ +void ep8_rhs(fp8_t rhs, const ep8_t p); + +/** + * Tests if a point is in the curve. + * + * @param[in] p - the point to test. + */ +int ep8_on_curve(const ep8_t p); + +/** + * Builds a precomputation table for multiplying a random prime elliptic point. + * + * @param[out] t - the precomputation table. + * @param[in] p - the point to multiply. + * @param[in] w - the window width. + */ +void ep8_tab(ep8_t *t, const ep8_t p, int w); + +/** + * Prints an elliptic curve point. + * + * @param[in] p - the elliptic curve point to print. + */ +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. + * + * @param[in] a - the prime field element. + * @param[in] pack - the flag to indicate compression. + * @return the number of bytes. + */ +int ep8_size_bin(const ep8_t a, int pack); + +/** + * Reads a prime elliptic curve point over a octic extension from a byte + * vector in big-endian format. + * + * @param[out] a - the result. + * @param[in] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @throw ERR_NO_VALID - if the encoded point is invalid. + * @throw ERR_NO_BUFFER - if the buffer capacity is invalid. + */ +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 + * vector in big-endian format with optional point compression. + * + * @param[out] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @param[in] a - the prime elliptic curve point to write. + * @param[in] pack - the flag to indicate compression. + * @throw ERR_NO_BUFFER - if the buffer capacity is invalid. + */ +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. + * + * @param[out] r - the result. + * @param[out] p - the point to negate. + */ +void ep8_neg(ep8_t r, const ep8_t p); + +/** + * Adds to points represented in affine coordinates in an elliptic curve over a + * 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_basic(ep8_t r, const ep8_t p, const ep8_t q); + +/** + * Adds to points represented in affine coordinates in an elliptic curve over a + * octic extension and returns the computed slope. + * + * @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. + */ +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. + * + * @param[out] r - the result. + * @param[in] p - the first point to add. + * @param[in] q - the second point to add. + */ +void ep8_add_projc(ep8_t r, const ep8_t p, const ep8_t q); + + /** + * Subtracts a point in an elliptic curve over a octic extension from + * another. + * + * @param[out] r - the result. + * @param[in] p - the first point. + * @param[in] q - the point to subtract. + */ +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. + * + * @param[out] r - the result. + * @param[int] p - the point to double. + */ +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. + * + * @param[out] r - the result. + * @param[out] s - the slope. + * @param[in] p - the point to double. + */ +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. + * + * @param[out] r - the result. + * @param[in] p - the point to double. + */ +void ep8_dbl_projc(ep8_t r, const ep8_t p); + +/** + * Multiplies a prime elliptic point by an integer using the binary method. + * + * @param[out] r - the result. + * @param[in] p - the point to multiply. + * @param[in] k - the integer. + */ +void ep8_mul_basic(ep8_t r, const ep8_t p, const bn_t k); + +/** + * Multiplies a prime elliptic point by an integer using the sliding window + * method. + * + * @param[out] r - the result. + * @param[in] p - the point to multiply. + * @param[in] k - the integer. + */ +void ep8_mul_slide(ep8_t r, const ep8_t p, const bn_t k); + +/** + * Multiplies a prime elliptic point by an integer using the constant-time + * Montgomery ladder point multiplication method. + * + * @param[out] r - the result. + * @param[in] p - the point to multiply. + * @param[in] k - the integer. + */ +void ep8_mul_monty(ep8_t r, const ep8_t p, const bn_t k); + +/** + * Multiplies a prime elliptic point by an integer using the w-NAF method. + * + * @param[out] r - the result. + * @param[in] p - the point to multiply. + * @param[in] k - the integer. + */ +void ep8_mul_lwnaf(ep8_t r, const ep8_t p, const bn_t k); + +/** + * Multiplies a prime elliptic point by an integer using a regular method. + * + * @param[out] r - the result. + * @param[in] p - the point to multiply. + * @param[in] k - the integer. + */ +void ep8_mul_lwreg(ep8_t r, const ep8_t p, const bn_t k); + +/** + * Multiplies the generator of an elliptic curve over a qaudratic extension. + * + * @param[out] r - the result. + * @param[in] k - the integer. + */ +void ep8_mul_gen(ep8_t r, const bn_t k); + +/** + * Multiplies a prime elliptic point by a small integer. + * + * @param[out] r - the result. + * @param[in] p - the point to multiply. + * @param[in] k - the integer. + */ +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 + * 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. + * + * @param[out] R - the result. + * @param[in] P - the point to multiply. + */ +void ep8_mul_cof(ep8_t r, const ep8_t p); + +/** + * Builds a precomputation table for multiplying a fixed prime elliptic point + * using the binary method. + * + * @param[out] t - the precomputation table. + * @param[in] p - the point to multiply. + */ +void ep8_mul_pre_basic(ep8_t *t, const ep8_t p); + +/** + * Builds a precomputation table for multiplying a fixed prime elliptic point + * using Yao's windowing method. + * + * @param[out] t - the precomputation table. + * @param[in] p - the point to multiply. + */ +void ep8_mul_pre_yaowi(ep8_t *t, const ep8_t p); + +/** + * Builds a precomputation table for multiplying a fixed prime elliptic point + * using the NAF windowing method. + * + * @param[out] t - the precomputation table. + * @param[in] p - the point to multiply. + */ +void ep8_mul_pre_nafwi(ep8_t *t, const ep8_t p); + +/** + * Builds a precomputation table for multiplying a fixed prime elliptic point + * using the single-table comb method. + * + * @param[out] t - the precomputation table. + * @param[in] p - the point to multiply. + */ +void ep8_mul_pre_combs(ep8_t *t, const ep8_t p); + +/** + * Builds a precomputation table for multiplying a fixed prime elliptic point + * using the double-table comb method. + * + * @param[out] t - the precomputation table. + * @param[in] p - the point to multiply. + */ +void ep8_mul_pre_combd(ep8_t *t, const ep8_t p); + +/** + * Builds a precomputation table for multiplying a fixed prime elliptic point + * using the w-(T)NAF method. + * + * @param[out] t - the precomputation table. + * @param[in] p - the point to multiply. + */ +void ep8_mul_pre_lwnaf(ep8_t *t, const ep8_t p); + +/** + * Multiplies a fixed prime elliptic point using a precomputation table and + * the binary method. + * + * @param[out] r - the result. + * @param[in] t - the precomputation table. + * @param[in] k - the integer. + */ +void ep8_mul_fix_basic(ep8_t r, const ep8_t *t, const bn_t k); + +/** + * Multiplies a fixed prime elliptic point using a precomputation table and + * Yao's windowing method + * + * @param[out] r - the result. + * @param[in] t - the precomputation table. + * @param[in] k - the integer. + */ +void ep8_mul_fix_yaowi(ep8_t r, const ep8_t *t, const bn_t k); + +/** + * Multiplies a fixed prime elliptic point using a precomputation table and + * the w-(T)NAF method. + * + * @param[out] r - the result. + * @param[in] t - the precomputation table. + * @param[in] k - the integer. + */ +void ep8_mul_fix_nafwi(ep8_t r, const ep8_t *t, const bn_t k); + +/** + * Multiplies a fixed prime elliptic point using a precomputation table and + * the single-table comb method. + * + * @param[out] r - the result. + * @param[in] t - the precomputation table. + * @param[in] k - the integer. + */ +void ep8_mul_fix_combs(ep8_t r, const ep8_t *t, const bn_t k); + +/** + * Multiplies a fixed prime elliptic point using a precomputation table and + * the double-table comb method. + * + * @param[out] r - the result. + * @param[in] t - the precomputation table. + * @param[in] k - the integer. + */ +void ep8_mul_fix_combd(ep8_t r, const ep8_t *t, const bn_t k); + +/** + * Multiplies a fixed prime elliptic point using a precomputation table and + * the w-(T)NAF method. + * + * @param[out] r - the result. + * @param[in] t - the precomputation table. + * @param[in] k - the integer. + */ +void ep8_mul_fix_lwnaf(ep8_t r, const ep8_t *t, const bn_t k); + +/** + * Multiplies and adds two prime elliptic curve points simultaneously using + * scalar multiplication and point addition. + * + * @param[out] r - the result. + * @param[in] p - the first point to multiply. + * @param[in] k - the first integer. + * @param[in] q - the second point to multiply. + * @param[in] m - the second integer, + */ +void ep8_mul_sim_basic(ep8_t r, const ep8_t p, const bn_t k, const ep8_t q, const bn_t m); + +/** + * Multiplies and adds two prime elliptic curve points simultaneously using + * shamir's trick. + * + * @param[out] r - the result. + * @param[in] p - the first point to multiply. + * @param[in] k - the first integer. + * @param[in] q - the second point to multiply. + * @param[in] m - the second integer, + */ +void ep8_mul_sim_trick(ep8_t r, const ep8_t p, const bn_t k, const ep8_t q, const bn_t m); + +/** + * Multiplies and adds two prime elliptic curve points simultaneously using + * interleaving of NAFs. + * + * @param[out] r - the result. + * @param[in] p - the first point to multiply. + * @param[in] k - the first integer. + * @param[in] q - the second point to multiply. + * @param[in] m - the second integer, + */ +void ep8_mul_sim_inter(ep8_t r, const ep8_t p, const bn_t k, const ep8_t q, const bn_t m); + +/** + * Multiplies and adds two prime elliptic curve points simultaneously using + * Solinas' Joint Sparse Form. + * + * @param[out] r - the result. + * @param[in] p - the first point to multiply. + * @param[in] k - the first integer. + * @param[in] q - the second point to multiply. + * @param[in] m - the second integer, + */ +void ep8_mul_sim_joint(ep8_t r, const ep8_t p, const bn_t k, const ep8_t q, const bn_t m); + +/** + * Multiplies simultaneously elements from a prime elliptic curve. + * Computes R = \Sum_i=0..n k_iP_i. + * + * @param[out] r - the result. + * @param[in] p - the points to multiply. + * @param[in] k - the integer scalars. + * @param[in] n - the number of elements to multiply. + */ +void ep8_mul_sim_lot(ep8_t r, const ep8_t p[], const bn_t k[], size_t n); + +/** + * Multiplies and adds the generator and a prime elliptic curve point + * simultaneously. Computes R = [k]G + [l]Q. + * + * @param[out] r - the result. + * @param[in] k - the first integer. + * @param[in] q - the second point to multiply. + * @param[in] m - the second integer, + */ +void ep8_mul_sim_gen(ep8_t r, const bn_t k, const ep8_t q, const bn_t m); + +/** + * Multiplies prime elliptic curve points by small scalars. + * Computes R = \sum k_iP_i. + * + * @param[out] r - the result. + * @param[in] p - the points to multiply. + * @param[in] k - the small scalars. + * @param[in] len - the number of points to multiply. + */ +void ep8_mul_sim_dig(ep8_t r, const ep8_t p[], const dig_t k[], size_t len); + +/** + * Converts a point to affine coordinates. + * + * @param[out] r - the result. + * @param[in] p - the point to convert. + */ +void ep8_norm(ep8_t r, const ep8_t p); + +/** + * Converts multiple points to affine coordinates. + * + * @param[out] r - the result. + * @param[in] t - the points to convert. + * @param[in] n - the number of points. + */ +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. + * + * @param[out] p - the result. + * @param[in] msg - the byte array to map. + * @param[in] len - the array length in bytes. + */ +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 + * Frobenius map of a point represented in affine coordinates in an elliptic + * curve over a 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. + * @param[in] i - the power of the Frobenius map. + */ +void ep8_frb(ep8_t r, const ep8_t p, int i); + +/** + * Compresses a point in an elliptic curve over a octic extension. + * + * @param[out] r - the result. + * @param[in] p - the point to compress. + */ +void ep8_pck(ep8_t r, const ep8_t p); + +/** + * Decompresses a point in an elliptic curve over a octic extension. + * + * @param[out] r - the result. + * @param[in] p - the point to decompress. + * @return if the decompression was successful + */ +int ep8_upk(ep8_t r, const ep8_t p); + #endif /* !RLC_EPX_H */ diff --git a/include/relic_fp.h b/include/relic_fp.h index 83bda0ea9..e5bf72632 100644 --- a/include/relic_fp.h +++ b/include/relic_fp.h @@ -64,8 +64,10 @@ * Finite field identifiers. */ enum { + /** Mersenne prime with 127 bits. */ + MP_127 = 1, /** SECG 160-bit fast reduction prime. */ - SECG_160 = 1, + SECG_160, /** SECG 160-bit denser reduction prime. */ SECG_160D, /** NIST 192-bit fast reduction prime. */ @@ -102,6 +104,8 @@ enum { NIST_384, /** Curve448 prime. */ PRIME_448, + /** 511-bit prime for CTIDH. */ + CTIDH_511, /** Curve511187 511-bit prime modulus. */ PRIME_511187, /** NIST 521-bit fast reduction polynomial. */ @@ -118,6 +122,8 @@ enum { B24_315, /** 317-bit prime for BLS curve of embedding degree 24 (SNARKs). */ B24_317, + /** 330-bit prime for KSS curve with embedding degree 16. */ + K16_330, /** 381-bit prime for BLS curve of embedding degree 12 (SNARKs). */ B12_377, /** 381-bit prime for BLS curve of embedding degree 12 (Zcash). */ @@ -135,9 +141,7 @@ enum { /** 477-bit prime for BLS curve of embedding degree 24. */ B24_509, /** 508-bit prime for KSS16 curve. */ - KSS_508, - /** 511-bit prime for Optimal TNFS-secure curve. */ - OT_511, + K18_508, /** Random 544-bit prime for Cocks-Pinch curve with embedding degree 8. */ GMT8_544, /** 569-bit prime for SG curve with embedding degree 54. */ @@ -152,10 +156,20 @@ 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, + /** 766-bit prime for KSS curve with embedding degree 16. */ + K16_766, + /** 1024-bit prime for CTIDH. */ + CTIDH_1024, /** 1536-bit prime for supersingular curve with embedding degree k = 2. */ SS_1536, + /** 2048-bit prime for CTDIH. */ + CTIDH_2048, /** 3072-bit prime for supersingular curve with embedding degree k = 1. */ - SS_3072, + K1_3072, + /** 4096-bit prime for SQALE. */ + SQALE_4096, }; /** @@ -386,8 +400,6 @@ typedef rlc_align dig_t fp_st[RLC_FP_DIGS + RLC_PAD(RLC_FP_BYTES)/(RLC_DIG / 8)] */ #if FP_SMB == BASIC #define fp_smb(A) fp_smb_basic(A) -#elif FP_SMB == BINAR -#define fp_smb(A) fp_smb_binar(A) #elif FP_SMB == DIVST #define fp_smb(A) fp_smb_divst(A) #elif FP_SMB == JMPDS @@ -447,6 +459,22 @@ const dig_t *fp_prime_get_rdc(void); */ const dig_t *fp_prime_get_conv(void); +/** + * Returns a 2^f-root of unity modulo the prime field modulus, for the maximum f + * such that 2^f divides (p-1). + * + * @return the root of unity. + */ +const dig_t *fp_prime_get_srt(void); + +/** + * Returns a 3^f-root of unity modulo the prime field modulus, for the maximum f + * such that 3^f divides (p-1). + * + * @return the root of unity. + */ +const dig_t *fp_prime_get_crt(void); + /** * Returns the result of prime order mod 8. * @@ -1112,14 +1140,6 @@ void fp_inv_sim(fp_t *c, const fp_t *a, int n); */ int fp_smb_basic(const fp_t a); -/** - * Computes Legendre symbol of a prime field element using the binary method. - * - * @param[in] a - the prime field element to compute. - * @return the result. - */ -int fp_smb_binar(const fp_t a); - /** * Computes Legendre symbol of a prime field element using the constant-time * division step approach by Bernstein and Bo-Yin Yang. @@ -1176,6 +1196,23 @@ void fp_exp_slide(fp_t c, const fp_t a, const bn_t b); */ void fp_exp_monty(fp_t c, const fp_t a, const bn_t b); +/** + * Computes a power of a field element by a small exponent. + * + * @param[out] c - the result. + * @param[in] a - the basis. + * @param[in] b - the exponent. + */ +void fp_exp_dig(fp_t c, const fp_t a, dig_t b); + +/** + * Tests if a prime field element is a quadratic residue. + * + * @param[in] a - the prime field element to test. + * @return 1 if the argument is even, 0 otherwise. + */ +int fp_is_sqr(const fp_t a); + /** * Extracts the square root of a prime field element. Computes c = sqrt(a). The * other square root is the negation of c. @@ -1186,4 +1223,22 @@ void fp_exp_monty(fp_t c, const fp_t a, const bn_t b); */ int fp_srt(fp_t c, const fp_t a); +/** + * Tests if a prime field element is a cubic residue. + * + * @param[in] a - the prime field element to test. + * @return 1 if the argument is even, 0 otherwise. + */ +int fp_is_cub(const fp_t a); + +/** + * Extracts the cube root of a prime field element. Computes c = crt(a). The + * other cube root is the square of c. + * + * @param[out] c - the result. + * @param[in] a - the prime field element. + * @return - 1 if there is a cube root, 0 otherwise. + */ +int fp_crt(fp_t c, const fp_t a); + #endif /* !RLC_FP_H */ diff --git a/include/relic_fpx.h b/include/relic_fpx.h index cfb6dfcd5..f410903f2 100644 --- a/include/relic_fpx.h +++ b/include/relic_fpx.h @@ -169,11 +169,30 @@ typedef fp6_t fp12_t[2]; */ typedef dv6_t dv12_t[2]; +/** + * Represents an octic extension prime field element. + * + * This extension is constructed with the basis {1, w}, where v^2 = v is an + * adjoined root in the underlying octic extension. + */ +typedef fp8_t fp16_t[2]; + +/** + * Represents a double-precision octic extension field element. + */ +typedef dv8_t dv16_t[2]; + +/** + * Represents an octic extension field element with automatic memory + * allocation. + */ +typedef fp8_st fp16_st[2]; + /** * Represents an octdecic extension field element. * * This extension is constructed with the basis {1, w}, where w^2 = v is an - * adjoined root in the underlying sextic extension. + * adjoined root in the underlying nonic extension. */ typedef fp9_t fp18_t[2]; @@ -185,8 +204,8 @@ typedef dv9_t dv18_t[2]; /** * Represents a 24-degree extension field element. * - * This extension is constructed with the basis {1, t, t^2}, where t^3 = w is an - * adjoined root in the underlying dodecic extension. + * This extension is constructed with the basis {1, t, t^2}, where t^3 = v is an + * adjoined root in the underlying octic extension. */ typedef fp8_t fp24_t[3]; @@ -199,7 +218,7 @@ typedef dv8_t dv24_t[3]; * Represents a 48-degree extension field element. * * This extension is constructed with the basis {1, u}, where u^2 = t is an - * adjoined root in the underlying dodecic extension. + * adjoined root in the underlying extension of degree 24. */ typedef fp24_t fp48_t[2]; @@ -207,7 +226,7 @@ typedef fp24_t fp48_t[2]; * Represents a 54-degree extension field element. * * This extension is constructed with the basis {1, u, u^2}, where u^3 = t is an - * adjoined root in the underlying dodecic extension. + * adjoined root in the underlying octdecic extension. */ typedef fp18_t fp54_t[3]; @@ -291,7 +310,7 @@ typedef fp18_t fp54_t[3]; #define fp2_sub(C, A, B) fp2_sub_integ(C, A, B) #endif -/** +/**ffp8 * Doubles a quadratic extension field element. Computes C = A + A. * * @param[out] C - the result. @@ -860,6 +879,93 @@ typedef fp18_t fp54_t[3]; #define fp12_sqr_pck(C, A) fp12_sqr_pck_lazyr(C, A) #endif +/** + * Initializes a double-precision sextadecic extension field with null. + * + * @param[out] A - the sextadecic extension element to initialize. + */ +#define dv16_null(A) \ + dv8_null(A[0]); dv8_null(A[1]); \ + +/** + * Allocates a double-precision sextadecic extension field element. + * + * @param[out] A - the new sextadecic extension field element. + */ +#define dv16_new(A) \ + dv8_new(A[0]); dv8_new(A[1]); \ + +/** + * Frees a double-precision sextadecic extension field element. + * + * @param[out] A - the sextadecic extension field element to free. + */ +#define dv16_free(A) \ + dv8_free(A[0]); dv8_free(A[1]); \ + +/** + * Initializes an sextadecic extension field with null. + * + * @param[out] A - the sextadecic extension element to initialize. + */ +#define fp16_null(A) \ + fp8_null(A[0]); fp8_null(A[1]); \ + +/** + * Allocates an sextadecic extension field element. + * + * @param[out] A - the new sextadecic extension field element. + */ +#define fp16_new(A) \ + fp8_new(A[0]); fp8_new(A[1]); \ + +/** + * Frees an sextadecic extension field element. + * + * @param[out] A - the sextadecic extension field element to free. + */ +#define fp16_free(A) \ + fp8_free(A[0]); fp8_free(A[1]); \ + +/** + * Multiplies two sextadecic extension field elements. Computes C = A * B. + * + * @param[out] C - the result. + * @param[in] A - the first sextadecic extension field element. + * @param[in] B - the second sextadecic extension field element. + */ +#if FPX_RDC == BASIC +#define fp16_mul(C, A, B) fp16_mul_basic(C, A, B) +#elif FPX_RDC == LAZYR +#define fp16_mul(C, A, B) fp16_mul_lazyr(C, A, B) +#endif + +/** + * Multiplies a dense and a sparse sextic extension field elements. Computes + * C = A * B. + * + * @param[out] C - the result. + * @param[in] A - the dense dodecic extension field element. + * @param[in] B - the sparse dodecic extension field element. + */ +#if FPX_RDC == BASIC +#define fp16_mul_dxs(C, A, B) fp16_mul_dxs_basic(C, A, B) +#elif FPX_RDC == LAZYR +#define fp16_mul_dxs(C, A, B) fp16_mul_dxs_lazyr(C, A, B) +#endif + +/** + * Squares an sextadecic extension field element. Computes C = A * A. + * + * @param[out] C - the result. + * @param[in] A - the sextadecic extension field element to square. + */ +#if FPX_RDC == BASIC +#define fp16_sqr(C, A) fp16_sqr_basic(C, A) +#elif FPX_RDC == LAZYR +#define fp16_sqr(C, A) fp16_sqr_lazyr(C, A) +#endif + /** * Initializes a double-precision sextic extension field with null. * @@ -1641,6 +1747,14 @@ void fp2_exp_cyc_sim(fp2_t e, const fp2_t a, const bn_t b, const fp2_t c, */ void fp2_frb(fp2_t c, const fp2_t a, int i); +/** + * Tests if a quadratic extension field element is a quadratic residue. + * + * @param[in] a - the prime field element to test. + * @return 1 if the argument is even, 0 otherwise. + */ +int fp2_is_sqr(const fp2_t a); + /** * Extracts the square root of a quadratic extension field element. Computes * c = sqrt(a). The other square root is the negation of c. @@ -1966,6 +2080,14 @@ void fp3_exp(fp3_t c, const fp3_t a, const bn_t b); */ void fp3_frb(fp3_t c, const fp3_t a, int i); +/** + * Tests if a cubic extension field element is a quadratic residue. + * + * @param[in] a - the prime field element to test. + * @return 1 if the argument is even, 0 otherwise. + */ +int fp3_is_sqr(const fp3_t a); + /** * Extracts the square root of a cubic extension field element. Computes * c = sqrt(a). The other square root is the negation of c. @@ -2269,6 +2391,14 @@ void fp4_exp(fp4_t c, const fp4_t a, const bn_t b); */ void fp4_frb(fp4_t c, const fp4_t a, int i); +/** + * Tests if a quartic extension field element is a quadratic residue. + * + * @param[in] a - the prime field element to test. + * @return 1 if the argument is even, 0 otherwise. + */ +int fp4_is_sqr(const fp4_t a); + /** * Extracts the square root of a quartic extension field element. Computes * c = sqrt(a). The other square root is the negation of c. @@ -2508,6 +2638,11 @@ void fp6_exp(fp6_t c, const fp6_t a, const bn_t b); */ void fp6_frb(fp6_t c, const fp6_t a, int i); +/** + * Initializes the octic extension field arithmetic module. + */ +void fp8_field_init(void); + /** * Copies the second argument to the first argument. * @@ -2676,6 +2811,17 @@ void fp8_mul_lazyr(fp8_t c, const fp8_t a, const fp8_t b); */ void fp8_mul_art(fp8_t c, const fp8_t a); +/** + * Multiplies an octic extension field element by a power of the constant + * needed to compute a power of the Frobenius map. + * + * @param[out] c - the result. + * @param[in] a - the field element to multiply. + * @param[in] i - the power of the Frobenius map. + * @param[in] j - the power of the constant. + */ +void fp8_mul_frb(fp8_t c, const fp8_t a, int i, int j); + /** * Multiples a dense octic extension field element by a sparse element. * @@ -2773,6 +2919,15 @@ void fp8_conv_cyc(fp8_t c, const fp8_t a); */ void fp8_exp(fp8_t c, const fp8_t a, const bn_t b); +/** + * Computes a power of an octic extension field element by a small exponent. + * + * @param[out] c - the result. + * @param[in] a - the basis. + * @param[in] b - the exponent. + */ +void fp8_exp_dig(fp8_t c, const fp8_t a, dig_t b); + /** * Computes a power of a cyclotomic octic extension field element. * @@ -2792,6 +2947,24 @@ void fp8_exp_cyc(fp8_t c, const fp8_t a, const bn_t b); */ void fp8_frb(fp8_t c, const fp8_t a, int i); +/** + * Tests if an octic extension field element is a quadratic residue. + * + * @param[in] a - the prime field element to test. + * @return 1 if the argument is even, 0 otherwise. + */ +int fp8_is_sqr(const fp8_t a); + +/** + * Extracts the square root of an octic extension field element. Computes + * c = sqrt(a). The other square root is the negation of c. + * + * @param[out] c - the result. + * @param[in] a - the extension field element. + * @return - 1 if there is a square root, 0 otherwise. + */ +int fp8_srt(fp8_t c, const fp8_t a); + /** * Copies the second argument to the first argument. * @@ -3432,6 +3605,337 @@ void fp12_pck_max(fp12_t c, const fp12_t a); */ int fp12_upk_max(fp12_t c, const fp12_t a); + +/** + * Initializes the sextadecic extension field arithmetic module. + */ +void fp16_field_init(void); + +/** + * Copies the second argument to the first argument. + * + * @param[out] c - the result. + * @param[in] a - the sextadecic extension field element to copy. + */ +void fp16_copy(fp16_t c, const fp16_t a); + +/** + * Assigns zero to an sextadecic extension field element. + * + * @param[out] a - the sextadecic extension field element to zero. + */ +void fp16_zero(fp16_t a); + +/** + * Tests if an sextadecic extension field element is zero or not. + * + * @param[in] a - the sextadecic extension field element to test. + * @return 1 if the argument is zero, 0 otherwise. + */ +int fp16_is_zero(const fp16_t a); + +/** + * Assigns a random value to an sextadecic extension field element. + * + * @param[out] a - the sextadecic extension field element to assign. + */ +void fp16_rand(fp16_t a); + +/** + * Prints an sextadecic extension field element to standard output. + * + * @param[in] a - the sextadecic extension field element to print. + */ +void fp16_print(const fp16_t a); + +/** + * Returns the number of bytes necessary to store an sextadecic extension field + * element. + * + * @param[in] a - the extension field element. + * @param[in] pack - the flag to indicate compression. + * @return the number of bytes. + */ +int fp16_size_bin(fp16_t a, int pack); + +/** + * Reads an sextadecic extension field element from a byte vector in big-endian + * format. + * + * @param[out] a - the result. + * @param[in] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp16_read_bin(fp16_t a, const uint8_t *bin, size_t len); + +/** + * Writes an sextadecic extension field element to a byte vector in big-endian + * format. + * + * @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 fp16_write_bin(uint8_t *bin, size_t len, const fp16_t a, int pack); + +/** + * Returns the result of a comparison between two sextadecic extension field + * elements. + * + * @param[in] a - the first sextadecic extension field element. + * @param[in] b - the second sextadecic extension field element. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp16_cmp(const fp16_t a, const fp16_t b); + +/** + * Returns the result of a signed comparison between an sextadecic extension + * field element and a digit. + * + * @param[in] a - the sextadecic extension field element. + * @param[in] b - the digit. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp16_cmp_dig(const fp16_t a, const dig_t b); + +/** + * Assigns an sextadecic extension field element to a digit. + * + * @param[in] a - the sextadecic extension field element. + * @param[in] b - the digit. + */ +void fp16_set_dig(fp16_t a, const dig_t b); + +/** + * Adds two sextadecic extension field elements. Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first sextadecic extension field element. + * @param[in] b - the second sextadecic extension field element. + */ +void fp16_add(fp16_t c, const fp16_t a, const fp16_t b); + +/** + * Subtracts an sextadecic extension field element from another. Computes + * c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the sextadecic extension field element. + * @param[in] b - the sextadecic extension field element. + */ +void fp16_sub(fp16_t c, const fp16_t a, const fp16_t b); + +/** + * Negates an sextadecic extension field element. Computes c = -a. + * + * @param[out] c - the result. + * @param[out] a - the sextadecic extension field element to negate. + */ +void fp16_neg(fp16_t c, const fp16_t a); + +/** + * Doubles an sextadecic extension field element. Computes c = 2 * a. + * + * @param[out] c - the result. + * @param[in] a - the sextadecic extension field element to double. + */ +void fp16_dbl(fp16_t c, const fp16_t a); + +/** + * Multiples two sextadecic extension field elements without performing modular + * reduction. + * + * @param[out] c - the result. + * @param[in] a - the sextadecic extension field element. + * @param[in] b - the sextadecic extension field element. + */ +void fp16_mul_unr(dv16_t c, const fp16_t a, const fp16_t b); + +/** + * Multiples two sextadecic extension field elements. + * + * @param[out] c - the result. + * @param[in] a - the sextadecic extension field element. + * @param[in] b - the sextadecic extension field element. + */ +void fp16_mul_basic(fp16_t c, const fp16_t a, const fp16_t b); + +/** + * Multiples two sextadecic extension field elements using lazy reduction. + * + * @param[out] c - the result. + * @param[in] a - the sextadecic extension field element. + * @param[in] b - the sextadecic extension field element. + */ +void fp16_mul_lazyr(fp16_t c, const fp16_t a, const fp16_t b); + +/** + * Multiplies an sextadecic extension field element by the adjoined root. + * + * @param[out] c - the result. + * @param[in] a - the sextadecic extension field element to multiply. + */ +void fp16_mul_art(fp16_t c, const fp16_t a); + +/** + * Multiplies an sextadecic extension field element by a power of the constant + * needed to compute a power of the Frobenius map. + * + * @param[out] c - the result. + * @param[in] a - the field element to multiply. + * @param[in] i - the power of the Frobenius map. + * @param[in] j - the power of the constant. + */ +void fp16_mul_frb(fp16_t c, const fp16_t a, int i, int j); + +/** + * Multiples a dense sextadecic extension field element by a sparse element. + * + * @param[out] c - the result. + * @param[in] a - an sextadecic extension field element. + * @param[in] b - a sparse sextadecic extension field element. + */ +void fp16_mul_dxs(fp16_t c, const fp16_t a, const fp16_t b); + +/** + * Computes the square of an sextadecic extension field element without + * performing modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the sextadecic extension field element to square. + */ +void fp16_sqr_unr(dv16_t c, const fp16_t a); + +/** + * Computes the squares of an sextadecic extension field element using basic + * arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the sextadecic extension field element to square. + */ +void fp16_sqr_basic(fp16_t c, const fp16_t a); + +/** + * Computes the square of an sextadecic extension field element using lazy + * reduction. + * + * @param[out] c - the result. + * @param[in] a - the sextadecic extension field element to square. + */ +void fp16_sqr_lazyr(fp16_t c, const fp16_t a); + +/** + * Computes the square of a cyclotomic sextadecic extension field element. + * + * @param[out] c - the result. + * @param[in] a - the cyclotomic extension element to square. + */ +void fp16_sqr_cyc(fp16_t c, const fp16_t a); + +/** + * Inverts an sextadecic extension field element. Computes c = 1/a. + * + * @param[out] c - the result. + * @param[in] a - the sextadecic extension field element to invert. + */ +void fp16_inv(fp16_t c, const fp16_t a); + +/** + * Computes the inverse of a cyclotomic sextadecic extension field element. + * + * For cyclotomic elements, this is equivalent to computing the conjugate. + * A cyclotomic element is one previously raised to the (p^4 - 1)-th power. + * + * @param[out] c - the result. + * @param[in] a - the sextadecic extension field element to invert. + */ +void fp16_inv_cyc(fp16_t c, const fp16_t a); + +/** + * Inverts multiple sextadecic extension field elements simultaneously. + * + * @param[out] c - the result. + * @param[in] a - the sextadecic extension field elements to invert. + * @param[in] n - the number of elements. + */ +void fp16_inv_sim(fp16_t *c, const fp16_t *a, int n); + +/** + * Tests if an sextadecic extension field element is cyclotomic. + * + * @param[in] a - the sextadecic extension field element to test. + * @return 1 if the extension field element is cyclotomic, 0 otherwise. + */ +int fp16_test_cyc(const fp16_t a); + +/** + * Converts an sextadecic extension field element to a cyclotomic element. + * Computes c = a^(p^8 - 1). + * + * @param[out] c - the result. + * @param[in] a - the sextadecic extension field element. + */ +void fp16_conv_cyc(fp16_t c, const fp16_t a); + +/** + * Computes a power of an sextadecic extension field element. Computes c = a^b. + * + * @param[out] c - the result. + * @param[in] a - the sextadecic extension element to exponentiate. + * @param[in] b - the exponent. + */ +void fp16_exp(fp16_t c, const fp16_t a, const bn_t b); + +/** + * Computes a power of a sextic extension field element by a small exponent. + * Faster formulas are used if the extension field element is cyclotomic. + * + * @param[out] c - the result. + * @param[in] a - the basis. + * @param[in] b - the exponent. + */ +void fp16_exp_dig(fp16_t c, const fp16_t a, dig_t b); + +/** + * Computes a power of a cyclotomic sextadecic extension field element. + * + * @param[out] c - the result. + * @param[in] a - the basis. + * @param[in] b - the exponent. + */ +void fp16_exp_cyc(fp16_t c, const fp16_t a, const bn_t b); + +/** + * Computes a power of the Frobenius endomorphism of an sextadecic extension + * field element. Computes c = a^p^i. + * + * @param[out] c - the result. + * @param[in] a - an sextadecic extension field element. + * @param[in] i - the power of the Frobenius map. + */ +void fp16_frb(fp16_t c, const fp16_t a, int i); + +/** + * Tests if an sextadecic extension field element is a quadratic residue. + * + * @param[in] a - the prime field element to test. + * @return 1 if the argument is even, 0 otherwise. + */ +int fp16_is_sqr(const fp16_t a); + +/** + * Extracts the square root of an sextadecic extension field element. Computes + * c = sqrt(a). The other square root is the negation of c. + * + * @param[out] c - the result. + * @param[in] a - the extension field element. + * @return - 1 if there is a square root, 0 otherwise. + */ +int fp16_srt(fp16_t c, const fp16_t a); + /** * Copies the second argument to the first argument. * @@ -3759,7 +4263,7 @@ void fp18_frb(fp18_t c, const fp18_t a, int i); void fp18_exp(fp18_t c, const fp18_t a, const bn_t b); /** - * Computes a power of a dodecic extension field element by a small exponent. + * Computes a power of a octdecic extension field element by a small exponent. * Faster formulas are used if the extension field element is cyclotomic. * * @param[out] c - the result. diff --git a/include/relic_label.h b/include/relic_label.h index f3850f24a..6abb25b5e 100644 --- a/include/relic_label.h +++ b/include/relic_label.h @@ -462,6 +462,8 @@ #undef fp_prime_get #undef fp_prime_get_rdc #undef fp_prime_get_conv +#undef fp_prime_get_srt +#undef fp_prime_get_crt #undef fp_prime_get_mod8 #undef fp_prime_get_mod18 #undef fp_prime_get_sps @@ -495,6 +497,7 @@ #undef fp_set_dig #undef fp_bits #undef fp_rand +#undef fp_norm #undef fp_print #undef fp_size_str #undef fp_read_str @@ -539,20 +542,24 @@ #undef fp_inv_lower #undef fp_inv_sim #undef fp_smb_basic -#undef fp_smb_binar #undef fp_smb_divst #undef fp_smb_jmpds #undef fp_smb_lower #undef fp_exp_basic #undef fp_exp_slide #undef fp_exp_monty +#undef fp_is_sqr #undef fp_srt +#undef fp_is_cub +#undef fp_crt #define fp_prime_init RLC_PREFIX(fp_prime_init) #define fp_prime_clean RLC_PREFIX(fp_prime_clean) #define fp_prime_get RLC_PREFIX(fp_prime_get) #define fp_prime_get_rdc RLC_PREFIX(fp_prime_get_rdc) #define fp_prime_get_conv RLC_PREFIX(fp_prime_get_conv) +#define fp_prime_get_srt RLC_PREFIX(fp_prime_get_srt) +#define fp_prime_get_crt RLC_PREFIX(fp_prime_get_crt) #define fp_prime_get_mod8 RLC_PREFIX(fp_prime_get_mod8) #define fp_prime_get_mod18 RLC_PREFIX(fp_prime_get_mod18) #define fp_prime_get_sps RLC_PREFIX(fp_prime_get_sps) @@ -586,6 +593,7 @@ #define fp_set_dig RLC_PREFIX(fp_set_dig) #define fp_bits RLC_PREFIX(fp_bits) #define fp_rand RLC_PREFIX(fp_rand) +#define fp_norm RLC_PREFIX(fp_norm) #define fp_print RLC_PREFIX(fp_print) #define fp_size_str RLC_PREFIX(fp_size_str) #define fp_read_str RLC_PREFIX(fp_read_str) @@ -630,14 +638,16 @@ #define fp_inv_lower RLC_PREFIX(fp_inv_lower) #define fp_inv_sim RLC_PREFIX(fp_inv_sim) #define fp_smb_basic RLC_PREFIX(fp_smb_basic) -#define fp_smb_binar RLC_PREFIX(fp_smb_binar) #define fp_smb_divst RLC_PREFIX(fp_smb_divst) #define fp_smb_jmpds RLC_PREFIX(fp_smb_jmpds) #define fp_smb_lower RLC_PREFIX(fp_smb_lower) #define fp_exp_basic RLC_PREFIX(fp_exp_basic) #define fp_exp_slide RLC_PREFIX(fp_exp_slide) #define fp_exp_monty RLC_PREFIX(fp_exp_monty) +#define fp_is_sqr RLC_PREFIX(fp_is_sqr) #define fp_srt RLC_PREFIX(fp_srt) +#define fp_is_cub RLC_PREFIX(fp_is_cub) +#define fp_crt RLC_PREFIX(fp_crt) #undef fp_add1_low #undef fp_addn_low @@ -964,6 +974,7 @@ #undef ep_mul_lwreg #undef ep_mul_gen #undef ep_mul_dig +#undef ep_mul_cof #undef ep_mul_pre_basic #undef ep_mul_pre_yaowi #undef ep_mul_pre_nafwi @@ -985,9 +996,9 @@ #undef ep_mul_sim_dig #undef ep_norm #undef ep_norm_sim -#undef ep_map_from_field -#undef ep_map -#undef ep_map_dst +#undef ep_map_basic +#undef ep_map_sswum +#undef ep_map_swift #undef ep_pck #undef ep_upk @@ -1058,6 +1069,7 @@ #define ep_mul_lwreg RLC_PREFIX(ep_mul_lwreg) #define ep_mul_gen RLC_PREFIX(ep_mul_gen) #define ep_mul_dig RLC_PREFIX(ep_mul_dig) +#define ep_mul_cof RLC_PREFIX(ep_mul_cof) #define ep_mul_pre_basic RLC_PREFIX(ep_mul_pre_basic) #define ep_mul_pre_yaowi RLC_PREFIX(ep_mul_pre_yaowi) #define ep_mul_pre_nafwi RLC_PREFIX(ep_mul_pre_nafwi) @@ -1079,9 +1091,9 @@ #define ep_mul_sim_dig RLC_PREFIX(ep_mul_sim_dig) #define ep_norm RLC_PREFIX(ep_norm) #define ep_norm_sim RLC_PREFIX(ep_norm_sim) -#define ep_map_from_field RLC_PREFIX(ep_map_from_field) -#define ep_map RLC_PREFIX(ep_map) -#define ep_map_dst RLC_PREFIX(ep_map_dst) +#define ep_map_basic RLC_PREFIX(ep_map_basic) +#define ep_map_sswum RLC_PREFIX(ep_map_sswum) +#define ep_map_swift RLC_PREFIX(ep_map_swift) #define ep_pck RLC_PREFIX(ep_pck) #define ep_upk RLC_PREFIX(ep_upk) @@ -1386,7 +1398,6 @@ #undef ep2_curve_clean #undef ep2_curve_get_a #undef ep2_curve_get_b -#undef ep2_curve_get_vs #undef ep2_curve_opt_a #undef ep2_curve_opt_b #undef ep2_curve_is_twist @@ -1448,9 +1459,9 @@ #undef ep2_mul_sim_dig #undef ep2_norm #undef ep2_norm_sim -#undef ep2_map_from_field -#undef ep2_map -#undef ep2_map_dst +#undef ep2_map_basic +#undef ep2_map_sswum +#undef ep2_map_swift #undef ep2_frb #undef ep2_pck #undef ep2_upk @@ -1459,7 +1470,6 @@ #define ep2_curve_clean RLC_PREFIX(ep2_curve_clean) #define ep2_curve_get_a RLC_PREFIX(ep2_curve_get_a) #define ep2_curve_get_b RLC_PREFIX(ep2_curve_get_b) -#define ep2_curve_get_vs RLC_PREFIX(ep2_curve_get_vs) #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_is_twist RLC_PREFIX(ep2_curve_is_twist) @@ -1521,9 +1531,9 @@ #define ep2_mul_sim_dig RLC_PREFIX(ep2_mul_sim_dig) #define ep2_norm RLC_PREFIX(ep2_norm) #define ep2_norm_sim RLC_PREFIX(ep2_norm_sim) -#define ep2_map_from_field RLC_PREFIX(ep2_map_from_field) -#define ep2_map RLC_PREFIX(ep2_map) -#define ep2_map_dst RLC_PREFIX(ep2_map_dst) +#define ep2_map_basic RLC_PREFIX(ep2_map_basic) +#define ep2_map_sswum RLC_PREFIX(ep2_map_sswum) +#define ep2_map_swift RLC_PREFIX(ep2_map_swift) #define ep2_frb RLC_PREFIX(ep2_frb) #define ep2_pck RLC_PREFIX(ep2_pck) #define ep2_upk RLC_PREFIX(ep2_upk) @@ -1537,7 +1547,6 @@ #undef ep3_curve_clean #undef ep3_curve_get_a #undef ep3_curve_get_b -#undef ep3_curve_get_vs #undef ep3_curve_opt_a #undef ep3_curve_opt_b #undef ep3_curve_is_twist @@ -1598,7 +1607,6 @@ #undef ep3_norm #undef ep3_norm_sim #undef ep3_map -#undef ep3_map_dst #undef ep3_frb #undef ep3_pck #undef ep3_upk @@ -1607,7 +1615,6 @@ #define ep3_curve_clean RLC_PREFIX(ep3_curve_clean) #define ep3_curve_get_a RLC_PREFIX(ep3_curve_get_a) #define ep3_curve_get_b RLC_PREFIX(ep3_curve_get_b) -#define ep3_curve_get_vs RLC_PREFIX(ep3_curve_get_vs) #define ep3_curve_opt_a RLC_PREFIX(ep3_curve_opt_a) #define ep3_curve_opt_b RLC_PREFIX(ep3_curve_opt_b) #define ep3_curve_is_twist RLC_PREFIX(ep3_curve_is_twist) @@ -1668,7 +1675,6 @@ #define ep3_norm RLC_PREFIX(ep3_norm) #define ep3_norm_sim RLC_PREFIX(ep3_norm_sim) #define ep3_map RLC_PREFIX(ep3_map) -#define ep3_map_dst RLC_PREFIX(ep3_map_dst) #define ep3_frb RLC_PREFIX(ep3_frb) #define ep3_pck RLC_PREFIX(ep3_pck) #define ep3_upk RLC_PREFIX(ep3_upk) @@ -1682,7 +1688,6 @@ #undef ep4_curve_clean #undef ep4_curve_get_a #undef ep4_curve_get_b -#undef ep4_curve_get_vs #undef ep4_curve_opt_a #undef ep4_curve_opt_b #undef ep4_curve_is_twist @@ -1743,7 +1748,6 @@ #undef ep4_norm #undef ep4_norm_sim #undef ep4_map -#undef ep4_map_dst #undef ep4_frb #undef ep4_pck #undef ep4_upk @@ -1752,7 +1756,6 @@ #define ep4_curve_clean RLC_PREFIX(ep4_curve_clean) #define ep4_curve_get_a RLC_PREFIX(ep4_curve_get_a) #define ep4_curve_get_b RLC_PREFIX(ep4_curve_get_b) -#define ep4_curve_get_vs RLC_PREFIX(ep4_curve_get_vs) #define ep4_curve_opt_a RLC_PREFIX(ep4_curve_opt_a) #define ep4_curve_opt_b RLC_PREFIX(ep4_curve_opt_b) #define ep4_curve_is_twist RLC_PREFIX(ep4_curve_is_twist) @@ -1813,11 +1816,151 @@ #define ep4_norm RLC_PREFIX(ep4_norm) #define ep4_norm_sim RLC_PREFIX(ep4_norm_sim) #define ep4_map RLC_PREFIX(ep4_map) -#define ep4_map_dst RLC_PREFIX(ep4_map_dst) #define ep4_frb RLC_PREFIX(ep4_frb) #define ep4_pck RLC_PREFIX(ep4_pck) #define ep4_upk RLC_PREFIX(ep4_upk) +#undef ep8_st +#undef ep8_t +#define ep8_st RLC_PREFIX(ep8_st) +#define ep8_t RLC_PREFIX(ep8_t) + +#undef ep8_curve_init +#undef ep8_curve_clean +#undef ep8_curve_get_a +#undef ep8_curve_get_b +#undef ep8_curve_opt_a +#undef ep8_curve_opt_b +#undef ep8_curve_is_twist +#undef ep8_curve_get_gen +#undef ep8_curve_get_tab +#undef ep8_curve_get_ord +#undef ep8_curve_get_cof +#undef ep8_curve_set +#undef ep8_curve_set_twist +#undef ep8_is_infty +#undef ep8_set_infty +#undef ep8_copy +#undef ep8_cmp +#undef ep8_rand +#undef ep8_blind +#undef ep8_rhs +#undef ep8_on_curve +#undef ep8_tab +#undef ep8_print +#undef ep8_size_bin +#undef ep8_read_bin +#undef ep8_write_bin +#undef ep8_neg +#undef ep8_add_basic +#undef ep8_add_slp_basic +#undef ep8_add_projc +#undef ep8_sub +#undef ep8_dbl_basic +#undef ep8_dbl_slp_basic +#undef ep8_dbl_projc +#undef ep8_mul_basic +#undef ep8_mul_slide +#undef ep8_mul_monty +#undef ep8_mul_lwnaf +#undef ep8_mul_lwreg +#undef ep8_mul_gen +#undef ep8_mul_dig +#undef ep8_mul_cof +#undef ep8_mul_pre_basic +#undef ep8_mul_pre_yaowi +#undef ep8_mul_pre_nafwi +#undef ep8_mul_pre_combs +#undef ep8_mul_pre_combd +#undef ep8_mul_pre_lwnaf +#undef ep8_mul_fix_basic +#undef ep8_mul_fix_yaowi +#undef ep8_mul_fix_nafwi +#undef ep8_mul_fix_combs +#undef ep8_mul_fix_combd +#undef ep8_mul_fix_lwnaf +#undef ep8_mul_sim_basic +#undef ep8_mul_sim_trick +#undef ep8_mul_sim_inter +#undef ep8_mul_sim_joint +#undef ep8_mul_sim_lot +#undef ep8_mul_sim_gen +#undef ep8_mul_sim_dig +#undef ep8_norm +#undef ep8_norm_sim +#undef ep8_map +#undef ep8_frb +#undef ep8_pck +#undef ep8_upk + +#define ep8_curve_init RLC_PREFIX(ep8_curve_init) +#define ep8_curve_clean RLC_PREFIX(ep8_curve_clean) +#define ep8_curve_get_a RLC_PREFIX(ep8_curve_get_a) +#define ep8_curve_get_b RLC_PREFIX(ep8_curve_get_b) +#define ep8_curve_opt_a RLC_PREFIX(ep8_curve_opt_a) +#define ep8_curve_opt_b RLC_PREFIX(ep8_curve_opt_b) +#define ep8_curve_is_twist RLC_PREFIX(ep8_curve_is_twist) +#define ep8_curve_get_gen RLC_PREFIX(ep8_curve_get_gen) +#define ep8_curve_get_tab RLC_PREFIX(ep8_curve_get_tab) +#define ep8_curve_get_ord RLC_PREFIX(ep8_curve_get_ord) +#define ep8_curve_get_cof RLC_PREFIX(ep8_curve_get_cof) +#define ep8_curve_set RLC_PREFIX(ep8_curve_set) +#define ep8_curve_set_twist RLC_PREFIX(ep8_curve_set_twist) +#define ep8_is_infty RLC_PREFIX(ep8_is_infty) +#define ep8_set_infty RLC_PREFIX(ep8_set_infty) +#define ep8_copy RLC_PREFIX(ep8_copy) +#define ep8_cmp RLC_PREFIX(ep8_cmp) +#define ep8_rand RLC_PREFIX(ep8_rand) +#define ep8_blind RLC_PREFIX(ep8_blind) +#define ep8_rhs RLC_PREFIX(ep8_rhs) +#define ep8_on_curve RLC_PREFIX(ep8_on_curve) +#define ep8_tab RLC_PREFIX(ep8_tab) +#define ep8_print RLC_PREFIX(ep8_print) +#define ep8_size_bin RLC_PREFIX(ep8_size_bin) +#define ep8_read_bin RLC_PREFIX(ep8_read_bin) +#define ep8_write_bin RLC_PREFIX(ep8_write_bin) +#define ep8_neg RLC_PREFIX(ep8_neg) +#define ep8_add_basic RLC_PREFIX(ep8_add_basic) +#define ep8_add_slp_basic RLC_PREFIX(ep8_add_slp_basic) +#define ep8_add_projc RLC_PREFIX(ep8_add_projc) +#define ep8_sub RLC_PREFIX(ep8_sub) +#define ep8_dbl_basic RLC_PREFIX(ep8_dbl_basic) +#define ep8_dbl_slp_basic RLC_PREFIX(ep8_dbl_slp_basic) +#define ep8_dbl_projc RLC_PREFIX(ep8_dbl_projc) +#define ep8_mul_basic RLC_PREFIX(ep8_mul_basic) +#define ep8_mul_slide RLC_PREFIX(ep8_mul_slide) +#define ep8_mul_monty RLC_PREFIX(ep8_mul_monty) +#define ep8_mul_lwnaf RLC_PREFIX(ep8_mul_lwnaf) +#define ep8_mul_lwreg RLC_PREFIX(ep8_mul_lwreg) +#define ep8_mul_gen RLC_PREFIX(ep8_mul_gen) +#define ep8_mul_dig RLC_PREFIX(ep8_mul_dig) +#define ep8_mul_cof RLC_PREFIX(ep8_mul_cof) +#define ep8_mul_pre_basic RLC_PREFIX(ep8_mul_pre_basic) +#define ep8_mul_pre_yaowi RLC_PREFIX(ep8_mul_pre_yaowi) +#define ep8_mul_pre_nafwi RLC_PREFIX(ep8_mul_pre_nafwi) +#define ep8_mul_pre_combs RLC_PREFIX(ep8_mul_pre_combs) +#define ep8_mul_pre_combd RLC_PREFIX(ep8_mul_pre_combd) +#define ep8_mul_pre_lwnaf RLC_PREFIX(ep8_mul_pre_lwnaf) +#define ep8_mul_fix_basic RLC_PREFIX(ep8_mul_fix_basic) +#define ep8_mul_fix_yaowi RLC_PREFIX(ep8_mul_fix_yaowi) +#define ep8_mul_fix_nafwi RLC_PREFIX(ep8_mul_fix_nafwi) +#define ep8_mul_fix_combs RLC_PREFIX(ep8_mul_fix_combs) +#define ep8_mul_fix_combd RLC_PREFIX(ep8_mul_fix_combd) +#define ep8_mul_fix_lwnaf RLC_PREFIX(ep8_mul_fix_lwnaf) +#define ep8_mul_sim_basic RLC_PREFIX(ep8_mul_sim_basic) +#define ep8_mul_sim_trick RLC_PREFIX(ep8_mul_sim_trick) +#define ep8_mul_sim_inter RLC_PREFIX(ep8_mul_sim_inter) +#define ep8_mul_sim_joint RLC_PREFIX(ep8_mul_sim_joint) +#define ep8_mul_sim_lot RLC_PREFIX(ep8_mul_sim_lot) +#define ep8_mul_sim_gen RLC_PREFIX(ep8_mul_sim_gen) +#define ep8_mul_sim_dig RLC_PREFIX(ep8_mul_sim_dig) +#define ep8_norm RLC_PREFIX(ep8_norm) +#define ep8_norm_sim RLC_PREFIX(ep8_norm_sim) +#define ep8_map RLC_PREFIX(ep8_map) +#define ep8_frb RLC_PREFIX(ep8_frb) +#define ep8_pck RLC_PREFIX(ep8_pck) +#define ep8_upk RLC_PREFIX(ep8_upk) + #undef fp2_st #undef fp2_t #undef dv2_t @@ -1879,8 +2022,6 @@ #define fp54_t RLC_PREFIX(fp54_t) #define dv54_t RLC_PREFIX(dv54_t) -#undef fp2_add_dig -#undef fp2_sub_dig #undef fp2_field_init #undef fp2_field_get_qnr #undef fp2_copy @@ -1896,8 +2037,10 @@ #undef fp2_set_dig #undef fp2_add_basic #undef fp2_add_integ +#undef fp2_add_dig #undef fp2_sub_basic #undef fp2_sub_integ +#undef fp2_sub_dig #undef fp2_neg #undef fp2_dbl_basic #undef fp2_dbl_integ @@ -1920,12 +2063,11 @@ #undef fp2_exp_cyc #undef fp2_exp_cyc_sim #undef fp2_frb +#undef fp2_is_sqr #undef fp2_srt #undef fp2_pck #undef fp2_upk -#define fp2_add_dig RLC_PREFIX(fp2_add_dig) -#define fp2_sub_dig RLC_PREFIX(fp2_sub_dig) #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) @@ -1941,8 +2083,10 @@ #define fp2_set_dig RLC_PREFIX(fp2_set_dig) #define fp2_add_basic RLC_PREFIX(fp2_add_basic) #define fp2_add_integ RLC_PREFIX(fp2_add_integ) +#define fp2_add_dig RLC_PREFIX(fp2_add_dig) #define fp2_sub_basic RLC_PREFIX(fp2_sub_basic) #define fp2_sub_integ RLC_PREFIX(fp2_sub_integ) +#define fp2_sub_dig RLC_PREFIX(fp2_sub_dig) #define fp2_neg RLC_PREFIX(fp2_neg) #define fp2_dbl_basic RLC_PREFIX(fp2_dbl_basic) #define fp2_dbl_integ RLC_PREFIX(fp2_dbl_integ) @@ -1965,6 +2109,7 @@ #define fp2_exp_cyc RLC_PREFIX(fp2_exp_cyc) #define fp2_exp_cyc_sim RLC_PREFIX(fp2_exp_cyc_sim) #define fp2_frb RLC_PREFIX(fp2_frb) +#define fp2_is_sqr RLC_PREFIX(fp2_is_sqr) #define fp2_srt RLC_PREFIX(fp2_srt) #define fp2_pck RLC_PREFIX(fp2_pck) #define fp2_upk RLC_PREFIX(fp2_upk) @@ -2022,8 +2167,10 @@ #undef fp3_set_dig #undef fp3_add_basic #undef fp3_add_integ +#undef fp3_add_dig #undef fp3_sub_basic #undef fp3_sub_integ +#undef fp3_sub_dig #undef fp3_neg #undef fp3_dbl_basic #undef fp3_dbl_integ @@ -2032,12 +2179,14 @@ #undef fp3_mul_art #undef fp3_mul_nor #undef fp3_mul_frb +#undef fp3_mul_dig #undef fp3_sqr_basic #undef fp3_sqr_integ #undef fp3_inv #undef fp3_inv_sim #undef fp3_exp #undef fp3_frb +#undef fp3_is_sqr #undef fp3_srt #define fp3_field_init RLC_PREFIX(fp3_field_init) @@ -2055,8 +2204,10 @@ #define fp3_set_dig RLC_PREFIX(fp3_set_dig) #define fp3_add_basic RLC_PREFIX(fp3_add_basic) #define fp3_add_integ RLC_PREFIX(fp3_add_integ) +#define fp3_add_dig RLC_PREFIX(fp3_add_dig) #define fp3_sub_basic RLC_PREFIX(fp3_sub_basic) #define fp3_sub_integ RLC_PREFIX(fp3_sub_integ) +#define fp3_sub_dig RLC_PREFIX(fp3_sub_dig) #define fp3_neg RLC_PREFIX(fp3_neg) #define fp3_dbl_basic RLC_PREFIX(fp3_dbl_basic) #define fp3_dbl_integ RLC_PREFIX(fp3_dbl_integ) @@ -2065,12 +2216,14 @@ #define fp3_mul_art RLC_PREFIX(fp3_mul_art) #define fp3_mul_nor RLC_PREFIX(fp3_mul_nor) #define fp3_mul_frb RLC_PREFIX(fp3_mul_frb) +#define fp3_mul_dig RLC_PREFIX(fp3_mul_dig) #define fp3_sqr_basic RLC_PREFIX(fp3_sqr_basic) #define fp3_sqr_integ RLC_PREFIX(fp3_sqr_integ) #define fp3_inv RLC_PREFIX(fp3_inv) #define fp3_inv_sim RLC_PREFIX(fp3_inv_sim) #define fp3_exp RLC_PREFIX(fp3_exp) #define fp3_frb RLC_PREFIX(fp3_frb) +#define fp3_is_sqr RLC_PREFIX(fp3_is_sqr) #define fp3_srt RLC_PREFIX(fp3_srt) #undef fp3_addn_low @@ -2122,7 +2275,9 @@ #undef fp4_cmp_dig #undef fp4_set_dig #undef fp4_add +#undef fp4_add_dig #undef fp4_sub +#undef fp4_sub_dig #undef fp4_neg #undef fp4_dbl #undef fp4_mul_unr @@ -2130,6 +2285,7 @@ #undef fp4_mul_lazyr #undef fp4_mul_art #undef fp4_mul_frb +#undef fp4_mul_dig #undef fp4_mul_dxs #undef fp4_sqr_unr #undef fp4_sqr_basic @@ -2139,6 +2295,7 @@ #undef fp4_inv_cyc #undef fp4_exp #undef fp4_frb +#undef fp4_is_sqr #undef fp4_srt #define fp4_field_init RLC_PREFIX(fp4_field_init) @@ -2154,7 +2311,9 @@ #define fp4_cmp_dig RLC_PREFIX(fp4_cmp_dig) #define fp4_set_dig RLC_PREFIX(fp4_set_dig) #define fp4_add RLC_PREFIX(fp4_add) +#define fp4_add_dig RLC_PREFIX(fp4_add_dig) #define fp4_sub RLC_PREFIX(fp4_sub) +#define fp4_sub_dig RLC_PREFIX(fp4_sub_dig) #define fp4_neg RLC_PREFIX(fp4_neg) #define fp4_dbl RLC_PREFIX(fp4_dbl) #define fp4_mul_unr RLC_PREFIX(fp4_mul_unr) @@ -2162,6 +2321,7 @@ #define fp4_mul_lazyr RLC_PREFIX(fp4_mul_lazyr) #define fp4_mul_art RLC_PREFIX(fp4_mul_art) #define fp4_mul_frb RLC_PREFIX(fp4_mul_frb) +#define fp4_mul_dig RLC_PREFIX(fp4_mul_dig) #define fp4_mul_dxs RLC_PREFIX(fp4_mul_dxs) #define fp4_sqr_unr RLC_PREFIX(fp4_sqr_unr) #define fp4_sqr_basic RLC_PREFIX(fp4_sqr_basic) @@ -2171,6 +2331,7 @@ #define fp4_inv_cyc RLC_PREFIX(fp4_inv_cyc) #define fp4_exp RLC_PREFIX(fp4_exp) #define fp4_frb RLC_PREFIX(fp4_frb) +#define fp4_is_sqr RLC_PREFIX(fp4_is_sqr) #define fp4_srt RLC_PREFIX(fp4_srt) #undef fp6_copy @@ -2227,6 +2388,7 @@ #define fp6_exp RLC_PREFIX(fp6_exp) #define fp6_frb RLC_PREFIX(fp6_frb) +#undef fp8_field_init #undef fp8_copy #undef fp8_zero #undef fp8_is_zero @@ -2246,6 +2408,7 @@ #undef fp8_mul_basic #undef fp8_mul_lazyr #undef fp8_mul_art +#undef fp8_mul_frb #undef fp8_mul_dxs #undef fp8_sqr_unr #undef fp8_sqr_basic @@ -2259,7 +2422,10 @@ #undef fp8_exp #undef fp8_exp_cyc #undef fp8_frb +#undef fp8_is_sqr +#undef fp8_srt +#define fp8_field_init RLC_PREFIX(fp8_field_init) #define fp8_copy RLC_PREFIX(fp8_copy) #define fp8_zero RLC_PREFIX(fp8_zero) #define fp8_is_zero RLC_PREFIX(fp8_is_zero) @@ -2279,6 +2445,7 @@ #define fp8_mul_basic RLC_PREFIX(fp8_mul_basic) #define fp8_mul_lazyr RLC_PREFIX(fp8_mul_lazyr) #define fp8_mul_art RLC_PREFIX(fp8_mul_art) +#define fp8_mul_frb RLC_PREFIX(fp8_mul_frb) #define fp8_mul_dxs RLC_PREFIX(fp8_mul_dxs) #define fp8_sqr_unr RLC_PREFIX(fp8_sqr_unr) #define fp8_sqr_basic RLC_PREFIX(fp8_sqr_basic) @@ -2292,6 +2459,8 @@ #define fp8_exp RLC_PREFIX(fp8_exp) #define fp8_exp_cyc RLC_PREFIX(fp8_exp_cyc) #define fp8_frb RLC_PREFIX(fp8_frb) +#define fp8_is_sqr RLC_PREFIX(fp8_is_sqr) +#define fp8_srt RLC_PREFIX(fp8_srt) #undef fp9_copy #undef fp9_zero @@ -2785,6 +2954,8 @@ #undef pp_map_init #undef pp_map_clean +#undef pp_add_k1_basic +#undef pp_add_k1_projc #undef pp_add_k2_basic #undef pp_add_k2_projc_basic #undef pp_add_k2_projc_lazyr @@ -2805,6 +2976,8 @@ #undef pp_add_k48_projc #undef pp_add_k54_basic #undef pp_add_k54_projc +#undef pp_dbl_k1_basic +#undef pp_dbl_k1_projc #undef pp_dbl_k2_basic #undef pp_dbl_k2_projc_basic #undef pp_dbl_k2_projc_lazyr @@ -2825,6 +2998,7 @@ #undef pp_dbl_k54_projc #undef pp_dbl_lit_k12 #undef pp_dbl_lit_k18 +#undef pp_exp_k1 #undef pp_exp_k2 #undef pp_exp_k8 #undef pp_exp_k12 @@ -2832,16 +3006,22 @@ #undef pp_exp_k24 #undef pp_exp_k48 #undef pp_exp_k54 +#undef pp_norm_k1 #undef pp_norm_k2 #undef pp_norm_k8 #undef pp_norm_k12 #undef pp_norm_k18 #undef pp_norm_k24 +#undef pp_norm_k48 +#undef pp_map_tatep_k1 +#undef pp_map_sim_tatep_k1 #undef pp_map_tatep_k2 #undef pp_map_sim_tatep_k2 +#undef pp_map_weilp_k1 +#undef pp_map_sim_weilp_k1 #undef pp_map_weilp_k2 -#undef pp_map_oatep_k8 #undef pp_map_sim_weilp_k2 +#undef pp_map_oatep_k8 #undef pp_map_tatep_k12 #undef pp_map_sim_tatep_k12 #undef pp_map_weilp_k12 @@ -2857,10 +3037,13 @@ #undef pp_map_k24 #undef pp_map_sim_k24 #undef pp_map_k48 +#undef pp_map_sim_k48 #undef pp_map_k54 #define pp_map_init RLC_PREFIX(pp_map_init) #define pp_map_clean RLC_PREFIX(pp_map_clean) +#define pp_add_k1_basic RLC_PREFIX(pp_add_k1_basic) +#define pp_add_k1_projc RLC_PREFIX(pp_add_k1_projc) #define pp_add_k2_basic RLC_PREFIX(pp_add_k2_basic) #define pp_add_k2_projc_basic RLC_PREFIX(pp_add_k2_projc_basic) #define pp_add_k2_projc_lazyr RLC_PREFIX(pp_add_k2_projc_lazyr) @@ -2881,6 +3064,8 @@ #define pp_add_k48_projc RLC_PREFIX(pp_add_k48_projc) #define pp_add_k54_basic RLC_PREFIX(pp_add_k54_basic) #define pp_add_k54_projc RLC_PREFIX(pp_add_k54_projc) +#define pp_dbl_k1_basic RLC_PREFIX(pp_dbl_k1_basic) +#define pp_dbl_k1_projc RLC_PREFIX(pp_dbl_k1_projc) #define pp_dbl_k2_basic RLC_PREFIX(pp_dbl_k2_basic) #define pp_dbl_k2_projc_basic RLC_PREFIX(pp_dbl_k2_projc_basic) #define pp_dbl_k2_projc_lazyr RLC_PREFIX(pp_dbl_k2_projc_lazyr) @@ -2901,6 +3086,7 @@ #define pp_dbl_k54_projc RLC_PREFIX(pp_dbl_k54_projc) #define pp_dbl_lit_k12 RLC_PREFIX(pp_dbl_lit_k12) #define pp_dbl_lit_k18 RLC_PREFIX(pp_dbl_lit_k18) +#define pp_exp_k1 RLC_PREFIX(pp_exp_k1) #define pp_exp_k2 RLC_PREFIX(pp_exp_k2) #define pp_exp_k8 RLC_PREFIX(pp_exp_k8) #define pp_exp_k12 RLC_PREFIX(pp_exp_k12) @@ -2908,16 +3094,22 @@ #define pp_exp_k24 RLC_PREFIX(pp_exp_k24) #define pp_exp_k48 RLC_PREFIX(pp_exp_k48) #define pp_exp_k54 RLC_PREFIX(pp_exp_k54) +#define pp_norm_k1 RLC_PREFIX(pp_norm_k1) #define pp_norm_k2 RLC_PREFIX(pp_norm_k2) #define pp_norm_k8 RLC_PREFIX(pp_norm_k8) #define pp_norm_k12 RLC_PREFIX(pp_norm_k12) #define pp_norm_k18 RLC_PREFIX(pp_norm_k18) #define pp_norm_k24 RLC_PREFIX(pp_norm_k24) +#define pp_norm_k48 RLC_PREFIX(pp_norm_k48) +#define pp_map_tatep_k1 RLC_PREFIX(pp_map_tatep_k1) +#define pp_map_sim_tatep_k1 RLC_PREFIX(pp_map_sim_tatep_k1) #define pp_map_tatep_k2 RLC_PREFIX(pp_map_tatep_k2) #define pp_map_sim_tatep_k2 RLC_PREFIX(pp_map_sim_tatep_k2) +#define pp_map_weilp_k1 RLC_PREFIX(pp_map_weilp_k1) +#define pp_map_sim_weilp_k1 RLC_PREFIX(pp_map_sim_weilp_k1) #define pp_map_weilp_k2 RLC_PREFIX(pp_map_weilp_k2) -#define pp_map_oatep_k8 RLC_PREFIX(pp_map_oatep_k8) #define pp_map_sim_weilp_k2 RLC_PREFIX(pp_map_sim_weilp_k2) +#define pp_map_oatep_k8 RLC_PREFIX(pp_map_oatep_k8) #define pp_map_tatep_k12 RLC_PREFIX(pp_map_tatep_k12) #define pp_map_sim_tatep_k12 RLC_PREFIX(pp_map_sim_tatep_k12) #define pp_map_weilp_k12 RLC_PREFIX(pp_map_weilp_k12) @@ -2933,6 +3125,7 @@ #define pp_map_k24 RLC_PREFIX(pp_map_k24) #define pp_map_sim_k24 RLC_PREFIX(pp_map_sim_k24) #define pp_map_k48 RLC_PREFIX(pp_map_k48) +#define pp_map_sim_k48 RLC_PREFIX(pp_map_sim_k48) #define pp_map_k54 RLC_PREFIX(pp_map_k54) #undef pc_core_init diff --git a/include/relic_pc.h b/include/relic_pc.h index e804be31b..d4c7850fc 100644 --- a/include/relic_pc.h +++ b/include/relic_pc.h @@ -36,9 +36,7 @@ #ifndef RLC_PC_H #define RLC_PC_H -#include "relic_fbx.h" #include "relic_ep.h" -#include "relic_eb.h" #include "relic_pp.h" #include "relic_bn.h" #include "relic_util.h" @@ -58,33 +56,52 @@ #define RLC_G1_LOWER ep_ #define RLC_G1_UPPER EP -#if FP_PRIME == 315 || FP_PRIME == 317 || FP_PRIME == 509 +#if FP_PRIME == 575 +#define RLC_G2_LOWER ep8_ +#define RLC_G2_BASEF(A) A[0][0][0] +#elif FP_PRIME == 315 || FP_PRIME == 317 || FP_PRIME == 330 || FP_PRIME == 509 || FP_PRIME == 765 || FP_PRIME == 766 #define RLC_G2_LOWER ep4_ -#elif FP_PRIME == 638 && !defined(FP_QNRES) -#define RLC_G2_LOWER ep3_ +#define RLC_G2_BASEF(A) A[0][0] +#elif FP_PRIME == 508 || FP_PRIME == 638 && !defined(FP_QNRES) +#define RLC_G2_LOWER ep3_ +#define RLC_G2_BASEF(A) A[0] #else #define RLC_G2_LOWER ep2_ +#define RLC_G2_BASEF(A) A[0] #endif #define RLC_G2_UPPER EP -#if FP_PRIME == 315 || FP_PRIME == 317 || FP_PRIME == 509 +#if FP_PRIME == 575 +#define RLC_GT_LOWER fp48_ +#define RLC_GT_EMBED 48 +#elif FP_PRIME == 315 || FP_PRIME == 317 || FP_PRIME == 509 #define RLC_GT_LOWER fp24_ -#elif FP_PRIME == 638 && !defined(FP_QNRES) -#define RLC_GT_LOWER fp18_ +#define RLC_GT_EMBED 24 +#elif FP_PRIME == 508 || FP_PRIME == 638 && !defined(FP_QNRES) +#define RLC_GT_LOWER fp18_ +#define RLC_GT_EMBED 18 +#elif FP_PRIME == 330 || FP_PRIME == 765 || FP_PRIME == 766 +#define RLC_GT_LOWER fp16_ +#define RLC_GT_EMBED 16 #else #define RLC_GT_LOWER fp12_ +#define RLC_GT_EMBED 12 #endif -#define RLC_PC_LOWER pp_ - #else #define RLC_G1_LOWER ep_ #define RLC_G1_UPPER EP #define RLC_G2_LOWER ep_ #define RLC_G2_UPPER EP +#define RLC_G2_BASEF(A) A +#if FP_PRIME == 1536 #define RLC_GT_LOWER fp2_ -#define RLC_PC_LOWER pp_ +#define RLC_GT_EMBED 2 +#else +#define RLC_GT_LOWER fp_ +#define RLC_GT_EMBED 1 +#endif #endif /** @} */ @@ -202,8 +219,6 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t; */ #define gt_free(A) RLC_CAT(RLC_GT_LOWER, free)(A) - - /** * Returns the generator of the group G_1. * @@ -246,12 +261,22 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t; * Returns the type of the configured pairing. * @{ */ -#if FP_PRIME < 1536 #define pc_map_is_type1() (0) +#define pc_map_is_type2() (0) +#define pc_map_is_type3() (0) +#define pc_map_is_type4() (0) +#define pc_map_is_typea() (0) +#define pc_map_is_typeb() (0) +#define pc_map_is_typec() (0) +#if FP_PRIME == 3072 +#undef pc_map_is_typeb +#define pc_map_is_typeb() (1) +#elif FP_PRIME < 1536 +#undef pc_map_is_type3 #define pc_map_is_type3() (1) #else +#undef pc_map_is_type1 #define pc_map_is_type1() (1) -#define pc_map_is_type3() (0) #endif /** * @} @@ -308,19 +333,41 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t; #define gt_is_unity(A) (RLC_CAT(RLC_GT_LOWER, cmp_dig)(A, 1) == RLC_EQ) /** - * Assigns a G_1 element to the unity. + * Assigns a G_1 element to the identity. * * @param[out] P - the element to assign. */ #define g1_set_infty(P) RLC_CAT(RLC_G1_LOWER, set_infty)(P) /** - * Assigns a G_2 element to the unity. + * Assigns a G_2 element to the identity. * * @param[out] P - the element to assign. */ #define g2_set_infty(P) RLC_CAT(RLC_G2_LOWER, set_infty)(P) +/** + * Assigns a G_1 element to a pair of coordinates in the extension field. + * + * @param[out] P - the element to assign. + * @param[out] Q - the G_2 element storing the coordinates. + */ +#define g1_set_g2(P, Q) \ + fp_copy((P)->x, RLC_G2_BASEF((Q)->x)); \ + fp_copy((P)->y, RLC_G2_BASEF((Q)->y)); \ + fp_copy((P)->z, RLC_G2_BASEF((Q)->z)); \ + +/** + * Assigns a G_2 element to a pair of coordinates in the base field. + * + * @param[out] Q - the element to assign. + * @param[out] P - the G_1 element storing the coordinates. + */ +#define g2_set_g1(Q, P) \ + fp_copy(RLC_G2_BASEF((Q)->x), (P)->x); \ + fp_copy(RLC_G2_BASEF((Q)->y), (P)->y); \ + fp_copy(RLC_G2_BASEF((Q)->z), (P)->z); \ + /** * Assigns a G_T element to zero. * @@ -329,7 +376,7 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t; #define gt_zero(A) RLC_CAT(RLC_GT_LOWER, zero)(A) /** - * Assigns a G_T element to the unity. + * Assigns a G_T element to the identity. * * @param[out] A - the element to assign. */ @@ -415,7 +462,7 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t; * @param[out] R - the blinded G_1 element. * @param[in] P - the G_1 element to blind. */ - #define g1_blind(R, P) RLC_CAT(RLC_G1_LOWER, blind)(R, P) +#define g1_blind(R, P) RLC_CAT(RLC_G1_LOWER, blind)(R, P) /** * Randomizes coordinates of a G_2 element. @@ -468,7 +515,11 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t; * @param[in] A - the element of G_T. * @param[in] C - the flag to indicate compression. */ +#if FP_PRIME <= 1536 #define gt_size_bin(A, C) RLC_CAT(RLC_GT_LOWER, size_bin)(A, C) +#else +#define gt_size_bin(A, C) RLC_FP_BYTES +#endif /** * Reads a G_1 element from a byte vector in big-endian format. @@ -534,7 +585,11 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t; * @param[in] C - the flag to indicate point compression. * @throw ERR_NO_BUFFER - if the buffer capacity is not sufficient. */ +#if FP_PRIME <= 1536 #define gt_write_bin(B, L, A, C) RLC_CAT(RLC_GT_LOWER, write_bin)(B, L, A, C) +#else +#define gt_write_bin(B, L, A, C) RLC_CAT(RLC_GT_LOWER, write_bin)(B, L, A) +#endif /** * Negates a element from G_1. Computes R = -P. @@ -558,7 +613,11 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t; * @param[out] C - the result. * @param[in] A - the element to invert. */ +#if FP_PRIME <= 1536 #define gt_inv(C, A) RLC_CAT(RLC_GT_LOWER, inv_cyc)(C, A) +#else +#define gt_inv(C, A) RLC_CAT(RLC_GT_LOWER, inv)(C, A) +#endif /** * Adds two elliptic elements from G_1. Computes R = P + Q. @@ -848,7 +907,11 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t; * @param[in] A - the element to exponentiate. * @param[in] I - the power of the Frobenius map. */ +#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) +#endif /** * Maps a byte array to an element in G_1. @@ -857,7 +920,7 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t; * @param[in] M - the byte array to map. * @param[in] L - the array length in bytes. */ -#define g1_map(P, M, L); RLC_CAT(RLC_G1_LOWER, map)(P, M, L) +#define g1_map(P, M, L) RLC_CAT(RLC_G1_LOWER, map)(P, M, L) /** * Maps a byte array to an element in G_2. @@ -866,7 +929,7 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t; * @param[in] M - the byte array to map. * @param[in] L - the array length in bytes. */ -#define g2_map(P, M, L); RLC_CAT(RLC_G2_LOWER, map)(P, M, L) +#define g2_map(P, M, L) RLC_CAT(RLC_G2_LOWER, map)(P, M, L) /** * Computes the bilinear pairing of a G_1 element and a G_2 element. Computes @@ -876,21 +939,7 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t; * @param[in] P - the first element. * @param[in] Q - the second element. */ -#if FP_PRIME < 1536 - -#if FP_PRIME == 315 || FP_PRIME == 317 || FP_PRIME == 509 -#define pc_map(R, P, Q); RLC_CAT(RLC_PC_LOWER, map_k24)(R, P, Q) -#elif FP_PRIME == 638 && !defined(FP_QNRES) -#define pc_map(R, P, Q); RLC_CAT(RLC_PC_LOWER, map_k18)(R, P, Q) -#else -#define pc_map(R, P, Q); RLC_CAT(RLC_PC_LOWER, map_k12)(R, P, Q) -#endif - -#else - -#define pc_map(R, P, Q); RLC_CAT(RLC_PC_LOWER, map_k2)(R, P, Q) - -#endif +#define pc_map(R, P, Q) RLC_CAT(pp_map_k, RLC_GT_EMBED)(R, P, Q) /** * Computes the multi-pairing of G_1 elements and G_2 elements. Computes @@ -901,19 +950,7 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t; * @param[in] Q - the second pairing arguments. * @param[in] M - the number of pairing arguments. */ -#if FP_PRIME < 1536 - -#if FP_PRIME == 315 || FP_PRIME == 317 || FP_PRIME == 509 -#define pc_map_sim(R, P, Q, M); RLC_CAT(RLC_PC_LOWER, map_sim_k24)(R, P, Q, M) -#elif FP_PRIME == 638 && !defined(FP_QNRES) -#define pc_map_sim(R, P, Q, M); RLC_CAT(RLC_PC_LOWER, map_sim_k18)(R, P, Q, M) -#else -#define pc_map_sim(R, P, Q, M); RLC_CAT(RLC_PC_LOWER, map_sim_k12)(R, P, Q, M) -#endif - -#else -#define pc_map_sim(R, P, Q, M); RLC_CAT(RLC_PC_LOWER, map_sim_k2)(R, P, Q, M) -#endif +#define pc_map_sim(R, P, Q, M) RLC_CAT(pp_map_sim_k, RLC_GT_EMBED)(R, P, Q, M) /** * Computes the final exponentiation of the pairing. @@ -921,19 +958,7 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t; * @param[out] C - the result. * @param[in] A - the field element to exponentiate. */ -#if FP_PRIME < 1536 - -#if FP_PRIME == 315 || FP_PRIME == 317 || FP_PRIME == 509 -#define pc_exp(C, A); RLC_CAT(RLC_PC_LOWER, exp_k24)(C, A) -#elif FP_PRIME == 638 && !defined(FP_QNRES) -#define pc_exp(C, A); RLC_CAT(RLC_PC_LOWER, exp_k18)(C, A) -#else -#define pc_exp(C, A); RLC_CAT(RLC_PC_LOWER, exp_k12)(C, A) -#endif - -#else -#define pc_exp(C, A); RLC_CAT(RLC_PC_LOWER, exp_k2)(C, A) -#endif +#define pc_exp(C, A); RLC_CAT(pp_exp_k, RLC_GT_EMBED)(C, A) /*============================================================================*/ /* Function prototypes */ diff --git a/include/relic_pp.h b/include/relic_pp.h index b2bdb9a31..2077bb691 100644 --- a/include/relic_pp.h +++ b/include/relic_pp.h @@ -45,6 +45,22 @@ /* Macro definitions */ /*============================================================================*/ +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 1. + * + * @param[out] L - the numerator of the result of the evaluation. + * @param[out] M - the denominator of the result of the evaluation. + * @param[in, out] R - the resulting point and first point to add. + * @param[in] P - the second point to add. + * @param[in] Q - the affine point to evaluate the line function. + */ +#if EP_ADD == BASIC +#define pp_add_k1(L, M, R, P, Q) pp_add_k1_basic(L, M, R, P, Q) +#else +#define pp_add_k1(L, M, R, P, Q) pp_add_k1_projc(L, M, R, P, Q) +#endif + /** * Adds two points and evaluates the corresponding line function at another * point on an elliptic curve with embedding degree 2 using projective @@ -56,9 +72,9 @@ * @param[in] Q - the affine point to evaluate the line function. */ #if PP_EXT == BASIC -#define pp_add_k2_projc(L, R, P, Q) pp_add_k2_projc_basic(L, R, P, Q) +#define pp_add_k2_projc(L, R, P, Q) pp_add_k2_projc_basic(L, R, P, Q) #else -#define pp_add_k2_projc(L, R, P, Q) pp_add_k2_projc_lazyr(L, R, P, Q) +#define pp_add_k2_projc(L, R, P, Q) pp_add_k2_projc_lazyr(L, R, P, Q) #endif /** @@ -138,6 +154,37 @@ #define pp_add_k12(L, R, Q, P) pp_add_k12_projc(L, R, Q, P) #endif +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 16 using projective + * coordinates. + * + * @param[out] L - the result of the evaluation. + * @param[in, out] R - the resulting point and first point to add. + * @param[in] Q - the second point to add. + * @param[in] P - the affine point to evaluate the line function. + */ +#if PP_EXT == BASIC +#define pp_add_k16_projc(L, R, Q, P) pp_add_k16_projc_basic(L, R, Q, P) +#elif PP_EXT == LAZYR +#define pp_add_k16_projc(L, R, Q, P) pp_add_k16_projc_lazyr(L, R, Q, P) +#endif + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 16. + * + * @param[out] L - the result of the evaluation. + * @param[in, out] R - the resulting point and first point to add. + * @param[in] Q - the second point to add. + * @param[in] P - the affine point to evaluate the line function. + */ +#if EP_ADD == BASIC +#define pp_add_k16(L, R, Q, P) pp_add_k16_basic(L, R, Q, P) +#else +#define pp_add_k16(L, R, Q, P) pp_add_k16_projc(L, R, Q, P) +#endif + /** * Adds two points and evaluates the corresponding line function at another * point on an elliptic curve with embedding degree 18 using projective @@ -194,9 +241,9 @@ * @param[in] P - the affine point to evaluate the line function. */ #if EP_ADD == BASIC -#define pp_add_k48(L, RX, RY, RZ, QX, QY, P) pp_add_k48_basic(L, RX, RY, QX, QY, P) +#define pp_add_k48(L, R, Q, P) pp_add_k48_basic(L, R, Q, P) #else -#define pp_add_k48(L, RX, RY, RZ, QX, QY, P) pp_add_k48_projc(L, RX, RY, RZ, QX, QY, P) +#define pp_add_k48(L, R, Q, P) pp_add_k48_projc(L, R, Q, P) #endif /** @@ -214,6 +261,22 @@ #define pp_add_k54(L, RX, RY, RZ, QX, QY, P) pp_add_k54_projc(L, RX, RY, RZ, QX, QY, P) #endif +/** + * Doubles a point and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 1. + * + * @param[out] L - the numerator of the result of the evaluation. + * @param[out] M - the denominator of the result of the evaluation. + * @param[out] R - the resulting point. + * @param[in] P - the point to double. + * @param[in] Q - the affine point to evaluate the line function. + */ +#if EP_ADD == BASIC +#define pp_dbl_k1(L, M, R, P, Q) pp_dbl_k1_basic(L, M, R, P, Q) +#else +#define pp_dbl_k1(L, M, R, P, Q) pp_dbl_k1_projc(L, M, R, P, Q) +#endif + /** * Doubles a point and evaluates the corresponding line function at another * point on an elliptic curve with embedding degree 2 using projective @@ -225,9 +288,9 @@ * @param[in] P - the affine point to evaluate the line function. */ #if PP_EXT == BASIC -#define pp_dbl_k2_projc(L, R, P, Q) pp_dbl_k2_projc_basic(L, R, P, Q) +#define pp_dbl_k2_projc(L, R, P, Q) pp_dbl_k2_projc_basic(L, R, P, Q) #elif PP_EXT == LAZYR -#define pp_dbl_k2_projc(L, R, P, Q) pp_dbl_k2_projc_lazyr(L, R, P, Q) +#define pp_dbl_k2_projc(L, R, P, Q) pp_dbl_k2_projc_lazyr(L, R, P, Q) #endif /** @@ -240,9 +303,9 @@ * @param[in] Q - the affine point to evaluate the line function. */ #if EP_ADD == BASIC -#define pp_dbl_k2(L, R, P, Q) pp_dbl_k2_basic(L, R, P, Q) +#define pp_dbl_k2(L, R, P, Q) pp_dbl_k2_basic(L, R, P, Q) #else -#define pp_dbl_k2(L, R, P, Q) pp_dbl_k2_projc(L, R, P, Q) +#define pp_dbl_k2(L, R, P, Q) pp_dbl_k2_projc(L, R, P, Q) #endif /** @@ -256,9 +319,9 @@ * @param[in] P - the affine point to evaluate the line function. */ #if PP_EXT == BASIC -#define pp_dbl_k8_projc(L, R, Q, P) pp_dbl_k8_projc_basic(L, R, Q, P) +#define pp_dbl_k8_projc(L, R, Q, P) pp_dbl_k8_projc_basic(L, R, Q, P) #elif PP_EXT == LAZYR -#define pp_dbl_k8_projc(L, R, Q, P) pp_dbl_k8_projc_lazyr(L, R, Q, P) +#define pp_dbl_k8_projc(L, R, Q, P) pp_dbl_k8_projc_lazyr(L, R, Q, P) #endif /** @@ -271,9 +334,9 @@ * @param[in] P - the affine point to evaluate the line function. */ #if EP_ADD == BASIC -#define pp_dbl_k8(L, R, Q, P) pp_dbl_k8_basic(L, R, Q, P) +#define pp_dbl_k8(L, R, Q, P) pp_dbl_k8_basic(L, R, Q, P) #else -#define pp_dbl_k8(L, R, Q, P) pp_dbl_k8_projc(L, R, Q, P) +#define pp_dbl_k8(L, R, Q, P) pp_dbl_k8_projc(L, R, Q, P) #endif /** @@ -302,9 +365,40 @@ * @param[in] P - the affine point to evaluate the line function. */ #if EP_ADD == BASIC -#define pp_dbl_k12(L, R, Q, P) pp_dbl_k12_basic(L, R, Q, P) +#define pp_dbl_k12(L, R, Q, P) pp_dbl_k12_basic(L, R, Q, P) #else -#define pp_dbl_k12(L, R, Q, P) pp_dbl_k12_projc(L, R, Q, P) +#define pp_dbl_k12(L, R, Q, P) pp_dbl_k12_projc(L, R, Q, P) +#endif + +/** + * Doubles a point and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 16 using projective + * coordinates. + * + * @param[out] L - the result of the evaluation. + * @param[in, out] R - the resulting point. + * @param[in] Q - the point to double. + * @param[in] P - the affine point to evaluate the line function. + */ +#if PP_EXT == BASIC +#define pp_dbl_k16_projc(L, R, Q, P) pp_dbl_k16_projc_basic(L, R, Q, P) +#elif PP_EXT == LAZYR +#define pp_dbl_k16_projc(L, R, Q, P) pp_dbl_k16_projc_lazyr(L, R, Q, P) +#endif + +/** + * Doubles a point and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 16. + * + * @param[out] L - the result of the evaluation. + * @param[out] R - the resulting point. + * @param[in] Q - the point to double. + * @param[in] P - the affine point to evaluate the line function. + */ +#if EP_ADD == BASIC +#define pp_dbl_k16(L, R, Q, P) pp_dbl_k16_basic(L, R, Q, P) +#else +#define pp_dbl_k16(L, R, Q, P) pp_dbl_k16_projc(L, R, Q, P) #endif /** @@ -333,9 +427,9 @@ * @param[in] P - the affine point to evaluate the line function. */ #if EP_ADD == BASIC -#define pp_dbl_k18(L, R, Q, P) pp_dbl_k18_basic(L, R, Q, P) +#define pp_dbl_k18(L, R, Q, P) pp_dbl_k18_basic(L, R, Q, P) #else -#define pp_dbl_k18(L, R, Q, P) pp_dbl_k18_projc(L, R, Q, P) +#define pp_dbl_k18(L, R, Q, P) pp_dbl_k18_projc(L, R, Q, P) #endif /** @@ -348,9 +442,9 @@ * @param[in] P - the affine point to evaluate the line function. */ #if EP_ADD == BASIC -#define pp_dbl_k24(L, R, Q, P) pp_dbl_k24_basic(L, R, Q, P) +#define pp_dbl_k24(L, R, Q, P) pp_dbl_k24_basic(L, R, Q, P) #else -#define pp_dbl_k24(L, R, Q, P) pp_dbl_k24_projc(L, R, Q, P) +#define pp_dbl_k24(L, R, Q, P) pp_dbl_k24_projc(L, R, Q, P) #endif /** @@ -363,9 +457,9 @@ * @param[in] P - the affine point to evaluate the line function. */ #if EP_ADD == BASIC -#define pp_dbl_k48(L, RX, RY, RZ, P) pp_dbl_k48_basic(L, RX, RY, P) +#define pp_dbl_k48(L, R, Q, P) pp_dbl_k48_basic(L, R, Q, P) #else -#define pp_dbl_k48(L, RX, RY, RZ, P) pp_dbl_k48_projc(L, RX, RY, RZ, P) +#define pp_dbl_k48(L, R, Q, P) pp_dbl_k48_projc(L, R, Q, P) #endif /** @@ -384,6 +478,22 @@ #endif /** + * Computes a pairing of two prime elliptic curve points defined on an elliptic + * curves of embedding degree 1. 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. + */ +#if PP_MAP == TATEP +#define pp_map_k1(R, P, Q) pp_map_tatep_k1(R, P, Q) +#elif PP_MAP == WEILP +#define pp_map_k1(R, P, Q) pp_map_weilp_k1(R, P, Q) +#elif PP_MAP == OATEP +#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). * @@ -392,11 +502,11 @@ * @param[in] Q - the second elliptic curve point. */ #if PP_MAP == TATEP -#define pp_map_k2(R, P, Q) pp_map_tatep_k2(R, P, Q) +#define pp_map_k2(R, P, Q) pp_map_tatep_k2(R, P, Q) #elif PP_MAP == WEILP -#define pp_map_k2(R, P, Q) pp_map_weilp_k2(R, P, Q) +#define pp_map_k2(R, P, Q) pp_map_weilp_k2(R, P, Q) #elif PP_MAP == OATEP -#define pp_map_k2(R, P, Q) pp_map_tatep_k2(R, P, Q) +#define pp_map_k2(R, P, Q) pp_map_tatep_k2(R, P, Q) #endif /** @@ -408,11 +518,27 @@ * @param[in] Q - the second elliptic curve point. */ #if PP_MAP == TATEP -#define pp_map_k12(R, P, Q) pp_map_tatep_k12(R, P, Q) +#define pp_map_k12(R, P, Q) pp_map_tatep_k12(R, P, Q) +#elif PP_MAP == WEILP +#define pp_map_k12(R, P, Q) pp_map_weilp_k12(R, P, Q) +#elif PP_MAP == OATEP +#define pp_map_k12(R, P, Q) pp_map_oatep_k12(R, P, Q) +#endif + +/** + * Computes a pairing of two prime elliptic curve points defined on an elliptic + * curve of embedding degree 16. 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. + */ +#if PP_MAP == TATEP +#define pp_map_k16(R, P, Q) pp_map_tatep_k16(R, P, Q) #elif PP_MAP == WEILP -#define pp_map_k12(R, P, Q) pp_map_weilp_k12(R, P, Q) +#define pp_map_k16(R, P, Q) pp_map_weilp_k16(R, P, Q) #elif PP_MAP == OATEP -#define pp_map_k12(R, P, Q) pp_map_oatep_k12(R, P, Q) +#define pp_map_k16(R, P, Q) pp_map_oatep_k16(R, P, Q) #endif /** @@ -424,16 +550,16 @@ * @param[in] Q - the second elliptic curve point. */ #if PP_MAP == TATEP -#define pp_map_k18(R, P, Q) pp_map_tatep_k18(R, P, Q) +#define pp_map_k18(R, P, Q) pp_map_tatep_k18(R, P, Q) #elif PP_MAP == WEILP -#define pp_map_k18(R, P, Q) pp_map_weilp_k18(R, P, Q) +#define pp_map_k18(R, P, Q) pp_map_weilp_k18(R, P, Q) #elif PP_MAP == OATEP -#define pp_map_k18(R, P, Q) pp_map_oatep_k18(R, P, Q) +#define pp_map_k18(R, P, Q) pp_map_oatep_k18(R, P, Q) #endif /** * Computes a multi-pairing of elliptic curve points defined on an elliptic - * curve of embedding degree 2. Computes \prod e(P_i, Q_i). + * curve of embedding degree 1. Computes \prod e(P_i, Q_i). * * @param[out] R - the result. * @param[in] P - the first pairing arguments. @@ -441,11 +567,25 @@ * @param[in] M - the number of pairings to evaluate. */ #if PP_MAP == WEILP -#define pp_map_sim_k2(R, P, Q, M) pp_map_sim_weilp_k2(R, P, Q, M) +#define pp_map_sim_k1(R, P, Q, M) pp_map_sim_weilp_k1(R, P, Q, M) #elif PP_MAP == TATEP || PP_MAP == OATEP -#define pp_map_sim_k2(R, P, Q, M) pp_map_sim_tatep_k2(R, P, Q, M) +#define pp_map_sim_k1(R, P, Q, M) pp_map_sim_tatep_k1(R, P, Q, M) #endif +/** + * Computes a multi-pairing of elliptic curve points defined on an elliptic + * curve of embedding degree 2. 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. + */ +#if PP_MAP == WEILP +#define pp_map_sim_k2(R, P, Q, M) pp_map_sim_weilp_k2(R, P, Q, M) +#elif PP_MAP == TATEP || PP_MAP == OATEP +#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 @@ -457,11 +597,28 @@ * @param[in] M - the number of pairings to evaluate. */ #if PP_MAP == TATEP -#define pp_map_sim_k12(R, P, Q, M) pp_map_sim_tatep_k12(R, P, Q, M) +#define pp_map_sim_k12(R, P, Q, M) pp_map_sim_tatep_k12(R, P, Q, M) #elif PP_MAP == WEILP -#define pp_map_sim_k12(R, P, Q, M) pp_map_sim_weilp_k12(R, P, Q, M) +#define pp_map_sim_k12(R, P, Q, M) pp_map_sim_weilp_k12(R, P, Q, M) #elif PP_MAP == OATEP -#define pp_map_sim_k12(R, P, Q, M) pp_map_sim_oatep_k12(R, P, Q, M) +#define pp_map_sim_k12(R, P, Q, M) pp_map_sim_oatep_k12(R, P, Q, M) +#endif + +/** + * Computes a multi-pairing of elliptic curve points defined on an elliptic + * curve of embedding degree 16. 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. + */ +#if PP_MAP == TATEP +#define pp_map_sim_k16(R, P, Q, M) pp_map_sim_tatep_k16(R, P, Q, M) +#elif PP_MAP == WEILP +#define pp_map_sim_k16(R, P, Q, M) pp_map_sim_weilp_k16(R, P, Q, M) +#elif PP_MAP == OATEP +#define pp_map_sim_k16(R, P, Q, M) pp_map_sim_oatep_k16(R, P, Q, M) #endif /** @@ -474,11 +631,11 @@ * @param[in] M - the number of pairings to evaluate. */ #if PP_MAP == TATEP -#define pp_map_sim_k18(R, P, Q, M) pp_map_sim_tatep_k18(R, P, Q, M) +#define pp_map_sim_k18(R, P, Q, M) pp_map_sim_tatep_k18(R, P, Q, M) #elif PP_MAP == WEILP -#define pp_map_sim_k18(R, P, Q, M) pp_map_sim_weilp_k18(R, P, Q, M) +#define pp_map_sim_k18(R, P, Q, M) pp_map_sim_weilp_k18(R, P, Q, M) #elif PP_MAP == OATEP -#define pp_map_sim_k18(R, P, Q, M) pp_map_sim_oatep_k18(R, P, Q, M) +#define pp_map_sim_k18(R, P, Q, M) pp_map_sim_oatep_k18(R, P, Q, M) #endif /*============================================================================*/ @@ -495,6 +652,31 @@ void pp_map_init(void); */ void pp_map_clean(void); +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 1 using affine coordinates. + * + * @param[out] l - the numerator of the result of the evaluation. + * @param[out] m - the denominator of the result of the evaluation. + * @param[in, out] r - the resulting point and first point to add. + * @param[in] p - the second point to add. + * @param[in] q - the affine point to evaluate the line function. + */ +void pp_add_k1_basic(fp_t l, fp_t m, ep_t r, const ep_t p, const ep_t q); + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 1 using projective + * coordinates. + * + * @param[out] l - the numerator of the result of the evaluation. + * @param[out] m - the denominator of the result of the evaluation. + * @param[in, out] r - the resulting point and first point to add. + * @param[in] p - the second point to add. + * @param[in] q - the affine point to evaluate the line function. + */ +void pp_add_k1_projc(fp_t l, fp_t m, ep_t r, const ep_t p, const ep_t q); + /** * Adds two points and evaluates the corresponding line function at another * point on an elliptic curve with embedding degree 2 using affine coordinates. @@ -612,6 +794,53 @@ void pp_add_k12_projc_lazyr(fp12_t l, ep2_t r, const ep2_t q, const ep_t p); */ void pp_add_lit_k12(fp12_t l, ep_t r, const ep_t p, const ep2_t q); +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 16 using affine coordinates. + * + * @param[out] l - the result of the evaluation. + * @param[in, out] r - the resulting point and first point to add. + * @param[in] q - the second point to add. + * @param[in] p - the affine point to evaluate the line function. + */ +void pp_add_k16_basic(fp16_t l, ep4_t r, const ep4_t q, const ep_t p); + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 16 using projective + * coordinates. + * + * @param[out] l - the result of the evaluation. + * @param[in, out] r - the resulting point and first point to add. + * @param[in] q - the second point to add. + * @param[in] p - the affine point to evaluate the line function. + */ +void pp_add_k16_projc_basic(fp16_t l, ep4_t r, const ep4_t q, const ep_t p); + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 16 using projective + * coordinates and lazy reduction. + * + * @param[out] l - the result of the evaluation. + * @param[in, out] r - the resulting point and first point to add. + * @param[in] q - the second point to add. + * @param[in] p - the affine point to evaluate the line function. + */ +void pp_add_k16_projc_lazyr(fp16_t l, ep4_t r, const ep4_t q, const ep_t p); + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve twist with embedding degree 16 using projective + * coordinates. + * + * @param[out] l - the result of the evaluation. + * @param[in, out] r - the resulting point and first point to add. + * @param[in] p - the second point to add. + * @param[in] q - the affine point to evaluate the line function. + */ +void pp_add_lit_k16(fp16_t l, ep_t r, const ep_t p, const ep4_t q); + /** * Adds two points and evaluates the corresponding line function at another * point on an elliptic curve with embedding degree 18 using affine coordinates. @@ -691,8 +920,7 @@ void pp_add_k24_projc(fp24_t l, ep4_t r, const ep4_t q, const ep_t p); * @param[in] q - the second point to add. * @param[in] p - the affine point to evaluate the line function. */ -void pp_add_k48_basic(fp48_t l, fp8_t rx, fp8_t ry, fp8_t qx, fp8_t qy, - const ep_t p); +void pp_add_k48_basic(fp48_t l, ep8_t r, const ep8_t q, const ep_t p); /** * Adds two points and evaluates the corresponding line function at another @@ -704,8 +932,7 @@ void pp_add_k48_basic(fp48_t l, fp8_t rx, fp8_t ry, fp8_t qx, fp8_t qy, * @param[in] q - the second point to add. * @param[in] p - the affine point to evaluate the line function. */ -void pp_add_k48_projc(fp48_t l, fp8_t rx, fp8_t ry, fp8_t rz, const fp8_t qx, - const fp8_t qy, const ep_t p); +void pp_add_k48_projc(fp48_t l, ep8_t r, const ep8_t q, const ep_t p); /** * Adds two points and evaluates the corresponding line function at another @@ -732,6 +959,32 @@ void pp_add_k54_basic(fp54_t l, fp9_t rx, fp9_t ry, const fp9_t qx, void pp_add_k54_projc(fp54_t l, fp9_t rx, fp9_t ry, fp9_t rz, const fp9_t qx, const fp9_t qy, const ep_t p); +/** + * Doubles a point and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 1 using affine + * coordinates. + * + * @param[out] l - the numerator of the result of the evaluation. + * @param[out] m - the denominator of the result of the evaluation. + * @param[in, out] r - the resulting point. + * @param[in] p - the point to double. + * @param[in] q - the affine point to evaluate the line function. + */ +void pp_dbl_k1_basic(fp_t l, fp_t m, ep_t r, const ep_t p, const ep_t q); + +/** + * Doubles a point and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 1 using projective + * coordinates. + * + * @param[out] l - the numerator of the result of the evaluation. + * @param[out] m - the denominator of the result of the evaluation. + * @param[in, out] r - the resulting point. + * @param[in] p - the point to double. + * @param[in] q - the affine point to evaluate the line function. + */ +void pp_dbl_k1_projc(fp_t l, fp_t m, ep_t r, const ep_t p, const ep_t q); + /** * Doubles a point and evaluates the corresponding line function at another * point on an elliptic curve with embedding degree 2 using affine @@ -746,7 +999,7 @@ void pp_dbl_k2_basic(fp2_t l, ep_t r, const ep_t p, const ep_t q); /** * Doubles a point and evaluates the corresponding line function at another - * point on an elliptic curve with embedding degree 12 using projective + * point on an elliptic curve with embedding degree 2 using projective * coordinates. * * @param[out] l - the result of the evaluation. @@ -758,7 +1011,7 @@ void pp_dbl_k2_projc_basic(fp2_t l, ep_t r, const ep_t p, const ep_t q); /** * Doubles a point and evaluates the corresponding line function at another - * point on an elliptic curve with embedding degree 12 using projective + * point on an elliptic curve with embedding degree 2 using projective * coordinates and lazy reduction. * * @param[out] l - the result of the evaluation. @@ -840,6 +1093,42 @@ void pp_dbl_k12_projc_basic(fp12_t l, ep2_t r, const ep2_t q, const ep_t p); */ void pp_dbl_k12_projc_lazyr(fp12_t l, ep2_t r, const ep2_t q, const ep_t p); +/** + * Doubles a point and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 16 using affine + * coordinates. + * + * @param[out] l - the result of the evaluation. + * @param[in, out] r - the resulting point. + * @param[in] q - the point to double. + * @param[in] p - the affine point to evaluate the line function. + */ +void pp_dbl_k16_basic(fp16_t l, ep4_t r, const ep4_t q, const ep_t p); + +/** + * Doubles a point and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 16 using projective + * coordinates. + * + * @param[out] l - the result of the evaluation. + * @param[in, out] r - the resulting point. + * @param[in] q - the point to double. + * @param[in] p - the affine point to evaluate the line function. + */ +void pp_dbl_k16_projc_basic(fp16_t l, ep4_t r, const ep4_t q, const ep_t p); + +/** + * Doubles a point and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 16 using projective + * coordinates and lazy reduction. + * + * @param[out] l - the result of the evaluation. + * @param[in, out] r - the resulting point. + * @param[in] q - the point to double. + * @param[in] p - the affine point to evaluate the line function. + */ +void pp_dbl_k16_projc_lazyr(fp16_t l, ep4_t r, const ep4_t q, const ep_t p); + /** * Doubles a point and evaluates the corresponding line function at another * point on an elliptic curve with embedding degree 18 using affine @@ -910,7 +1199,7 @@ void pp_dbl_k24_projc(fp24_t l, ep4_t r, const ep4_t q, const ep_t p); * @param[in] q - the point to double. * @param[in] p - the affine point to evaluate the line function. */ -void pp_dbl_k48_basic(fp48_t l, fp8_t rx, fp8_t ry, const ep_t p); +void pp_dbl_k48_basic(fp48_t l, ep8_t r, const ep8_t q, const ep_t p); /** * Doubles a point and evaluates the corresponding line function at another @@ -922,7 +1211,7 @@ void pp_dbl_k48_basic(fp48_t l, fp8_t rx, fp8_t ry, const ep_t p); * @param[in] q - the point to double. * @param[in] p - the affine point to evaluate the line function. */ -void pp_dbl_k48_projc(fp48_t l, fp8_t rx, fp8_t ry, fp8_t rz, const ep_t p); +void pp_dbl_k48_projc(fp48_t l, ep8_t r, const ep8_t q, const ep_t p); /** * Doubles a point and evaluates the corresponding line function at another @@ -960,6 +1249,18 @@ void pp_dbl_k54_projc(fp54_t l, fp9_t rx, fp9_t ry, fp9_t rz, const ep_t p); */ void pp_dbl_lit_k12(fp12_t l, ep_t r, const ep_t p, const ep2_t q); +/** + * Doubles a point and evaluates the corresponding line function at another + * point on an elliptic curve twist with embedding degree 16 using projective + * coordinates. + * + * @param[out] l - the result of the evaluation. + * @param[in, out] r - the resulting point. + * @param[in] p - the point to double. + * @param[in] q - the affine point to evaluate the line function. + */ +void pp_dbl_lit_k16(fp16_t l, ep_t r, const ep_t p, const ep4_t q); + /** * Doubles a point and evaluates the corresponding line function at another * point on an elliptic curve twist with embedding degree 18 using projective @@ -972,6 +1273,15 @@ void pp_dbl_lit_k12(fp12_t l, ep_t r, const ep_t p, const ep2_t q); */ void pp_dbl_lit_k18(fp18_t l, ep_t r, const ep_t p, const ep3_t q); +/** + * Computes the final exponentiation for a pairing defined over curves of + * embedding degree 1. Computes c = a^(p - 1)/r. + * + * @param[out] c - the result. + * @param[in] a - the extension field element to exponentiate. + */ +void pp_exp_k1(fp_t c, fp_t a); + /** * Computes the final exponentiation for a pairing defined over curves of * embedding degree 2. Computes c = a^(p^2 - 1)/r. @@ -999,6 +1309,15 @@ void pp_exp_k8(fp8_t c, fp8_t a); */ void pp_exp_k12(fp12_t c, fp12_t a); +/** + * Computes the final exponentiation for a pairing defined over curves of + * embedding degree 16. Computes c = a^(p^16 - 1)/r. + * + * @param[out] c - the result. + * @param[in] a - the extension field element to exponentiate. + */ +void pp_exp_k16(fp16_t c, fp16_t a); + /** * Computes the final exponentiation for a pairing defined over curves of * embedding degree 18. Computes c = a^(p^18 - 1)/r. @@ -1035,6 +1354,15 @@ void pp_exp_k48(fp48_t c, fp48_t a); */ void pp_exp_k54(fp54_t c, fp54_t a); +/** + * Normalizes the accumulator point used inside pairing computation defined + * over curves of embedding degree 1. + * + * @param[out] r - the resulting point. + * @param[in] p - the point to normalize. + */ +void pp_norm_k1(ep_t c, const ep_t a); + /** * Normalizes the accumulator point used inside pairing computation defined * over curves of embedding degree 2. @@ -1062,6 +1390,15 @@ void pp_norm_k8(ep2_t c, const ep2_t a); */ void pp_norm_k12(ep2_t c, const ep2_t a); +/** + * Normalizes the accumulator point used inside pairing computation defined + * over curves of embedding degree 16. + * + * @param[out] r - the resulting point. + * @param[in] p - the point to normalize. + */ +void pp_norm_k16(ep4_t c, const ep4_t a); + /** * Normalizes the accumulator point used inside pairing computation defined * over curves of embedding degree 18. @@ -1080,9 +1417,39 @@ void pp_norm_k18(ep3_t c, const ep3_t a); */ void pp_norm_k24(ep4_t c, const ep4_t a); +/** + * Normalizes the accumulator point used inside pairing computation defined + * over curves of embedding degree 48. + * + * @param[out] r - the resulting point. + * @param[in] p - the point to normalize. + */ +void pp_norm_k48(ep8_t c, const ep8_t a); + /** * Computes the Tate pairing of two points in a parameterized elliptic curve - * with embedding degree 12. + * with embedding degree 1. + * + * @param[out] r - the result. + * @param[in] q - the first elliptic curve point. + * @param[in] p - the second elliptic curve point. + */ +void pp_map_tatep_k1(fp_t r, const ep_t p, const ep_t q); + +/** + * Computes the Tate multi-pairing in a parameterized elliptic curve with + * embedding degree 1. + * + * @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_tatep_k1(fp_t r, const ep_t *p, const ep_t *q, int m); + +/** + * Computes the Tate pairing of two points in a parameterized elliptic curve + * with embedding degree 2. * * @param[out] r - the result. * @param[in] q - the first elliptic curve point. @@ -1091,7 +1458,7 @@ void pp_norm_k24(ep4_t c, const ep4_t a); void pp_map_tatep_k2(fp2_t r, const ep_t p, const ep_t q); /** - * Computes the Tate multi-pairing of in a parameterized elliptic curve with + * Computes the Tate multi-pairing in a parameterized elliptic curve with * embedding degree 2. * * @param[out] r - the result. @@ -1103,26 +1470,37 @@ void pp_map_sim_tatep_k2(fp2_t r, const ep_t *p, const ep_t *q, int m); /** * Computes the Weil pairing of two points in a parameterized elliptic curve - * with embedding degree 2. + * with embedding degree 1. * * @param[out] r - the result. * @param[in] q - the first elliptic curve point. * @param[in] p - the second elliptic curve point. */ -void pp_map_weilp_k2(fp2_t r, const ep_t p, const ep_t q); +void pp_map_weilp_k1(fp_t r, const ep_t p, const ep_t q); /** - * Computes the optimal ate pairing of two points in a parameterized elliptic - * curve with embedding degree 8. + * Computes the Weil multi-pairing in a parameterized elliptic curve with + * embedding degree 1. + * + * @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_weilp_k1(fp_t r, const ep_t *p, const ep_t *q, int m); + +/** + * Computes the Weil pairing of two points in a parameterized elliptic curve + * with embedding degree 2. * * @param[out] r - the result. * @param[in] q - the first elliptic curve point. * @param[in] p - the second elliptic curve point. */ -void pp_map_oatep_k8(fp8_t r, const ep_t p, const ep2_t q); +void pp_map_weilp_k2(fp2_t r, const ep_t p, const ep_t q); /** - * Computes the Weil multi-pairing of in a parameterized elliptic curve with + * Computes the Weil multi-pairing in a parameterized elliptic curve with * embedding degree 2. * * @param[out] r - the result. @@ -1132,6 +1510,16 @@ void pp_map_oatep_k8(fp8_t r, const ep_t p, const ep2_t q); */ void pp_map_sim_weilp_k2(fp2_t r, const ep_t *p, const ep_t *q, int m); +/** + * Computes the optimal ate pairing of two points in a parameterized elliptic + * curve with embedding degree 8. + * + * @param[out] r - the result. + * @param[in] q - the first elliptic curve point. + * @param[in] p - the second elliptic curve point. + */ +void pp_map_oatep_k8(fp8_t r, const ep_t p, const ep2_t q); + /** * Computes the Tate pairing of two points in a parameterized elliptic curve * with embedding degree 12. @@ -1143,7 +1531,7 @@ void pp_map_sim_weilp_k2(fp2_t r, const ep_t *p, const ep_t *q, int m); void pp_map_tatep_k12(fp12_t r, const ep_t p, const ep2_t q); /** - * Computes the Tate multi-pairing of in a parameterized elliptic curve with + * Computes the Tate multi-pairing in a parameterized elliptic curve with * embedding degree 12. * * @param[out] r - the result. @@ -1164,7 +1552,7 @@ void pp_map_sim_tatep_k12(fp12_t r, const ep_t *p, const ep2_t *q, int m); void pp_map_weilp_k12(fp12_t r, const ep_t p, const ep2_t q); /** - * Computes the Weil multi-pairing of in a parameterized elliptic curve with + * Computes the Weil multi-pairing in a parameterized elliptic curve with * embedding degree 12. * * @param[out] r - the result. @@ -1185,7 +1573,7 @@ void pp_map_sim_weilp_k12(fp12_t r, const ep_t *p, const ep2_t *q, int m); void pp_map_oatep_k12(fp12_t r, const ep_t p, const ep2_t q); /** - * Computes the optimal ate multi-pairing of in a parameterized elliptic + * Computes the optimal ate multi-pairing in a parameterized elliptic * curve with embedding degree 12. * * @param[out] r - the result. @@ -1195,6 +1583,69 @@ void pp_map_oatep_k12(fp12_t r, const ep_t p, const ep2_t q); */ void pp_map_sim_oatep_k12(fp12_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 16. + * + * @param[out] r - the result. + * @param[in] q - the first elliptic curve point. + * @param[in] p - the second elliptic curve point. + */ +void pp_map_tatep_k16(fp16_t r, const ep_t p, const ep4_t q); + +/** + * Computes the Tate multi-pairing in a parameterized elliptic curve with + * embedding degree 16. + * + * @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_tatep_k16(fp16_t r, const ep_t *p, const ep4_t *q, int m); + +/** + * Computes the Weil pairing of two points in a parameterized elliptic curve + * with embedding degree 16. + * + * @param[out] r - the result. + * @param[in] q - the first elliptic curve point. + * @param[in] p - the second elliptic curve point. + */ +void pp_map_weilp_k16(fp16_t r, const ep_t p, const ep4_t q); + +/** + * Computes the Weil multi-pairing in a parameterized elliptic curve with + * embedding degree 16. + * + * @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_weilp_k16(fp16_t r, const ep_t *p, const ep4_t *q, int m); + +/** + * Computes the optimal ate pairing of two points in a parameterized elliptic + * curve with embedding degree 16. + * + * @param[out] r - the result. + * @param[in] q - the first elliptic curve point. + * @param[in] p - the second elliptic curve point. + */ +void pp_map_oatep_k16(fp16_t r, const ep_t p, const ep4_t q); + +/** + * Computes the optimal ate multi-pairing in a parameterized elliptic + * curve with embedding degree 16. + * + * @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_k16(fp16_t r, const ep_t *p, const ep4_t *q, int m); + /** * Computes the Tate pairing of two points in a parameterized elliptic curve * with embedding degree 18. @@ -1206,7 +1657,7 @@ void pp_map_sim_oatep_k12(fp12_t r, const ep_t *p, const ep2_t *q, int m); void pp_map_tatep_k18(fp18_t r, const ep_t p, const ep3_t q); /** - * Computes the Tate multi-pairing of in a parameterized elliptic curve with + * Computes the Tate multi-pairing in a parameterized elliptic curve with * embedding degree 18. * * @param[out] r - the result. @@ -1227,7 +1678,7 @@ void pp_map_sim_tatep_k18(fp18_t r, const ep_t *p, const ep3_t *q, int m); void pp_map_weilp_k18(fp18_t r, const ep_t p, const ep3_t q); /** - * Computes the Weil multi-pairing of in a parameterized elliptic curve with + * Computes the Weil multi-pairing in a parameterized elliptic curve with * embedding degree 18. * * @param[out] r - the result. @@ -1248,7 +1699,7 @@ void pp_map_sim_weilp_k18(fp18_t r, const ep_t *p, const ep3_t *q, int m); void pp_map_oatep_k18(fp18_t r, const ep_t p, const ep3_t q); /** - * Computes the optimal ate multi-pairing of in a parameterized elliptic + * Computes the optimal ate multi-pairing in a parameterized elliptic * curve with embedding degree 18. * * @param[out] r - the result. @@ -1269,7 +1720,7 @@ void pp_map_sim_oatep_k18(fp18_t r, const ep_t *p, const ep3_t *q, int m); void pp_map_k24(fp24_t r, const ep_t p, const ep4_t q); /** - * Computes the optimal ate multi-pairing of in a parameterized elliptic + * Computes the optimal ate multi-pairing in a parameterized elliptic * curve with embedding degree 24. * * @param[out] r - the result. @@ -1287,7 +1738,18 @@ void pp_map_sim_k24(fp24_t r, const ep_t *p, const ep4_t *q, int m); * @param[in] q - the first elliptic curve point. * @param[in] p - the second elliptic curve point. */ -void pp_map_k48(fp48_t r, const ep_t p, const fp8_t qx, const fp8_t qy); +void pp_map_k48(fp48_t r, const ep_t p, const ep8_t q); + +/** + * Computes the optimal ate multi-pairing in a parameterized elliptic + * curve with embedding degree 48. + * + * @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_k48(fp48_t r, const ep_t *p, const ep8_t *q, int m); /** * Computes the Optimal Ate pairing of two points in a parameterized elliptic diff --git a/include/relic_types.h b/include/relic_types.h index ca034d5cd..7c6b93a7f 100644 --- a/include/relic_types.h +++ b/include/relic_types.h @@ -178,7 +178,7 @@ typedef unsigned long uint_t; #if ALIGN > 1 #define rlc_align __attribute__ ((aligned (ALIGN))) #else -#define rlc_align /* empty*/ +#define rlc_align /* empty */ #endif /** diff --git a/preset/avr-pbc-80.sh b/preset/avr-pbc-80.sh index 4bf44ede6..fb5ef4235 100755 --- a/preset/avr-pbc-80.sh +++ b/preset/avr-pbc-80.sh @@ -1,2 +1,2 @@ #!/bin/sh -CC=avr-gcc CXX=c++ LDFLAGS="-mmcu=atmega128 -Wl,-gc-sections" CFLAGS="-O2 -ggdb -Wa,-mmcu=atmega128 -mmcu=atmega128 -ffunction-sections -fdata-sections" cmake -DARCH=AVR -DWSIZE=8 -DOPSYS= -DSEED=LIBC -DSHLIB=OFF -DSTBIN=ON -DTIMER= -DWITH="DV;MD;BN;FP;FPX;EP;EC;PP;PC" -DBENCH=20 -DTESTS=20 -DCHECK=off -DVERBS=off -DSTRIP=on -DQUIET=on -DARITH=avr-asm-158 -DFP_PRIME=158 -DBN_METHD="COMBA;COMBA;MONTY;BASIC;BINAR;LOWER;BASIC" -DFP_QNRES=off -DFP_METHD="INTEG;COMBA;COMBA;MONTY;MONTY;SLIDE" -DBN_PRECI=160 -DBN_MAGNI=DOUBLE -DEP_PRECO=off -DEP_METHD="PROJC;LWNAF;LWNAF;BASIC" -DEP_ENDOM=on -DEP_PLAIN=on -DEC_METHD="PRIME" -DFPX_METHD="INTEG;INTEG;BASIC" -DPP_METHD="BASIC;OATEP" -DRAND=HASHD -DSEED=LIBC -DMD_METHD=SH256 $1 +CC=avr-gcc CXX=c++ LDFLAGS="-mmcu=atmega128 -Wl,-gc-sections" CFLAGS="-O2 -ggdb -Wa,-mmcu=atmega128 -mmcu=atmega128 -ffunction-sections -fdata-sections" cmake -DARCH=AVR -DWSIZE=8 -DOPSYS= -DSEED=LIBC -DSHLIB=OFF -DSTBIN=ON -DTIMER= -DWITH="DV;MD;BN;FP;FPX;EP;EC;PP;PC" -DBENCH=20 -DTESTS=20 -DCHECK=off -DVERBS=off -DSTRIP=on -DQUIET=on -DARITH=avr-asm-158 -DFP_PRIME=158 -DBN_METHD="COMBA;COMBA;MONTY;BASIC;BINAR;LOWER;BASIC" -DFP_QNRES=off -DFP_METHD="INTEG;COMBA;COMBA;MONTY;MONTY;SLIDE" -DBN_PRECI=160 -DBN_MAGNI=DOUBLE -DEP_PRECO=off -DEP_METHD="PROJC;LWNAF;LWNAF;BASIC;SSWUM" -DEP_ENDOM=on -DEP_PLAIN=on -DEC_METHD="PRIME" -DFPX_METHD="INTEG;INTEG;BASIC" -DPP_METHD="BASIC;OATEP" -DRAND=HASHD -DSEED=LIBC -DMD_METHD=SH256 $1 diff --git a/preset/fiat-pbc-bls381.sh b/preset/fiat-pbc-bls381.sh index 51143840f..e0575f649 100755 --- a/preset/fiat-pbc-bls381.sh +++ b/preset/fiat-pbc-bls381.sh @@ -1,2 +1,2 @@ #!/bin/sh -cmake -DCHECK=off -DARITH=x64-fiat-381 -DFP_PRIME=381 -DFP_QNRES=on -DFP_METHD="BASIC;COMBA;COMBA;MONTY;LOWER;LOWER;SLIDE" -DFPX_METHD="INTEG;INTEG;LAZYR" -DPP_METHD="LAZYR;OATEP" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -finline-small-functions -march=native -mtune=native" $1 +cmake -DCHECK=off -DARITH=x64-fiat-381 -DFP_PRIME=381 -DFP_QNRES=on -DFP_METHD="BASIC;COMBA;COMBA;MONTY;JMPDS;JMPDS;SLIDE" -DFPX_METHD="INTEG;INTEG;LAZYR" -DPP_METHD="LAZYR;OATEP" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -finline-small-functions -march=native -mtune=native" $1 diff --git a/preset/gmp-pbc-bls381.sh b/preset/gmp-pbc-bls381.sh index 3fc96146a..8de5aac57 100755 --- a/preset/gmp-pbc-bls381.sh +++ b/preset/gmp-pbc-bls381.sh @@ -1,2 +1,2 @@ #!/bin/sh -cmake -DCHECK=off -DARITH=gmp -DFP_PRIME=381 -DFP_QNRES=on -DFP_METHD="BASIC;COMBA;COMBA;MONTY;LOWER;LOWER;SLIDE" -DFPX_METHD="INTEG;INTEG;LAZYR" -DPP_METHD="LAZYR;OATEP" -DCFLAGS="-O2 -funroll-loops -fomit-frame-pointer" $1 +cmake -DCHECK=off -DARITH=gmp -DFP_PRIME=381 -DFP_QNRES=on -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" $1 diff --git a/preset/gmp-pbc-bn254.sh b/preset/gmp-pbc-bn254.sh index ce18da40a..cf29d8bfa 100755 --- a/preset/gmp-pbc-bn254.sh +++ b/preset/gmp-pbc-bn254.sh @@ -1,2 +1,2 @@ #!/bin/sh -cmake -DCHECK=off -DARITH=gmp -DFP_PRIME=254 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;LOWER;LOWER;SLIDE" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -finline-small-functions -march=native -mtune=native" -DFP_PMERS=off -DFP_QNRES=on -DFPX_METHD="INTEG;INTEG;LAZYR" -DPP_METHD="LAZYR;OATEP" $1 +cmake -DCHECK=off -DARITH=gmp -DFP_PRIME=254 -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=on -DFPX_METHD="INTEG;INTEG;LAZYR" -DPP_METHD="LAZYR;OATEP" $1 diff --git a/preset/gmp-pbc-ss1536.sh b/preset/gmp-pbc-ss1536.sh index e08dbb044..3879f4c30 100755 --- a/preset/gmp-pbc-ss1536.sh +++ b/preset/gmp-pbc-ss1536.sh @@ -1,2 +1,2 @@ #!/bin/sh -cmake -DCHECK=off -DARITH=gmp -DBN_PRECI=1536 -DFP_PRIME=1536 -DFP_QNRES=on -DFP_METHD="BASIC;COMBA;COMBA;MONTY;LOWER;LOWER;SLIDE" -DFPX_METHD="INTEG;INTEG;LAZYR" -DPP_METHD="LAZYR;OATEP" -DCFLAGS="-O2 -funroll-loops -fomit-frame-pointer" $1 +cmake -DCHECK=off -DARITH=gmp -DBN_PRECI=1536 -DFP_PRIME=1536 -DFP_QNRES=on -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" $1 diff --git a/preset/x64-ecc-128.sh b/preset/x64-ecc-128.sh index bc6009727..dd05a799b 100755 --- a/preset/x64-ecc-128.sh +++ b/preset/x64-ecc-128.sh @@ -1,2 +1,2 @@ #!/bin/sh -cmake -DCHECK=off -DARITH=x64-hacl-25519 -DFP_PRIME=255 -DFP_QNRES=off -DEC_METHD="EDDIE" -DFP_METHD="INTEG;INTEG;INTEG;QUICK;LOWER;LOWER;SLIDE" -DED_METHD='EXTND;LWNAF;COMBS;INTER' -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -march=native -mtune=native" $1 +cmake -DCHECK=off -DARITH=x64-hacl-25519 -DFP_PRIME=255 -DFP_QNRES=off -DSTRIP=on -DEC_ENDOM=off -DEC_METHD="EDDIE" -DFP_METHD="INTEG;INTEG;INTEG;QUICK;JMPDS;JMPDS;SLIDE" -DED_METHD='EXTND;LWNAF;COMBS;INTER' -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -march=native -mtune=native" -DWITH="DV;MD;BC;BN;FP;ED;EC;CP" $1 diff --git a/preset/x64-pbc-afg16-765.sh b/preset/x64-pbc-afg16-765.sh new file mode 100755 index 000000000..4cc9fbcdb --- /dev/null +++ b/preset/x64-pbc-afg16-765.sh @@ -0,0 +1,2 @@ +#!/bin/sh +cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-12l -DBN_PRECI=3072 -DFP_PRIME=765 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;JMPDS;JMPDS;SLIDE" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -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" -DWITH="ALL" $1 diff --git a/preset/x64-pbc-bls12-377.sh b/preset/x64-pbc-bls12-377.sh index a5fbe7367..82f57ec53 100755 --- a/preset/x64-pbc-bls12-377.sh +++ b/preset/x64-pbc-bls12-377.sh @@ -1,2 +1,2 @@ #!/bin/sh -cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-6l -DFP_PRIME=377 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;LOWER;LOWER;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 +cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-6l -DFP_PRIME=377 -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/x64-pbc-bls12-381.sh b/preset/x64-pbc-bls12-381.sh index e3ed68136..8e388f68b 100755 --- a/preset/x64-pbc-bls12-381.sh +++ b/preset/x64-pbc-bls12-381.sh @@ -1,2 +1,2 @@ #!/bin/sh -cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-6l -DFP_PRIME=381 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;LOWER;LOWER;SLIDE" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -finline-small-functions -march=native -mtune=native" -DFP_PMERS=off -DFP_QNRES=on -DFPX_METHD="INTEG;INTEG;LAZYR" -DEP_PLAIN=off -DEP_SUPER=off -DPP_METHD="LAZYR;OATEP" $1 +cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-6l -DFP_PRIME=381 -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=on -DFPX_METHD="INTEG;INTEG;LAZYR" -DEP_METHD="JACOB;LWNAF;COMBS;INTER;SWIFT" -DEP_PLAIN=off -DEP_SUPER=off -DPP_METHD="LAZYR;OATEP" $1 diff --git a/preset/x64-pbc-bls12-446.sh b/preset/x64-pbc-bls12-446.sh index 07406b5df..26bd71d20 100755 --- a/preset/x64-pbc-bls12-446.sh +++ b/preset/x64-pbc-bls12-446.sh @@ -1,2 +1,2 @@ #!/bin/sh -cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-7l -DFP_PRIME=446 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;LOWER;LOWER;SLIDE" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -finline-small-functions -march=native -mtune=native" -DFP_PMERS=off -DFP_QNRES=on -DFPX_METHD="INTEG;INTEG;LAZYR" -DEP_PLAIN=off -DEP_SUPER=off -DPP_METHD="LAZYR;OATEP" $1 +cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-7l -DFP_PRIME=446 -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=on -DFPX_METHD="INTEG;INTEG;LAZYR" -DEP_PLAIN=off -DEP_SUPER=off -DPP_METHD="LAZYR;OATEP" $1 diff --git a/preset/x64-pbc-bls12-455.sh b/preset/x64-pbc-bls12-455.sh index 302570ad2..9cb313591 100755 --- a/preset/x64-pbc-bls12-455.sh +++ b/preset/x64-pbc-bls12-455.sh @@ -1,2 +1,2 @@ #!/bin/sh -cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-8l -DFP_PRIME=455 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;LOWER;LOWER;SLIDE" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -finline-small-functions -march=native -mtune=native" -DFP_PMERS=off -DFP_QNRES=on -DFPX_METHD="INTEG;INTEG;LAZYR" -DEP_PLAIN=off -DEP_SUPER=off -DPP_METHD="LAZYR;OATEP" $1 +cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-8l -DFP_PRIME=455 -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=on -DFPX_METHD="INTEG;INTEG;LAZYR" -DEP_PLAIN=off -DEP_SUPER=off -DPP_METHD="LAZYR;OATEP" $1 diff --git a/preset/x64-pbc-bls12-638.sh b/preset/x64-pbc-bls12-638.sh index 2b4eaabab..f9e551709 100755 --- a/preset/x64-pbc-bls12-638.sh +++ b/preset/x64-pbc-bls12-638.sh @@ -1,2 +1,2 @@ #!/bin/sh -cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-10l -DFP_PRIME=638 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;LOWER;LOWER;SLIDE" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -finline-small-functions -march=native -mtune=native" -DFP_PMERS=off -DFP_QNRES=on -DFPX_METHD="INTEG;INTEG;LAZYR" -DEP_PLAIN=off -DEP_SUPER=off -DPP_METHD="LAZYR;OATEP" $1 +cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-10l -DFP_PRIME=638 -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=on -DFPX_METHD="INTEG;INTEG;LAZYR" -DEP_PLAIN=off -DEP_SUPER=off -DPP_METHD="LAZYR;OATEP" $1 diff --git a/preset/x64-pbc-bls24-315.sh b/preset/x64-pbc-bls24-315.sh index d7a294c9a..d80fb07ba 100755 --- a/preset/x64-pbc-bls24-315.sh +++ b/preset/x64-pbc-bls24-315.sh @@ -1,2 +1,2 @@ #!/bin/sh -cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-5l -DFP_PRIME=315 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;LOWER;LOWER;SLIDE" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -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" -DWITH="ALL" $1 +cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-5l -DFP_PRIME=315 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;JMPDS;JMPDS;SLIDE" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -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" -DWITH="ALL" $1 diff --git a/preset/x64-pbc-bls24-317.sh b/preset/x64-pbc-bls24-317.sh index 987b3b7f8..80d80dc83 100755 --- a/preset/x64-pbc-bls24-317.sh +++ b/preset/x64-pbc-bls24-317.sh @@ -1,2 +1,2 @@ #!/bin/sh -cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-5l -DFP_PRIME=317 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;LOWER;LOWER;SLIDE" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -march=native -mtune=native" -DFP_PMERS=off -DFP_QNRES=on -DFPX_METHD="INTEG;INTEG;LAZYR" -DEP_PLAIN=off -DEP_SUPER=off -DPP_METHD="LAZYR;OATEP" -DWITH="ALL" $1 +cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-5l -DFP_PRIME=317 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;JMPDS;JMPDS;SLIDE" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -march=native -mtune=native" -DFP_PMERS=off -DFP_QNRES=on -DFPX_METHD="INTEG;INTEG;LAZYR" -DEP_PLAIN=off -DEP_SUPER=off -DPP_METHD="LAZYR;OATEP" -DWITH="ALL" $1 diff --git a/preset/x64-pbc-bls24-509.sh b/preset/x64-pbc-bls24-509.sh index 51eafeae6..3792bd2f7 100755 --- a/preset/x64-pbc-bls24-509.sh +++ b/preset/x64-pbc-bls24-509.sh @@ -1,2 +1,2 @@ #!/bin/sh -cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-8l -DFP_PRIME=509 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;LOWER;LOWER;SLIDE" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -march=native -mtune=native" -DFP_PMERS=off -DFP_QNRES=on -DFPX_METHD="INTEG;INTEG;LAZYR" -DEP_PLAIN=off -DEP_SUPER=off -DPP_METHD="LAZYR;OATEP" -DWITH="ALL" $1 +cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-8l -DFP_PRIME=509 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;JMPDS;JMPDS;SLIDE" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -march=native -mtune=native" -DFP_PMERS=off -DFP_QNRES=on -DFPX_METHD="INTEG;INTEG;LAZYR" -DEP_METHD="JACOB;LWNAF;COMBS;INTER;SWIFT" -DEP_PLAIN=off -DEP_SUPER=off -DPP_METHD="LAZYR;OATEP" -DWITH="ALL" $1 diff --git a/preset/x64-pbc-bls48-575.sh b/preset/x64-pbc-bls48-575.sh index 83c171bcd..32388fe17 100755 --- a/preset/x64-pbc-bls48-575.sh +++ b/preset/x64-pbc-bls48-575.sh @@ -1,2 +1,2 @@ #!/bin/sh -cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-9l -DFP_PRIME=575 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;LOWER;LOWER;SLIDE" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -finline-small-functions -march=native -mtune=native" -DFP_PMERS=off -DFP_QNRES=on -DFPX_METHD="INTEG;INTEG;LAZYR" -DEP_PLAIN=off -DEP_SUPER=off -DPP_METHD="LAZYR;OATEP" $1 +cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-9l -DBN_PRECI=3072 -DFP_PRIME=575 -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=on -DFPX_METHD="INTEG;INTEG;LAZYR" -DEP_METHD="JACOB;LWNAF;COMBS;INTER;SWIFT" -DEP_PLAIN=off -DEP_SUPER=off -DPP_METHD="LAZYR;OATEP" $1 diff --git a/preset/x64-pbc-bn254.sh b/preset/x64-pbc-bn254.sh index b3a0924cd..59f61e4d4 100755 --- a/preset/x64-pbc-bn254.sh +++ b/preset/x64-pbc-bn254.sh @@ -1,2 +1,2 @@ #!/bin/sh -cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-4l -DFP_PRIME=254 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;LOWER;LOWER;SLIDE" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -finline-small-functions -march=native -mtune=native" -DFP_PMERS=off -DFP_QNRES=on -DFPX_METHD="INTEG;INTEG;LAZYR" -DPP_METHD="LAZYR;OATEP" $1 +cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-4l -DFP_PRIME=254 -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=on -DFPX_METHD="INTEG;INTEG;LAZYR" -DPP_METHD="LAZYR;OATEP" $1 diff --git a/preset/x64-pbc-bn382.sh b/preset/x64-pbc-bn382.sh index bb3094695..b62906f6d 100755 --- a/preset/x64-pbc-bn382.sh +++ b/preset/x64-pbc-bn382.sh @@ -1,2 +1,2 @@ #!/bin/sh -cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-6l -DFP_PRIME=382 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;LOWER;LOWER;SLIDE" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -finline-small-functions -march=native -mtune=native" -DFP_PMERS=off -DFP_QNRES=on -DFPX_METHD="INTEG;INTEG;LAZYR" -DEP_PLAIN=off -DEP_SUPER=off -DPP_METHD="LAZYR;OATEP" $1 +cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-6l -DFP_PRIME=382 -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=on -DFPX_METHD="INTEG;INTEG;LAZYR" -DEP_PLAIN=off -DEP_SUPER=off -DPP_METHD="LAZYR;OATEP" $1 diff --git a/preset/x64-pbc-bn446.sh b/preset/x64-pbc-bn446.sh index fb353e6b1..6fff36685 100755 --- a/preset/x64-pbc-bn446.sh +++ b/preset/x64-pbc-bn446.sh @@ -1,2 +1,2 @@ #!/bin/sh -cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-7l -DFP_PRIME=446 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;LOWER;LOWER;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 +cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-7l -DFP_PRIME=446 -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/x64-pbc-kss16-330.sh b/preset/x64-pbc-kss16-330.sh new file mode 100755 index 000000000..86457dbbe --- /dev/null +++ b/preset/x64-pbc-kss16-330.sh @@ -0,0 +1,2 @@ +#!/bin/sh +cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-6l -DFP_PRIME=330 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;JMPDS;JMPDS;SLIDE" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -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" -DWITH="ALL" $1 diff --git a/preset/x64-pbc-kss16-766.sh b/preset/x64-pbc-kss16-766.sh new file mode 100755 index 000000000..1f1de18ae --- /dev/null +++ b/preset/x64-pbc-kss16-766.sh @@ -0,0 +1,2 @@ +#!/bin/sh +cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-12l -DBN_PRECI=3072 -DFP_PRIME=766 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;JMPDS;JMPDS;SLIDE" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -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" -DWITH="ALL" $1 diff --git a/preset/x64-pbc-kss18-638.sh b/preset/x64-pbc-kss18-638.sh index ffffd7aea..c5806438a 100755 --- a/preset/x64-pbc-kss18-638.sh +++ b/preset/x64-pbc-kss18-638.sh @@ -1,2 +1,2 @@ #!/bin/sh -cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-10l -DFP_PRIME=638 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;LOWER;LOWER;SLIDE" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -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" -DWITH="ALL" $1 +cmake -DWSIZE=64 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=x64-asm-10l -DFP_PRIME=638 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;JMPDS;JMPDS;SLIDE" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -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" -DWITH="ALL" $1 diff --git a/src/bn/relic_bn_prime.c b/src/bn/relic_bn_prime.c index 044748601..d562780dc 100644 --- a/src/bn/relic_bn_prime.c +++ b/src/bn/relic_bn_prime.c @@ -286,7 +286,7 @@ int bn_is_prime_rabin(const bn_t a) { bn_set_dig(t, primes[i]); /* Ensure t <= n - 2 as per HAC */ - if( bn_cmp(t, n1) != RLC_LT ) { + if (bn_cmp(t, n1) != RLC_LT) { result = 1; break; } @@ -523,32 +523,34 @@ int bn_gen_prime_factor(bn_t a, bn_t b, size_t abits, size_t bbits) { bn_t t, u; int result = RLC_OK; - if (! (bbits>abits) ) { + if (!(bbits > abits)) { return RLC_ERR; - } + } - bn_null(t); + bn_null(t); bn_null(u); - RLC_TRY { - bn_new(t); + RLC_TRY { + bn_new(t); + bn_new(u); + bn_gen_prime(a, abits); - bn_set_dig(t,1); - bn_lsh(t, t, bbits - bn_bits(a) - 1); - do { - bn_rand(u, RLC_POS, bbits - bn_bits(a) - 1); - bn_add(u, u, t); - bn_mul(b, a, u); - bn_add_dig(b, b, 1); - } while ((bn_bits(b) != bbits) || (! bn_is_prime(b))); - } - RLC_CATCH_ANY { + bn_set_dig(t, 1); + bn_lsh(t, t, bbits - bn_bits(a) - 1); + do { + bn_rand(u, RLC_POS, bbits - bn_bits(a) - 1); + bn_add(u, u, t); + bn_mul(b, a, u); + bn_add_dig(b, b, 1); + } while ((bn_bits(b) != bbits) || (!bn_is_prime(b))); + } + RLC_CATCH_ANY { result = RLC_ERR; - } - RLC_FINALLY { - bn_free(t); + } + RLC_FINALLY { + bn_free(t); bn_free(u); - } + } - return result; + return result; } diff --git a/src/cp/relic_cp_cmlhs.c b/src/cp/relic_cp_cmlhs.c index 83b8c0980..db734fe8e 100644 --- a/src/cp/relic_cp_cmlhs.c +++ b/src/cp/relic_cp_cmlhs.c @@ -79,8 +79,7 @@ int cp_cmlhs_gen(bn_t x[], gt_t hs[], size_t len, uint8_t prf[], size_t plen, result = cp_bls_gen(sk, pk); } else { if (cp_ecdsa_gen(sk, g1) == RLC_OK) { - fp_copy(pk->x[0], g1->x); - fp_copy(pk->y[0], g1->y); + g2_set_g1(pk, g1); } else { result = RLC_ERR; } @@ -106,7 +105,7 @@ int cp_cmlhs_sig(g1_t sig, g2_t z, g1_t a, g1_t c, g1_t r, g2_t s, g1_t t; uint8_t mac[RLC_MD_LEN]; size_t len, dlen = strlen(data); - uint8_t *buf = RLC_ALLOCA(uint8_t, 1 + 8 * RLC_PC_BYTES + dlen); + uint8_t *buf = RLC_ALLOCA(uint8_t, 1 + 16 * RLC_PC_BYTES + dlen); int result = RLC_OK; bn_null(k); @@ -217,7 +216,7 @@ int cp_cmlhs_ver(const g1_t r, const g2_t s, const g1_t sig[], const g2_t z[], gt_t e, u, v; bn_t k, n; size_t len, dlen = strlen(data); - uint8_t *buf = RLC_ALLOCA(uint8_t, 1 + 8 * RLC_PC_BYTES + dlen); + uint8_t *buf = RLC_ALLOCA(uint8_t, 1 + g2_size_bin(s, 0) + dlen); int result = 1; g1_null(g1); @@ -249,8 +248,7 @@ int cp_cmlhs_ver(const g1_t r, const g2_t s, const g1_t sig[], const g2_t z[], } else { fp_prime_back(k, sig[i]->x); fp_prime_back(n, sig[i]->y); - fp_copy(g1->x, pk[i]->x[0]); - fp_copy(g1->y, pk[i]->y[0]); + g1_set_g2(g1, pk[i]); fp_set_dig(g1->z, 1); result &= cp_ecdsa_ver(k, n, buf, len + dlen, 0, g1); } @@ -338,7 +336,7 @@ int cp_cmlhs_onv(const g1_t r, const g2_t s, const g1_t sig[], const g2_t z[], gt_t e, u, v; bn_t k, n; size_t len, dlen = strlen(data); - uint8_t *buf = RLC_ALLOCA(uint8_t, 1 + 8 * RLC_FP_BYTES + dlen); + uint8_t *buf = RLC_ALLOCA(uint8_t, 1 + g2_size_bin(s, 0) + dlen); int result = 1; g1_null(g1); @@ -370,9 +368,7 @@ int cp_cmlhs_onv(const g1_t r, const g2_t s, const g1_t sig[], const g2_t z[], } else { fp_prime_back(k, sig[i]->x); fp_prime_back(n, sig[i]->y); - fp_copy(g1->x, pk[i]->x[0]); - fp_copy(g1->y, pk[i]->y[0]); - fp_set_dig(g1->z, 1); + g1_set_g2(g1, pk[i]); result &= cp_ecdsa_ver(k, n, buf, len + dlen, 0, g1); } } diff --git a/src/cp/relic_cp_rsa.c b/src/cp/relic_cp_rsa.c index eb5565a00..c7ea1d67f 100644 --- a/src/cp/relic_cp_rsa.c +++ b/src/cp/relic_cp_rsa.c @@ -246,7 +246,7 @@ static uint8_t *hash_id(int md, int *len) { */ static int pad_pkcs1(bn_t m, int *p_len, size_t m_len, size_t k_len, int op) { uint8_t *id, pad = 0; - size_t len; + size_t len = 0; int result = RLC_ERR; bn_t t; diff --git a/src/eb/relic_eb_map.c b/src/eb/relic_eb_map.c index 69fd5ba7d..bbc61810f 100644 --- a/src/eb/relic_eb_map.c +++ b/src/eb/relic_eb_map.c @@ -56,8 +56,6 @@ void eb_map(eb_t p, const uint8_t *msg, size_t len) { fb_set_dig(p->z, 1); while (1) { - bn_add_dig(k, k, 1); - bn_mod_2b(k, k, RLC_FB_BITS); dv_copy(p->x, k->dp, RLC_FB_DIGS); eb_rhs(t1, p); @@ -68,7 +66,10 @@ void eb_map(eb_t p, const uint8_t *msg, size_t len) { /* t0 = t1/x1^2. */ fb_mul(t0, t0, t1); /* Solve t1^2 + t1 = t0. */ - if (fb_trc(t0) == 0) { + if (fb_trc(t0) != 0) { + bn_add_dig(k, k, 1); + bn_mod_2b(k, k, RLC_FB_BITS); + } else { fb_slv(t1, t0); /* x3 = x1, y3 = t1 * x1, z3 = 1. */ fb_mul(p->y, t1, p->x); diff --git a/src/eb/relic_eb_mul.c b/src/eb/relic_eb_mul.c index e1c7e028a..b23b81141 100644 --- a/src/eb/relic_eb_mul.c +++ b/src/eb/relic_eb_mul.c @@ -617,22 +617,33 @@ static void eb_mul_rnaf_imp(eb_t r, const eb_t p, const bn_t k) { void eb_mul_basic(eb_t r, const eb_t p, const bn_t k) { eb_t t; + int8_t u, *naf = RLC_ALLOCA(int8_t, bn_bits(k) + 1); + size_t l; + + eb_null(t); if (bn_is_zero(k) || eb_is_infty(p)) { eb_set_infty(r); return; } - eb_null(t); - RLC_TRY { eb_new(t); + if (naf == NULL) { + RLC_THROW(ERR_NO_BUFFER); + } - eb_copy(t, p); - for (int i = bn_bits(k) - 2; i >= 0; i--) { + l = bn_bits(k) + 1; + bn_rec_naf(naf, &l, k, 2); + eb_set_infty(t); + for (int i = l - 1; i >= 0; i--) { eb_dbl(t, t); - if (bn_get_bit(k, i)) { + + u = naf[i]; + if (u > 0) { eb_add(t, t, p); + } else if (u < 0) { + eb_sub(t, t, p); } } @@ -646,6 +657,7 @@ void eb_mul_basic(eb_t r, const eb_t p, const bn_t k) { } RLC_FINALLY { eb_free(t); + RLC_FREE(naf); } } @@ -718,7 +730,7 @@ void eb_mul_lodah(eb_t r, const eb_t p, const bn_t k) { break; } - /* Blind both points independently. */ + /* Blind both points indebendently. */ fb_rand(z1); fb_mul(x1, z1, p->x); fb_rand(r1); diff --git a/src/eb/relic_eb_mul_sim.c b/src/eb/relic_eb_mul_sim.c index e84497caa..9717f6a02 100644 --- a/src/eb/relic_eb_mul_sim.c +++ b/src/eb/relic_eb_mul_sim.c @@ -109,12 +109,6 @@ static void eb_mul_sim_kbltz(eb_t r, const eb_t p, const bn_t k, const eb_t q, l = RLC_MAX(l0, l1); _k = tnaf0 + l - 1; _m = tnaf1 + l - 1; - for (i = l0; i < l; i++) { - tnaf0[i] = 0; - } - for (i = l1; i < l; i++) { - tnaf1[i] = 0; - } if (bn_sign(k) == RLC_NEG) { for (i = 0; i < l0; i++) { @@ -184,7 +178,7 @@ static void eb_mul_sim_kbltz(eb_t r, const eb_t p, const bn_t k, const eb_t q, */ static void eb_mul_sim_plain(eb_t r, const eb_t p, const bn_t k, const eb_t q, const bn_t m, const eb_t *t) { - int i, n0, n1, w, g; + int i, n0, n1, w, g = (t == NULL ? 0 : 1); int8_t naf0[RLC_FB_BITS + 1], naf1[RLC_FB_BITS + 1], *_k, *_m; eb_t t0[1 << (RLC_WIDTH - 2)]; eb_t t1[1 << (RLC_WIDTH - 2)]; @@ -196,7 +190,6 @@ static void eb_mul_sim_plain(eb_t r, const eb_t p, const bn_t k, const eb_t q, } RLC_TRY { - g = (t == NULL ? 0 : 1); if (!g) { for (i = 0; i < (1 << (RLC_WIDTH - 2)); i++) { eb_new(t0[i]); @@ -368,18 +361,12 @@ void eb_mul_sim_trick(eb_t r, const eb_t p, const bn_t k, const eb_t q, } #if RLC_WIDTH > 2 && defined(EB_MIXED) - eb_norm_sim(t + 1, (const eb_t *)(t + 1), (1 << RLC_WIDTH) - 1); + eb_norm_sim(t + 2, (const eb_t *)(t + 2), (1 << (w + w)) - 2); #endif l0 = l1 = RLC_CEIL(RLC_FB_BITS + 1, w); bn_rec_win(w0, &l0, k, w); bn_rec_win(w1, &l1, m, w); - for (int i = l0; i < l1; i++) { - w0[i] = 0; - } - for (int i = l1; i < l0; i++) { - w1[i] = 0; - } eb_set_infty(r); for (int i = RLC_MAX(l0, l1) - 1; i >= 0; i--) { diff --git a/src/ed/relic_ed_mul.c b/src/ed/relic_ed_mul.c index f2a66a5fa..c52972926 100644 --- a/src/ed/relic_ed_mul.c +++ b/src/ed/relic_ed_mul.c @@ -117,10 +117,6 @@ static void ed_mul_reg_imp(ed_t r, const ed_t p, const bn_t k) { size_t l; bn_null(_k); - if (bn_is_zero(k)) { - ed_set_infty(r); - return; - } RLC_TRY { bn_new(_k); @@ -139,7 +135,7 @@ static void ed_mul_reg_imp(ed_t r, const ed_t p, const bn_t k) { _k->dp[0] |= bn_is_even(_k); /* Compute the w-NAF representation of k. */ - l = RLC_CEIL(RLC_FP_BITS + 1, RLC_WIDTH - 1); + l = RLC_CEIL(RLC_FP_BITS + 1, RLC_WIDTH - 1) + 1; bn_rec_reg(reg, &l, _k, RLC_FP_BITS, RLC_WIDTH); ed_set_infty(r); @@ -197,22 +193,34 @@ static void ed_mul_reg_imp(ed_t r, const ed_t p, const bn_t k) { void ed_mul_basic(ed_t r, const ed_t p, const bn_t k) { ed_t t; + int8_t u, *naf = RLC_ALLOCA(int8_t, bn_bits(k) + 1); + size_t l; ed_null(t); if (bn_is_zero(k) || ed_is_infty(p)) { + RLC_FREE(naf); ed_set_infty(r); return; } RLC_TRY { ed_new(t); + if (naf == NULL) { + RLC_THROW(ERR_NO_BUFFER); + } - ed_copy(t, p); - for (int i = bn_bits(k) - 2; i >= 0; i--) { + l = bn_bits(k) + 1; + bn_rec_naf(naf, &l, k, 2); + ed_set_infty(t); + for (int i = l - 1; i >= 0; i--) { ed_dbl(t, t); - if (bn_get_bit(k, i)) { + + u = naf[i]; + if (u > 0) { ed_add(t, t, p); + } else if (u < 0) { + ed_sub(t, t, p); } } @@ -226,6 +234,7 @@ void ed_mul_basic(ed_t r, const ed_t p, const bn_t k) { } RLC_FINALLY { ed_free(t); + RLC_FREE(naf); } } diff --git a/src/ed/relic_ed_mul_sim.c b/src/ed/relic_ed_mul_sim.c index a7b28d8b3..1cb62a4b7 100644 --- a/src/ed/relic_ed_mul_sim.c +++ b/src/ed/relic_ed_mul_sim.c @@ -53,14 +53,13 @@ */ static void ed_mul_sim_plain(ed_t r, const ed_t p, const bn_t k, const ed_t q, const bn_t m, const ed_t *t) { - int i, n0, n1, w, gen; + int i, n0, n1, w, gen = (t == NULL ? 0 : 1); int8_t naf0[RLC_FP_BITS + 1], naf1[RLC_FP_BITS + 1], *_k, *_m; ed_t t0[1 << (RLC_WIDTH - 2)]; ed_t t1[1 << (RLC_WIDTH - 2)]; size_t l, l0, l1; RLC_TRY { - gen = (t == NULL ? 0 : 1); if (!gen) { for (i = 0; i < (1 << (RLC_WIDTH - 2)); i++) { ed_null(t0[i]); @@ -232,20 +231,13 @@ void ed_mul_sim_trick(ed_t r, const ed_t p, const bn_t k, const ed_t q, } #if defined(ED_MIXED) - ed_norm_sim(t + 1, (const ed_t *)t + 1, (1 << (RLC_WIDTH)) - 1); + ed_norm_sim(t + 2, (const ed_t *)t + 2, (1 << ((w + w))) - 2); #endif l0 = l1 = RLC_CEIL(RLC_FP_BITS, w); bn_rec_win(w0, &l0, k, w); bn_rec_win(w1, &l1, m, w); - for (int i = l0; i < l1; i++) { - w0[i] = 0; - } - for (int i = l1; i < l0; i++) { - w1[i] = 0; - } - ed_set_infty(r); for (int i = RLC_MAX(l0, l1) - 1; i >= 0; i--) { for (int j = 0; j < w; j++) { diff --git a/src/ep/relic_ep_curve.c b/src/ep/relic_ep_curve.c index f4aa0f329..9f3cf7e7b 100644 --- a/src/ep/relic_ep_curve.c +++ b/src/ep/relic_ep_curve.c @@ -79,19 +79,20 @@ static void detect_opt(int *opt, fp_t a) { * @param[in] u - the non-square used for hashing to this curve. * @param[in] ctmap - true if this curve will use an isogeny for mapping. */ -static void ep_curve_set_map(const fp_t u) { +static void ep_curve_set_map(void) { bn_t t; bn_null(t); - const int abNeq0 = (ep_curve_opt_a() != RLC_ZERO) && (ep_curve_opt_b() != RLC_ZERO); + const int abNeq0 = (ep_curve_opt_a() * ep_curve_opt_b()) != RLC_ZERO; ctx_t *ctx = core_get(); - dig_t *c1 = ctx->ep_map_c[0]; - dig_t *c2 = ctx->ep_map_c[1]; - dig_t *c3 = ctx->ep_map_c[2]; - dig_t *c4 = ctx->ep_map_c[3]; - - fp_copy(ctx->ep_map_u, u); + dig_t *c0 = ctx->ep_map_c[0]; + dig_t *c1 = ctx->ep_map_c[1]; + 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); @@ -101,56 +102,118 @@ static void ep_curve_set_map(const fp_t u) { /* constants 3 and 4: a and b for either the curve or the isogeny */ #ifdef EP_CTMAP if (ep_curve_is_ctmap()) { - fp_copy(c3, ctx->ep_iso.a); - fp_copy(c4, ctx->ep_iso.b); + fp_copy(c2, ctx->ep_iso.a); + fp_copy(c3, ctx->ep_iso.b); } else { #endif - fp_copy(c3, ctx->ep_a); - fp_copy(c4, ctx->ep_b); + fp_copy(c2, ctx->ep_a); + fp_copy(c3, ctx->ep_b); + /* Generate a non-square u to define the map. */ + fp_set_dig(ctx->ep_map_u, 0); + do { + fp_add_dig(ctx->ep_map_u, ctx->ep_map_u, 1); + /* Check that g(b/ua) = u^3 + a * u + b is square*/ + fp_mul(c1, ctx->ep_a, ctx->ep_map_u); + fp_inv(c1, c1); + fp_mul(c1, c1, ctx->ep_b); + fp_sqr(c0, c1); + fp_add(c0, c0, ctx->ep_a); + fp_mul(c0, c0, ctx->ep_map_u); + fp_add(c0, c0, ctx->ep_b); + } while (fp_is_sqr(ctx->ep_map_u) || !fp_is_sqr(c0)); #ifdef EP_CTMAP } #endif /* constant 1: -b / a */ - fp_neg(c1, c3); /* c1 = -a */ - fp_inv(c1, c1); /* c1 = -1 / a */ - fp_mul(c1, c1, c4); /* c1 = -b / a */ + fp_neg(c0, c2); /* c0 = -a */ + fp_inv(c0, c0); /* c0 = -1 / a */ + fp_mul(c0, c0, c3); /* c0 = -b / a */ /* constant 2 is unused in this case */ } else { /* SvdW map constants */ - /* constant 1: g(u) = u^3 + a * u + b */ - fp_sqr(c1, ctx->ep_map_u); - fp_add(c1, c1, ctx->ep_a); - fp_mul(c1, c1, ctx->ep_map_u); - fp_add(c1, c1, ctx->ep_b); - - /* constant 2: -u / 2 */ - fp_set_dig(c2, 1); - fp_neg(c2, c2); /* -1 */ - fp_hlv(c2, c2); /* -1/2 */ - fp_mul(c2, c2, ctx->ep_map_u); /* c2 = -1/2 * u */ - - /* constant 3: sqrt(-g(u) * (3 * u^2 + 4 * a)) */ - fp_sqr(c3, ctx->ep_map_u); /* c3 = u^2 */ - fp_mul_dig(c3, c3, 3); /* c3 = 3 * u^2 */ - fp_mul_dig(c4, ctx->ep_a, 4); /* c4 = 4 * a */ - fp_add(c4, c3, c4); /* c4 = 3 * u^2 + 4 * a */ - fp_neg(c4, c4); /* c4 = -(3 * u^2 + 4 * a) */ - fp_mul(c3, c4, c1); /* c3 = -g(u) * (3 * u^2 + 4 * a) */ - if (!fp_srt(c3, c3)) { /* c3 = sqrt(-g(u) * (3 * u^2 + 4 * a)) */ + fp_set_dig(ctx->ep_map_u, 0); + do { + /* Generate u by trial and error. */ + fp_add_dig(ctx->ep_map_u, ctx->ep_map_u, 1); + + /* constant 1: g(u) = u^3 + a * u + b */ + fp_sqr(c0, ctx->ep_map_u); + fp_add(c0, c0, ctx->ep_a); + fp_mul(c0, c0, ctx->ep_map_u); + fp_add(c0, c0, ctx->ep_b); + + /* constant 2: -u / 2 */ + fp_set_dig(c1, 1); + fp_neg(c1, c1); /* -1 */ + fp_hlv(c1, c1); /* -1/2 */ + fp_mul(c1, c1, ctx->ep_map_u); /* c1 = -1/2 * u */ + + /* constant 3: sqrt(-g(u) * (3 * u^2 + 4 * a)) */ + fp_sqr(c2, ctx->ep_map_u); /* c2 = u^2 */ + fp_mul_dig(c2, c2, 3); /* c2 = 3 * u^2 */ + fp_mul_dig(c3, ctx->ep_a, 4); /* c3 = 4 * a */ + fp_add(c3, c2, c3); /* c3 = 3 * u^2 + 4 * a */ + fp_neg(c3, c3); /* c3 = -(3 * u^2 + 4 * a) */ + fp_mul(c2, c3, c0); /* c2 = -g(u) * (3 * u^2 + 4 * a) */ + } while (fp_is_zero(c2) || !fp_is_sqr(c2)); + if (!fp_srt(c2, c2)) { /* c2 = sqrt(-g(u) * (3 * u^2 + 4 * a)) */ RLC_THROW(ERR_NO_VALID); } - /* make sure sgn0(c3) == 0 */ - fp_prime_back(t, c3); + /* make sure sgn0(c2) == 0 */ + fp_prime_back(t, c2); if (bn_get_bit(t, 0) != 0) { - /* set sgn0(c3) == 0 */ - fp_neg(c3, c3); + /* set sgn0(c2) == 0 */ + fp_neg(c2, c2); } /* constant 4: -4 * g(u) / (3 * u^2 + 4 * a) */ - fp_inv(c4, c4); /* c4 = -1 / (3 * u^2 + 4 * a) */ - fp_mul(c4, c4, c1); /* c4 *= g(u) */ - fp_mul_dig(c4, c4, 4); /* c4 *= 4 */ + fp_inv(c3, c3); /* c3 = -1 / (3 * u^2 + 4 * a) */ + fp_mul(c3, c3, c0); /* c3 *= g(u) */ + 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) { + fp_set_dig(c4, 3); + fp_neg(c4, c4); + if (!fp_srt(c4, c4)) { + RLC_THROW(ERR_NO_VALID); + } } } RLC_CATCH_ANY { @@ -173,7 +236,7 @@ static void ep_curve_set_map(const fp_t u) { * @param[in] ctmap - true if this curve will use an isogeny for mapping. */ static void ep_curve_set(const fp_t a, const fp_t b, const ep_t g, const bn_t r, - const bn_t h, const fp_t u, int ctmap) { + const bn_t h, int ctmap) { ctx_t *ctx = core_get(); fp_copy(ctx->ep_a, a); @@ -186,7 +249,7 @@ static void ep_curve_set(const fp_t a, const fp_t b, const ep_t g, const bn_t r, detect_opt(&(ctx->ep_opt_b3), ctx->ep_b3); ctx->ep_is_ctmap = ctmap; - ep_curve_set_map(u); + ep_curve_set_map(); ep_norm(&(ctx->ep_g), g); bn_copy(&(ctx->ep_r), r); @@ -391,12 +454,21 @@ iso_t ep_curve_get_iso() { #if defined(EP_PLAIN) void ep_curve_set_plain(const fp_t a, const fp_t b, const ep_t g, const bn_t r, - const bn_t h, const fp_t u, int ctmap) { + const bn_t h, int ctmap) { ctx_t *ctx = core_get(); ctx->ep_is_endom = 0; ctx->ep_is_super = 0; - ep_curve_set(a, b, g, r, h, u, ctmap); + /* We do not use beta due to lack of endomorphisms so compute and cache + * square root of -1 for evaluating the distortion map in pairing-friendly + * curves with embedding degree 1. */ + if (ctx->ep_is_pairf) { + fp_set_dig(ctx->beta, 1); + fp_neg(ctx->beta, ctx->beta); + fp_srt(ctx->beta, ctx->beta); + } + + ep_curve_set(a, b, g, r, h, ctmap); } #endif @@ -404,12 +476,12 @@ void ep_curve_set_plain(const fp_t a, const fp_t b, const ep_t g, const bn_t r, #if defined(EP_SUPER) void ep_curve_set_super(const fp_t a, const fp_t b, const ep_t g, const bn_t r, - const bn_t h, const fp_t u, int ctmap) { + const bn_t h, int ctmap) { ctx_t *ctx = core_get(); ctx->ep_is_endom = 0; ctx->ep_is_super = 1; - ep_curve_set(a, b, g, r, h, u, ctmap); + ep_curve_set(a, b, g, r, h, ctmap); } #endif @@ -417,13 +489,13 @@ void ep_curve_set_super(const fp_t a, const fp_t b, const ep_t g, const bn_t r, #if defined(EP_ENDOM) 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, const fp_t u, int ctmap) { + const bn_t h, const fp_t beta, const bn_t l, int ctmap) { int bits = bn_bits(r); ctx_t *ctx = core_get(); ctx->ep_is_endom = 1; ctx->ep_is_super = 0; - ep_curve_set(a, b, g, r, h, u, ctmap); + ep_curve_set(a, b, g, r, h, ctmap); /* Precompute endomorphism constants. */ #if EP_MUL == LWNAF || EP_FIX == COMBS || EP_FIX == LWNAF || EP_SIM == INTER || !defined(STRIP) @@ -441,20 +513,27 @@ void ep_curve_set_endom(const fp_t a, const fp_t b, const ep_t g, const bn_t r, /* Check if [m]P = \psi(P). */ fp_copy(ctx->beta, beta); - bn_copy(m, l); - ep_psi(p, g); - ep_copy(q, g); - for (int i = bn_bits(m) - 2; i >= 0; i--) { - ep_dbl(q, q); - if (bn_get_bit(m, i)) { - ep_add(q, q, g); - } + /* Fix lambda in case it is negative. */ + if (bn_sign(l) == RLC_NEG) { + bn_add(m, l, r); + } else { + bn_copy(m, l); } - ep_norm(q, q); + /* Now check that beta and lambda match each other. */ + ep_psi(p, g); + ep_mul_basic(q, g, m); /* Fix beta in case it is the wrong value. */ if (ep_cmp(q, p) != RLC_EQ) { fp_neg(ctx->beta, ctx->beta); - fp_sub_dig(ctx->beta, ctx->beta, 1); + if (fp_is_zero(a)) { + /* In this case, look for other choice of beta. */ + fp_sub_dig(ctx->beta, ctx->beta, 1); + } + ep_psi(p, g); + ep_mul_basic(q, g, m); + if (ep_cmp(q, p) != RLC_EQ) { + RLC_THROW(ERR_NO_VALID); + } } bn_gcd_ext_mid(&(ctx->ep_v1[1]), &(ctx->ep_v1[2]), &(ctx->ep_v2[1]), &(ctx->ep_v2[2]), m, r); diff --git a/src/ep/relic_ep_map.c b/src/ep/relic_ep_map.c index c34d3a4cc..f95f9d047 100644 --- a/src/ep/relic_ep_map.c +++ b/src/ep/relic_ep_map.c @@ -72,23 +72,25 @@ TMPL_MAP_SVDW(ep, fp, dig_t, EP_MAP_COPY_COND); #undef EP_MAP_COPY_COND -/* caution: this function overwrites k, which used as an auxiliary variable */ -static inline int fp_sgn0(const fp_t t, bn_t k) { - fp_prime_back(k, t); - return bn_get_bit(k, 0); -} - -/*============================================================================*/ -/* Public definitions */ -/*============================================================================*/ - -void ep_map_from_field(ep_t p, const uint8_t *uniform_bytes, size_t len) { +/** + * Maps an array of uniformly random bytes to a point in a prime elliptic + * curve. + * That array is expected to have a length suitable for two field elements plus + * extra bytes for uniformity. + * + * @param[out] p - the result. + * @param[in] uniform_bytes - the array of uniform bytes to map. + * @param[in] len - the array length in bytes. + * @param[in] map_fn - the mapping function. + */ +static void ep_map_from_field(ep_t p, const uint8_t *uniform_bytes, size_t len, + const void (*const map_fn)(ep_t, const fp_t)) { bn_t k; fp_t t; ep_t q; int neg; /* enough space for two field elements plus extra bytes for uniformity */ - const int len_per_elm = (FP_PRIME + ep_param_level() + 7) / 8; + const size_t len_per_elm = (FP_PRIME + ep_param_level() + 7) / 8; bn_null(k); fp_null(t); @@ -103,29 +105,23 @@ void ep_map_from_field(ep_t p, const uint8_t *uniform_bytes, size_t len) { fp_new(t); ep_new(q); - /* figure out which hash function to use */ - const int abNeq0 = (ep_curve_opt_a() != RLC_ZERO) && - (ep_curve_opt_b() != RLC_ZERO); - void (*const map_fn)(ep_t, fp_t) = (ep_curve_is_ctmap() || - abNeq0) ? ep_map_sswu : ep_map_svdw; - #define EP_MAP_CONVERT_BYTES(IDX) \ - do { \ - bn_read_bin(k, uniform_bytes + IDX * len_per_elm, len_per_elm); \ - fp_prime_conv(t, k); \ - } while (0) + do { \ + bn_read_bin(k, uniform_bytes + IDX * len_per_elm, len_per_elm); \ + fp_prime_conv(t, k); \ + } while (0) #define EP_MAP_APPLY_MAP(PT) \ - do { \ - /* check sign of t */ \ - neg = fp_sgn0(t, k); \ - /* convert */ \ - map_fn(PT, t); \ - /* compare sign of y and sign of t; fix if necessary */ \ - neg = neg != fp_sgn0(PT->y, k); \ - fp_neg(t, PT->y); \ - dv_copy_cond(PT->y, t, RLC_FP_DIGS, neg); \ - } while (0) + do { \ + /* check sign of t */ \ + neg = fp_is_even(t); \ + /* convert */ \ + map_fn(PT, t); \ + /* 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); \ + } while (0) /* first map invocation */ EP_MAP_CONVERT_BYTES(0); @@ -146,34 +142,7 @@ void ep_map_from_field(ep_t p, const uint8_t *uniform_bytes, size_t len) { /* sum the result */ ep_add(p, p, q); ep_norm(p, p); - - /* clear cofactor */ - switch (ep_curve_is_pairf()) { - case EP_BN: - /* h = 1 */ - break; - case EP_B12: - case EP_B24: - /* Multiply by (1-x) to get the correct group, as proven in - * Piellard. https://eprint.iacr.org/2022/352.pdf */ - fp_prime_get_par(k); - bn_neg(k, k); - bn_add_dig(k, k, 1); - if (bn_bits(k) < RLC_DIG) { - ep_mul_dig(p, p, k->dp[0]); - } else { - ep_mul(p, p, k); - } - break; - default: - /* multiply by cofactor to get the correct group. */ - ep_curve_get_cof(k); - if (bn_bits(k) < RLC_DIG) { - ep_mul_dig(p, p, k->dp[0]); - } else { - ep_mul_basic(p, p, k); - } - } + ep_mul_cof(p, p); } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); @@ -185,29 +154,427 @@ void ep_map_from_field(ep_t p, const uint8_t *uniform_bytes, size_t len) { } } -void ep_map_dst(ep_t p, const uint8_t *msg, size_t len, const uint8_t *dst, - size_t dst_len) { +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +#if EP_MAP == BASIC || !defined(STRIP) + +void ep_map_basic(ep_t p, const uint8_t *msg, size_t len) { + bn_t x; + fp_t t0; + uint8_t digest[RLC_MD_LEN]; + + bn_null(x); + fp_null(t0); + + RLC_TRY { + bn_new(x); + fp_new(t0); + + md_map(digest, msg, len); + bn_read_bin(x, digest, RLC_MIN(RLC_FP_BYTES, RLC_MD_LEN)); + + fp_zero(p->x); + fp_prime_conv(p->x, x); + fp_set_dig(p->z, 1); + + while (1) { + ep_rhs(t0, p); + + if (fp_smb(t0) == 1) { + fp_srt(p->y, t0); + p->coord = BASIC; + break; + } + + fp_add_dig(p->x, p->x, 1); + } + + ep_mul_cof(p, p); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + bn_free(x); + fp_free(t0); + } +} + +#endif +#if EP_MAP == SSWUM || !defined(STRIP) + +void ep_map_sswum(ep_t p, const uint8_t *msg, size_t len) { /* enough space for two field elements plus extra bytes for uniformity */ - const int len_per_elm = (FP_PRIME + ep_param_level() + 7) / 8; - uint8_t *pseudo_random_bytes = RLC_ALLOCA(uint8_t, 2 * len_per_elm); + const size_t elm = (FP_PRIME + ep_param_level() + 7) / 8; + uint8_t *r = RLC_ALLOCA(uint8_t, 2 * elm); RLC_TRY { /* for hash_to_field, need to hash to a pseudorandom string */ /* XXX(rsw) the below assumes that we want to use MD_MAP for hashing. * Consider making the hash function a per-curve option! */ - md_xmd(pseudo_random_bytes, 2 * len_per_elm, msg, len, dst, dst_len); - ep_map_from_field(p, pseudo_random_bytes, 2 * len_per_elm); + md_xmd(r, 2 * elm, msg, len, (const uint8_t *)"RELIC", 5); + /* figure out which hash function to use */ + const int abNeq0 = (ep_curve_opt_a() != RLC_ZERO) && + (ep_curve_opt_b() != RLC_ZERO); + const void (*const map_fn)(ep_t, const fp_t) = (void (*const)) + (ep_curve_is_ctmap() || abNeq0 ? ep_map_sswu : ep_map_svdw); + ep_map_from_field(p, r, 2 * elm, map_fn); } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { - RLC_FREE(pseudo_random_bytes); + RLC_FREE(r); } } -void ep_map(ep_t p, const uint8_t *msg, size_t len) { - ep_map_dst(p, msg, len, (const uint8_t *)"RELIC", 5); +#endif + +#if EP_MAP == SWIFT || !defined(STRIP) + +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 c, t, u, v, w, y, x1, y1, z1; + ctx_t *ctx = core_get(); + bn_t k; + + bn_null(k); + fp_null(c); + fp_null(t); + fp_null(u); + fp_null(v); + fp_null(w); + fp_null(y); + fp_null(x1); + fp_null(y1); + fp_null(z1); + + RLC_TRY { + bn_new(k); + fp_new(c); + fp_new(t); + fp_new(u); + fp_new(v); + fp_new(w); + fp_new(y); + fp_new(x1); + fp_new(y1); + fp_new(z1); + + md_xmd(pseudo_random_bytes, 2 * len_per_elm + 1, msg, len, + (const uint8_t *)"RELIC", 5); + + bn_read_bin(k, pseudo_random_bytes, len_per_elm); + fp_prime_conv(u, k); + bn_read_bin(k, pseudo_random_bytes + len_per_elm, len_per_elm); + fp_prime_conv(t, k); + s = pseudo_random_bytes[2 * len_per_elm] & 1; + + 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 */ + + /* 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); + + /* Compute x^2, x^4 and x^6 in sequence. */ + fp_sqr(z1, u); + fp_sqr(y1, z1); + fp_mul(t, z1, y1); + + 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 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, ep_curve_get_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, ep_curve_get_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, ep_curve_get_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, ep_curve_get_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); + } + 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, ep_curve_get_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_copy(p->x, v); + fp_sqr(p->y, y); + p->coord = BASIC; + /* We use zp as temporary, but there is no problem with \psi. */ + int index = 0; + fp_copy(y1, u); + /* Make the following constant-time. */ + for (int m = 0; m < 4; m++) { + fp_mul(y1, y1, ctx->ep_map_c[5]); + index += (fp_bits(y1) < fp_bits(u)); + } + for (int m = 0; m < index; m++) { + ep_psi(p, p); + } + 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); + /* Multiply by cofactor. */ + fp_set_dig(p->z, 1); + ep_mul_cof(p, p); + } else { + /* This is the SwiftEC case per se. */ + if (ep_curve_opt_a() != RLC_ZERO) { + RLC_THROW(ERR_NO_VALID); + } else { + fp_sqr(x1, u); + fp_mul(x1, x1, u); + fp_sqr(y1, t); + fp_add(x1, x1, ctx->ep_b); + fp_sub(x1, x1, y1); + fp_dbl(y1, y1); + fp_add(y1, y1, x1); + fp_mul(z1, u, ctx->ep_map_c[4]); + fp_mul(x1, x1, z1); + fp_mul(z1, z1, t); + fp_dbl(z1, z1); + + fp_dbl(y, y1); + fp_sqr(y, y); + fp_mul(v, y1, u); + fp_sub(v, x1, v); + fp_mul(v, v, z1); + fp_mul(w, y1, z1); + fp_dbl(w, w); + + if (fp_is_zero(w)) { + ep_set_infty(p); + } else { + fp_inv(w, w); + fp_mul(x1, v, w); + fp_add(y1, u, x1); + fp_neg(y1, y1); + fp_mul(z1, y, w); + fp_sqr(z1, z1); + fp_add(z1, z1, u); + + fp_sqr(t, x1); + fp_mul(t, t, x1); + fp_add(t, t, ep_curve_get_b()); + + fp_sqr(u, y1); + fp_mul(u, u, y1); + fp_add(u, u, ep_curve_get_b()); + + fp_sqr(v, z1); + fp_mul(v, v, z1); + fp_add(v, v, ep_curve_get_b()); + + 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); + + 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(p->x, x1); + fp_copy(p->y, t); + fp_set_dig(p->z, 1); + p->coord = BASIC; + ep_mul_cof(p, p); + } + } + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + bn_free(k); + fp_free(c); + fp_free(t); + fp_free(u); + fp_free(v); + fp_free(w); + fp_free(y); + fp_free(x1); + fp_free(y1); + fp_free(z1); + RLC_FREE(pseudo_random_bytes); + } } + +#endif diff --git a/src/ep/relic_ep_mul.c b/src/ep/relic_ep_mul.c index 5b51b9119..6a47f081a 100644 --- a/src/ep/relic_ep_mul.c +++ b/src/ep/relic_ep_mul.c @@ -124,9 +124,6 @@ static void ep_mul_glv_imp(ep_t r, const ep_t p, const bn_t k) { } /* Convert r to affine coordinates. */ ep_norm(r, r); - if (bn_sign(_k) == RLC_NEG) { - ep_neg(r, r); - } } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); @@ -145,7 +142,6 @@ static void ep_mul_glv_imp(ep_t r, const ep_t p, const bn_t k) { bn_free(v1[i]); bn_free(v2[i]); } - } } @@ -195,9 +191,6 @@ static void ep_mul_naf_imp(ep_t r, const ep_t p, const bn_t k) { } /* Convert r to affine coordinates. */ ep_norm(r, r); - if (bn_sign(_k) == RLC_NEG) { - ep_neg(r, r); - } } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); @@ -215,8 +208,6 @@ 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) { @@ -260,8 +251,7 @@ 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_abs(_k, k); - bn_mod(_k, _k, n); + bn_mod(_k, k, n); bn_rec_glv(k0, k1, _k, n, (const bn_t *)v1, (const bn_t *)v2); s0 = bn_sign(k0); @@ -341,8 +331,6 @@ static void ep_mul_reg_glv(ep_t r, const ep_t p, const bn_t 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); } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); @@ -378,11 +366,6 @@ static void ep_mul_reg_imp(ep_t r, const ep_t p, const bn_t k) { ep_t t[1 << (RLC_WIDTH - 2)], u, v; size_t l; - if (bn_is_zero(k)) { - ep_set_infty(r); - return; - } - bn_null(_k); RLC_TRY { @@ -460,7 +443,6 @@ 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 == LWNAF */ /*============================================================================*/ /* Public definitions */ @@ -468,22 +450,34 @@ static void ep_mul_reg_imp(ep_t r, const ep_t p, const bn_t k) { void ep_mul_basic(ep_t r, const ep_t p, const bn_t k) { ep_t t; + int8_t u, *naf = RLC_ALLOCA(int8_t, bn_bits(k) + 1); + size_t l; ep_null(t); if (bn_is_zero(k) || ep_is_infty(p)) { ep_set_infty(r); + RLC_FREE(naf); return; } RLC_TRY { ep_new(t); + if (naf == NULL) { + RLC_THROW(ERR_NO_BUFFER); + } - ep_copy(t, p); - for (int i = bn_bits(k) - 2; i >= 0; i--) { + l = bn_bits(k) + 1; + bn_rec_naf(naf, &l, k, 2); + ep_set_infty(t); + for (int i = l - 1; i >= 0; i--) { ep_dbl(t, t); - if (bn_get_bit(k, i)) { + + u = naf[i]; + if (u > 0) { ep_add(t, t, p); + } else if (u < 0) { + ep_sub(t, t, p); } } @@ -497,6 +491,7 @@ void ep_mul_basic(ep_t r, const ep_t p, const bn_t k) { } RLC_FINALLY { ep_free(t); + RLC_FREE(naf); } } @@ -560,9 +555,6 @@ void ep_mul_slide(ep_t r, const ep_t p, const bn_t k) { } ep_norm(r, q); - if (bn_sign(_k) == RLC_NEG) { - ep_neg(r, r); - } } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); @@ -578,7 +570,7 @@ void ep_mul_slide(ep_t r, const ep_t p, const bn_t k) { } #endif -#include "assert.h" + #if EP_MUL == MONTY || !defined(STRIP) void ep_mul_monty(ep_t r, const ep_t p, const bn_t k) { @@ -623,7 +615,7 @@ void ep_mul_monty(ep_t r, const ep_t p, const bn_t k) { ep_blind(t[1], t[1]); for (int i = bits - 1; i >= 0; i--) { - int j = bn_get_bit(l, 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); @@ -635,8 +627,6 @@ void ep_mul_monty(ep_t r, const ep_t p, const bn_t k) { } ep_norm(r, t[0]); - ep_neg(t[0], r); - dv_copy_cond(r->y, t[0]->y, RLC_FP_DIGS, bn_sign(_k) == RLC_NEG); } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } @@ -673,8 +663,8 @@ void ep_mul_lwnaf(ep_t r, const ep_t p, const bn_t k) { #endif -#if EP_MUL == LWREG || !defined(STRIP) - +/* Conditional compilation of the function below was turned off because it + * is used by the default for protected scalar multiplication in G1. */ void ep_mul_lwreg(ep_t r, const ep_t p, const bn_t k) { if (bn_is_zero(k) || ep_is_infty(p)) { ep_set_infty(r); @@ -693,8 +683,6 @@ void ep_mul_lwreg(ep_t r, const ep_t p, const bn_t k) { #endif } -#endif - void ep_mul_gen(ep_t r, const bn_t k) { if (bn_is_zero(k)) { ep_set_infty(r); diff --git a/src/ep/relic_ep_mul_cof.c b/src/ep/relic_ep_mul_cof.c new file mode 100644 index 000000000..1da814637 --- /dev/null +++ b/src/ep/relic_ep_mul_cof.c @@ -0,0 +1,153 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2022 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 + * + * Implementation of point multiplication of a prime elliptic curve by the + * curve cofactor. + * + * @ingroup epx + */ + +#include "relic_core.h" +#include "relic_md.h" + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +void ep_mul_cof(ep_t r, const ep_t p) { + ep_t v; + bn_t k; + bn_t l; + + bn_null(k); + bn_null(l); + ep_null(v); + + RLC_TRY { + bn_new(k); + bn_new(l); + ep_new(v); + + switch (ep_curve_is_pairf()) { +#if defined(EP_ENDOM) && !defined(STRIP) + case EP_BN: + /* h = 1 */ + break; + case EP_B12: + case EP_B24: + case EP_B48: + /* Multiply by (1-x) to get the correct group, as proven in + * Piellard. https://eprint.iacr.org/2022/352.pdf */ + fp_prime_get_par(k); + bn_neg(k, k); + bn_add_dig(k, k, 1); + if (bn_bits(k) < RLC_DIG) { + ep_mul_dig(r, p, k->dp[0]); + } else { + ep_mul_basic(r, p, k); + } + break; + case EP_N16: + /* if (u % 2) == 0, compute = (u * (u**3+1)//2)*P + * else Compute (u * (u**3+1))*P */ + fp_prime_get_par(k); + bn_sqr(l, k); + bn_mul(l, l, k); + bn_add_dig(l, l, 1); + bn_mul(k, l, k); + if (bn_is_even(k)) { + bn_hlv(k, k); + } + if (bn_bits(k) < RLC_DIG) { + ep_mul_dig(r, p, k->dp[0]); + } else { + ep_mul_basic(r, p, k); + } + break; + case EP_K16: + /* Compute 1250*(P + [(u+1)/2]phi(P)) */ + fp_prime_get_par(k); + bn_add_dig(k, k, 1); + bn_hlv(k, k); + ep_dbl(r, p); + ep_norm(r, r); + ep_psi(v, r); + ep_neg(v, v); + ep_mul_dig(v, v, 182); + ep_add(r, r, v); + ep_norm(r, r); + ep_psi(v, r); + ep_neg(v, v); + if (bn_bits(k) < RLC_DIG) { + ep_mul_dig(v, v, k->dp[0]); + } else { + ep_mul_basic(v, v, k); + } + ep_add(r, r, v); + ep_norm(r, r); + break; + case EP_K18: + /* Compute 343*(P + [u+3]psi(P)). */ + fp_prime_get_par(k); + bn_add_dig(k, k, 3); + ep_psi(v, p); + if (bn_bits(k) < RLC_DIG) { + ep_mul_dig(v, v, k->dp[0]); + } else { + ep_mul_basic(v, v, k); + } + ep_add(v, v, p); + ep_norm(r, v); + ep_mul_dig(r, r, 49); + ep_mul_dig(r, r, 7); + break; + case EP_SG18: + /* Compute [3u^2-1]P. */ + fp_prime_get_par(k); + ep_mul_basic(v, p, k); + bn_mul_dig(k, k, 3); + ep_mul_basic(v, v, k); + ep_sub(v, v, p); + ep_norm(r, v); + break; +#endif + default: + /* multiply by cofactor to get the correct group. */ + ep_curve_get_cof(k); + if (bn_bits(k) < RLC_DIG) { + ep_mul_dig(r, p, k->dp[0]); + } else { + ep_mul_basic(r, p, k); + } + } + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + bn_free(k); + bn_free(l); + ep_free(v); + } +} diff --git a/src/ep/relic_ep_mul_fix.c b/src/ep/relic_ep_mul_fix.c index 5505cafb2..cb7dcbe56 100644 --- a/src/ep/relic_ep_mul_fix.c +++ b/src/ep/relic_ep_mul_fix.c @@ -175,9 +175,6 @@ static void ep_mul_combs_endom(ep_t r, const ep_t *t, const bn_t k) { } } ep_norm(r, r); - if (bn_sign(_k) == RLC_NEG) { - ep_neg(r, r); - } } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); @@ -250,9 +247,6 @@ static void ep_mul_combs_plain(ep_t r, const ep_t *t, const bn_t k) { } } ep_norm(r, r); - if (bn_sign(_k) == RLC_NEG) { - ep_neg(r, r); - } } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); @@ -323,9 +317,6 @@ void ep_mul_fix_basic(ep_t r, const ep_t *t, const bn_t k) { } } ep_norm(r, r); - if (bn_sign(_k) == RLC_NEG) { - ep_neg(r, r); - } } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { @@ -500,9 +491,6 @@ void ep_mul_fix_combd(ep_t r, const ep_t *t, const bn_t k) { ep_add(r, r, t[(1 << RLC_DEPTH) + w1]); } ep_norm(r, r); - if (bn_sign(_k) == RLC_NEG) { - ep_neg(r, r); - } } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); diff --git a/src/ep/relic_ep_mul_sim.c b/src/ep/relic_ep_mul_sim.c index 3e74ae224..9f6cacdb3 100644 --- a/src/ep/relic_ep_mul_sim.c +++ b/src/ep/relic_ep_mul_sim.c @@ -488,14 +488,13 @@ void ep_mul_sim_lot_endom(ep_t r, const ep_t p[], const bn_t k[], int n) { */ static void ep_mul_sim_plain(ep_t r, const ep_t p, const bn_t k, const ep_t q, const bn_t m, const ep_t *t) { - int i, w, gen; + int i, w, gen = (t == NULL ? 0 : 1); int8_t naf0[RLC_FP_BITS + 1], naf1[RLC_FP_BITS + 1], n0, n1, *u, *v; ep_t t0[1 << (RLC_WIDTH - 2)]; ep_t t1[1 << (RLC_WIDTH - 2)]; size_t l, l0, l1; RLC_TRY { - gen = (t == NULL ? 0 : 1); if (!gen) { for (i = 0; i < (1 << (RLC_WIDTH - 2)); i++) { ep_null(t0[i]); @@ -719,18 +718,12 @@ void ep_mul_sim_trick(ep_t r, const ep_t p, const bn_t k, const ep_t q, ep_set_infty(t0[0]); ep_copy(t0[1], p); - if (bn_sign(_k) == RLC_NEG) { - ep_neg(t0[1], t0[1]); - } for (int i = 2; i < (1 << w); i++) { ep_add(t0[i], t0[i - 1], t0[1]); } ep_set_infty(t1[0]); ep_copy(t1[1], q); - if (bn_sign(_m) == RLC_NEG) { - ep_neg(t1[1], t1[1]); - } for (int i = 2; i < (1 << w); i++) { ep_add(t1[i], t1[i - 1], t1[1]); } @@ -742,18 +735,12 @@ void ep_mul_sim_trick(ep_t r, const ep_t p, const bn_t k, const ep_t q, } #if RLC_WIDTH > 2 && defined(EP_MIXED) - ep_norm_sim(t + 1, (const ep_t *)(t + 1), (1 << RLC_WIDTH) - 1); + ep_norm_sim(t + 2, (const ep_t *)(t + 2), (1 << (w + w)) - 2); #endif l0 = l1 = RLC_CEIL(RLC_FP_BITS + 1, w); bn_rec_win(w0, &l0, _k, w); bn_rec_win(w1, &l1, _m, w); - for (int i = l0; i < l1; i++) { - w0[i] = 0; - } - for (int i = l1; i < l0; i++) { - w1[i] = 0; - } ep_set_infty(r); for (int i = RLC_MAX(l0, l1) - 1; i >= 0; i--) { diff --git a/src/ep/relic_ep_param.c b/src/ep/relic_ep_param.c index 2f5e5150a..eec143808 100644 --- a/src/ep/relic_ep_param.c +++ b/src/ep/relic_ep_param.c @@ -64,7 +64,6 @@ #define SECG_P160_Y "23A628553168947D59DCC912042351377AC5FB32" #define SECG_P160_R "100000000000000000001F4C8F927AED3CA752257" #define SECG_P160_H "1" -#define SECG_P160_MAPU "3" /** @} */ #endif @@ -79,7 +78,6 @@ #define SECG_K160_Y "938CF935318FDCED6BC28286531733C3F03C4FEE" #define SECG_K160_R "100000000000000000001B8FA16DFAB9ACA16B6B3" #define SECG_K160_H "1" -#define SECG_K160_MAPU "-1" /** @} */ #endif @@ -94,7 +92,6 @@ #define NIST_P192_Y "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811" #define NIST_P192_R "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831" #define NIST_P192_H "1" -#define NIST_P192_MAPU "-5" /** @} */ #endif @@ -109,7 +106,6 @@ #define SECG_K192_Y "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D" #define SECG_K192_R "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D" #define SECG_K192_H "1" -#define SECG_K192_MAPU "1" /** @} */ #endif @@ -124,7 +120,6 @@ #define CURVE_22103_Y "36429404D97E1E217BAD2E5601F6551F95D8FE9481BD454D1F3E7B6" #define CURVE_22103_R "3FFFFFFFFFFFFFFFFFFFFFFFFFFF5CD04695A145C3067CF4AAE2025" #define CURVE_22103_H "8" -#define CURVE_22103_MAPU "F" /** @} */ #endif @@ -139,7 +134,6 @@ #define NIST_P224_Y "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34" #define NIST_P224_R "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D" #define NIST_P224_H "1" -#define NIST_P224_MAPU "1F" /** @} */ #endif @@ -154,9 +148,6 @@ #define SECG_K224_Y "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5" #define SECG_K224_R "10000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7" #define SECG_K224_H "1" -#define SECG_K224_BETA "FE0E87005B4E83761908C5131D552A850B3F58B749C37CF5B84D6768" -#define SECG_K224_LAMB "60DCD2104C4CBC0BE6EEEFC2BDD610739EC34E317F9B33046C9E4788" -#define SECG_K224_MAPU "-1" /** @} */ #endif @@ -171,7 +162,6 @@ #define CURVE_4417_Y "3E9036ADC1A41FCE2F2CA08E2D1BE4F6D97E30CA7761DB1F3E2F2CE96" #define CURVE_4417_R "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFC4A75594D4923FC93D42713CDAF" #define CURVE_4417_H "4" -#define CURVE_4417_MAPU "-E" /** @} */ #endif @@ -186,7 +176,6 @@ #define CURVE_1174_Y "66FE4E7B8B6FE152F743393029A61BFB839747C8FB00F7B27A6841C07532A0" #define CURVE_1174_R "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF77965C4DFD307348944D45FD166C971" #define CURVE_1174_H "4" -#define CURVE_1174_MAPU "-A" /** @} */ #endif @@ -201,7 +190,6 @@ #define CURVE_25519_Y "72FB43CD5568B3B691204CA8E6A2930633716B80FE7DADAF91E072344991E1F1" #define CURVE_25519_R "1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED" #define CURVE_25519_H "8" -#define CURVE_25519_MAPU "8" /** @} */ #endif @@ -216,7 +204,6 @@ #define NIST_P256_Y "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5" #define NIST_P256_R "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551" #define NIST_P256_H "1" -#define NIST_P256_MAPU "-A" /** @} */ #endif @@ -231,7 +218,6 @@ #define BSI_P256_Y "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997" #define BSI_P256_R "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7" #define BSI_P256_H "1" -#define BSI_P256_MAPU "-2" /** @} */ #endif @@ -246,9 +232,6 @@ #define SECG_K256_Y "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8" #define SECG_K256_R "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141" #define SECG_K256_H "1" -#define SECG_K256_BETA "7AE96A2B657C07106E64479EAC3434E99CF0497512F58995C1396C28719501EE" -#define SECG_K256_LAMB "5363AD4CC05C30E0A5261C028812645A122E22EA20816678DF02967C1B23BD72" -#define SECG_K256_MAPU "1" /** @} */ #endif @@ -263,7 +246,6 @@ #define SM2_P256_Y "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0" #define SM2_P256_R "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123" #define SM2_P256_H "1" -#define SM2_P256_MAPU "-A" /** @} */ #endif @@ -278,7 +260,6 @@ #define CURVE_67254_Y "D51BF79D968F4A076022E750F821058E2B5073697B639EDD355EBF8AD32352B1EFA9478DE7EB5662EF0D26EF6EEA795" #define CURVE_67254_R "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD5FB21F21E95EEE17C5E69281B102D2773E27E13FD3C9719" #define CURVE_67254_H "4" -#define CURVE_67254_MAPU "-9" /** @} */ #endif @@ -293,7 +274,6 @@ #define CURVE_383187_Y "55AB95F2C81569A8E2EADF7C823B133547094AF055BDB287DF4B89F07F1E187D6FCF17FAFA89375C092463FD3D750C55" #define CURVE_383187_R "1000000000000000000000000000000000000000000000000E85A85287A1488ACD41AE84B2B7030446F72088B00A0E21" #define CURVE_383187_H "8" -#define CURVE_383187_MAPU "2" /** @} */ #endif @@ -308,7 +288,6 @@ #define NIST_P384_Y "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F" #define NIST_P384_R "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973" #define NIST_P384_H "1" -#define NIST_P384_MAPU "-C" /** @} */ #endif @@ -323,7 +302,6 @@ #define CURVE_511187_Y "4515C654CEF9B490BDD32C5DC3930C3E287752AF10D0438213A2873B4A71BA95DD90EE5B3A0D0A1ACD6DBEECC0AB188B748EDF0D31BF92E434867B5948DE59C9" #define CURVE_511187_R "100000000000000000000000000000000000000000000000000000000000000017B5FEFF30C7F5677AB2AEEBD13779A2AC125042A6AA10BFA54C15BAB76BAF1B" #define CURVE_511187_H "8" -#define CURVE_511187_MAPU "-18" /** @} */ #endif @@ -338,7 +316,6 @@ #define NIST_P521_Y "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650" #define NIST_P521_R "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409" #define NIST_P521_H "1" -#define NIST_P521_MAPU "-4" /** @} */ #endif @@ -353,7 +330,6 @@ #define BN_P158_Y "4" #define BN_P158_R "240000006ED000007FE96000419F59800C9FFD81" #define BN_P158_H "1" -#define BN_P158_MAPU "1" /** @} */ #endif @@ -368,7 +344,6 @@ #define BN_P254_Y "1" #define BN_P254_R "2523648240000001BA344D8000000007FF9F800000000010A10000000000000D" #define BN_P254_H "1" -#define BN_P254_MAPU "-1" /** @} */ #endif @@ -383,9 +358,6 @@ #define TWEEDLEDUM_Y "D27E5D5B7C3AFAED0754EA62B947B23546EBF597530A7369EDC466E456761D8" #define TWEEDLEDUM_R "40000000000000000000000000000000038AA127696286C9842CAFD400000001" #define TWEEDLEDUM_H "1" -#define TWEEDLEDUM_BETA "1508415AB5E97C949BEBC9146EF83D9A7881FB239BA41A268598ABB3A410C9C8" -#define TWEEDLEDUM_LAMB "36C66D3A1E049A5887AD8B5FF9731FFE69CF8DE720E52EC14394C2BD148FA4FD" -#define TWEEDLEDUM_MAPU "-1" /** @} */ #endif @@ -400,7 +372,6 @@ #define BN_P256_Y "4" #define BN_P256_R "B64000000000FF2F2200000085FD547FD8001F44B6B7F4B7C2BC818F7B6BEF99" #define BN_P256_H "1" -#define BN_P256_MAPU "1" /** @} */ #endif @@ -415,7 +386,6 @@ #define SM9_P256_Y "21FE8DDA4F21E607631065125C395BBC1C1C00CBFA6024350C464CD70A3EA616" #define SM9_P256_R "B640000002A3A6F1D603AB4FF58EC74449F2934B18EA8BEEE56EE19CD69ECF25" #define SM9_P256_H "1" -#define SM9_P256_MAPU "-1" /** @} */ #endif @@ -430,7 +400,6 @@ #define B24_P315_Y "2E6F83C55DEFF20227ECDF0DB2BB2EBB5D72C8A29010871D3CCE9059E83DFB96F2922D5DA4E4E5F" #define B24_P315_R "196DEAC24A9DA12B25FC7EC9CF927A98C8C480ECE644E36419D0C5FD00C00001" #define B24_P315_H "2FE8030000000000" -#define B24_P315_MAPU "-2" /** @} */ #endif @@ -445,7 +414,20 @@ #define B24_P317_Y "32239CB1D737F2283BA0707D11B291DF9AC9255DF42134F7D5C9A6B3B4038E13B4544BDC6F7E333" #define B24_P317_R "443F917EA68DAFC2D0B097F28D83CD491CD1E79196BF0E7AF000000000000001" #define B24_P317_H "3D512E5584A9AAAB" -#define B24_P317_MAPU "-3" +/** @} */ +#endif + +#if defined(EP_ENDOM) && FP_PRIME == 330 +/** + * Parameters for a 766-bit pairing-friendly prime curve. + */ +/** @{ */ +#define K16_P330_A "1" +#define K16_P330_B "0" +#define K16_P330_X "033596D1D0B1FEB292325D72BB9872B1A8DF543FFFFF83B0802DC45CA4B714C533D085235CD2F470111" +#define K16_P330_Y "1FCDBF207B0F767A67CFCFB017C7EEB580CF5C9D39B6D872AE2F091E12028107C097DCB606B30388E5D" +#define K16_P330_R "A9AE90F426EE7F9DB56D9C82F1C0B2CA3CB15B2F8ABF5803C963444D043D2731" +#define K16_P330_H "3772AC7257379575CB4" /** @} */ #endif @@ -460,7 +442,6 @@ #define B12_P377_Y "1914A69C5102EFF1F674F5D30AFEEC4BD7FB348CA3E52D96D182AD44FB82305C2FE3D3634A9591AFD82DE55559C8EA6" #define B12_P377_R "12AB655E9A2CA55660B44D1E5C37B00159AA76FED00000010A11800000000001" #define B12_P377_H "170B5D44300000000000000000000000" -#define B12_P377_MAPU "-2" /** @} */ #endif @@ -483,8 +464,6 @@ #define B12_P381_ISO_YN "90D97C81BA24EE0259D1F094980DCFA11AD138E48A869522B52AF6C956543D3CD0C7AEE9B3BA3C2BE9845719707BB33;134996A104EE5811D51036D776FB46831223E96C254F383D0F906343EB67AD34D6C56711962FA8BFE097E75A2E41C696;CC786BAA966E66F4A384C86A3B49942552E2D658A31CE2C344BE4B91400DA7D26D521628B00523B8DFE240C72DE1F6;1F86376E8981C217898751AD8746757D42AA7B90EEB791C09E4A3EC03251CF9DE405ABA9EC61DECA6355C77B0E5F4CB;8CC03FDEFE0FF135CAF4FE2A21529C4195536FBE3CE50B879833FD221351ADC2EE7F8DC099040A841B6DAECF2E8FEDB;16603FCA40634B6A2211E11DB8F0A6A074A7D0D4AFADB7BD76505C3D3AD5544E203F6326C95A807299B23AB13633A5F0;4AB0B9BCFAC1BBCB2C977D027796B3CE75BB8CA2BE184CB5231413C4D634F3747A87AC2460F415EC961F8855FE9D6F2;987C8D5333AB86FDE9926BD2CA6C674170A05BFE3BDD81FFD038DA6C26C842642F64550FEDFE935A15E4CA31870FB29;9FC4018BD96684BE88C9E221E4DA1BB8F3ABD16679DC26C1E8B6E6A1F20CABE69D65201C78607A360370E577BDBA587;E1BBA7A1186BDB5223ABDE7ADA14A23C42A0CA7915AF6FE06985E7ED1E4D43B9B3F7055DD4EBA6F2BAFAAEBCA731C30;19713E47937CD1BE0DFD0B8F1D43FB93CD2FCBCB6CAF493FD1183E416389E61031BF3A5CCE3FBAFCE813711AD011C132;18B46A908F36F6DEB918C143FED2EDCC523559B8AAF0C2462E6BFE7F911F643249D9CDF41B44D606CE07C8A4D0074D8E;B182CAC101B9399D155096004F53F447AA7B12A3426B08EC02710E807B4633F06C851C1919211F20D4C04F00B971EF8;245A394AD1ECA9B72FC00AE7BE315DC757B3B080D4C158013E6632D3C40659CC6CF90AD1C232A6442D9D3F5DB980133;5C129645E44CF1102A159F748C4A3FC5E673D81D7E86568D9AB0F5D396A7CE46BA1049B6579AFB7866B1E715475224B;15E6BE4E990F03CE4EA50B3B42DF2EB5CB181D8F84965A3957ADD4FA95AF01B2B665027EFEC01C7704B456BE69C8B604" #define B12_P381_ISO_YD "16112C4C3A9C98B252181140FAD0EAE9601A6DE578980BE6EEC3232B5BE72E7A07F3688EF60C206D01479253B03663C1;1962D75C2381201E1A0CBD6C43C348B885C84FF731C4D59CA4A10356F453E01F78A4260763529E3532F6102C2E49A03D;58DF3306640DA276FAAAE7D6E8EB15778C4855551AE7F310C35A5DD279CD2ECA6757CD636F96F891E2538B53DBF67F2;16B7D288798E5395F20D23BF89EDB4D1D115C5DBDDBCD30E123DA489E726AF41727364F2C28297ADA8D26D98445F5416;BE0E079545F43E4B00CC912F8228DDCC6D19C9F0F69BBB0542EDA0FC9DEC916A20B15DC0FD2EDEDDA39142311A5001D;8D9E5297186DB2D9FB266EAAC783182B70152C65550D881C5ECD87B6F0F5A6449F38DB9DFA9CCE202C6477FAAF9B7AC;166007C08A99DB2FC3BA8734ACE9824B5EECFDFA8D0CF8EF5DD365BC400A0051D5FA9C01A58B1FB93D1A1399126A775C;16A3EF08BE3EA7EA03BCDDFABBA6FF6EE5A4375EFA1F4FD7FEB34FD206357132B920F5B00801DEE460EE415A15812ED9;1866C8ED336C61231A1BE54FD1D74CC4F9FB0CE4C6AF5920ABC5750C4BF39B4852CFE2F7BB9248836B233D9D55535D4A;167A55CDA70A6E1CEA820597D94A84903216F763E13D87BB5308592E7EA7D4FBC7385EA3D529B35E346EF48BB8913F55;4D2F259EEA405BD48F010A01AD2911D9C6DD039BB61A6290E591B36E636A5C871A5C29F4F83060400F8B49CBA8F6AA8;ACCBB67481D033FF5852C1E48C50C477F94FF8AEFCE42D28C0F9A88CEA7913516F968986F7EBBEA9684B529E2561092;AD6B9514C767FE3C3613144B45F1496543346D98ADF02267D5CEEF9A00D9B8693000763E3B90AC11E99B138573345CC;2660400EB2E4F3B628BDD0D53CD76F2BF565B94E72927C1CB748DF27942480E420517BD8714CC80D1FADC1326ED06F7;E0FA1D816DDC03E6B24255E0D7819C171C40F65E273B853324EFCD6356CAA205CA2F570F13497804415473A1D634B8F;1" #define B12_P381_MAPU "B" -#else /* !defined(EP_CTMAP) */ -#define B12_P381_MAPU "-3" #endif /* EP_CTMAP */ /** @} */ #endif @@ -500,7 +479,6 @@ #define BN_P382_Y "1" #define BN_P382_R "24009015183F94892D996CC179C6D1666F82CEFBE47879BB46E4CDA2E2E2281D08DC008E80108252004200000000000D" #define BN_P382_H "1" -#define BN_P382_MAPU "2" /** @} */ #endif @@ -515,7 +493,6 @@ #define B12_P383_Y "DD3BFDE4A26B777CEDA2A8F1C4C4E6192C586D8227CC05A34705CCC5A32288C0944408D54909F31BF5C664E81778B03" #define B12_P383_R "1002001800C00B809C04401C81698B381DE05F095A120D3973B2099EBFEBC0001" #define B12_P383_H "555AAAC000AABBFFB550556155169EAB" -#define B12_P383_MAPU "5" /** @} */ #endif @@ -530,7 +507,6 @@ #define BN_P446_Y "10" #define BN_P446_R "2400000000000000002400000002D00000000D800000021C00000017A0000000870000000AD400000054C000000156000000126000000061" #define BN_P446_H "1" -#define BN_P446_MAPU "1" #endif #if defined(EP_ENDOM) && FP_PRIME == 446 @@ -544,7 +520,6 @@ #define B12_P446_Y "DC40DDCBAB2823A7870B5C688AA04FEE40369D913E4F2F0947A152FE1C27A79B7F787E9C35B869C3846FAC4F12A70D0FE22D2E244268CC" #define B12_P446_R "511B70539F27995B34995830FA4D04C98CCC4C050BC7BB9B0E8D8CA34610428001400040001" #define B12_P446_H "C02082602B0055D560AB0AD5AAAAC0002AAAC" -#define B12_P446_MAPU "2" #endif #if defined(EP_ENDOM) && FP_PRIME == 455 @@ -558,7 +533,6 @@ #define B12_P455_Y "19A8A9C4C3AC2FFB4C6B380D17B8282E029615052EAA6416C16C8F36F251D87C272657F0702CC58C4E072628D7BAD3C0E9B3A8AEBFC6B2357C" #define B12_P455_R "10000080000380002E0000F10004F00025E000750001D1000A00000400001C00007FFFFC00001" #define B12_P455_H "555556AAAAB15555B54AAB6A9557FFAABFFAAB" -#define B12_P455_MAPU "-1" #endif #if defined(EP_ENDOM) && FP_PRIME == 508 @@ -566,15 +540,12 @@ * Parameters for a 508-bit pairing-friendly prime curve at the 192-bit security level. */ /** @{ */ -#define KSS_P508_A "0" -#define KSS_P508_B "2" -#define KSS_P508_X "3ADD59EAC7B6A0ABC781139CE46388AB3426C6619C27187CB1F2B48AC92E04608AFBD25DA121EDB06015CB5D2BCF369C03C163605BBA21FAF7D550960553784" -#define KSS_P508_Y "8773227730CBE52483BF6AAAA9E4FE2870B463FA14D92C31D0F99C6B6EE13106A0E8C87AD7631F8ECCE0DD6189B4C2232C644E4B857F325923FC8A80A947FFA" -#define KSS_P508_R "BF33E1C9934E7868ECE51D291E5644DA8A2F179CEE74854EE6819B240F20CE4E7D19F4CDABA6EAEA5B0E3000000001" -#define KSS_P508_H "10565283D505534A492ADC6AAABB051B1D" -#define KSS_P508_BETA "926C960A5EC3B3A6C6B9CEF2CB923D3240E4780BC1AE423EE39586AD923B1C949768022369DD2CE502E7FCA0670B3A996AC44B48B523DAA7390CCB1F6D9012F" -#define KSS_P508_LAMB "1001740B431D14BFD17F4BD000300173FFFFFFFEFFFFFFFED" -#define KSS_P508_MAPU "1" +#define K18_P508_A "0" +#define K18_P508_B "2" +#define K18_P508_X "3ADD59EAC7B6A0ABC781139CE46388AB3426C6619C27187CB1F2B48AC92E04608AFBD25DA121EDB06015CB5D2BCF369C03C163605BBA21FAF7D550960553784" +#define K18_P508_Y "8773227730CBE52483BF6AAAA9E4FE2870B463FA14D92C31D0F99C6B6EE13106A0E8C87AD7631F8ECCE0DD6189B4C2232C644E4B857F325923FC8A80A947FFA" +#define K18_P508_R "BF33E1C9934E7868ECE51D291E5644DA8A2F179CEE74854EE6819B240F20CE4E7D19F4CDABA6EAEA5B0E3000000001" +#define K18_P508_H "10565283D505534A492ADC6AAABB051B1D" /** @} */ #endif @@ -589,24 +560,6 @@ #define B24_P509_Y "101264A0ACB6129DE3CEB5FF829968E5030855FAD666E88506531D46050023ACB15843C4EA8F8AB478F618D263D4B6271D5972803F2046DDD7C7DBC2F6232FFD" #define B24_P509_R "100000FFFF870FF91CE195DB5B6F3EBD1E08C94C9E193B724ED58B907FF7C311A80D7CABC647746AE3ECB627C943998457FE001" #define B24_P509_H "155555AAAA805FFFAAC0154AAC" -#define B24_P509_MAPU "2" -/** @} */ -#endif - -#if defined(EP_ENDOM) && FP_PRIME == 511 -/** - * Parameters for the 511-bit jacobi quartic curve. - */ -/** @{ */ -#define OT8_P511_A "1" -#define OT8_P511_B "0" -#define OT8_P511_X "17D8A9281052D5C14B26B88FBDA0DE7001F384C09F7425270874BD187725FF7D68887EC3539658E3C60F6FFADCED61F47267CCDAF5B850DF4A441105AE49CE6" -#define OT8_P511_Y "9CB933777C7E567A2040EC255073F2C271F632E6E81490D85377DD77659416965584F5F44DFB146E33393CE36D908F79A4ED5B4B411D78572E6CA972F66DEC8" -#define OT8_P511_R "100000000002AC000000002AD56000000131304C0000032F6D0B1000000000001" -#define OT8_P511_H "40000000000AB000000000AB5580000044C4C130000564BDB42C401C8E400000" -#define OT8_P511_BETA "20000000000AB0000000018FC7800000816148500019C9EF620CC291655380BA94133E310D1CC71ED0A7EBD9B2AB859C0F60AC90F7A2E5A1140C3FCBF1DD5400" -#define OT8_P511_LAMB "100000000002AC000000002AD55FFFFFF131304BFFFEAD2F6D0B0FF8DC7000001" -#define OT8_P511_MAPU "1" /** @} */ #endif @@ -623,7 +576,6 @@ #define GMT8_P544_H "BC5A106E29D336CBF340F2BB98248FFC0719523D3233C6B3909C882E2BD2251BD3B22F14" #define GMT8_P544_BETA "AEB8BAFC09BEB98DE5FB37D9FC56F9EAC4F908F09D88B1CD8622513C94499803C18F54E6B4FB9180292A2FD4C8AFD2AF43F54BCF308198872F3A6B591394AED0EBF7961A" #define GMT8_P544_LAMB "FF801041EF80043901FFFEF800000010" -#define GMT8_P544_MAPU "5" #endif /** @} */ @@ -640,7 +592,6 @@ #define SG54_P569_H "1C242734823F3D3" #define SG54_P569_BETA "11B4A0273012B3534BEA4F2B96E641113A156E510AED07E600BE9DD709E2015B0F8E69E3F1A44690DA0652831007C27346D9F444F22DA68B20C46EDC4889EA0B49C773C72195876" #define SG54_P569_LAMB "15FB59F1AFF4B536CBEBB5F1317A6D0332AAEF63DBEE47A528280DACBB244A601" -#define SG54_P569_MAPU "-1" /** @} */ #endif @@ -655,9 +606,6 @@ #define B48_P575_Y "4E0AB4BE01EEA9C4A3EA81C84E2081B03934596D846AC24862A851F811CBE5078CD4AF03DECAD5571C4BB90F502155F462E23D3180562EED28C72882F3F538893BD643EDE63C4567" #define B48_P575_R "FFBFC68EB6176EFB58025E547BF4EBACB1315C184DC37EAAF67BBCCE069D07F425050E765ABB8B40D5E6D7AE8A2A5698B771DDBD6E109D56D59C3DFF00000001" #define B48_P575_H "5552A7FA0ADD830B" -#define B48_P575_BETA "FFBBC37DA1869F31B9AAFAF31296EECB5167E1C9E9CE0B077E9903AE049FC122282856929B2DF0C32C0B39C487860D76077734153C1C276F79B75B1CB20A7935EB5F2611" -#define B48_P575_LAMB "FFDFE14381A38FBBE3439A4861838B75D01E7A1E85BAE6AA2A63C200FFFFFFFF" -#define B48_P575_MAPU "1" /** @} */ #endif @@ -672,7 +620,6 @@ #define BN_P638_Y "128AC488584B7C05EFD5436E559D741C978A5027926525B3DECB22D40E03FC7BD8D4235FD7E9DD2F3BFF3945D54C25E701624E27AFEF8F27F7DDEADEDAF3FE3AA0234D35290703FCE6254A7D75B6A304" #define BN_P638_R "23FFFFFDC000000D7FFFFFB8000001D3FFFFF942D000165E3FFF94870000D52FFFFDD0E00008DE55600086550021E555FFFFF54FFFF4EAC000000049800154D9FFFFFFFFFFFFEDA00000000000000061" #define BN_P638_H "1" -#define BN_P638_MAPU "-1" /** @} */ /** @@ -685,7 +632,6 @@ #define B12_P638_Y "2D340B33877480A9785E86ED2EDCAFC170B82568CB21B708B79FC6DA3748461FCD80697E486695F3CAE76FCB1781E784F6812F57BE05DFC850426650DED8B40A464B00A35718228EC8E02B52B59D876E" #define B12_P638_R "50F94035FF4000FFFFFFFFFFF9406BFDC0040000000000000035FB801DFFBFFFFFFFFFFFFFFF401BFF80000000000000000000FFC01" #define B12_P638_H "BFF8001555555555555555554D957EAAAAAAAAAAAAAAAAAAAABEB" -#define B12_P638_MAPU "3" /** @} */ /** @@ -698,10 +644,45 @@ #define K18_P638_Y "1AD0E6C8D2F8B84E81E17D20277BFF5E7784849B6B3F570F6CB7DDD7BB51E680A9B01A9E2CBF87B7D1CA40F3F9DB65DCDD485800C7D6BCE6F11F85F4FC91381A1F6FF721BE1FA7DC73B1452EC9E067C1" #define K18_P638_R "217C6AD09A8C1501A39F40A5CAE9A8FA6C1D721892617A6D5AB381B7B89EF9B4A91AE277CAAA0EE0BC3E2910806BDC08EA69545693C740000000001" #define K18_P638_H "1708507726EC82EBF64DB756506B2000010540EB1D" -#define K18_P638_MAPU "1" +/** @} */ + +/** + * Parameters for a 638-bit pairing-friendly prime curve. + */ +/** @{ */ +#define SG18_P638_A "0" +#define SG18_P638_B "F" +#define SG18_P638_X "E0D4EFF000926F3F04EC069C865F33B6ABD8F70B19B71E93111193736C505A211C527AF75475C92513B4601BA248A97A6717B631A462BF7366F2767D3C9ECB1A1782524B131853E2684A33EB28C518B" +#define SG18_P638_Y "1F11E9002370B0A9F5E3A3CCFF9468621FE85FB70CC024C3636B7427714C19140A00B09975E0F42921C8839A3D0E3DDCE74B09A556771D5A072F4B5F77C8F816B69C4F093B1FAA547EA906F1E405F229" +#define SG18_P638_R "6D45960E65595E64AE55954202C604A99543E572A870006483A877DC004A61BE5000000D793FFFFFFFF7000000000001" +#define SG18_P638_H "9120D848090486C36090000D8D835FFE7E91A8FFFFF9FD08FFFFFFFA00000001" /** @} */ #endif +/** + * 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 766-bit pairing-friendly prime curve. + */ +/** @{ */ +#define K16_P766_A "1" +#define K16_P766_B "0" +#define K16_P766_X "025F4A0BE80AC747A4C260A96F17BACD76B068415EC40DBAC38FCDD5FF14A5974A3B73AFE417CB4391CFC9A5E8F5DA2C7E6244E30CFE1097AE864DD3FC5B45450043F0EFE0C181D198E6C07129367CF4A7E78ACD4D1C438AD486AF79BB712017" +#define K16_P766_Y "1F9736A1ED817C6B41A07FD71902DF11786996DEAA1C9707671D491C4A8C430BABECE74E1664C0DE5C73A08B3758D2E3EBEB42F69DF624DEDEEDDD0F94EF01658AAD2F3426DD91CA34545DBF5FCBA7CF0784F2C3DCFAB7A1EBDCE75566F0538A" +#define K16_P766_R "1B6C1BFC8E56CCE359E1D8A9B94553D096A506CE2ECF4A33C5D526AC5F3B61CB0A6D76FCD8487EDEE0B0F9BA2DFA29D5AB0B164B8792C233ED1E6EB350BA9F4D37112A98DE816BEB1EA8DDB1" +#define K16_P766_H "2327FFFFFFFFE8905E7E6E0003E7E080C57EE9EF4" +/** @} */ + #if defined(EP_SUPER) && FP_PRIME == 1536 /** * Parameters for a 1536-bit supersingular elliptic curve. @@ -713,7 +694,20 @@ #define SS_P1536_Y "76F05A21A057DB46D591CED876EDCA9241A4A9618E13E091EE383BE3D8ECDA72C42449CB20CEA8C21B4A58B08F5871C6E101473933ABCD0BBB61C36F51BE5309138BA1040325EFE2D47B2216923BAC07BA64E6668C67D4647DA5916BF2305280A1BFFA1407ED68F0D28C2C2FC200BA7D1B7C5D71492CD39A2FC6BB7EF2D162B69984460A81D324DA69B0949DA2C7D0F79E39333EAF074F360243BAA824C762A039EBB3DEFF1ABDE3157482134BE93D73B4D8CB308C3ED0E72BA644DEFE22AAB9" #define SS_P1536_R "8000000000000000000000000000000000000000000000000000020000000001" #define SS_P1536_H "106126E85211A9AA539DE0D8E432340BABCC0E7FD0C3CC6FAEE8F87CA5F7725B54BBBE7DE38C3EBEE164AD00490346D95FD32BFC679AA8029708CEA26C981A77064FB3C8A6CDD411E36688D584793A96CAD10CE6351A0AC319F434764054488B5741CEF8BE9E019424732EB40A6EE109E4ADBD540FA43899E5484F37822EC07596F62045187571F182E85ACE872AE0376040E3510D06083B388463D1DD30571B4" -#define SS_P1536_MAPU "1" +/** @} */ +#endif + +#if defined(EP_PLAIN) && FP_PRIME == 3072 +/** + * Parameters for a 1536-bit supersingular elliptic curve. + */ +/** @{ */ +#define K1_P3072_A "-4" +#define K1_P3072_B "0" +#define K1_P3072_X "8253FA83029E6059E1B34C169D6F471EE952E41C9E24B9AF67F53289914A337D7C34E8703B78C56A45B3E4DD8D55B5958092C76B871F9CE74CBA96B087FA8C9454B51F22C2A23BCEC5136DA5D4A008B5EC42A46B333793B4E94C458AC0DB61A7A3B28756760E9B40B55979B7DE7D313FBA9214653F37510AC65E923D9FC96AEC907B22582D86E4E95EA5B9ACA3ED56BB2A0367FC8BA6DB0388F9EEB44AA937F834F89C2281B35F5283BDA9C31F17D3B8F2C226AB7A075F01E95817C36F808B9262932ECDFD40DE1C49DCE71D9E4ECAF6CA054996058B8305AB8A0AB17F5AC1B83191B80EB7961AB5DC357C0212D317E1FA0F3FC15409B61D67ED257376C6758A772D84B43FC36212DD84908E9FA8F16608C1C980FCD42350C484DE107959DD26C6AD463674B1C59B8CFDFAA9FFC7BFF06DE608327A9FCD9D227981C30503C0766056F7AC560509889512020EB0AC38A65B62D8376813AB64623C16DBB119232C6B2ABD266E58DD2366F86E407C5C474DB1A127A360F75BE1B3540FD74F758139" +#define K1_P3072_Y "38EEF990FF8CE03E21336501356D3BDAA765D96BE110FAF7A7FD0DA5D876AE0A8F25AF2FCA3F17A0D98FA886B9EC40CEAB625D60BD1EAB1533D271F35BBC7D232135D2173565F2E6C35F616079C98A5D116BC5829AC90A1D5FCBAE7E1995ABB00D5125449DBDC3DA5D577BC740A8896C488E8322D1B2A284349BE8A87D0A49D31FC39E22E5933126FF43D735CA53EF6ED20537B6F3D0DF4904F80A5D1307946A8CBEF4451620E97CDD4CB35F525D5969DED0049325A9B012BE0036A67023DDE37265D0E59484FEFE00FE5CF9A79F008E2F021D8E3E55A46BED45424AB8B6B09C7704DB227D591A871D856CF61563FACD2DC5D6BC498B55ED9F590E8D8ED1BD1F9BA20F41EA7D9707C60F50A759EF923953CA91334C0CEA6A12AF7DE44FFFD001BCD724491C86644664BEAB79245B546E23EC95D0927B2254671BC2311B9E9EDC44A4CC6B0404EC933327B602ED435CFDE8892C406908B6F98ED941514E4AA5123F84957B15D523A14040943C72379E12D83F7B79FEC3FFC8C99B32FE0E0E6901" +#define K1_P3072_R "10000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF" +#define K1_P3072_H "E4C6467513F6DA5D303FCF2C5285C33206AC48901ADBE523D00F9F3B9E4895075BEB07DD1AAEEBF957F2DCBBEC4FB900E2ADE744AA7206BC2A60709BA08CA540000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" /** @} */ #endif @@ -737,8 +731,6 @@ bn_read_str(r, str, strlen(str), 16); \ RLC_GET(str, CURVE##_H, sizeof(CURVE##_H)); \ bn_read_str(h, str, strlen(str), 16); \ - RLC_GET(str, CURVE##_MAPU, sizeof(CURVE##_MAPU)); \ - fp_read_str(u, str, strlen(str), 16); \ /** * Assigns a set of parameters for an elliptic curve with endomorphisms. @@ -762,7 +754,7 @@ */ #define ASSIGNM(CURVE) \ ep_param_set_ctmap(CURVE##_ISO_A, CURVE##_ISO_B, CURVE##_ISO_XN, \ - CURVE##_ISO_XD, CURVE##_ISO_YN, CURVE##_ISO_YD) \ + CURVE##_ISO_XD, CURVE##_ISO_YN, CURVE##_ISO_YD, CURVE##_MAPU) \ #endif /* EP_CTMAP */ @@ -815,11 +807,12 @@ static int ep_param_get_coeffs(fp_st *coeffs, const char *str) { */ /* declaring this function inline suppresses unused function warnings */ static inline void ep_param_set_ctmap(const char *a_str, const char *b_str, - const char *xn_str, const char *xd_str, - const char *yn_str, const char *yd_str) { + const char *xn_str, const char *xd_str, const char *yn_str, + const char *yd_str, const char *u_str) { /* coefficients of isogenous curve */ fp_read_str(ep_curve_get_iso()->a, a_str, strlen(a_str), 16); fp_read_str(ep_curve_get_iso()->b, b_str, strlen(b_str), 16); + fp_read_str(core_get()->ep_map_u, u_str, strlen(u_str), 16); /* isogeny map coeffs */ iso_t coeffs = ep_curve_get_iso(); @@ -842,14 +835,13 @@ int ep_param_get(void) { void ep_param_set(int param) { int plain = 0, endom = 0, super = 0, pairf = 0, ctmap = 0; char str[2 * RLC_FP_BYTES + 2]; - fp_t a, b, beta, u; + fp_t a, b, beta; ep_t g; bn_t r, t, h, lamb; fp_null(a); fp_null(b); fp_null(beta); - fp_null(u); bn_null(lamb); ep_null(g); bn_null(r); @@ -860,7 +852,6 @@ void ep_param_set(int param) { fp_new(a); fp_new(b); fp_new(beta); - fp_new(u); bn_new(lamb); ep_new(g); bn_new(r); @@ -868,6 +859,8 @@ void ep_param_set(int param) { bn_new(h); core_get()->ep_id = 0; + fp_zero(beta); + bn_zero(lamb); switch (param) { #if defined(EP_ENDOM) && FP_PRIME == 158 @@ -885,7 +878,7 @@ void ep_param_set(int param) { #endif #if defined(EP_ENDOM) && FP_PRIME == 160 case SECG_K160: - ASSIGNK(SECG_K160, SECG_160D); + ASSIGN(SECG_K160, SECG_160D); endom = 1; break; #endif @@ -915,7 +908,7 @@ void ep_param_set(int param) { #endif #if defined(EP_ENDOM) && FP_PRIME == 224 case SECG_K224: - ASSIGNK(SECG_K224, SECG_224); + ASSIGN(SECG_K224, SECG_224); endom = 1; break; #endif @@ -946,7 +939,7 @@ void ep_param_set(int param) { #endif #if defined(EP_ENDOM) && FP_PRIME == 255 case TWEEDLEDUM: - ASSIGNK(TWEEDLEDUM, PRIME_H2ADC); + ASSIGN(TWEEDLEDUM, PRIME_H2ADC); endom = 1; break; #endif @@ -966,7 +959,7 @@ void ep_param_set(int param) { #endif #if defined(EP_ENDOM) && FP_PRIME == 256 case SECG_K256: - ASSIGNK(SECG_K256, SECG_256); + ASSIGN(SECG_K256, SECG_256); endom = 1; break; case SM9_P256: @@ -994,6 +987,13 @@ void ep_param_set(int param) { pairf = EP_B24; break; #endif +#if defined(EP_ENDOM) & FP_PRIME == 330 + case K16_P330: + ASSIGN(K16_P330, K16_330); + endom = 1; + pairf = EP_K16; + break; +#endif #if defined(EP_ENDOM) & FP_PRIME == 377 case B12_P377: ASSIGN(B12_P377, B12_377); @@ -1064,9 +1064,10 @@ void ep_param_set(int param) { break; #endif #if defined(EP_ENDOM) && FP_PRIME == 508 - case KSS_P508: - ASSIGNK(KSS_P508, KSS_508); + case K18_P508: + ASSIGN(K18_P508, K18_508); endom = 1; + pairf = EP_K18; break; #endif #if defined(EP_ENDOM) && FP_PRIME == 509 @@ -1076,12 +1077,6 @@ void ep_param_set(int param) { pairf = EP_B24; break; #endif -#if defined(EP_ENDOM) && FP_PRIME == 511 - case OT8_P511: - ASSIGNK(OT8_P511, OT_511); - endom = 1; - break; -#endif #if defined(EP_PLAIN) && FP_PRIME == 511 case CURVE_511187: ASSIGN(CURVE_511187, PRIME_511187); @@ -1110,7 +1105,7 @@ void ep_param_set(int param) { #endif #if defined(EP_ENDOM) && FP_PRIME == 575 case B48_P575: - ASSIGNK(B48_P575, B48_575); + ASSIGN(B48_P575, B48_575); endom = 1; pairf = EP_B48; break; @@ -1131,11 +1126,38 @@ void ep_param_set(int param) { endom = 1; pairf = EP_K18; break; + case SG18_P638: + ASSIGN(SG18_P638, SG18_638); + endom = 1; + pairf = EP_SG18; + break; +#endif +#if defined(EP_ENDOM) && FP_PRIME == 765 + case N16_P765: + ASSIGN(N16_P765, N16_765); + endom = 1; + pairf = EP_N16; + break; +#endif +#if defined(EP_ENDOM) && FP_PRIME == 766 + case K16_P766: + ASSIGN(K16_P766, K16_766); + endom = 1; + pairf = EP_K16; + break; #endif #if defined(EP_SUPER) && FP_PRIME == 1536 case SS_P1536: ASSIGN(SS_P1536, SS_1536); super = 1; + pairf = EP_SS2; + break; +#endif +#if defined(EP_PLAIN) && FP_PRIME == 3072 + case K1_P3072: + ASSIGN(K1_P3072, K1_3072); + plain = 1; + pairf = EP_K1; break; #endif default: @@ -1146,15 +1168,29 @@ void ep_param_set(int param) { #if defined(EP_ENDOM) if (endom) { - switch(pairf) { - /* beta = (-1+sqrt(-3))/2, lambda = 36*u^3 + 18*u^2 + 6*u + 1 */ - case EP_BN: + if (fp_is_zero(beta)) { + if (fp_is_zero(b)) { + /* beta = sqrt(-1). */ + fp_set_dig(beta, 1); + fp_neg(beta, beta); + fp_srt(beta, beta); + } else { + /* beta = (-1+sqrt(-3))/2 */ fp_set_dig(beta, 3); fp_neg(beta, beta); fp_srt(beta, beta); fp_sub_dig(beta, beta, 1); fp_hlv(beta, beta); - fp_prime_get_par(lamb); + } + } + + if (bn_is_zero(lamb)) { + fp_prime_get_par(lamb); + } + + switch(pairf) { + case EP_BN: + /* lambda = 36*u^3 + 18*u^2 + 6*u + 1 */ bn_sqr(lamb, lamb); bn_sqr(lamb, lamb); bn_mul_dig(lamb, lamb, 36); @@ -1164,61 +1200,63 @@ void ep_param_set(int param) { bn_sub_dig(lamb, lamb, 1); } break; - /* beta = (-1 + sqrt(-3))/2, lambda = z^2 - 1 */ case EP_B12: - fp_set_dig(beta, 3); - fp_neg(beta, beta); - fp_srt(beta, beta); - fp_sub_dig(beta, beta, 1); - fp_hlv(beta, beta); - fp_prime_get_par(lamb); + /* lambda = z^2 - 1 */ bn_sqr(lamb, lamb); bn_sub_dig(lamb, lamb, 1); break; - /* beta = (-1 + sqrt(-3))/2, lambda = z^3 + 18 */ + case EP_N16: + bn_sqr(lamb, lamb); + bn_sqr(lamb, lamb); + bn_neg(lamb, lamb); + break; + case EP_K16: + /* lambda = -(z^4 + 24)/7 */ + bn_sqr(t, lamb); + bn_sqr(lamb, t); + bn_add_dig(lamb, lamb, 24); + bn_div_dig(lamb, lamb, 7); + bn_neg(lamb, lamb); + break; case EP_K18: - fp_set_dig(beta, 3); - fp_neg(beta, beta); - fp_srt(beta, beta); - fp_sub_dig(beta, beta, 1); - fp_hlv(beta, beta); - fp_prime_get_par(lamb); + /* lambda = z^3 + 18 */ bn_sqr(t, lamb); bn_mul(lamb, t, lamb); bn_add_dig(lamb, lamb, 18); break; + case EP_SG18: + /* lambda = -9z^3 - 2 */ + bn_sqr(t, lamb); + bn_mul(lamb, t, lamb); + bn_mul_dig(lamb, lamb, 9); + bn_add_dig(lamb, lamb, 2); + bn_neg(lamb, lamb); + break; case EP_B24: - /* beta = (-1 + sqrt(-3))/2, lambda = z^4 - 1. */ - fp_set_dig(beta, 3); - fp_neg(beta, beta); - fp_srt(beta, beta); - fp_sub_dig(beta, beta, 1); - fp_hlv(beta, beta); - fp_prime_get_par(lamb); + /* lambda = z^4 - 1. */ bn_sqr(lamb, lamb); bn_sqr(lamb, lamb); bn_sub_dig(lamb, lamb, 1); break; + case EP_B48: + /* lambda = z^8 - 1. */ + bn_sqr(lamb, lamb); + bn_sqr(lamb, lamb); + bn_sqr(lamb, lamb); + bn_sub_dig(lamb, lamb, 1); + break; default: if (bn_cmp_dig(h, 1) == RLC_EQ) { - /* SECG curves with endomorphisms. */ - fp_set_dig(beta, 2); - h->used = RLC_FP_DIGS; - dv_copy(h->dp, fp_prime_get(), RLC_FP_DIGS); - /* Borrow h but restore at the end. */ - bn_sub_dig(h, h, 1); - bn_div_dig(h, h, 3); - fp_exp(beta, beta, h); + /* other curves with endomorphisms. */ bn_set_dig(lamb, 3); - bn_sub_dig(h, r, 1); - bn_div_dig(h, h, 3); - bn_mxp(lamb, lamb, h, r); + bn_sub_dig(t, r, 1); + bn_div_dig(t, t, 3); + bn_mxp(lamb, lamb, t, r); /* Try another primitive root. */ if (bn_cmp_dig(lamb, 1) == RLC_EQ) { bn_set_dig(lamb, 2); - bn_mxp(lamb, lamb, h, r); + bn_mxp(lamb, lamb, t, r); } - bn_set_dig(h, 1); } break; } @@ -1236,25 +1274,25 @@ void ep_param_set(int param) { fp_set_dig(g->z, 1); g->coord = BASIC; + core_get()->ep_id = param; + core_get()->ep_is_pairf = pairf; + #if defined(EP_PLAIN) if (plain) { - ep_curve_set_plain(a, b, g, r, h, u, ctmap); - core_get()->ep_id = param; + ep_curve_set_plain(a, b, g, r, h, ctmap); } + #endif #if defined(EP_ENDOM) if (endom) { - ep_curve_set_endom(a, b, g, r, h, beta, lamb, u, ctmap); - core_get()->ep_id = param; - core_get()->ep_is_pairf = pairf; + ep_curve_set_endom(a, b, g, r, h, beta, lamb, ctmap); } #endif #if defined(EP_SUPER) if (super) { - ep_curve_set_super(a, b, g, r, h, u, ctmap); - core_get()->ep_id = param; + ep_curve_set_super(a, b, g, r, h, ctmap); } #endif } @@ -1265,7 +1303,6 @@ void ep_param_set(int param) { fp_free(a); fp_free(b); fp_free(beta); - fp_free(u); bn_free(lamb); ep_free(g); bn_free(r); @@ -1345,6 +1382,8 @@ int ep_param_set_any_endom(void) { ep_param_set(B24_P315); #elif FP_PRIME == 317 ep_param_set(B24_P317); +#elif FP_PRIME == 330 + ep_param_set(K16_P330); #elif FP_PRIME == 377 ep_param_set(B12_P377); #elif FP_PRIME == 381 @@ -1362,11 +1401,9 @@ int ep_param_set_any_endom(void) { #elif FP_PRIME == 455 ep_param_set(B12_P455); #elif FP_PRIME == 508 - ep_param_set(KSS_P508); + ep_param_set(K18_P508); #elif FP_PRIME == 509 ep_param_set(B24_P509); -#elif FP_PRIME == 511 - ep_param_set(OT8_P511); #elif FP_PRIME == 544 ep_param_set(GMT8_P544); #elif FP_PRIME == 638 @@ -1374,7 +1411,12 @@ int ep_param_set_any_endom(void) { ep_param_set(B12_P638); #else ep_param_set(K18_P638); + //ep_param_set(SG18_P638); #endif +#elif FP_PRIME == 765 + ep_param_set(N16_P765); +#elif FP_PRIME == 766 + ep_param_set(K16_P766); #else r = RLC_ERR; #endif @@ -1389,9 +1431,6 @@ int ep_param_set_any_super(void) { #if defined(EP_SUPER) #if FP_PRIME == 1536 ep_param_set(SS_P1536); -#elif FP_PRIME == 3072 - ep_param_set(SS_P3072); -#else r = RLC_ERR; #endif #else @@ -1401,98 +1440,110 @@ int ep_param_set_any_super(void) { } int ep_param_set_any_pairf(void) { - int type = 0, degree = 0, r = RLC_OK; + int type = 0, extension = 0, r = RLC_OK; #if defined(EP_ENDOM) #if FP_PRIME == 158 ep_param_set(BN_P158); type = RLC_EP_DTYPE; - degree = 2; + extension = 2; #elif FP_PRIME == 254 ep_param_set(BN_P254); type = RLC_EP_DTYPE; - degree = 2; + extension = 2; #elif FP_PRIME == 256 ep_param_set(BN_P256); type = RLC_EP_DTYPE; - degree = 2; + extension = 2; #elif FP_PRIME == 315 ep_param_set(B24_P315); type = RLC_EP_DTYPE; - degree = 4; + extension = 4; #elif FP_PRIME == 317 ep_param_set(B24_P317); type = RLC_EP_MTYPE; - degree = 4; + extension = 4; +#elif FP_PRIME == 330 + ep_param_set(K16_P330); + type = RLC_EP_MTYPE; + extension = 4; #elif FP_PRIME == 377 ep_param_set(B12_P377); type = RLC_EP_DTYPE; - degree = 2; + extension = 2; #elif FP_PRIME == 381 ep_param_set(B12_P381); type = RLC_EP_MTYPE; - degree = 2; + extension = 2; #elif FP_PRIME == 382 ep_param_set(BN_P382); type = RLC_EP_DTYPE; - degree = 2; + extension = 2; #elif FP_PRIME == 383 ep_param_set(B12_P383); type = RLC_EP_MTYPE; - degree = 2; + extension = 2; #elif FP_PRIME == 446 #ifdef FP_QNRES ep_param_set(B12_P446); type = RLC_EP_MTYPE; - degree = 2; + extension = 2; #else ep_param_set(BN_P446); type = RLC_EP_DTYPE; - degree = 2; + extension = 2; #endif #elif FP_PRIME == 455 ep_param_set(B12_P455); type = RLC_EP_DTYPE; - degree = 2; + extension = 2; #elif FP_PRIME == 508 - ep_param_set(KSS_P508); + ep_param_set(K18_P508); type = RLC_EP_DTYPE; - degree = 3; + extension = 3; #elif FP_PRIME == 509 ep_param_set(B24_P509); type = RLC_EP_DTYPE; - degree = 4; -#elif FP_PRIME == 511 - ep_param_set(OT8_P511); - type = RLC_EP_DTYPE; - degree = 2; + extension = 4; #elif FP_PRIME == 544 ep_param_set(GMT8_P544); type = RLC_EP_MTYPE; - degree = 2; + extension = 2; #elif FP_PRIME == 569 ep_param_set(SG54_P569); type = RLC_EP_MTYPE; - degree = 9; + extension = 9; #elif FP_PRIME == 575 ep_param_set(B48_P575); type = RLC_EP_MTYPE; - degree = 8; + extension = 8; #elif FP_PRIME == 638 #ifdef FP_QNRES ep_param_set(B12_P638); type = RLC_EP_MTYPE; - degree = 2; + extension = 2; #else + //ep_param_set(BN_P638); + //type = RLC_EP_DTYPE; + //extension = 2; ep_param_set(K18_P638); + //ep_param_set(SG18_P638); type = RLC_EP_MTYPE; - degree = 3; + extension = 3; #endif +#elif FP_PRIME == 765 + ep_param_set(N16_P765); + type = RLC_EP_MTYPE; + extension = 4; +#elif FP_PRIME == 766 + ep_param_set(K16_P766); + type = RLC_EP_MTYPE; + extension = 4; #elif FP_PRIME == 1536 ep_param_set(SS_P1536); - degree = 0; + extension = 1; #elif FP_PRIME == 3072 - ep_param_set(SS_P3072); - degree = 0; + ep_param_set(K1_P3072); + extension = 1; #else r = RLC_ERR; #endif @@ -1501,10 +1552,8 @@ int ep_param_set_any_pairf(void) { #endif #ifdef WITH_PP if (r == RLC_OK) { - switch (degree) { - case 0: - ep2_curve_set_twist(0); - /* Compute pairing generator. */ + switch (extension) { + case 1: pc_core_calc(); break; case 2: @@ -1516,6 +1565,9 @@ int ep_param_set_any_pairf(void) { case 4: ep4_curve_set_twist(type); break; + case 8: + ep8_curve_set_twist(type); + break; } } #else @@ -1584,6 +1636,12 @@ void ep_param_print(void) { case B24_P317: util_banner("Curve B24-P317:", 0); break; + case K16_P330: + util_banner("Curve K16-P330:", 0); + break; + case B12_P377: + util_banner("Curve B12-P377:", 0); + break; case B12_P381: util_banner("Curve B12-P381:", 0); break; @@ -1605,15 +1663,12 @@ void ep_param_print(void) { case B12_P455: util_banner("Curve B12-P455:", 0); break; - case KSS_P508: - util_banner("Curve KSS-P508:", 0); + case K18_P508: + util_banner("Curve K18-P508:", 0); break; case B24_P509: util_banner("Curve B24-P509:", 0); break; - case OT8_P511: - util_banner("Curve OT8-P511:", 0); - break; case SG54_P569: util_banner("Curve SG54-P569:", 0); break; @@ -1629,11 +1684,20 @@ void ep_param_print(void) { case K18_P638: util_banner("Curve K18-P638:", 0); break; + case SG18_P638: + util_banner("Curve SG18-P638:", 0); + break; + case N16_P765: + util_banner("Curve N16-P765:", 0); + break; + case K16_P766: + util_banner("Curve K16-P766:", 0); + break; case SS_P1536: util_banner("Curve SS-P1536:", 0); break; - case SS_P3072: - util_banner("Curve SS-3072:", 0); + case K1_P3072: + util_banner("Curve K1-P3072:", 0); break; case CURVE_1174: util_banner("Curve Curve1174:", 0); @@ -1674,7 +1738,9 @@ int ep_param_level(void) { case TWEEDLEDUM: return 128; case B24_P315: + case B24_P317: case B12_P377: + case K16_P330: case B12_P381: case BN_P382: case B12_P383: @@ -1686,6 +1752,7 @@ int ep_param_level(void) { case B12_P455: return 140; case NIST_P384: + case K16_P766: case K18_P638: case B24_P509: return 192; @@ -1693,6 +1760,7 @@ int ep_param_level(void) { return 256; case BN_P638: case B12_P638: + case K18_P508: return 160; } return 0; @@ -1700,19 +1768,20 @@ int ep_param_level(void) { int ep_param_embed(void) { switch (core_get()->ep_is_pairf) { - case EP_SS1: + case EP_K1: return 1; case EP_SS2: return 2; - case EP_OT8: case EP_GMT8: return 8; case EP_BN: case EP_B12: return 12; + case EP_N16: case EP_K16: return 16; case EP_K18: + case EP_SG18: return 18; case EP_B24: return 24; diff --git a/src/ep/relic_ep_psi.c b/src/ep/relic_ep_psi.c index 28352ece5..d080fcbbb 100644 --- a/src/ep/relic_ep_psi.c +++ b/src/ep/relic_ep_psi.c @@ -36,8 +36,6 @@ /* Public definitions */ /*============================================================================*/ -#if defined(EP_ENDOM) && !defined(STRIP) - void ep_psi(ep_t r, const ep_t p) { if (ep_is_infty(p)) { ep_set_infty(r); @@ -55,4 +53,3 @@ void ep_psi(ep_t r, const ep_t p) { } } -#endif diff --git a/src/epx/relic_ep2_curve.c b/src/epx/relic_ep2_curve.c index bd97a5efe..26a3b7216 100644 --- a/src/epx/relic_ep2_curve.c +++ b/src/epx/relic_ep2_curve.c @@ -241,23 +241,6 @@ /** @} */ #endif -#if defined(EP_ENDOM) && FP_PRIME == 511 -/** @{ */ -#define OT8_P511_A0 "0" -#define OT8_P511_A1 "1" -#define OT8_P511_B0 "0" -#define OT8_P511_B1 "0" -#define OT8_P511_X0 "09541B7BB446EBE58277E0183B448E09D567ACFAAA07F2D3C01967088544C6FA844B803CFC8C8A91D0DFFAB5F55B95372C5AB5DD38E13EE92DAA6882535A1244" -#define OT8_P511_X1 "332FBBD88DA3493CAF2F082C9C43E463523C8611AC52AB498F1D28D7844E42C67AF62A9BF0F4D9DDD38F79F51C9DBDB10735AC3CD69FF7867E27EBD65DD8D3EF" -#define OT8_P511_Y0 "2E298CA6C71CE0C6CABA9208E6350B73B0E8BF3EE7CC1777C64BD3680AC857D1823993C8877CBD0203CD3A9835A053F5549BDF7DC206EE1B40BA43A2BD59B793" -#define OT8_P511_Y1 "109CF99B6C312D74CEFF87959789AF53D231988B0E77FF424C8738C20EA91E7F634399A3899E101EBF5C6A0DBE2E40ACA8D0DBCE0F2C6A0300987BBABD9097DC" -#define OT8_P511_R "100000000002AC000000002AD56000000131304C0000032F6D0B1000000000001" -#define OT8_P511_H "1000000000080400000001D72B20000061916054001384B3D863F2EBD23CF44774A8836D060A488CB13701DF690F23AF2A5394A1F9EE0B564F725AD505A8F75463E3DBDF97FBE852B96A19E4477DB82D7C260034DEDA6C75853BB18EE3956002" -#define OT8_P511_MAPU0 "0" -#define OT8_P511_MAPU1 "1" -/** @} */ -#endif - #if defined(EP_ENDOM) && FP_PRIME == 544 /** @{ */ #define GMT8_P544_A0 "0" @@ -678,53 +661,6 @@ fp_t *ep2_curve_get_b(void) { return core_get()->ep2_b; } -void ep2_curve_get_vs(bn_t *v) { - bn_t x, t; - - bn_null(x); - bn_null(t); - - RLC_TRY { - bn_new(x); - bn_new(t); - - fp_prime_get_par(x); - bn_copy(v[1], x); - bn_copy(v[2], x); - bn_copy(v[3], x); - - /* t = 2x^2. */ - bn_sqr(t, x); - bn_dbl(t, t); - - /* v0 = 2x^2 + 3x + 1. */ - bn_mul_dig(v[0], x, 3); - bn_add_dig(v[0], v[0], 1); - bn_add(v[0], v[0], t); - - /* v3 = -(2x^2 + x). */ - bn_add(v[3], v[3], t); - bn_neg(v[3], v[3]); - - /* v1 = 12x^3 + 8x^2 + x, v2 = 6x^3 + 4x^2 + x. */ - bn_dbl(t, t); - bn_add(v[2], v[2], t); - bn_dbl(t, t); - bn_add(v[1], v[1], t); - bn_rsh(t, t, 2); - bn_mul(t, t, x); - bn_mul_dig(t, t, 3); - bn_add(v[2], v[2], t); - bn_dbl(t, t); - bn_add(v[1], v[1], t); - } RLC_CATCH_ANY { - RLC_THROW(ERR_CAUGHT); - } RLC_FINALLY { - bn_free(x); - bn_free(t); - } -} - void ep2_curve_get_ord(bn_t n) { ctx_t *ctx = core_get(); if (ctx->ep2_is_twist) { @@ -835,10 +771,6 @@ void ep2_curve_set_twist(int type) { case B12_P455: ASSIGN(B12_P455); break; -#elif FP_PRIME == 511 - case OT8_P511: - ASSIGN(OT8_P511); - break; #elif FP_PRIME == 544 case GMT8_P544: ASSIGN(GMT8_P544); diff --git a/src/epx/relic_ep2_frb.c b/src/epx/relic_ep2_frb.c index 833759d96..b43695e04 100644 --- a/src/epx/relic_ep2_frb.c +++ b/src/epx/relic_ep2_frb.c @@ -37,14 +37,34 @@ /*============================================================================*/ void ep2_frb(ep2_t r, const ep2_t p, int i) { - ctx_t *ctx = core_get(); + if (ep2_curve_opt_a() == RLC_ZERO) { + ctx_t *ctx = core_get(); - ep2_copy(r, p); - for (; i > 0; i--) { - fp2_frb(r->x, r->x, 1); - fp2_frb(r->y, r->y, 1); - fp2_frb(r->z, r->z, 1); - fp2_mul(r->x, r->x, ctx->ep2_frb[0]); - fp2_mul(r->y, r->y, ctx->ep2_frb[1]); + ep2_copy(r, p); + for (; i > 0; i--) { + fp2_frb(r->x, r->x, 1); + fp2_frb(r->y, r->y, 1); + fp2_frb(r->z, r->z, 1); + fp2_mul(r->x, r->x, ctx->ep2_frb[0]); + fp2_mul(r->y, r->y, ctx->ep2_frb[1]); + } + } else { + bn_t t; + + bn_null(t); + + RLC_TRY { + bn_new(t); + + /* Can we do faster than this? */ + fp_prime_get_par(t); + for (; i > 0; i--) { + ep2_mul_basic(r, p, t); + } + } RLC_CATCH_ANY { + RLC_THROW(ERR_NO_MEMORY); + } RLC_FINALLY { + bn_free(t); + } } } diff --git a/src/epx/relic_ep2_map.c b/src/epx/relic_ep2_map.c index 8a130c0fc..31f2c8db9 100644 --- a/src/epx/relic_ep2_map.c +++ b/src/epx/relic_ep2_map.c @@ -48,11 +48,13 @@ * @param[in] len - the degree of the polynomial. */ TMPL_MAP_HORNER(fp2, fp2_t) + /** * Generic isogeny map evaluation for use with SSWU map. */ TMPL_MAP_ISOGENY_MAP(ep2, fp2, iso2) #endif /* EP_CTMAP */ + /** * Simplified SWU mapping. */ @@ -62,11 +64,14 @@ TMPL_MAP_ISOGENY_MAP(ep2, fp2, iso2) dv_copy_cond(O[1], I[1], RLC_FP_DIGS, C); \ } while (0) TMPL_MAP_SSWU(ep2, fp2, fp_t, EP2_MAP_COPY_COND) + /** * Shallue--van de Woestijne map. */ TMPL_MAP_SVDW(ep2, fp2, fp_t, EP2_MAP_COPY_COND) + #undef EP2_MAP_COPY_COND + /* caution: this function overwrites k, which it uses as an auxiliary variable */ static inline int fp2_sgn0(const fp2_t t, bn_t k) { const int t_0_zero = fp_is_zero(t[0]); @@ -81,11 +86,17 @@ static inline int fp2_sgn0(const fp2_t t, bn_t k) { return t_0_neg | (t_0_zero & t_1_neg); } -/*============================================================================*/ -/* Public definitions */ -/*============================================================================*/ - -void ep2_map_from_field(ep2_t p, const uint8_t *uniform_bytes, size_t len) { +/** + * Maps a byte array to a point in an elliptic curve over a quadratic extension + * using an explicit domain separation tag. + * + * @param[out] p - the result. + * @param[in] msg - the byte array to map. + * @param[in] len - the array length in bytes. + * @param[in] dst - the domain separatoin tag. + * @param[in] dst_len - the domain separation tag length in bytes. + */ +static void ep2_map_from_field(ep2_t p, const uint8_t *r, size_t len) { bn_t k; fp2_t t; ep2_t q; @@ -109,14 +120,14 @@ void ep2_map_from_field(ep2_t p, const uint8_t *uniform_bytes, size_t len) { /* which hash function should we use? */ const int abNeq0 = (ep2_curve_opt_a() != RLC_ZERO) && (ep2_curve_opt_b() != RLC_ZERO); - void (*const map_fn)(ep2_t, fp2_t) = (ep2_curve_is_ctmap() || - abNeq0) ? ep2_map_sswu : ep2_map_svdw; + const void (*const map_fn)(ep2_t, fp2_t) = (void (*const)) + (ep2_curve_is_ctmap() || abNeq0 ? ep2_map_sswu : ep2_map_svdw); #define EP2_MAP_CONVERT_BYTES(IDX) \ do { \ - bn_read_bin(k, uniform_bytes + 2 * IDX * lpe, lpe); \ + bn_read_bin(k, r + 2 * IDX * lpe, lpe); \ fp_prime_conv(t[0], k); \ - bn_read_bin(k, uniform_bytes + (2 * IDX + 1) * lpe, lpe); \ + bn_read_bin(k, r + (2 * IDX + 1) * lpe, lpe); \ fp_prime_conv(t[1], k); \ } while (0) @@ -164,27 +175,221 @@ void ep2_map_from_field(ep2_t p, const uint8_t *uniform_bytes, size_t len) { } } +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +#if EP_MAP == BASIC || !defined(STRIP) + +void ep2_map_basic(ep2_t p, const uint8_t *msg, size_t len) { + bn_t x; + fp2_t t0; + uint8_t digest[RLC_MD_LEN]; + + bn_null(x); + fp2_null(t0); + + RLC_TRY { + bn_new(x); + fp2_new(t0); + + md_map(digest, msg, len); + bn_read_bin(x, digest, RLC_MIN(RLC_FP_BYTES, RLC_MD_LEN)); + + fp2_zero(p->x); + fp_prime_conv(p->x[0], x); + fp2_set_dig(p->z, 1); + + while (1) { + ep2_rhs(t0, p); + + if (fp2_is_sqr(t0) == 1) { + fp2_srt(p->y, t0); + p->coord = BASIC; + break; + } + + fp2_add_dig(p->x, p->x, 1); + } + + ep2_mul_cof(p, p); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + bn_free(x); + fp2_free(t0); + } +} + +#endif -void ep2_map_dst(ep2_t p, const uint8_t *msg, size_t len, const uint8_t *dst, - size_t dst_len) { +#if EP_MAP == SSWUM || !defined(STRIP) + +void ep2_map_sswum(ep2_t p, const uint8_t *msg, size_t len) { /* enough space for two field elements plus extra bytes for uniformity */ const int lpe = (FP_PRIME + ep_param_level() + 7) / 8; - uint8_t *pseudo_random_bytes = RLC_ALLOCA(uint8_t, 4 * lpe); + uint8_t *r = RLC_ALLOCA(uint8_t, 4 * lpe); RLC_TRY { + if (r == NULL) { + RLC_THROW(ERR_NO_MEMORY); + } /* XXX(rsw) See note in ep/relic_ep_map.c about using MD_MAP. */ /* hash to a pseudorandom string using md_xmd */ - md_xmd(pseudo_random_bytes, 4 * lpe, msg, len, dst, dst_len); - ep2_map_from_field(p, pseudo_random_bytes, 2 * lpe); + md_xmd(r, 4 * lpe, msg, len, (const uint8_t *)"RELIC", 5); + ep2_map_from_field(p, r, 2 * lpe); } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { - RLC_FREE(pseudo_random_bytes); + RLC_FREE(r); } } -void ep2_map(ep2_t p, const uint8_t *msg, size_t len) { - ep2_map_dst(p, msg, len, (const uint8_t *)"RELIC", 5); +#endif + +#if EP_MAP == SWIFT || !defined(STRIP) + +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; + ctx_t *ctx = core_get(); + dig_t c2, c3; + bn_t k; + + bn_null(k); + fp2_null(t); + fp2_null(u); + fp2_null(v); + fp2_null(w); + fp2_null(y); + fp2_null(x1); + fp2_null(y1); + fp2_null(z1); + + RLC_TRY { + bn_new(k); + fp2_new(t); + fp2_new(u); + fp2_new(v); + fp2_new(w); + fp2_new(y); + fp2_new(x1); + fp2_new(y1); + fp2_new(z1); + + md_xmd(r, 4 * elm + 1, msg, len, (const uint8_t *)"RELIC", 5); + + for (int i = 0; i < 2; i++) { + bn_read_bin(k, r, elm); + fp_prime_conv(u[i], k); + r += elm; + bn_read_bin(k, r, elm); + fp_prime_conv(t[i], k); + r += elm; + } + sign = r[0] & 1; + + /* 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 (!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); + 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); + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + bn_free(k); + fp2_free(t); + fp2_free(u); + fp2_free(v); + fp2_free(w); + fp2_free(y); + fp2_free(x1); + fp2_free(y1); + fp2_free(z1); + RLC_FREE(r); + } } + +#endif diff --git a/src/epx/relic_ep2_mul.c b/src/epx/relic_ep2_mul.c index ba087bbfa..ed49a8062 100644 --- a/src/epx/relic_ep2_mul.c +++ b/src/epx/relic_ep2_mul.c @@ -112,9 +112,11 @@ static void ep2_mul_glv_imp(ep2_t r, const ep2_t p, const bn_t k) { #endif /* EP_ENDOM */ +#if defined(EP_PLAIN) || defined(EP_SUPER) + static void ep2_mul_naf_imp(ep2_t r, const ep2_t p, const bn_t k) { - size_t l, n; - int8_t naf[RLC_FP_BITS + 1]; + size_t l; + int8_t n, naf[RLC_FP_BITS + 1]; ep2_t t[1 << (RLC_WIDTH - 2)]; RLC_TRY { @@ -159,6 +161,7 @@ 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 */ /*============================================================================*/ @@ -167,22 +170,25 @@ static void ep2_mul_naf_imp(ep2_t r, const ep2_t p, const bn_t k) { void ep2_mul_basic(ep2_t r, const ep2_t p, const bn_t k) { ep2_t t; - int8_t u, naf[2 * RLC_FP_BITS + 1]; + int8_t u, *naf = RLC_ALLOCA(int8_t, bn_bits(k) + 1); size_t l; ep2_null(t); if (bn_is_zero(k) || ep2_is_infty(p)) { + RLC_FREE(naf); ep2_set_infty(r); return; } RLC_TRY { ep2_new(t); + if (naf == NULL) { + RLC_THROW(ERR_NO_BUFFER); + } - l = 2 * RLC_FP_BITS + 1; + l = bn_bits(k) + 1; bn_rec_naf(naf, &l, k, 2); - ep2_set_infty(t); for (int i = l - 1; i >= 0; i--) { ep2_dbl(t, t); @@ -205,6 +211,7 @@ void ep2_mul_basic(ep2_t r, const ep2_t p, const bn_t k) { } RLC_FINALLY { ep2_free(t); + RLC_FREE(naf); } } @@ -282,7 +289,12 @@ void ep2_mul_slide(ep2_t r, const ep2_t p, const bn_t k) { void ep2_mul_monty(ep2_t r, const ep2_t p, const bn_t k) { ep2_t t[2]; + bn_t n, l, _k; + size_t bits; + bn_null(n); + bn_null(l); + bn_null(_k); ep2_null(t[0]); ep2_null(t[1]); @@ -292,14 +304,32 @@ void ep2_mul_monty(ep2_t r, const ep2_t p, const bn_t k) { } RLC_TRY { + bn_new(n); + bn_new(l); + bn_new(_k); ep2_new(t[0]); ep2_new(t[1]); - ep2_set_infty(t[0]); - ep2_copy(t[1], p); + ep2_curve_get_ord(n); + bits = bn_bits(n); - for (int i = bn_bits(k) - 1; i >= 0; i--) { - int j = bn_get_bit(k, i); + bn_mod(_k, k, n); + 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), + bn_get_bit(l, bits) == 0); + l->used = RLC_SEL(l->used, n->used, bn_get_bit(l, bits) == 0); + + ep2_norm(t[0], p); + ep2_dbl(t[1], t[0]); + + /* Blind both points independently. */ + ep2_blind(t[0], t[0]); + ep2_blind(t[1], t[1]); + + 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); @@ -317,13 +347,13 @@ void ep2_mul_monty(ep2_t r, const ep2_t p, const bn_t k) { } ep2_norm(r, t[0]); - if (bn_sign(k) == RLC_NEG) { - ep2_neg(r, r); - } } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { + bn_free(n); + bn_free(l); + bn_free(_k); ep2_free(t[1]); ep2_free(t[0]); } @@ -341,11 +371,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()) { - if (ep2_curve_opt_a() == RLC_ZERO) { - ep2_mul_glv_imp(r, p, k); - } else { - ep2_mul_naf_imp(r, p, k); - } + ep2_mul_glv_imp(r, p, k); return; } #endif diff --git a/src/epx/relic_ep2_mul_fix.c b/src/epx/relic_ep2_mul_fix.c index 70efb83a1..075c9227a 100644 --- a/src/epx/relic_ep2_mul_fix.c +++ b/src/epx/relic_ep2_mul_fix.c @@ -136,9 +136,6 @@ void ep2_mul_fix_basic(ep2_t r, const ep2_t *t, const bn_t k) { } } ep2_norm(r, r); - if (bn_sign(_k) == RLC_NEG) { - ep2_neg(r, r); - } } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { @@ -244,9 +241,6 @@ void ep2_mul_fix_combs(ep2_t r, const ep2_t *t, const bn_t k) { } } ep2_norm(r, r); - if (bn_sign(_k) == RLC_NEG) { - ep2_neg(r, r); - } } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); @@ -361,9 +355,6 @@ void ep2_mul_fix_combd(ep2_t r, const ep2_t *t, const bn_t k) { ep2_add(r, r, t[(1 << RLC_DEPTH) + w1]); } ep2_norm(r, r); - if (bn_sign(_k) == RLC_NEG) { - ep2_neg(r, r); - } } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); diff --git a/src/epx/relic_ep2_mul_sim.c b/src/epx/relic_ep2_mul_sim.c index 1e8d7ab6f..a4c69bfd2 100644 --- a/src/epx/relic_ep2_mul_sim.c +++ b/src/epx/relic_ep2_mul_sim.c @@ -56,8 +56,7 @@ static void ep2_mul_sim_endom(ep2_t r, const ep2_t p, const bn_t k, const ep2_t q, const bn_t m) { size_t l, _l[4]; bn_t _k[4], _m[4], n, u; - int8_t naf0[4][RLC_FP_BITS + 1]; - int8_t naf1[4][RLC_FP_BITS + 1]; + int8_t naf0[4][RLC_FP_BITS + 1], naf1[4][RLC_FP_BITS + 1]; ep2_t _p[4], _q[4]; bn_null(n); @@ -162,14 +161,12 @@ static void ep2_mul_sim_endom(ep2_t r, const ep2_t p, const bn_t k, */ static void ep2_mul_sim_plain(ep2_t r, const ep2_t p, const bn_t k, const ep2_t q, const bn_t m, const ep2_t *t) { - int i, n0, n1, w, gen; - int8_t naf0[2 * RLC_FP_BITS + 1], naf1[2 * RLC_FP_BITS + 1], *_k, *_m; - ep2_t t0[1 << (RLC_WIDTH - 2)]; - ep2_t t1[1 << (RLC_WIDTH - 2)]; + int i, w, gen = (t == NULL ? 0 : 1); + int8_t n0, n1, naf0[2 * RLC_FP_BITS + 1], naf1[2 * RLC_FP_BITS + 1]; + ep2_t t0[1 << (RLC_WIDTH - 2)], t1[1 << (RLC_WIDTH - 2)]; size_t l, l0, l1; RLC_TRY { - gen = (t == NULL ? 0 : 1); if (!gen) { for (i = 0; i < (1 << (RLC_WIDTH - 2)); i++) { ep2_null(t0[i]); @@ -198,8 +195,6 @@ static void ep2_mul_sim_plain(ep2_t r, const ep2_t p, const bn_t k, bn_rec_naf(naf1, &l1, m, RLC_WIDTH); l = RLC_MAX(l0, l1); - _k = naf0 + l - 1; - _m = naf1 + l - 1; if (bn_sign(k) == RLC_NEG) { for (i = 0; i < l0; i++) { naf0[i] = -naf0[i]; @@ -212,11 +207,11 @@ static void ep2_mul_sim_plain(ep2_t r, const ep2_t p, const bn_t k, } ep2_set_infty(r); - for (i = l - 1; i >= 0; i--, _k--, _m--) { + for (i = l - 1; i >= 0; i--) { ep2_dbl(r, r); - n0 = *_k; - n1 = *_m; + n0 = naf0[i]; + n1 = naf1[i]; if (n0 > 0) { ep2_add(r, r, t[n0 / 2]); } @@ -250,7 +245,6 @@ static void ep2_mul_sim_plain(ep2_t r, const ep2_t p, const bn_t k, } #endif /* EP_PLAIN || EP_SUPER */ - #endif /* EP_SIM == INTER */ /*============================================================================*/ @@ -358,13 +352,6 @@ void ep2_mul_sim_trick(ep2_t r, const ep2_t p, const bn_t k, const ep2_t q, bn_rec_win(w0, &l0, k, w); bn_rec_win(w1, &l1, m, w); - for (int i = l0; i < l1; i++) { - w0[i] = 0; - } - for (int i = l1; i < l0; i++) { - w1[i] = 0; - } - ep2_set_infty(r); for (int i = RLC_MAX(l0, l1) - 1; i >= 0; i--) { for (int j = 0; j < w; j++) { @@ -395,7 +382,6 @@ void ep2_mul_sim_trick(ep2_t r, const ep2_t p, const bn_t k, const ep2_t q, void ep2_mul_sim_inter(ep2_t r, const ep2_t p, const bn_t k, const ep2_t q, const bn_t m) { - int flag = 0; bn_t n, _k, _m; if (bn_is_zero(k) || ep2_is_infty(p)) { @@ -424,16 +410,14 @@ void ep2_mul_sim_inter(ep2_t r, const ep2_t p, const bn_t k, const ep2_t q, #if defined(EP_ENDOM) if (ep_curve_is_endom()) { ep2_mul_sim_endom(r, p, _k, q, _m); - flag = 1; + return; } #endif #if defined(EP_PLAIN) || defined(EP_SUPER) - if (!flag) { - ep2_mul_sim_plain(r, p, _k, q, _m, NULL); - } + ep2_mul_sim_plain(r, p, _k, q, _m, NULL); #endif - (void)flag; + } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } diff --git a/src/epx/relic_ep2_norm.c b/src/epx/relic_ep2_norm.c index 265c502a0..3276649d3 100644 --- a/src/epx/relic_ep2_norm.c +++ b/src/epx/relic_ep2_norm.c @@ -36,7 +36,7 @@ /* Private definitions */ /*============================================================================*/ -#if EP_ADD == PROJC || !defined(STRIP) +#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP) /** * Normalizes a point represented in projective coordinates. @@ -95,7 +95,7 @@ void ep2_norm(ep2_t r, const ep2_t p) { /* If the point is represented in affine coordinates, we just copy it. */ ep2_copy(r, p); } -#if EP_ADD == PROJC || !defined(STRIP) +#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP) ep2_norm_imp(r, p, 0); #endif } @@ -122,9 +122,11 @@ void ep2_norm_sim(ep2_t *r, const ep2_t *t, int n) { 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 } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); diff --git a/src/epx/relic_ep2_pck.c b/src/epx/relic_ep2_pck.c index e51b4a07a..699ebde41 100644 --- a/src/epx/relic_ep2_pck.c +++ b/src/epx/relic_ep2_pck.c @@ -39,28 +39,28 @@ void ep2_pck(ep2_t r, const ep2_t p) { bn_t halfQ, yValue; - bn_null(halfQ); - bn_null(yValue); + bn_null(halfQ); + bn_null(yValue); RLC_TRY { bn_new(halfQ); bn_new(yValue); - halfQ->used = RLC_FP_DIGS; - dv_copy(halfQ->dp, fp_prime_get(), RLC_FP_DIGS); - bn_hlv(halfQ, halfQ); + halfQ->used = RLC_FP_DIGS; + dv_copy(halfQ->dp, fp_prime_get(), RLC_FP_DIGS); + bn_hlv(halfQ, halfQ); - fp_prime_back(yValue, p->y[1]); + fp_prime_back(yValue, p->y[1]); - int b = bn_cmp(yValue, halfQ) == RLC_GT; + int b = bn_cmp(yValue, halfQ) == RLC_GT; - fp2_copy(r->x, p->x); - fp2_zero(r->y); - fp_set_bit(r->y[0], 0, b); - fp_zero(r->y[1]); - fp_set_dig(r->z[0], 1); - fp_zero(r->z[1]); - r->coord = BASIC; + fp2_copy(r->x, p->x); + fp2_zero(r->y); + fp_set_bit(r->y[0], 0, b); + fp_zero(r->y[1]); + fp_set_dig(r->z[0], 1); + fp_zero(r->z[1]); + r->coord = BASIC; } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } diff --git a/src/epx/relic_ep3_curve.c b/src/epx/relic_ep3_curve.c index 8c0c44c3c..8e4996cdb 100644 --- a/src/epx/relic_ep3_curve.c +++ b/src/epx/relic_ep3_curve.c @@ -36,7 +36,27 @@ /* Private definitions */ /*============================================================================*/ -/* See ep/relic_ep_param.c for discussion of MAP_U parameters. */ +#if defined(EP_ENDOM) && FP_PRIME == 508 +/** + * Parameters for a pairing-friendly prime curve over a quadratic extension. + */ +/** @{ */ +#define K18_P508_A0 "0" +#define K18_P508_A1 "0" +#define K18_P508_A2 "0" +#define K18_P508_B0 "0" +#define K18_P508_B1 "0" +#define K18_P508_B2 "1" +#define K18_P508_X0 "0481B38AB0B95B9F699145EE9E0F5BB85063ADEC07039B7464F659BEAB3CC3AE5157FCB2D4F5D88503AAF143C9A9D039A351AA833A08506F7F079885DF87D8D" +#define K18_P508_X1 "AE31CBE29A26EF9A326FC66011A14B6DE0C28B0E117DD8EB86741147BDC64FEE7676A00F3E824BAAEF393CC9BED562D2E5B2F307278ACE7F75A9664F06331FC" +#define K18_P508_X2 "A7B35C55E843DD3D9C8D1785C3023D5983AF01D86662DCFAED2BB86798BE458539192D4E3CCA863D6A9D1E7B9DEBF7DCAB8AD3D8708BE2D79057F3191ADDD16" +#define K18_P508_Y0 "A9E391BA5067387349BAB815425F98056D9841347A1D4B18EBD2C3AA409389F972559F3605324A71BDB3D6AD2F019AA11078B9CF6DE4CF2BEEAF383AFD2936E" +#define K18_P508_Y1 "B4783EC28E495F56D7E84F616367F95BC34F4A23031E5944066F611AA47EB1538EFACDC386CDA4BE64F845ACC2097B93891ECB5DAF450BF817A5CEA3ED70021" +#define K18_P508_Y2 "016AAD68D7ABF2F5AA8910FDE09231927194F3EE1507264418367CBA2DAC99666E0FE4E7FD65D604198E858E0DF718AC2F1B35246DC4087ECE1580FCFA9FE14" +#define K18_P508_R "BF33E1C9934E7868ECE51D291E5644DA8A2F179CEE74854EE6819B240F20CE4E7D19F4CDABA6EAEA5B0E3000000001" +#define K18_P508_H "9806E5E0CE73547F36E994F52B22DD8416121B7A9BA69D6384DFD0B9B51D54E2090C657EF80A51D82E653A1E7902C7FB690AC973C4CA83469894F5F75495B65B1185A9AD5AF835E3F2B54A4E90CDA9F00FF09AFF09AC5BF7B13ACCE2E862BB30718D4D9806D5488EB4BDA0B0D5A5B770050C4FA6C9148DA1C77BEBE19701967DAA73F47B10D257F2A942F1860DCEB6B" +/** @} */ +#endif #if defined(EP_ENDOM) && FP_PRIME == 638 /** @{ */ @@ -55,6 +75,23 @@ #define K18_P638_R "217C6AD09A8C1501A39F40A5CAE9A8FA6C1D721892617A6D5AB381B7B89EF9B4A91AE277CAAA0EE0BC3E2910806BDC08EA69545693C740000000001" #define K18_P638_H "D10F161A65711BAE126EE4D96E29E6BF525A11BD7BC76B44C5EFF1E59229DCDCAC7CDF4627E564E2046C46D868DA9C8A13B6DF56D99B94D915E385CDC71C047AA9B5E11835A3B37571D1822F23B77B2ECA4F71FC1DF25E659264279F89AB8F7490ED9354E08614239C571B3BD7DDAD3C6C8DD23E27CC0F87C40EE0945B05D3349FE931900ACE29582AF47FCD57C6C3ADCF1F67FFEE4767D4ECB7969FEC7AFFC48C84E9719C0A2C2D4D830FCDEA56F4F1F3CECB6B" /** @} */ + +/** @{ */ +#define SG18_P638_A0 "0" +#define SG18_P638_A1 "0" +#define SG18_P638_A2 "0" +#define SG18_P638_B0 "2D" +#define SG18_P638_B1 "F" +#define SG18_P638_B2 "0" +#define SG18_P638_X0 "1755624848CF51F3209A74B978D9E0547518D2F0E563A6EE4759652BF199892BFBF175C37E4E0726ABFFF10CCB23EAA292F85F286706CF3B2B9397212F6DD1F5EDDD294CFDD9F0459DFF37080FEC2612" +#define SG18_P638_X1 "1A879D2ED904732EC6DA468711A78B088661F67CC580045FC8F2E964EFF69C7DF46D4BAB135385DF79E9BF10DF7F5672B483A6F325B1D17B0345C864030A097D822AE6CD0C97C88D6057212C105D05BE" +#define SG18_P638_X2 "152B2968451C399C716962F3B418022D93E33A083A9E093D1CFFF0A7AC85F279E6FC17AEE2A55B89BCBA9280C69EFA3C19B4EAC0A5598AEED18978DE95DD6291C39A2108DC982418C705116AFAB8406E" +#define SG18_P638_Y0 "1BA3F3688C6CAEB5CDE7E1EC316C4C239F04E21AF8C3A29FEA60D1AD10BE89534DC29EDA41F11ABCEF877FDC72331F6AB3B91F5A9A0EACECAB6185D0F70BF16A200C775AF6FFA8C7FA929D336ABD5933" +#define SG18_P638_Y1 "2341147722E627ACA8F027D929976CE638412C3D310C556D2CCF16DCFED3BB7F5FA5C62278C1D67EEF6C93181BC15B16BC8FFC7AC419077BA7BE92DCDF2A81BD8F98EBB58E70F91EE9B725CB0D84F632" +#define SG18_P638_Y2 "2F32085FC7D6305CB13F58995ACAB1A0B0BBC5C642E0804470F84E0F80E9E1FBA51F8DD11ADDC122EA9A632B276DD9331174A6CBF5E7FBD500A38930DBB26F2C59220C1299B79C4752C8ADF87E1AF255" +#define SG18_P638_R "6D45960E65595E64AE55954202C604A99543E572A870006483A877DC004A61BE5000000D793FFFFFFFF7000000000001" +#define SG18_P638_H "87F77ECC6011A73A6F9B3C239413E8278746F3627BECED8355475CE8177053C1DBBEAC0159D2293A4B0F440F9ABCA65386C7305E1888F5A70111BDCE2772A8DA52DE9869A61C0A345DD4AE51209AC13095F27A9636D5B798073A9056163BBB7B3B393CFB5D537C932BFF5EA26FB1455D22D7362313A54DB182588963081F5B011858B919A5BDE89A2F1345AB93F7BE8DD7D186476A6E1B8F3F9A7CA17FF609E65AB7E05B61E57D63A1F73B483C8FAF0C5C1000000A200000000000000000003" +/** @} */ #endif /** @@ -202,53 +239,6 @@ void ep3_curve_get_b(fp3_t b) { fp3_copy(b, core_get()->ep3_b); } -void ep3_curve_get_vs(bn_t *v) { - bn_t x, t; - - bn_null(x); - bn_null(t); - - RLC_TRY { - bn_new(x); - bn_new(t); - - fp_prime_get_par(x); - bn_copy(v[1], x); - bn_copy(v[2], x); - bn_copy(v[3], x); - - /* t = 2x^2. */ - bn_sqr(t, x); - bn_dbl(t, t); - - /* v0 = 2x^2 + 3x + 1. */ - bn_mul_dig(v[0], x, 3); - bn_add_dig(v[0], v[0], 1); - bn_add(v[0], v[0], t); - - /* v3 = -(2x^2 + x). */ - bn_add(v[3], v[3], t); - bn_neg(v[3], v[3]); - - /* v1 = 12x^3 + 8x^2 + x, v2 = 6x^3 + 4x^2 + x. */ - bn_dbl(t, t); - bn_add(v[2], v[2], t); - bn_dbl(t, t); - bn_add(v[1], v[1], t); - bn_rsh(t, t, 2); - bn_mul(t, t, x); - bn_mul_dig(t, t, 3); - bn_add(v[2], v[2], t); - bn_dbl(t, t); - bn_add(v[1], v[1], t); - } RLC_CATCH_ANY { - RLC_THROW(ERR_CAUGHT); - } RLC_FINALLY { - bn_free(x); - bn_free(t); - } -} - void ep3_curve_get_ord(bn_t n) { ctx_t *ctx = core_get(); if (ctx->ep3_is_twist) { @@ -305,10 +295,17 @@ void ep3_curve_set_twist(int type) { bn_new(h); switch (ep_param_get()) { -#if FP_PRIME == 638 +#if FP_PRIME == 508 + case K18_P508: + ASSIGN(K18_P508); + break; +#elif FP_PRIME == 638 case K18_P638: ASSIGN(K18_P638); break; + case SG18_P638: + ASSIGN(SG18_P638); + break; #endif default: (void)str; @@ -339,6 +336,8 @@ void ep3_curve_set_twist(int type) { if (type == RLC_EP_MTYPE) { fp3_inv(ctx->ep3_frb[0], ctx->ep3_frb[0]); fp3_inv(ctx->ep3_frb[1], ctx->ep3_frb[1]); + } else { + fp3_mul_art(ctx->ep3_frb[0], ctx->ep3_frb[0]); } fp18_zero(c); diff --git a/src/epx/relic_ep3_map.c b/src/epx/relic_ep3_map.c index 2e545943f..dd398ede7 100644 --- a/src/epx/relic_ep3_map.c +++ b/src/epx/relic_ep3_map.c @@ -37,43 +37,149 @@ /* Public definitions */ /*============================================================================*/ -void ep3_map(ep3_t p, const uint8_t *msg, int len) { - bn_t x; - fp3_t t0; - uint8_t digest[RLC_MD_LEN]; +void ep3_map(ep3_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, t1z, t2, sign, *r = RLC_ALLOCA(uint8_t, 6 * elm + 1); + fp3_t t, u, v, w, y, x1, y1, z1; + ctx_t *ctx = core_get(); + dig_t c2, c3; + bn_t k; - bn_null(x); - fp3_null(t0); + bn_null(k); + fp3_null(t); + fp3_null(u); + fp3_null(v); + fp3_null(w); + fp3_null(y); + fp3_null(x1); + fp3_null(y1); + fp3_null(z1); RLC_TRY { - bn_new(x); - fp3_new(t0); + bn_new(k); + fp3_new(t); + fp3_new(u); + fp3_new(v); + fp3_new(w); + fp3_new(y); + fp3_new(x1); + fp3_new(y1); + fp3_new(z1); - md_map(digest, msg, len); - bn_read_bin(x, digest, RLC_MIN(RLC_FP_BYTES, RLC_MD_LEN)); + md_xmd(r, 6 * elm + 1, msg, len, (const uint8_t *)"RELIC", 5); - fp3_zero(p->x); - fp_prime_conv(p->x[0], x); - fp3_set_dig(p->z, 1); + for (int i = 0; i <= 2; i++) { + bn_read_bin(k, r, elm); + fp_prime_conv(u[i], k); + r += elm; + bn_read_bin(k, r, elm); + fp_prime_conv(t[i], k); + r += elm; + } + sign = r[0] & 1; + + /* Assume that a = 0. */ + fp3_sqr(x1, u); + fp3_mul(x1, x1, u); + fp3_sqr(y1, t); + fp3_add(x1, x1, ctx->ep3_b); + fp3_sub(x1, x1, y1); + fp3_dbl(y1, y1); + fp3_add(y1, y1, x1); + fp3_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]); + fp_mul(z1[2], z1[2], ctx->ep_map_c[4]); + fp3_mul(x1, x1, z1); + fp3_mul(z1, z1, t); + fp3_dbl(z1, z1); + + fp3_dbl(y, y1); + fp3_sqr(y, y); + fp3_mul(v, y1, u); + fp3_sub(v, x1, v); + fp3_mul(v, v, z1); + fp3_mul(w, y1, z1); + fp3_dbl(w, w); + + if (fp3_is_zero(w)) { + ep3_set_infty(p); + } else { + fp3_inv(w, w); + fp3_mul(x1, v, w); + fp3_add(y1, u, x1); + fp3_neg(y1, y1); + fp3_mul(z1, y, w); + 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); - while (1) { - ep3_rhs(t0, p); + c2 = fp3_is_sqr(u); + c3 = fp3_is_sqr(v); - if (fp3_srt(p->y, t0)) { - p->coord = BASIC; - break; + 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); } - fp_add_dig(p->x[0], p->x[0], 1); - } + if (!fp3_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); + t1z = fp_is_zero(t[1]); + fp_prime_back(k, t[1]); + t1 = bn_get_bit(k, 0); + fp_prime_back(k, t[2]); + t2 = bn_get_bit(k, 0); + + /* t[0] == 0 ? sgn0(t[1]) : sgn0(t[0]) */ + sign ^= (t0 | (t0z & (t1 | (t1z & t2)))); - ep3_mul_cof(p, p); + 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(p->x, x1); + fp3_copy(p->y, t); + fp3_set_dig(p->z, 1); + p->coord = BASIC; + + ep3_mul_cof(p, p); + } } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { - bn_free(x); - fp3_free(t0); + bn_free(k); + fp3_free(t); + fp3_free(u); + fp3_free(v); + fp3_free(w); + fp3_free(y); + fp3_free(x1); + fp3_free(y1); + fp3_free(z1); + RLC_FREE(r); } } diff --git a/src/epx/relic_ep3_mul.c b/src/epx/relic_ep3_mul.c index c72714620..e034f5c21 100644 --- a/src/epx/relic_ep3_mul.c +++ b/src/epx/relic_ep3_mul.c @@ -53,12 +53,20 @@ static void ep3_psi(ep3_t r, const ep3_t p) { RLC_TRY { ep3_new(q); - /* We have that u mod n = p^4 - 3*p mod n. */ - ep3_dbl(q, p); - ep3_add(q, q, p); - ep3_frb(r, p, 3); - ep3_sub(r, r, q); - ep3_frb(r, r, 1); + if (ep_curve_is_pairf() == EP_SG18) { + /* -3*u = (2*p^2 - p^5) mod r */ + ep3_frb(q, p, 5); + ep3_frb(r, p, 2); + ep3_dbl(r, r); + ep3_sub(r, r, q); + } else { + /* For KSS18, we have that u = p^4 - 3*p mod r. */ + ep3_dbl(q, p); + ep3_add(q, q, p); + ep3_frb(r, p, 3); + ep3_sub(r, r, q); + ep3_frb(r, r, 1); + } } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); @@ -88,8 +96,14 @@ static void ep3_mul_glv_imp(ep3_t r, const ep3_t p, const bn_t k) { ep3_new(q[i]); } - ep3_curve_get_ord(n); 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); + } + ep3_curve_get_ord(n); bn_mod(_k[0], k, n); bn_rec_frb(_k, 6, _k[0], u, n, ep_curve_is_pairf() == EP_BN); @@ -103,6 +117,9 @@ static void ep3_mul_glv_imp(ep3_t r, const ep3_t p, const bn_t k) { l = 0; for (i = 0; i < 6; i++) { + if (bn_sign(_k[i]) == RLC_NEG) { + ep3_neg(q[i], q[i]); + } _l[i] = RLC_FP_BITS + 1; bn_rec_naf(naf[i], &_l[i], _k[i], 2); l = RLC_MAX(l, _l[i]); @@ -197,22 +214,25 @@ static void ep3_mul_naf_imp(ep3_t r, const ep3_t p, const bn_t k) { void ep3_mul_basic(ep3_t r, const ep3_t p, const bn_t k) { ep3_t t; - int8_t u, naf[2 * RLC_FP_BITS + 1]; + int8_t u, *naf = RLC_ALLOCA(int8_t, bn_bits(k) + 1); size_t l; ep3_null(t); if (bn_is_zero(k) || ep3_is_infty(p)) { + RLC_FREE(naf); ep3_set_infty(r); return; } RLC_TRY { ep3_new(t); + if (naf == NULL) { + RLC_THROW(ERR_NO_BUFFER); + } - l = 2 * RLC_FP_BITS + 1; + l = bn_bits(k) + 1; bn_rec_naf(naf, &l, k, 2); - ep3_set_infty(t); for (int i = l - 1; i >= 0; i--) { ep3_dbl(t, t); @@ -235,6 +255,7 @@ void ep3_mul_basic(ep3_t r, const ep3_t p, const bn_t k) { } RLC_FINALLY { ep3_free(t); + RLC_FREE(naf); } } @@ -313,7 +334,12 @@ void ep3_mul_slide(ep3_t r, const ep3_t p, const bn_t k) { void ep3_mul_monty(ep3_t r, const ep3_t p, const bn_t k) { ep3_t t[2]; + bn_t n, l, _k; + size_t bits; + bn_null(n); + bn_null(l); + bn_null(_k); ep3_null(t[0]); ep3_null(t[1]); @@ -323,14 +349,32 @@ void ep3_mul_monty(ep3_t r, const ep3_t p, const bn_t k) { } RLC_TRY { + bn_new(n); + bn_new(l); + bn_new(_k); ep3_new(t[0]); ep3_new(t[1]); - ep3_set_infty(t[0]); - ep3_copy(t[1], p); + ep3_curve_get_ord(n); + bits = bn_bits(n); + + bn_mod(_k, k, n); + 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), + bn_get_bit(l, bits) == 0); + l->used = RLC_SEL(l->used, n->used, bn_get_bit(l, bits) == 0); + + ep3_norm(t[0], p); + ep3_dbl(t[1], t[0]); + + /* Blind both points independently. */ + ep3_blind(t[0], t[0]); + ep3_blind(t[1], t[1]); - for (int i = bn_bits(k) - 1; i >= 0; i--) { - int j = bn_get_bit(k, i); + 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); @@ -354,13 +398,13 @@ void ep3_mul_monty(ep3_t r, const ep3_t p, const bn_t k) { } ep3_norm(r, t[0]); - if (bn_sign(k) == RLC_NEG) { - ep3_neg(r, r); - } } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { + bn_free(n); + bn_free(l); + bn_free(_k); ep3_free(t[1]); ep3_free(t[0]); } diff --git a/src/epx/relic_ep3_mul_cof.c b/src/epx/relic_ep3_mul_cof.c index 1fc9c4fc7..02a47498d 100644 --- a/src/epx/relic_ep3_mul_cof.c +++ b/src/epx/relic_ep3_mul_cof.c @@ -35,16 +35,19 @@ #include "relic_tmpl_map.h" /*============================================================================*/ -/* Public definitions */ +/* Private definitions */ /*============================================================================*/ -void ep3_mul_cof(ep3_t r, const ep3_t p) { - ep3_t tx1, tx2, tx3, t0, t1, t2, t3, t4, t5; +/** + * Multiplies a point by the cofactor in a KSS18 curve. + * + * @param[out] r - the result. + * @param[in] p - the point to multiply. + */ +static void ep3_mul_cof_k18(ep3_t r, const ep3_t p) { + ep3_t t0, t1, t2, t3, t4, t5; bn_t x; - ep3_null(tx1); - ep3_null(tx2); - ep3_null(tx3); ep3_null(t0); ep3_null(t1); ep3_null(t2); @@ -54,9 +57,6 @@ void ep3_mul_cof(ep3_t r, const ep3_t p) { bn_null(x); RLC_TRY { - ep3_new(tx1); - ep3_new(tx2); - ep3_new(tx3); ep3_new(t0); ep3_new(t1); ep3_new(t2); @@ -65,54 +65,78 @@ void ep3_mul_cof(ep3_t r, const ep3_t p) { ep3_new(t5); bn_new(x); + /* Method from "Faster Hashing to G2" by Laura Fuentes-Castañeda, + * Edward Knapp and Francisco Rodríguez-Henríquez. + . */ + + /* Compute multi-addition-subtraction chain \sum \lambda_i \psi^P, where + * \lambda_0 = 5u + 18 + * \lambda_1 = (u^3+3u^2+1) + * \lambda_2 = -(3u^2+8*u) + * \lambda_3 = (3u+1) + * \lambda_4 = -(u^2+2) + * \lambda_5 = (u^2+5u) + + * We will write the subscalars below as vectors for simplicity. + */ + fp_prime_get_par(x); - ep3_mul_basic(tx1, p, x); - ep3_mul_basic(tx2, tx1, x); - ep3_mul_basic(tx3, tx2, x); + /* t0 = [u]P, t4 = [u^2]P, later t2 = [u^3]P. */ + ep3_mul_basic(t0, p, x); + ep3_mul_basic(t4, t0, x); - ep3_frb(t1, tx1, 2); + /* t1 = [1, 0, -u, 0, 0, 0]. */ + ep3_frb(t1, t0, 2); + /* t2 = [u, 0, 0, 0, 0, u]. */ ep3_frb(t2, t1, 3); - ep3_add(t2, t2, tx1); + ep3_add(t2, t2, t0); + /* t3 = [0, 0, 0, -u, 0, 0]. */ ep3_frb(t3, t1, 1); ep3_neg(t1, t1); - - ep3_frb(t4, tx2, 1); - ep3_add(t3, t3, t4); - ep3_frb(t4, t4, 1); - ep3_sub(t3, t3, t4); - - ep3_frb(t4, p, 4); - ep3_neg(t4, t4); - - ep3_frb(t5, p, 1); - ep3_frb(tx1, t5, 2); - ep3_add(t5, t5, tx1); - ep3_frb(tx1, tx2, 4); - ep3_sub(t5, t5, tx1); - ep3_frb(tx2, tx1, 1); - ep3_add(t5, t5, tx2); - ep3_frb(tx3, tx3, 1); - ep3_add(t5, t5, tx3); - ep3_add(t1, t1, p); + /* t0 = [u+3, 0, -u, 0, 0, u]. */ ep3_dbl(t0, p); ep3_add(t0, t0, t2); ep3_add(t0, t0, t1); + + /* t2 = [0, 0, u^2, 0, 0, 0], t3 = [0, u^2, -u^2, -u, 0, 0]. */ + ep3_frb(t2, t4, 1); + ep3_add(t3, t3, t2); + ep3_frb(t2, t2, 1); + ep3_sub(t3, t3, t2); + + /* t5 = [0, u^3 + 1, 0, 1, -u^2, u^2] */ + ep3_frb(t5, p, 1); + ep3_frb(t2, t5, 2); + ep3_add(t5, t5, t2); + ep3_frb(t2, t4, 4); + ep3_sub(t5, t5, t2); + ep3_frb(t2, t2, 1); + ep3_add(t5, t5, t2); + ep3_mul_basic(t2, t4, x); + ep3_frb(t2, t2, 1); + ep3_add(t5, t5, t2); + + /* t4 = [0, 0, 0, 0, -1, 0], t3 = [1, u^2, -u^2-u, -u, 0, 0]. */ + ep3_frb(t4, p, 4); + ep3_neg(t4, t4); ep3_add(t3, t3, t1); + /* t4 = [u+3, 0, -u, 0, -1, u]. */ ep3_add(t4, t4, t0); + /* t3 = [u+4, u^2, -u^2-2u, -u, -1, u]. */ ep3_add(t3, t3, t0); + /* t4 = [2u+7, u^2, -u^2-3u, -u, -1, 2u]. */ ep3_add(t4, t4, t3); + /* t3 = [u+4, u^3+u^2+1, -u^2-2u, -u+1, -u^2, u^2+u]. */ ep3_add(t3, t3, t5); + /* t4 = [4u+14, 2u^2, -2u^2-6u, -2u, -2, 4u]. */ ep3_dbl(t4, t4); + /* r = [5u+18, u^3+3u^2+1, -3u^2-8u, -3u+1, -u^2-2, u^2+5u]. */ ep3_add(r, t4, t3); - } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { - ep3_free(tx1); - ep3_free(tx2); - ep3_free(tx3); ep3_free(t0); ep3_free(t1); ep3_free(t2); @@ -122,3 +146,104 @@ void ep3_mul_cof(ep3_t r, const ep3_t p) { bn_free(x); } } + +/** + * Multiplies a point by the cofactor in a Scott-Guillevic curve. + * + * @param[out] r - the result. + * @param[in] p - the point to multiply. + */ +static void ep3_mul_cof_sg18(ep3_t r, const ep3_t p) { + ep3_t t0, t1, t2, t3, t4; + bn_t x; + + ep3_null(t0); + ep3_null(t1); + ep3_null(t2); + ep3_null(t3); + ep3_null(t4); + bn_null(x); + + RLC_TRY { + ep3_new(t0); + ep3_new(t1); + ep3_new(t2); + ep3_new(t3); + ep3_new(t4); + bn_new(x); + + /* Vector computed by Guillevic's MAGMA script: + [9*u^4-3*u^2+u, 3*u^2-1, -6*u^3 + 2*u, -2*u, 0, 3*u^3-u+1] */ + fp_prime_get_par(x); + + /* t0 = [u]P, t1 = [3u^2]P, t2 = [3u^3]P, t3 = [9u^4]P. */ + ep3_mul_basic(t0, p, x); + bn_mul_dig(x, x, 3); + ep3_mul_basic(t1, t0, x); + bn_div_dig(x, x, 3); + ep3_mul_basic(t2, t1, x); + bn_mul_dig(x, x, 3); + ep3_mul_basic(t3, t2, x); + ep3_sub(t3, t3, t1); + ep3_add(t3, t3, t0); + + ep3_sub(t4, t1, p), + ep3_frb(t4, t4, 1); + ep3_add(t3, t3, t4); + + ep3_sub(t2, t2, t0); + ep3_frb(t4, t2, 2); + ep3_dbl(t4, t4); + ep3_sub(t3, t3, t4); + ep3_add(t2, t2, p); + ep3_frb(t2, t2, 5); + ep3_add(t3, t3, t2); + + ep3_dbl(t4, t0); + ep3_frb(t4, t4, 3); + ep3_sub(r, t3, t4); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + ep3_free(t0); + ep3_free(t1); + ep3_free(t2); + ep3_free(t3); + ep3_free(t4); + bn_free(x); + } +} + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +void ep3_mul_cof(ep3_t r, const ep3_t p) { + bn_t k; + + bn_null(k); + + RLC_TRY { + switch (ep_curve_is_pairf()) { + case EP_K18: + ep3_mul_cof_k18(r, p); + break; + case EP_SG18: + ep3_mul_cof_sg18(r, p); + break; + default: + /* Now, multiply by cofactor to get the correct group. */ + ep3_curve_get_cof(k); + if (bn_bits(k) < RLC_DIG) { + ep3_mul_dig(r, p, k->dp[0]); + } else { + ep3_mul_basic(r, p, k); + } + break; + } + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + bn_free(k); + } +} diff --git a/src/epx/relic_ep3_mul_fix.c b/src/epx/relic_ep3_mul_fix.c index 241aeee9c..66276d5a2 100644 --- a/src/epx/relic_ep3_mul_fix.c +++ b/src/epx/relic_ep3_mul_fix.c @@ -136,9 +136,6 @@ void ep3_mul_fix_basic(ep3_t r, const ep3_t *t, const bn_t k) { } } ep3_norm(r, r); - if (bn_sign(_k) == RLC_NEG) { - ep3_neg(r, r); - } } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { @@ -244,9 +241,6 @@ void ep3_mul_fix_combs(ep3_t r, const ep3_t *t, const bn_t k) { } } ep3_norm(r, r); - if (bn_sign(_k) == RLC_NEG) { - ep3_neg(r, r); - } } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); @@ -361,9 +355,6 @@ void ep3_mul_fix_combd(ep3_t r, const ep3_t *t, const bn_t k) { ep3_add(r, r, t[(1 << RLC_DEPTH) + w1]); } ep3_norm(r, r); - if (bn_sign(_k) == RLC_NEG) { - ep3_neg(r, r); - } } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); diff --git a/src/epx/relic_ep3_mul_sim.c b/src/epx/relic_ep3_mul_sim.c index 08bfab688..408232a57 100644 --- a/src/epx/relic_ep3_mul_sim.c +++ b/src/epx/relic_ep3_mul_sim.c @@ -52,14 +52,13 @@ */ static void ep3_mul_sim_plain(ep3_t r, const ep3_t p, const bn_t k, const ep3_t q, const bn_t m, ep3_t *t) { - int i, n0, n1, w, gen; + int i, n0, n1, w, gen = (t == NULL ? 0 : 1); size_t l, l0, l1; int8_t naf0[2 * RLC_FP_BITS + 1], naf1[2 * RLC_FP_BITS + 1], *_k, *_m; ep3_t t0[1 << (RLC_WIDTH - 2)]; ep3_t t1[1 << (RLC_WIDTH - 2)]; RLC_TRY { - gen = (t == NULL ? 0 : 1); if (!gen) { for (i = 0; i < (1 << (RLC_WIDTH - 2)); i++) { ep3_null(t0[i]); @@ -390,14 +389,14 @@ void ep3_mul_sim_gen(ep3_t r, const bn_t k, const ep3_t q, const bn_t m) { } } -void ep3_mul_sim_dig(ep3_t r, const ep3_t p[], const dig_t k[], int len) { +void ep3_mul_sim_dig(ep3_t r, const ep3_t p[], const dig_t k[], size_t len) { ep3_t t; int max; ep3_null(t); max = util_bits_dig(k[0]); - for (int i = 1; i < len; i++) { + for (size_t i = 1; i < len; i++) { max = RLC_MAX(max, util_bits_dig(k[i])); } diff --git a/src/epx/relic_ep3_norm.c b/src/epx/relic_ep3_norm.c index 84d475e47..0015c2711 100644 --- a/src/epx/relic_ep3_norm.c +++ b/src/epx/relic_ep3_norm.c @@ -36,7 +36,7 @@ /* Private definitions */ /*============================================================================*/ -#if EP_ADD == PROJC || !defined(STRIP) +#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP) /** * Normalizes a point represented in projective coordinates. @@ -95,7 +95,7 @@ void ep3_norm(ep3_t r, const ep3_t p) { /* If the point is represented in affine coordinates, we just copy it. */ ep3_copy(r, p); } -#if EP_ADD == PROJC || !defined(STRIP) +#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP) ep3_norm_imp(r, p, 0); #endif } @@ -121,10 +121,11 @@ void ep3_norm_sim(ep3_t *r, const ep3_t *t, int n) { fp3_copy(r[i]->y, t[i]->y); 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 } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); diff --git a/src/epx/relic_ep3_util.c b/src/epx/relic_ep3_util.c index c28b95ad5..723bfdfcf 100644 --- a/src/epx/relic_ep3_util.c +++ b/src/epx/relic_ep3_util.c @@ -248,7 +248,7 @@ int ep3_size_bin(const ep3_t a, int pack) { return size; } -void ep3_read_bin(ep3_t a, const uint8_t *bin, int len) { +void ep3_read_bin(ep3_t a, const uint8_t *bin, size_t len) { if (len == 1) { if (bin[0] == 0) { ep3_set_infty(a); @@ -282,7 +282,7 @@ void ep3_read_bin(ep3_t a, const uint8_t *bin, int len) { } } -void ep3_write_bin(uint8_t *bin, int len, const ep3_t a, int pack) { +void ep3_write_bin(uint8_t *bin, size_t len, const ep3_t a, int pack) { ep3_t t; ep3_null(t); diff --git a/src/epx/relic_ep4_curve.c b/src/epx/relic_ep4_curve.c index dafdf678d..5b228c439 100644 --- a/src/epx/relic_ep4_curve.c +++ b/src/epx/relic_ep4_curve.c @@ -84,6 +84,29 @@ /** @} */ #endif +#if defined(EP_ENDOM) && FP_PRIME == 330 +/** @{ */ +#define K16_P330_A0 "0" +#define K16_P330_A1 "0" +#define K16_P330_A2 "1" +#define K16_P330_A3 "0" +#define K16_P330_B0 "0" +#define K16_P330_B1 "0" +#define K16_P330_B2 "0" +#define K16_P330_B3 "0" +#define K16_P330_X0 "0A8E1814295DCD3B32115B7ECA482E00E799D573C1C87226DF403C088C4E0D6867D0F782463D75EF703" +#define K16_P330_X1 "1C35DF89EBA1F4F7F0914CCC2217236A2DEBD627A4140DB7DE5B6C34B64CBFEB0D6A81D37175FC2D2D0" +#define K16_P330_X2 "121D8B058C749480DBD0C3B80A7A87A6062EAFBA48C38A4209D366182B5CF34144A63EA4D2D22A49810" +#define K16_P330_X3 "13DD1C6C7EF26A3BE18758FDD4DA5B1FC973B9C7B2FE6F95742E63209743DA5DC9D78508FFF7D6577F5" +#define K16_P330_Y0 "1D6E4D1204B71D526B26E4F9659A56950863CA7A11798AD0002A662C94925555508BDC74A72AFF20761" +#define K16_P330_Y1 "174D707AAB7BE8D7FD66A81C116C35FAA3DE173AF8E78EBF4D21946D1DAE273D2F01D18BF58FB6774F9" +#define K16_P330_Y2 "07B52F66D7F4F13D402C90F25289B984F4803D5AB4C5D27C38205B96A35D4BA7E21128C628CB8533252" +#define K16_P330_Y3 "230B103DC9594C0EAC2F136CAF4CC297EE32FBB5D6F2EB1F39F73ED0715410E528827C27A28E47E32C3" +#define K16_P330_R "A9AE90F426EE7F9DB56D9C82F1C0B2CA3CB15B2F8ABF5803C963444D043D2731" +#define K16_P330_H "29FFFB0947F8B82A090873C9E956B3A36AB6E037E0A77753117BF9F84FF2EB53D7B3AA3AFB0124167228D28EA26DF7AB6B4A69C60F0F66576B9A07331B9FB744EEF9DEB9AC59EF48BA9872139AF319E427E6DEEF4D6F24C1525725A22B36AA73476912FE2295DE6353A113DB8C14637D012DD09C2637D6F6EA569A3ABC835DF9E3AB55DA62" +/** @} */ +#endif + #if defined(EP_ENDOM) && FP_PRIME == 509 /** @{ */ #define B24_P509_A0 "0" @@ -107,6 +130,53 @@ /** @} */ #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 == 766 +/** @{ */ +#define K16_P766_A0 "0" +#define K16_P766_A1 "0" +#define K16_P766_A2 "1" +#define K16_P766_A3 "0" +#define K16_P766_B0 "0" +#define K16_P766_B1 "0" +#define K16_P766_B2 "0" +#define K16_P766_B3 "0" +#define K16_P766_X0 "2864F5E5FB6FED078FAD04D5587701E9973407697AB1BBF402111C686E6FD2AFD20658BB74DCE094C1316032413E662255F923A11D68AB9851527074A01855830F521B431F14026FCB0BD075402203D31C4DA096A9B85EC3B297144700D2D377" +#define K16_P766_X1 "2823AC7365F9C56A3B5C27882F05C971087A0D54E44AA1C4D697C1BF371E7DA060FC680601C3F78AA6D8BD91BDCD213ACA6D65A3700742900FB4D3A3AA78C2EBD61763CD4727C057BF9EEA3A5EACC023B66B61A3473BE5BCF98125A91F1C084E" +#define K16_P766_X2 "37FC8358DC23B2A6FE3763ED787841E4355D203DD94A113A6EFEF3ED4E4ED1D7D47E5B7B8F85CF52C0B2479ECC74AAB21C56537D80708D65C1BC1E5E6FF69CC93B2F292DA61270386520FB79B780DE7BEF87EF43006EADCDF3AF82ED9556A0A4" +#define K16_P766_X3 "2E699CE6FA1448A9523F867F0C1FCB9C4CE22B007C058C474EF0BAEA2B3E3F486BC1A6A3BF0C396D23E60C60C7FBCDFF8AFF535E9786923B3E8798E23724355422DA4E3AB07D9FF519C94A79610CBF0449A4FC8AB1EEB75EC87879F22655F850" +#define K16_P766_Y0 "03F2F35FCFCCEA92B77B4C6F7A331D1EF96E9616CB26539FF018D0DE51B2A536CE69C9E564B665A6C806CE46AF3DD7FA478AB78548526E0305545C332A5DD7A19694069C2D9585197ED80C81BF9F2CBDD7A0F0FE37156FACF93D2FCC4F2241D5" +#define K16_P766_Y1 "02F05261C24AC6F7948C6F86E458E011E71E619BE8C8119E438EE184979A5F64D07A3845A7189FB1B9D0BC90E625C7194C43EA281559DD09A2E2FCE5A7D1CC50E8176F5458A620C70DCD32F1FEAB870D7B9AEC8F9620B9D88BA201C59511228D" +#define K16_P766_Y2 "12936CF6E9B0279986ABD00C068B7376CA39D4EEAF2598D4276DC1060D75069A8E11E61C526BEDF38E523B9C176E34EF193B958B818CEF1FEE3FCB092D903EA747CB08F9B98338CE500030BE5539EDA6FBEE2B47A60EF989E180B50E125565BF" +#define K16_P766_Y3 "16CBBA489FA40077403ECBE1817781E753BEBA8507D44A7FB6D40737E84C754ECA100C336243F9E763D8D71D31117EACDAB48C59E55065CEABAE97EC2CC66E0878F2377CF8E9312FF6615661D909314C28D5173B725BB81DF63465D862BBD53D" +#define K16_P766_R "1B6C1BFC8E56CCE359E1D8A9B94553D096A506CE2ECF4A33C5D526AC5F3B61CB0A6D76FCD8487EDEE0B0F9BA2DFA29D5AB0B164B8792C233ED1E6EB350BA9F4D37112A98DE816BEB1EA8DDB1" +#define K16_P766_H "755986B96E4AAB1797EAEDDCB714FA0EC4E13C9AF468746FEE467D8D27293EF56C4CFA83CC6DD8774B03009353D93F100EC1314BAB5764E3D32F3DA621C7B3DDACB086098C31F7999CA8F4EA67165C3595BFAD8DBE5B7951091040E97CC5A27149F16A9A960F2557EC038032C876E49E4C40E56C1BD543BD910CB3BAABFA2F9179D2B1711E168A6472FCC1A8D8AF3415559DBF3108029DB68CC8343D397F78577E9EF7DFE8E239D9F5D9EBC1011B8F9E6043DD53C1B98C12BFA48E8A17B3BB0F5DE92DEEA7C9088EA9A643C66D4016BF81616AE20C609045A3EBA6AF3F7BEDC6AE78ABBF788F36CA894B789C84C484B4D31B83DB5CC95783DA34FC601EF7D7F07F60128E0F0E007AE29AB2F98C7A483F0E4CA614E4E45650D3E210A2EB030A6C339DB66CC198FE0EAC1CA827A8A975D094B7862" +/** @} */ +#endif + /** * Assigns a set of ordinary elliptic curve parameters. * @@ -260,53 +330,6 @@ void ep4_curve_get_b(fp4_t b) { fp4_copy(b, core_get()->ep4_b); } -void ep4_curve_get_vs(bn_t *v) { - bn_t x, t; - - bn_null(x); - bn_null(t); - - RLC_TRY { - bn_new(x); - bn_new(t); - - fp_prime_get_par(x); - bn_copy(v[1], x); - bn_copy(v[2], x); - bn_copy(v[3], x); - - /* t = 2x^2. */ - bn_sqr(t, x); - bn_dbl(t, t); - - /* v0 = 2x^2 + 3x + 1. */ - bn_mul_dig(v[0], x, 3); - bn_add_dig(v[0], v[0], 1); - bn_add(v[0], v[0], t); - - /* v3 = -(2x^2 + x). */ - bn_add(v[3], v[3], t); - bn_neg(v[3], v[3]); - - /* v1 = 12x^3 + 8x^2 + x, v2 = 6x^3 + 4x^2 + x. */ - bn_dbl(t, t); - bn_add(v[2], v[2], t); - bn_dbl(t, t); - bn_add(v[1], v[1], t); - bn_rsh(t, t, 2); - bn_mul(t, t, x); - bn_mul_dig(t, t, 3); - bn_add(v[2], v[2], t); - bn_dbl(t, t); - bn_add(v[1], v[1], t); - } RLC_CATCH_ANY { - RLC_THROW(ERR_CAUGHT); - } RLC_FINALLY { - bn_free(x); - bn_free(t); - } -} - void ep4_curve_get_ord(bn_t n) { ctx_t *ctx = core_get(); if (ctx->ep4_is_twist) { @@ -368,10 +391,22 @@ void ep4_curve_set_twist(int type) { case B24_P317: ASSIGN(B24_P317); break; +#elif FP_PRIME == 330 + case K16_P330: + ASSIGN(K16_P330); + break; #elif FP_PRIME == 509 case B24_P509: ASSIGN(B24_P509); break; +#elif FP_PRIME == 765 + case N16_P765: + ASSIGN(N16_P765); + break; +#elif FP_PRIME == 766 + case K16_P766: + ASSIGN(K16_P766); + break; #endif default: (void)str; @@ -393,13 +428,27 @@ void ep4_curve_set_twist(int type) { bn_copy(&(ctx->ep4_r), r); bn_copy(&(ctx->ep4_h), h); - if (type == RLC_EP_MTYPE) { + if (ep4_curve_opt_b() == RLC_ZERO) { fp2_zero(a[0]); - fp_copy(a[1][0], ctx->fp4_p1[0]); - fp_copy(a[1][1], ctx->fp4_p1[1]); + fp_copy(a[1][0], ctx->fp2_p2[1][0]); + fp_copy(a[1][1], ctx->fp2_p2[1][1]); fp4_inv(a, a); fp_copy(ctx->fp4_p1[0], a[1][0]); fp_copy(ctx->fp4_p1[1], a[1][1]); + if (fp2_is_zero(a[1])) { + ctx->frb4 = 0; + } else { + ctx->frb4 = 1; + } + } else { + if (type == RLC_EP_MTYPE) { + fp2_zero(a[0]); + fp_copy(a[1][0], ctx->fp4_p1[0]); + fp_copy(a[1][1], ctx->fp4_p1[1]); + fp4_inv(a, a); + fp_copy(ctx->fp4_p1[0], a[1][0]); + fp_copy(ctx->fp4_p1[1], a[1][1]); + } } #if defined(WITH_PC) diff --git a/src/epx/relic_ep4_map.c b/src/epx/relic_ep4_map.c index 6701e8fbd..55d37cd39 100644 --- a/src/epx/relic_ep4_map.c +++ b/src/epx/relic_ep4_map.c @@ -38,42 +38,262 @@ /*============================================================================*/ void ep4_map(ep4_t p, const uint8_t *msg, size_t len) { - bn_t x; - fp4_t t0; - uint8_t digest[RLC_MD_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; + ctx_t *ctx = core_get(); + bn_t k; - bn_null(x); - fp4_null(t0); + bn_null(k); + fp4_null(a); + fp4_null(c); + fp4_null(t); + fp4_null(u); + fp4_null(v); + fp4_null(w); + fp4_null(y); + fp4_null(x1); + fp4_null(y1); + fp4_null(z1); RLC_TRY { - bn_new(x); - fp4_new(t0); + bn_new(k); + fp4_new(a); + fp4_new(c); + fp4_new(t); + fp4_new(u); + fp4_new(v); + fp4_new(w); + fp4_new(y); + fp4_new(x1); + fp4_new(y1); + fp4_new(z1); - md_map(digest, msg, len); - bn_read_bin(x, digest, RLC_MIN(RLC_FP_BYTES, RLC_MD_LEN)); + 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; + } + } - fp4_zero(p->x); - fp_prime_conv(p->x[0][0], x); - fp4_set_dig(p->z, 1); + /* 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); - while (1) { - ep4_rhs(t0, p); + 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); - if (fp4_srt(p->y, t0)) { - p->coord = BASIC; - break; + 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); - fp_add_dig(p->x[0][0], p->x[0][0], 1); + /* 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); + + /* Multiply by cofactor. */ + p->coord = JACOB; + ep4_norm(p, p); } + 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; + + 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_curve_get_b(w); + + fp4_sqr(t, x1); + fp4_mul(t, t, x1); + fp4_add(t, t, w); + + 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); + + 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); + } + } + + 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(p->x, x1); + fp4_copy(p->y, t); + fp4_set_dig(p->z, 1); + p->coord = BASIC; + } + } + ep4_mul_cof(p, p); } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { - bn_free(x); - fp4_free(t0); + bn_free(k); + fp4_free(a); + fp4_free(c); + fp4_free(t); + fp4_free(u); + fp4_free(v); + fp4_free(w); + fp4_free(y); + fp4_free(x1); + fp4_free(y1); + fp4_free(z1); + RLC_FREE(h); } } diff --git a/src/epx/relic_ep4_mul.c b/src/epx/relic_ep4_mul.c index 8510e5dcc..912742dcf 100644 --- a/src/epx/relic_ep4_mul.c +++ b/src/epx/relic_ep4_mul.c @@ -41,67 +41,49 @@ #if defined(EP_ENDOM) static void ep4_mul_glv_imp(ep4_t r, const ep4_t p, const bn_t k) { - int sign, i, j; - bn_t n, _k[8], u, v; + size_t l, _l[8]; + bn_t n, _k[8], u; int8_t naf[8][RLC_FP_BITS + 1]; ep4_t q[8]; - size_t l, _l[8]; bn_null(n); bn_null(u); - bn_null(v); RLC_TRY { bn_new(n); bn_new(u); - bn_new(v); - for (i = 0; i < 8; i++) { + for (int i = 0; i < 8; i++) { bn_null(_k[i]); ep4_null(q[i]); bn_new(_k[i]); ep4_new(q[i]); } - bn_abs(v, k); ep4_curve_get_ord(n); - if (bn_cmp_abs(v, n) == RLC_GT) { - bn_mod(v, v, n); - } - fp_prime_get_par(u); - sign = bn_sign(u); - bn_abs(u, u); + bn_mod(_k[0], k, n); + bn_rec_frb(_k, 8, _k[0], u, n, ep_curve_is_pairf() == EP_BN); ep4_norm(q[0], p); - for (i = 0; i < 8; i++) { - bn_mod(_k[i], v, u); - bn_div(v, v, u); - if ((sign == RLC_NEG) && (i % 2 != 0)) { - bn_neg(_k[i], _k[i]); - } - if (bn_sign(k) == RLC_NEG) { - bn_neg(_k[i], _k[i]); - } - if (i > 0) { - ep4_frb(q[i], q[i - 1], 1); - } + for (size_t i = 1; i < 8; i++) { + ep4_frb(q[i], q[i - 1], 1); } - l = 0; - for (i = 0; i < 8; i++) { + l = 0; + for (size_t i = 0; i < 8; i++) { if (bn_sign(_k[i]) == RLC_NEG) { ep4_neg(q[i], q[i]); } _l[i] = RLC_FP_BITS + 1; bn_rec_naf(naf[i], &_l[i], _k[i], 2); - l = RLC_MAX(l, _l[i]); + l = RLC_MAX(l, _l[i]); } ep4_set_infty(r); - for (j = l - 1; j >= 0; j--) { + for (int j = l - 1; j >= 0; j--) { ep4_dbl(r, r); - for (i = 0; i < 8; i++) { + for (int i = 0; i < 8; i++) { if (naf[i][j] > 0) { ep4_add(r, r, q[i]); } @@ -119,9 +101,8 @@ static void ep4_mul_glv_imp(ep4_t r, const ep4_t p, const bn_t k) { } RLC_FINALLY { bn_free(n); - bn_free(u); - bn_free(v); - for (i = 0; i < 8; i++) { + bn_free(u); + for (int i = 0; i < 8; i++) { bn_free(_k[i]); ep4_free(q[i]); } @@ -186,35 +167,39 @@ static void ep4_mul_naf_imp(ep4_t r, const ep4_t p, const bn_t k) { /*============================================================================*/ void ep4_mul_basic(ep4_t r, const ep4_t p, const bn_t k) { - int i, l; ep4_t t; + int8_t u, *naf = RLC_ALLOCA(int8_t, bn_bits(k) + 1); + size_t l; ep4_null(t); if (bn_is_zero(k) || ep4_is_infty(p)) { + RLC_FREE(naf); ep4_set_infty(r); return; } RLC_TRY { ep4_new(t); - l = bn_bits(k); - - if (bn_get_bit(k, l - 1)) { - ep4_copy(t, p); - } else { - ep4_set_infty(t); + if (naf == NULL) { + RLC_THROW(ERR_NO_BUFFER); } - for (i = l - 2; i >= 0; i--) { + l = bn_bits(k) + 1; + bn_rec_naf(naf, &l, k, 2); + ep4_set_infty(t); + for (int i = l - 1; i >= 0; i--) { ep4_dbl(t, t); - if (bn_get_bit(k, i)) { + + u = naf[i]; + if (u > 0) { ep4_add(t, t, p); + } else if (u < 0) { + ep4_sub(t, t, p); } } - ep4_copy(r, t); - ep4_norm(r, r); + ep4_norm(r, t); if (bn_sign(k) == RLC_NEG) { ep4_neg(r, r); } @@ -224,6 +209,7 @@ void ep4_mul_basic(ep4_t r, const ep4_t p, const bn_t k) { } RLC_FINALLY { ep4_free(t); + RLC_FREE(naf); } } @@ -301,7 +287,12 @@ void ep4_mul_slide(ep4_t r, const ep4_t p, const bn_t k) { void ep4_mul_monty(ep4_t r, const ep4_t p, const bn_t k) { ep4_t t[2]; + bn_t n, l, _k; + size_t bits; + bn_null(n); + bn_null(l); + bn_null(_k); ep4_null(t[0]); ep4_null(t[1]); @@ -311,14 +302,32 @@ void ep4_mul_monty(ep4_t r, const ep4_t p, const bn_t k) { } RLC_TRY { + bn_new(n); + bn_new(l); + bn_new(_k); ep4_new(t[0]); ep4_new(t[1]); - ep4_set_infty(t[0]); - ep4_copy(t[1], p); + ep4_curve_get_ord(n); + bits = bn_bits(n); + + bn_mod(_k, k, n); + 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), + bn_get_bit(l, bits) == 0); + l->used = RLC_SEL(l->used, n->used, bn_get_bit(l, bits) == 0); + + ep4_norm(t[0], p); + ep4_dbl(t[1], t[0]); - for (int i = bn_bits(k) - 1; i >= 0; i--) { - int j = bn_get_bit(k, i); + /* Blind both points independently. */ + ep4_blind(t[0], t[0]); + ep4_blind(t[1], t[1]); + + 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); @@ -348,13 +357,13 @@ void ep4_mul_monty(ep4_t r, const ep4_t p, const bn_t k) { } ep4_norm(r, t[0]); - if (bn_sign(k) == RLC_NEG) { - ep4_neg(r, r); - } } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { + bn_free(n); + bn_free(l); + bn_free(_k); ep4_free(t[1]); ep4_free(t[0]); } @@ -372,7 +381,7 @@ void ep4_mul_lwnaf(ep4_t r, const ep4_t p, const bn_t k) { #if defined(EP_ENDOM) if (ep_curve_is_endom()) { - if (ep_curve_opt_a() == RLC_ZERO) { + if (ep4_curve_opt_a() == RLC_ZERO) { ep4_mul_glv_imp(r, p, k); } else { ep4_mul_naf_imp(r, p, k); diff --git a/src/epx/relic_ep4_mul_cof.c b/src/epx/relic_ep4_mul_cof.c index 2884290b3..ed3285e24 100644 --- a/src/epx/relic_ep4_mul_cof.c +++ b/src/epx/relic_ep4_mul_cof.c @@ -25,7 +25,7 @@ * @file * * Implementation of point multiplication of a prime elliptic curve over a - * quadratic extension by the curve cofactor. + * quartic extension by the curve cofactor. * * @ingroup epx */ @@ -38,7 +38,177 @@ /* Public definitions */ /*============================================================================*/ -void ep4_mul_cof(ep4_t r, const ep4_t p) { +/** + * Multiplies a point by the cofactor in a KSS16 curve. + * + * @param[out] r - the result. + * @param[in] p - the point to multiply. + */ +static void ep4_mul_cof_k16(ep4_t r, const ep4_t p) { + bn_t x; + ep4_t t0, t1, t2, t3, t4, t5; + + ep4_null(t0); + ep4_null(t1); + ep4_null(t2); + ep4_null(t3); + ep4_null(t4); + ep4_null(t5); + bn_null(x); + + RLC_TRY { + bn_new(x); + ep4_new(t0); + ep4_new(t1); + ep4_new(t2); + ep4_new(t3); + ep4_new(t4); + ep4_new(t5); + + fp_prime_get_par(x); + + /* [x^3-3*x^2, 3*x^2+11*x, -11*x-7, 2*x^3+14, -2*x^3-4*x^2, 4*x^2-2*x, 2*x+24, x^4+x^3] */ + ep4_mul_basic(t1, p, x); + ep4_mul_basic(t2, t1, x); + ep4_mul_basic(t3, t2, x); + + ep4_dbl(t0, t2); + ep4_add(t2, t2, t0); + ep4_sub(t5, t3, t2); + + ep4_dbl(t0, t0); + ep4_dbl(t4, t3); + ep4_add(t4, t4, t0); + ep4_frb(t4, t4, 4); + ep4_sub(t5, t5, t4); + + ep4_sub(t4, t0, t1); + ep4_sub(t4, t4, t1); + ep4_frb(t4, t4, 5); + ep4_add(t5, t5, t4); + + ep4_dbl(t0, t1); + ep4_mul_dig(t4, p, 24); + ep4_add(t4, t4, t0); + ep4_frb(t4, t4, 6); + ep4_add(t5, t5, t4); + + ep4_mul_dig(t4, t1, 11); + ep4_mul_dig(t0, p, 7); + ep4_add(t0, t0, t4); + ep4_add(t4, t4, t2); + ep4_frb(t4, t4, 1); + ep4_add(t5, t5, t4); + ep4_frb(t4, t0, 2); + ep4_sub(t5, t5, t4); + + ep4_dbl(t0, t3); + ep4_mul_dig(t4, p, 14); + ep4_add(t4, t4, t0); + ep4_frb(t4, t4, 3); + ep4_add(t5, t5, t4); + + ep4_mul_basic(t4, t3, x); + ep4_add(t4, t4, t3); + ep4_frb(t4, t4, 7); + ep4_add(t5, t5, t4); + + ep4_norm(r, t5); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + ep4_free(t0); + ep4_free(t1); + ep4_free(t2); + ep4_free(t3); + ep4_free(t4); + ep4_free(t5); + bn_free(x); + + } +} + +/** + * Multiplies a point by the cofactor in a KSS16 curve. + * + * @param[out] r - the result. + * @param[in] p - the point to multiply. + */ +static void ep4_mul_cof_n16(ep4_t r, const ep4_t p) { + bn_t x; + ep4_t t0, t1, t2, t3, t4, t5; + + ep4_null(t0); + ep4_null(t1); + ep4_null(t2); + ep4_null(t3); + ep4_null(t4); + ep4_null(t5); + bn_null(x); + + RLC_TRY { + bn_new(x); + ep4_new(t0); + ep4_new(t1); + ep4_new(t2); + ep4_new(t3); + ep4_new(t4); + ep4_new(t5); + + fp_prime_get_par(x); + + /* [2*(1+u^3), -u^3*(1+u^3), -2*u, u*(1+u^3), -u^4*(u^3+1), -2*u^2, u^2*(1+u^3), 2] */ + ep4_mul_basic(t1, p, x); + ep4_mul_basic(t2, t1, x); + ep4_mul_basic(t3, t2, x); + + ep4_frb(t5, p, 7); + ep4_frb(t4, t1, 2); + ep4_sub(t5, t5, t4); + ep4_frb(t4, t2, 5); + ep4_sub(t5, t5, t4); + ep4_add(t3, t3, p); + ep4_add(t5, t5, t3); + ep4_dbl(t5, t5); + + ep4_mul_basic(t0, t3, x); + ep4_frb(t4, t0, 3); + ep4_add(t5, t5, t4); + + ep4_mul_basic(t0, t0, x); + ep4_frb(t4, t0, 6); + ep4_add(t5, t5, t4); + + ep4_mul_basic(t0, t0, x); + ep4_frb(t4, t0, 1); + ep4_sub(t5, t5, t4); + + ep4_mul_basic(t0, t0, x); + ep4_frb(t4, t0, 4); + ep4_sub(t5, t5, t4); + + ep4_norm(r, t5); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + ep4_free(t0); + ep4_free(t1); + ep4_free(t2); + ep4_free(t3); + ep4_free(t4); + ep4_free(t5); + bn_free(x); + + } +} + +/** + * Multiplies a point by the cofactor in a BLS24 curve. + * + * @param[out] r - the result. + * @param[in] p - the point to multiply. + */ +void ep4_mul_cof_b24(ep4_t r, const ep4_t p) { bn_t z; ep4_t t0, t1, t2, t3; @@ -57,21 +227,21 @@ void ep4_mul_cof(ep4_t r, const ep4_t p) { fp_prime_get_par(z); + bn_sub_dig(z, z, 1); ep4_mul_basic(t0, p, z); + bn_add_dig(z, z, 1); ep4_mul_basic(t1, t0, z); ep4_mul_basic(t2, t1, z); ep4_mul_basic(t3, t2, z); - ep4_sub(t3, t3, t2); - ep4_sub(t3, t3, p); - ep4_sub(t2, t2, t1); + /* Compute t0 = [u - 1]*\psi^3(P). */ + ep4_frb(t0, t0, 3); + /* Compute t2 = [u^2*(u-1)]\psi(P). */ ep4_frb(t2, t2, 1); - - ep4_sub(t1, t1, t0); + /* Compute t1 = [u*(u-1)]\psi^2(P). */ ep4_frb(t1, t1, 2); - - ep4_sub(t0, t0, p); - ep4_frb(t0, t0, 3); + /* Compute t3 = [u^3(u-1) - 1]P. */ + ep4_sub(t3, t3, p); ep4_dbl(r, p); ep4_frb(r, r, 4); @@ -92,3 +262,40 @@ void ep4_mul_cof(ep4_t r, const ep4_t p) { } } + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +void ep4_mul_cof(ep4_t r, const ep4_t p) { + bn_t k; + + bn_null(k); + + RLC_TRY { + switch (ep_curve_is_pairf()) { + case EP_K16: + ep4_mul_cof_k16(r, p); + break; + case EP_N16: + ep4_mul_cof_n16(r, p); + break; + case EP_B24: + ep4_mul_cof_b24(r, p); + break; + default: + /* Now, multiply by cofactor to get the correct group. */ + ep4_curve_get_cof(k); + if (bn_bits(k) < RLC_DIG) { + ep4_mul_dig(r, p, k->dp[0]); + } else { + ep4_mul_basic(r, p, k); + } + break; + } + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + bn_free(k); + } +} diff --git a/src/epx/relic_ep4_mul_fix.c b/src/epx/relic_ep4_mul_fix.c index 96fe25a3a..33b8dac4c 100644 --- a/src/epx/relic_ep4_mul_fix.c +++ b/src/epx/relic_ep4_mul_fix.c @@ -140,21 +140,35 @@ void ep4_mul_pre_basic(ep4_t *t, const ep4_t p) { } void ep4_mul_fix_basic(ep4_t r, const ep4_t *t, const bn_t k) { + bn_t n, _k; + if (bn_is_zero(k)) { ep4_set_infty(r); return; } - ep4_set_infty(r); + bn_null(n); + bn_null(_k); + + RLC_TRY { + bn_new(n); + bn_new(_k); - for (int i = 0; i < bn_bits(k); i++) { - if (bn_get_bit(k, i)) { - ep4_add(r, r, t[i]); + ep4_curve_get_ord(n); + bn_mod(_k, k, n); + + ep4_set_infty(r); + for (int i = 0; i < bn_bits(_k); i++) { + if (bn_get_bit(_k, i)) { + ep4_add(r, r, t[i]); + } } - } - ep4_norm(r, r); - if (bn_sign(k) == RLC_NEG) { - ep4_neg(r, r); + ep4_norm(r, r); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + bn_free(n); + bn_free(_k); } } @@ -206,7 +220,7 @@ void ep4_mul_pre_combs(ep4_t *t, const ep4_t p) { void ep4_mul_fix_combs(ep4_t r, const ep4_t *t, const bn_t k) { int i, j, l, w, n0, p0, p1; - bn_t n; + bn_t n, _k; if (bn_is_zero(k)) { ep4_set_infty(r); @@ -214,15 +228,18 @@ void ep4_mul_fix_combs(ep4_t r, const ep4_t *t, const bn_t k) { } bn_null(n); + bn_null(_k); RLC_TRY { bn_new(n); + bn_new(_k); ep4_curve_get_ord(n); l = bn_bits(n); l = ((l % RLC_DEPTH) == 0 ? (l / RLC_DEPTH) : (l / RLC_DEPTH) + 1); - n0 = bn_bits(k); + bn_mod(_k, k, n); + n0 = bn_bits(_k); p0 = (RLC_DEPTH) * l - 1; @@ -230,7 +247,7 @@ void ep4_mul_fix_combs(ep4_t r, const ep4_t *t, const bn_t k) { p1 = p0--; for (j = RLC_DEPTH - 1; j >= 0; j--, p1 -= l) { w = w << 1; - if (p1 < n0 && bn_get_bit(k, p1)) { + if (p1 < n0 && bn_get_bit(_k, p1)) { w = w | 1; } } @@ -243,7 +260,7 @@ void ep4_mul_fix_combs(ep4_t r, const ep4_t *t, const bn_t k) { p1 = p0--; for (j = RLC_DEPTH - 1; j >= 0; j--, p1 -= l) { w = w << 1; - if (p1 < n0 && bn_get_bit(k, p1)) { + if (p1 < n0 && bn_get_bit(_k, p1)) { w = w | 1; } } @@ -252,15 +269,13 @@ void ep4_mul_fix_combs(ep4_t r, const ep4_t *t, const bn_t k) { } } ep4_norm(r, r); - if (bn_sign(k) == RLC_NEG) { - ep4_neg(r, r); - } } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { bn_free(n); + bn_free(_k); } } diff --git a/src/epx/relic_ep4_mul_sim.c b/src/epx/relic_ep4_mul_sim.c index 2d789bf38..719332f38 100644 --- a/src/epx/relic_ep4_mul_sim.c +++ b/src/epx/relic_ep4_mul_sim.c @@ -52,7 +52,7 @@ */ static void ep4_mul_sim_plain(ep4_t r, const ep4_t p, const bn_t k, const ep4_t q, const bn_t m, ep4_t *t) { - int i, n0, n1, w, gen; + int i, n0, n1, w, gen = (t == NULL ? 0 : 1); int8_t naf0[2 * RLC_FP_BITS + 1], naf1[2 * RLC_FP_BITS + 1], *_k, *_m; ep4_t t0[1 << (RLC_WIDTH - 2)]; ep4_t t1[1 << (RLC_WIDTH - 2)]; @@ -240,13 +240,6 @@ void ep4_mul_sim_trick(ep4_t r, const ep4_t p, const bn_t k, const ep4_t q, bn_rec_win(w0, &l0, k, w); bn_rec_win(w1, &l1, m, w); - for (int i = l0; i < l1; i++) { - w0[i] = 0; - } - for (int i = l1; i < l0; i++) { - w1[i] = 0; - } - ep4_set_infty(r); for (int i = RLC_MAX(l0, l1) - 1; i >= 0; i--) { for (int j = 0; j < w; j++) { @@ -484,14 +477,6 @@ void ep4_mul_sim_lot(ep4_t r, const ep4_t p[], const bn_t k[], size_t n) { } } - for (i = 0; i < n; i++) { - for (j = 0; j < 8; j++) { - for (m = _l[8*i + j]; m < l; m++) { - naf[(8*i + j)*len + m] = 0; - } - } - } - ep4_set_infty(r); for (i = l - 1; i >= 0; i--) { ep4_dbl(r, r); diff --git a/src/epx/relic_ep4_norm.c b/src/epx/relic_ep4_norm.c index ed41baa7f..ca2646dd5 100644 --- a/src/epx/relic_ep4_norm.c +++ b/src/epx/relic_ep4_norm.c @@ -36,7 +36,7 @@ /* Private definitions */ /*============================================================================*/ -#if EP_ADD == PROJC || !defined(STRIP) +#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP) /** * Normalizes a point represented in projective coordinates. @@ -95,7 +95,7 @@ void ep4_norm(ep4_t r, const ep4_t p) { /* If the point is represented in affine coordinates, we just copy it. */ ep4_copy(r, p); } -#if EP_ADD == PROJC || !defined(STRIP) +#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP) ep4_norm_imp(r, p, 0); #endif } @@ -121,10 +121,11 @@ void ep4_norm_sim(ep4_t *r, const ep4_t *t, int n) { fp4_copy(r[i]->y, t[i]->y); 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 } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); diff --git a/src/epx/relic_ep4_util.c b/src/epx/relic_ep4_util.c index c358369c9..6b036da4d 100644 --- a/src/epx/relic_ep4_util.c +++ b/src/epx/relic_ep4_util.c @@ -238,7 +238,7 @@ int ep4_size_bin(const ep4_t a, int pack) { ep4_norm(t, a); size = 1 + 8 * RLC_FP_BYTES; - //TODO: Implement compression. + //TODO: implement compression properly } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { diff --git a/src/epx/relic_ep8_add.c b/src/epx/relic_ep8_add.c new file mode 100644 index 000000000..1141da873 --- /dev/null +++ b/src/epx/relic_ep8_add.c @@ -0,0 +1,434 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 + * + * Implementation of addition on prime elliptic curves over quartic + * extensions. + * + * @ingroup epx + */ + +#include "relic_core.h" + +/*============================================================================*/ +/* Private definitions */ +/*============================================================================*/ + +#if EP_ADD == BASIC || !defined(STRIP) + +/** + * 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. + */ +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); + } +} + +#endif /* EP_ADD == BASIC */ + +#if EP_ADD == PROJC || !defined(STRIP) + +#if defined(EP_MIXED) || !defined(STRIP) + +/** + * Adds a point represented in affine coordinates to a point represented in + * projective coordinates. + * + * @param r - the result. + * @param s - the slope. + * @param p - the affine point. + * @param q - the projective point. + */ +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; + + fp8_null(t0); + fp8_null(t1); + fp8_null(t2); + fp8_null(t3); + fp8_null(t4); + fp8_null(t5); + fp8_null(t6); + + 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); + } +} + +#endif + +/** + * Adds two points represented in projective 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. + */ +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); + + 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 */ + +/*============================================================================*/ + /* Public definitions */ +/*============================================================================*/ + +#if EP_ADD == BASIC || !defined(STRIP) + +void ep8_add_basic(ep8_t r, const ep8_t p, const ep8_t q) { + if (ep8_is_infty(p)) { + ep8_copy(r, q); + return; + } + + if (ep8_is_infty(q)) { + ep8_copy(r, p); + return; + } + + ep8_add_basic_imp(r, NULL, p, q); +} + +void ep8_add_slp_basic(ep8_t r, fp8_t s, const ep8_t p, const ep8_t q) { + if (ep8_is_infty(p)) { + ep8_copy(r, q); + return; + } + + if (ep8_is_infty(q)) { + ep8_copy(r, p); + return; + } + + ep8_add_basic_imp(r, s, p, q); +} + +#endif + +#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)) { + ep8_copy(r, q); + return; + } + + if (ep8_is_infty(q)) { + ep8_copy(r, p); + return; + } + + if (p == q) { + /* TODO: This is a quick hack. Should we fix this? */ + ep8_dbl(r, p); + return; + } + + ep8_add_projc_imp(r, p, q); +} + +#endif + +void ep8_sub(ep8_t r, const ep8_t p, const ep8_t q) { + ep8_t t; + + ep8_null(t); + + if (p == q) { + ep8_set_infty(r); + return; + } + + RLC_TRY { + ep8_new(t); + + ep8_neg(t, q); + ep8_add(r, p, t); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + ep8_free(t); + } +} diff --git a/src/epx/relic_ep8_cmp.c b/src/epx/relic_ep8_cmp.c new file mode 100644 index 000000000..cf00e38a6 --- /dev/null +++ b/src/epx/relic_ep8_cmp.c @@ -0,0 +1,82 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 + * + * Implementation of utilities for prime elliptic curves over quadratic + * extensions. + * + * @ingroup epx + */ + +#include "relic_core.h" + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +int ep8_cmp(const ep8_t p, const ep8_t q) { + 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); + + 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); + } + + 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 new file mode 100644 index 000000000..a76921115 --- /dev/null +++ b/src/epx/relic_ep8_curve.c @@ -0,0 +1,364 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 + * + * Implementation of configuration of prime elliptic curves over octic + * extensions. + * + * @ingroup epx + */ + +#include "relic_core.h" + +/*============================================================================*/ +/* Private definitions */ +/*============================================================================*/ + +/* See ep/relic_ep_param.c for discussion of MAP_U parameters. */ + +#if defined(EP_ENDOM) && FP_PRIME == 575 +/** @{ */ +#define B48_P575_B0 "0" +#define B48_P575_B1 "0" +#define B48_P575_B2 "0" +#define B48_P575_B3 "0" +#define B48_P575_B4 "4" +#define B48_P575_B5 "0" +#define B48_P575_B6 "0" +#define B48_P575_B7 "0" +#define B48_P575_X0 "266A6ACAA4B8DDCFBF97F09DFBEB01999BFBFF872276FA7700114F761E8971C6C25A53CC77E96BCC9579F63D8A39D641B8070B07EF40E93C301A5B49CE87110CC30E044BEE5A2D43" +#define B48_P575_X1 "5009EEB2A67C52B79D0727B408A193FFCE76B4F80C8DCF4D61ECEE5471601CD7A94341F697CE9D375DB5470EA055B73C256CCC0AC12F52EAD276C26E001DDCE02DE634BEFCB9CC7C" +#define B48_P575_X2 "11A8DDB59724C01696BE52862B5AC2C7E1C0C42EFCAF456A80F6C6D9F95F89649D5575DE3BA8D28D1012E14308DE1D8F15CE1617611F961032B0B5DFA27EF3E3670B9B537ACC66B9" +#define B48_P575_X3 "4E8BDED03587581A173AD008DFF600EB24054E4CDDCA8D7BFABA2898822DB5ED701BF59BD3F108AD7C714B6A6C7ECB11A1BC5DEEC1D49AE7FCA597C43943A66441B03164975D9BE0" +#define B48_P575_X4 "29E2751CAC7D0FBA8E12CC818BDE6F2A7173D3C2ED74EC1991B936071DEB1AED1E07CDF71EA3501BEB4645C86BDC8A575898303FF6A058C7062F079F594E5B865626D0C031CF7E44" +#define B48_P575_X5 "2F3A1BE54DFFB814DA4AE6311B9B1EEE6198CDB9F36CE92084272416462F4D0AC9ACAC025FDA6D3D0D1C239FE8CE4B7F22A1D0F65582DDA36EEB328843FDE5C0BDA02E871796CC8E" +#define B48_P575_X6 "2FEE7B15EB22B05476A462374860140DCC9F00910E0555918D6357F6E32E623B88B893647AD07B615F364093D6F6D2A7B7614590A8833385B5A833563C0DD6C89AF89D06428E8AFE" +#define B48_P575_X7 "005082322BB5E610DC0E61E3D01B8BFF23D195117F58B1FA68EC04A6769FEB754A58742C7F729E2A684386C40EFB871CB3D32A040966155649DC45C49E6FB5DEE58DB1586CBFD33E" +#define B48_P575_Y0 "3B603A4C408A402FB885B607C4A661BF92354D22F46945F222C6F51CCDEBF4006640346AE6BFD60F7E22240D4BF83EFDA1B575267A89597D7BC54FA4899BFBAAC4138E30C8DA55C0" +#define B48_P575_Y1 "35D3ECCC1F3C69A921E57CCDEA6C794A5ED01A53E19208854EA3B10D519CCCE64A30007CD7A57673567F2FFA070E5CE01C4E5C8BF1C61225DAC36A93C6524F4D0350C6358C67F85B" +#define B48_P575_Y2 "4228DA69A29E14E2CF00EC8FDD877CA9049DA161778A6ACE8DC275D4CE94C90AD9176280703AD9C6714A4865EF6160ED2FA7A5FC601025CF096AB6CF21B8FAA41421C7913DECF3B5" +#define B48_P575_Y3 "5273C1679E18D316C6988820E06335094FCCCD5E8FD870492EB96FCBC5B5494B2B9D0869C18309FF2D49CD80CF6E6FE1A660027A6E924831F8D5A070645A7B794BA7AE72507809AE" +#define B48_P575_Y4 "0ABD2F582F0D4C3C89770C13F02FF17CDEA5B22CDD661B6F82905ADCDC44E59900C5D09F8CAC90760CCC57D1987DE4BA21F34455E5B7394B68A7883E3F8D918AF308F0C3E6F98F4B" +#define B48_P575_Y5 "36FAE1DE9DD31FFE238526F618C14E5CB61EEA8E8E6D82235E43E45E306C5E60B4E5499BF4663516CE1202EF6CDE3B2E098E406B3186937483FC104A173707C6419F460A23ADF628" +#define B48_P575_Y6 "09E1BB455FCB47E98C5263B5098E2D148EC2EDEE5634B8F94F10AF9221D09BD60D28920342C11B1987A24B7F56AC4F5E290E7EA483727ED16FFC88C0F5EAD00892FDA66BA68FACE4" +#define B48_P575_Y7 "4F781C32F5CAFD446F299BE6BC600BF3482DF6ECAF4ABE3D410A7255B18A88DB77CC539CAC4A0D30A00690CCA8CC7661BCE042D0AC40FF8DC9171847A8E42696E4EF9DD8A5907A3D" +#define B48_P575_R "FFBFC68EB6176EFB58025E547BF4EBACB1315C184DC37EAAF67BBCCE069D07F425050E765ABB8B40D5E6D7AE8A2A5698B771DDBD6E109D56D59C3DFF00000001" +#define B48_P575_H "9E9223EB731FB087A7A45CA84E1C06F79C4326124DE74264AA1FCFB1FB41AFF2CBA999F970BD426881824E1A7562ED4F1E249817937F029045954EED2EB984ED650EF97D1189758800D5926B4CA05A197A0B8D1FD9697173D9B8389AAA1B76E1AF1AAC3B9999905ADD15F51DB643E2B16361CD2E54E7B18B29AB0A08ECF2818F8EAB997AC33C00D0901C913B44817E1E3F5B89E3CA71C8A59556AF31D4998B77BE410ADC0C19CAE9A82DEAC267087E382A39F4ADC7043BD46F38D00454D2A8D7EFA4109F3AE1157580E650F5614A3BB05A8DDFEB789CEEE1F91A31CFA50BB5E689A006B43B4D4364E3001144F12DA0A5F388DE9A09B24A00CE5D91E42C0BFDA4BBE3A59C60439B347B5A727EE436069DBF413F6190F212C5BE3F02F9381AB92830E65AA13C3D583D63C077777F32BFC912726FC49B5082059BFDC912C81C4259542DA560430230B4D0E905E3ADAA2AF0E0BEB18C5B6BC52A452BE1E70CCAC2A23F954EA5548B11FE3FD7C02940A6DA75340BB3459CCC74EA778E3B3B239FB5D1B815B929BAF390372BB0043C3A920B878F4AC32243ED6E2A7F79D85A5D66C9ED8D08A20E5EC0E9145561868EB5987EF043EF9A1176149B3618D96F9F179519B89027A2648576E807E1A4B1C8E9F5C0A147D2750E65DF130DF53D7AAD8D4EA7D0CEB1C03BAF8A0C7BE62F433C5747E851661399976495246EAF448690CD4B1" +/** @} */ +#endif + +/** + * Assigns a set of ordinary elliptic curve parameters. + * + * @param[in] CURVE - the curve parameters to assign. + */ +#define ASSIGN(CURVE) \ + RLC_GET(str, CURVE##_B0, sizeof(CURVE##_B0)); \ + fp_read_str(b[0][0][0], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_B1, sizeof(CURVE##_B1)); \ + fp_read_str(b[0][0][1], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_B2, sizeof(CURVE##_B2)); \ + fp_read_str(b[0][1][0], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_B3, sizeof(CURVE##_B3)); \ + fp_read_str(b[0][1][1], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_B4, sizeof(CURVE##_B4)); \ + fp_read_str(b[1][0][0], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_B5, sizeof(CURVE##_B5)); \ + fp_read_str(b[1][0][1], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_B6, sizeof(CURVE##_B6)); \ + fp_read_str(b[1][1][0], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_B7, sizeof(CURVE##_B7)); \ + fp_read_str(b[1][1][1], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_X0, sizeof(CURVE##_X0)); \ + fp_read_str(g->x[0][0][0], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_X1, sizeof(CURVE##_X1)); \ + fp_read_str(g->x[0][0][1], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_X2, sizeof(CURVE##_X2)); \ + fp_read_str(g->x[0][1][0], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_X3, sizeof(CURVE##_X3)); \ + fp_read_str(g->x[0][1][1], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_X4, sizeof(CURVE##_X4)); \ + fp_read_str(g->x[1][0][0], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_X5, sizeof(CURVE##_X5)); \ + fp_read_str(g->x[1][0][1], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_X6, sizeof(CURVE##_X6)); \ + fp_read_str(g->x[1][1][0], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_X7, sizeof(CURVE##_X7)); \ + fp_read_str(g->x[1][1][1], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_Y0, sizeof(CURVE##_Y0)); \ + fp_read_str(g->y[0][0][0], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_Y1, sizeof(CURVE##_Y1)); \ + fp_read_str(g->y[0][0][1], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_Y2, sizeof(CURVE##_Y2)); \ + fp_read_str(g->y[0][1][0], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_Y3, sizeof(CURVE##_Y3)); \ + fp_read_str(g->y[0][1][1], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_Y4, sizeof(CURVE##_Y4)); \ + fp_read_str(g->y[1][0][0], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_Y5, sizeof(CURVE##_Y5)); \ + fp_read_str(g->y[1][0][1], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_Y6, sizeof(CURVE##_Y6)); \ + fp_read_str(g->y[1][1][0], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_Y7, sizeof(CURVE##_Y7)); \ + fp_read_str(g->y[1][1][1], str, strlen(str), 16); \ + RLC_GET(str, CURVE##_R, sizeof(CURVE##_R)); \ + bn_read_str(r, str, strlen(str), 16); \ + RLC_GET(str, CURVE##_H, sizeof(CURVE##_H)); \ + bn_read_str(h, str, strlen(str), 16); \ + +/** + * Detects an optimization based on the curve coefficients. + */ +static void detect_opt(int *opt, fp8_t a) { + fp8_t t; + fp8_null(t); + + RLC_TRY { + fp8_new(t); + fp8_set_dig(t, 3); + fp8_neg(t, t); + + if (fp8_cmp(a, t) == RLC_EQ) { + *opt = RLC_MIN3; + } else if (fp8_is_zero(a)) { + *opt = RLC_ZERO; + } else if (fp8_cmp_dig(a, 1) == RLC_EQ) { + *opt = RLC_ONE; + } else if (fp8_cmp_dig(a, 2) == RLC_EQ) { + *opt = RLC_TWO; + } else if ((fp_bits(a[0][0][0]) <= RLC_DIG) && fp_is_zero(a[0][0][1]) && + fp2_is_zero(a[0][1]) && fp4_is_zero(a[1])) { + *opt = RLC_TINY; + } else { + *opt = RLC_HUGE; + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + fp8_free(t); + } +} + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +void ep8_curve_init(void) { + ctx_t *ctx = core_get(); + +#ifdef EP_PRECO + for (int i = 0; i < RLC_EP_TABLE; i++) { + ctx->ep8_ptr[i] = &(ctx->ep8_pre[i]); + } +#endif + +#if ALLOC == DYNAMIC + ep8_new(ctx->ep8_g); + fp8_new(ctx->ep8_a); + fp8_new(ctx->ep8_b); +#endif + +#ifdef EP_PRECO +#if ALLOC == DYNAMIC + for (int i = 0; i < RLC_EP_TABLE; i++) { + fp8_new(ctx->ep8_pre[i].x); + fp8_new(ctx->ep8_pre[i].y); + fp8_new(ctx->ep8_pre[i].z); + } +#endif +#endif + ep8_set_infty(ctx->ep8_g); + bn_make(&(ctx->ep8_r), RLC_FP_DIGS); + bn_make(&(ctx->ep8_h), RLC_FP_DIGS); +} + +void ep8_curve_clean(void) { + ctx_t *ctx = core_get(); + if (ctx != NULL) { +#ifdef EP_PRECO + for (int i = 0; i < RLC_EP_TABLE; i++) { + fp8_free(ctx->ep8_pre[i].x); + fp8_free(ctx->ep8_pre[i].y); + fp8_free(ctx->ep8_pre[i].z); + } +#endif + bn_clean(&(ctx->ep8_r)); + bn_clean(&(ctx->ep8_h)); + ep8_free(ctx->ep8_g); + fp8_free(ctx->ep8_a); + fp8_free(ctx->ep8_b); + } +} + +int ep8_curve_opt_a(void) { + return core_get()->ep8_opt_a; +} + +int ep8_curve_opt_b(void) { + return core_get()->ep8_opt_b; +} + +int ep8_curve_is_twist(void) { + return core_get()->ep8_is_twist; +} + +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); +} + +void ep8_curve_get_b(fp8_t b) { + fp8_copy(b, core_get()->ep8_b); +} + +void ep8_curve_get_ord(bn_t n) { + ctx_t *ctx = core_get(); + if (ctx->ep8_is_twist) { + ep_curve_get_ord(n); + } else { + bn_copy(n, &(ctx->ep8_r)); + } +} + +void ep8_curve_get_cof(bn_t h) { + bn_copy(h, &(core_get()->ep8_h)); +} + +#if defined(EP_PRECO) + +ep8_t *ep8_curve_get_tab(void) { +#if ALLOC == AUTO + return (ep8_t *)*(core_get()->ep8_ptr); +#else + return core_get()->ep8_ptr; +#endif +} + +#endif + +void ep8_curve_set_twist(int type) { + char str[16 * RLC_FP_BYTES + 1]; + ctx_t *ctx = core_get(); + ep8_t g; + fp8_t a, b; + bn_t r, h; + + ep8_null(g); + fp8_null(a); + fp8_null(b); + bn_null(r); + bn_null(h); + + ctx->ep8_is_twist = 0; + if (type == RLC_EP_MTYPE || type == RLC_EP_DTYPE) { + ctx->ep8_is_twist = type; + } else { + return; + } + + RLC_TRY { + ep8_new(g); + fp8_new(a); + fp8_new(b); + bn_new(r); + bn_new(h); + + switch (ep_param_get()) { +#if FP_PRIME == 575 + case B48_P575: + fp8_zero(a); + ASSIGN(B48_P575); + break; +#endif + default: + (void)str; + RLC_THROW(ERR_NO_VALID); + break; + } + + fp8_zero(g->z); + fp8_set_dig(g->z, 1); + g->coord = BASIC; + + ep8_copy(ctx->ep8_g, g); + fp8_copy(ctx->ep8_a, a); + fp8_copy(ctx->ep8_b, b); + + detect_opt(&(ctx->ep8_opt_a), ctx->ep8_a); + detect_opt(&(ctx->ep8_opt_b), ctx->ep8_b); + + bn_copy(&(ctx->ep8_r), r); + bn_copy(&(ctx->ep8_h), h); + + if (type == RLC_EP_MTYPE) { + fp8_zero(a); + fp_copy(a[1][1][0], ctx->fp8_p1[0]); + fp_copy(a[1][1][1], ctx->fp8_p1[1]); + fp8_inv(a, a); + fp_copy(ctx->fp8_p1[0], a[1][0][0]); + fp_copy(ctx->fp8_p1[1], a[1][0][1]); + } + +#if defined(WITH_PC) + /* Compute pairing generator. */ + pc_core_calc(); +#endif + +#if defined(EP_PRECO) + ep8_mul_pre((ep8_t *)ep8_curve_get_tab(), ctx->ep8_g); +#endif + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + ep8_free(g); + fp8_free(a); + fp8_free(b); + bn_free(r); + bn_free(h); + } +} + +void ep8_curve_set(const fp8_t a, const fp8_t b, const ep8_t g, const bn_t r, const bn_t h) { + ctx_t *ctx = core_get(); + ctx->ep8_is_twist = 0; + + fp8_copy(ctx->ep8_a, a); + fp8_copy(ctx->ep8_b, b); + + ep8_norm(ctx->ep8_g, g); + bn_copy(&(ctx->ep8_r), r); + bn_copy(&(ctx->ep8_h), h); + +#if defined(EP_PRECO) + ep8_mul_pre((ep8_t *)ep8_curve_get_tab(), ctx->ep8_g); +#endif +} diff --git a/src/epx/relic_ep8_dbl.c b/src/epx/relic_ep8_dbl.c new file mode 100644 index 000000000..2fa1449e1 --- /dev/null +++ b/src/epx/relic_ep8_dbl.c @@ -0,0 +1,276 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 + * + * Implementation of doubling on elliptic prime curves over quartic + * extensions. + * + * @ingroup epx + */ + +#include "relic_core.h" + +/*============================================================================*/ +/* Private definitions */ +/*============================================================================*/ + +#if EP_ADD == BASIC || !defined(STRIP) + +/** + * Doubles a point represented in affine coordinates on an ordinary prime + * elliptic curve. + * + * @param[out] r - the result. + * @param[out] s - the resulting 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); + } +} + +#endif /* EP_ADD == BASIC */ + +#if EP_ADD == PROJC || !defined(STRIP) + +/** + * Doubles a point represented in affine coordinates on an ordinary prime + * elliptic curve. + * + * @param[out] r - the result. + * @param[in] 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 { + if (ep_curve_opt_a() == RLC_ZERO) { + fp8_new(t0); + fp8_new(t1); + fp8_new(t2); + fp8_new(t3); + fp8_new(t4); + fp8_new(t5); + + 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); + + 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); + + /* 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); + } + + 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); + } +} + +#endif /* EP_ADD == PROJC */ + +/*============================================================================*/ + /* Public definitions */ +/*============================================================================*/ + +#if EP_ADD == BASIC || !defined(STRIP) + +void ep8_dbl_basic(ep8_t r, const ep8_t p) { + if (ep8_is_infty(p)) { + ep8_set_infty(r); + return; + } + + ep8_dbl_basic_imp(r, NULL, p); +} + +void ep8_dbl_slp_basic(ep8_t r, fp8_t s, const ep8_t p) { + if (ep8_is_infty(p)) { + ep8_set_infty(r); + return; + } + + ep8_dbl_basic_imp(r, s, p); +} + +#endif + +#if EP_ADD == PROJC || !defined(STRIP) + +void ep8_dbl_projc(ep8_t r, const ep8_t p) { + if (ep8_is_infty(p)) { + ep8_set_infty(r); + return; + } + + ep8_dbl_projc_imp(r, p); +} + +#endif diff --git a/src/epx/relic_ep8_frb.c b/src/epx/relic_ep8_frb.c new file mode 100644 index 000000000..1cd8c4f72 --- /dev/null +++ b/src/epx/relic_ep8_frb.c @@ -0,0 +1,48 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 + * + * Implementation of frobenius action on prime elliptic curves over + * quartic extensions. + * + * @ingroup epx + */ + +#include "relic_core.h" + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +void ep8_frb(ep8_t r, const ep8_t p, int i) { + ep8_copy(r, p); + for (; i > 0; i--) { + fp8_frb(r->x, r->x, 1); + fp8_frb(r->y, r->y, 1); + fp8_frb(r->z, r->z, 1); + fp8_mul_frb(r->x, r->x, 1, 2); + fp8_mul_frb(r->y, r->y, 1, 3); + } +} diff --git a/src/epx/relic_ep8_map.c b/src/epx/relic_ep8_map.c new file mode 100644 index 000000000..898d45ea5 --- /dev/null +++ b/src/epx/relic_ep8_map.c @@ -0,0 +1,205 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 + * + * Implementation of hashing to a prime elliptic curve over a quadratic + * extension. + * + * @ingroup epx + */ + +#include "relic_core.h" +#include "relic_md.h" + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +void ep8_map(ep8_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][2], sign, *r = RLC_ALLOCA(uint8_t, 16 * elm + 1); + fp8_t t, u, v, w, y, x1, y1, z1; + ctx_t *ctx = core_get(); + dig_t c2, c3; + bn_t k; + + bn_null(k); + fp8_null(t); + fp8_null(u); + fp8_null(v); + fp8_null(w); + fp8_null(y); + fp8_null(x1); + fp8_null(y1); + fp8_null(z1); + + RLC_TRY { + bn_new(k); + fp8_new(t); + fp8_new(u); + fp8_new(v); + fp8_new(w); + fp8_new(y); + fp8_new(x1); + fp8_new(y1); + fp8_new(z1); + + md_xmd(r, 16 * elm + 1, msg, len, (const uint8_t *)"RELIC", 5); + + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + for (int l = 0; l < 2; l++) { + bn_read_bin(k, r, elm); + fp_prime_conv(u[i][j][l], k); + r += elm; + bn_read_bin(k, r, elm); + fp_prime_conv(t[i][j][l], k); + r += elm; + } + } + } + sign = r[0] & 1; + + /* Assume that a = 0. */ + fp8_sqr(x1, u); + fp8_mul(x1, x1, u); + fp8_sqr(y1, t); + fp8_add(x1, x1, ctx->ep8_b); + fp8_sub(x1, x1, y1); + fp8_dbl(y1, y1); + fp8_add(y1, y1, x1); + fp8_copy(z1, u); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + for (int l = 0; l < 2; l++) { + fp_mul(z1[i][j][l], z1[i][j][l], ctx->ep_map_c[4]); + } + } + } + + fp8_mul(x1, x1, z1); + fp8_mul(z1, z1, t); + fp8_dbl(z1, z1); + + fp8_dbl(y, y1); + fp8_sqr(y, y); + fp8_mul(v, y1, u); + fp8_sub(v, x1, v); + fp8_mul(v, v, z1); + fp8_mul(w, y1, z1); + fp8_dbl(w, w); + + if (fp8_is_zero(w)) { + ep8_set_infty(p); + } else { + fp8_inv(w, w); + fp8_mul(x1, v, w); + fp8_add(y1, u, x1); + fp8_neg(y1, y1); + fp8_mul(z1, y, w); + 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); + + 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); + } + } + } + + if (!fp8_srt(t, t)) { + RLC_THROW(ERR_NO_VALID); + } + + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + t0z = fp_is_zero(t[i][j][0]); + fp_prime_back(k, t[i][j][0]); + t0 = bn_get_bit(k, 0); + fp_prime_back(k, t[i][j][1]); + t1 = bn_get_bit(k, 0); + /* t[0] == 0 ? sgn0(t[1]) : sgn0(t[0]) */ + s[i][j] = t0 | (t0z & t1); + } + + t0z = fp4_is_zero(t[i]); + sign ^= (s[i][0] | (t0z & s[i][1])); + } + + 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(p->x, x1); + fp8_copy(p->y, t); + fp8_set_dig(p->z, 1); + p->coord = BASIC; + + ep8_mul_cof(p, p); + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + bn_free(k); + fp8_free(t); + fp8_free(u); + fp8_free(v); + fp8_free(w); + fp8_free(y); + fp8_free(x1); + fp8_free(y1); + fp8_free(z1); + RLC_FREE(r); + } +} diff --git a/src/epx/relic_ep8_mul.c b/src/epx/relic_ep8_mul.c new file mode 100644 index 000000000..14e02fe74 --- /dev/null +++ b/src/epx/relic_ep8_mul.c @@ -0,0 +1,454 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 + * + * Implementation of point multiplication on prime elliptic curves over + * quadratic extensions. + * + * @ingroup epx + */ + +#include "relic_core.h" + +/*============================================================================*/ +/* Private definitions */ +/*============================================================================*/ + +#if EP_MUL == LWNAF || !defined(STRIP) + +#if defined(EP_ENDOM) + +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; + int8_t naf[16][RLC_FP_BITS + 1]; + ep8_t q[16]; + + bn_null(n); + bn_null(u); + + RLC_TRY { + bn_new(n); + bn_new(u); + for (int i = 0; i < 16; i++) { + bn_null(_k[i]); + ep8_null(q[i]); + bn_new(_k[i]); + ep8_new(q[i]); + } + + 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); + + ep8_norm(q[0], p); + for (size_t i = 1; i < 16; i++) { + ep8_frb(q[i], q[i - 1], 1); + } + + l = 0; + for (size_t i = 0; i < 16; i++) { + if (bn_sign(_k[i]) == RLC_NEG) { + ep8_neg(q[i], q[i]); + } + _l[i] = RLC_FP_BITS + 1; + bn_rec_naf(naf[i], &_l[i], _k[i], 2); + l = RLC_MAX(l, _l[i]); + } + + ep8_set_infty(r); + for (int j = l - 1; j >= 0; j--) { + ep8_dbl(r, r); + + for (int i = 0; i < 16; i++) { + if (naf[i][j] > 0) { + ep8_add(r, r, q[i]); + } + if (naf[i][j] < 0) { + ep8_sub(r, r, q[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); + for (int i = 0; i < 16; i++) { + bn_free(_k[i]); + ep8_free(q[i]); + } + + } +} + +#endif /* EP_ENDOM */ + +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]; + ep8_t t[1 << (RLC_WIDTH - 2)]; + size_t l; + + RLC_TRY { + /* Prepare the precomputation table. */ + for (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); + + /* Compute the w-NAF representation of k. */ + l = sizeof(naf); + bn_rec_naf(naf, &l, k, RLC_WIDTH); + + ep8_set_infty(r); + for (i = l - 1; i >= 0; i--) { + ep8_dbl(r, r); + + n = naf[i]; + if (n > 0) { + ep8_add(r, r, t[n / 2]); + } + if (n < 0) { + ep8_sub(r, r, t[-n / 2]); + } + } + /* Convert r to affine coordinates. */ + ep8_norm(r, r); + if (bn_sign(k) == RLC_NEG) { + ep8_neg(r, r); + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + /* Free the precomputation table. */ + for (i = 0; i < (1 << (RLC_WIDTH - 2)); i++) { + ep8_free(t[i]); + } + } +} + +#endif /* EP_MUL == LWNAF */ + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +void ep8_mul_basic(ep8_t r, const ep8_t p, const bn_t k) { + ep8_t t; + int8_t u, *naf = RLC_ALLOCA(int8_t, bn_bits(k) + 1); + size_t l; + + ep8_null(t); + + if (bn_is_zero(k) || ep8_is_infty(p)) { + RLC_FREE(naf); + ep8_set_infty(r); + return; + } + + RLC_TRY { + ep8_new(t); + if (naf == NULL) { + RLC_THROW(ERR_NO_BUFFER); + } + + l = bn_bits(k) + 1; + bn_rec_naf(naf, &l, k, 2); + ep8_set_infty(t); + for (int i = l - 1; i >= 0; i--) { + ep8_dbl(t, t); + + u = naf[i]; + if (u > 0) { + ep8_add(t, t, p); + } else if (u < 0) { + ep8_sub(t, t, p); + } + } + + ep8_norm(r, t); + if (bn_sign(k) == RLC_NEG) { + ep8_neg(r, r); + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + ep8_free(t); + RLC_FREE(naf); + } +} + +#if EP_MUL == SLIDE || !defined(STRIP) + +void ep8_mul_slide(ep8_t r, const ep8_t p, const bn_t k) { + ep8_t t[1 << (RLC_WIDTH - 1)], q; + uint8_t win[RLC_FP_BITS + 1]; + size_t l; + + ep8_null(q); + + if (bn_is_zero(k) || ep8_is_infty(p)) { + ep8_set_infty(r); + return; + } + + RLC_TRY { + for (size_t i = 0; i < (1 << (RLC_WIDTH - 1)); i ++) { + ep8_null(t[i]); + ep8_new(t[i]); + } + + ep8_new(q); + + ep8_copy(t[0], p); + ep8_dbl(q, p); + +#if defined(EP_MIXED) + ep8_norm(q, q); +#endif + + /* Create table. */ + for (size_t i = 1; i < (1 << (RLC_WIDTH - 1)); i++) { + ep8_add(t[i], t[i - 1], q); + } + +#if defined(EP_MIXED) + ep8_norm_sim(t + 1, t + 1, (1 << (RLC_WIDTH - 1)) - 1); +#endif + + ep8_set_infty(q); + l = RLC_FP_BITS + 1; + bn_rec_slw(win, &l, k, RLC_WIDTH); + for (size_t i = 0; i < l; i++) { + if (win[i] == 0) { + ep8_dbl(q, q); + } else { + for (size_t j = 0; j < util_bits_dig(win[i]); j++) { + ep8_dbl(q, q); + } + ep8_add(q, q, t[win[i] >> 1]); + } + } + + ep8_norm(r, q); + if (bn_sign(k) == RLC_NEG) { + ep8_neg(r, r); + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + for (size_t i = 0; i < (1 << (RLC_WIDTH - 1)); i++) { + ep8_free(t[i]); + } + ep8_free(q); + } +} + +#endif + +#if EP_MUL == MONTY || !defined(STRIP) + +void ep8_mul_monty(ep8_t r, const ep8_t p, const bn_t k) { + ep8_t t[2]; + bn_t n, l, _k; + size_t bits; + + bn_null(n); + bn_null(l); + bn_null(_k); + ep8_null(t[0]); + ep8_null(t[1]); + + if (bn_is_zero(k) || ep8_is_infty(p)) { + ep8_set_infty(r); + return; + } + + RLC_TRY { + bn_new(n); + bn_new(l); + bn_new(_k); + ep8_new(t[0]); + ep8_new(t[1]); + + ep8_curve_get_ord(n); + bits = bn_bits(n); + + bn_mod(_k, k, n); + 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), + bn_get_bit(l, bits) == 0); + l->used = RLC_SEL(l->used, n->used, bn_get_bit(l, bits) == 0); + + ep8_norm(t[0], p); + ep8_dbl(t[1], t[0]); + + /* Blind both points independently. */ + ep8_blind(t[0], t[0]); + ep8_blind(t[1], t[1]); + + for (int i = bits - 1; i >= 0; i--) { + int j = bn_get_bit(l, i); + 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); + } + } + } + ep8_add(t[0], t[0], t[1]); + ep8_dbl(t[1], t[1]); + 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); + } + } + } + } + + ep8_norm(r, t[0]); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + bn_free(n); + bn_free(l); + bn_free(_k); + ep8_free(t[1]); + ep8_free(t[0]); + } +} + +#endif + +#if EP_MUL == LWNAF || !defined(STRIP) + +void ep8_mul_lwnaf(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()) { + if (ep_curve_opt_a() == RLC_ZERO) { + ep8_mul_glv_imp(r, p, k); + } else { + ep8_mul_naf_imp(r, p, k); + } + return; + } +#endif + +#if defined(EP_PLAIN) || defined(EP_SUPER) + ep8_mul_naf_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); + return; + } + +#ifdef EP_PRECO + ep8_mul_fix(r, ep8_curve_get_tab(), k); +#else + ep8_t g; + + ep8_null(g); + + RLC_TRY { + ep8_new(g); + ep8_curve_get_gen(g); + ep8_mul(r, g, k); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + ep8_free(g); + } +#endif +} + +void ep8_mul_dig(ep8_t r, const ep8_t p, const dig_t k) { + int i, l; + ep8_t t; + + ep8_null(t); + + if (k == 0 || ep8_is_infty(p)) { + ep8_set_infty(r); + return; + } + + RLC_TRY { + ep8_new(t); + + l = util_bits_dig(k); + + ep8_copy(t, p); + + for (i = l - 2; i >= 0; i--) { + ep8_dbl(t, t); + if (k & ((dig_t)1 << i)) { + ep8_add(t, t, p); + } + } + + ep8_norm(r, t); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + ep8_free(t); + } +} diff --git a/src/epx/relic_ep8_mul_cof.c b/src/epx/relic_ep8_mul_cof.c new file mode 100644 index 000000000..65f85a660 --- /dev/null +++ b/src/epx/relic_ep8_mul_cof.c @@ -0,0 +1,122 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 + * + * Implementation of point multiplication of a prime elliptic curve over an + * octic extension by the curve cofactor. + * + * @ingroup epx + */ + +#include "relic_core.h" +#include "relic_md.h" +#include "relic_tmpl_map.h" + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +void ep8_mul_cof(ep8_t r, const ep8_t p) { + bn_t z; + ep8_t t0, t1, t2, t3, t4, t5, t6, t7; + + ep8_null(t0); + ep8_null(t1); + ep8_null(t2); + ep8_null(t3); + ep8_null(t4); + ep8_null(t5); + ep8_null(t6); + ep8_null(t7); + bn_null(z); + + RLC_TRY { + bn_new(z); + ep8_new(t0); + ep8_new(t1); + ep8_new(t2); + ep8_new(t3); + + fp_prime_get_par(z); + + ep8_mul_basic(t0, p, z); + ep8_mul_basic(t1, t0, z); + ep8_mul_basic(t2, t1, z); + ep8_mul_basic(t3, t2, z); + ep8_mul_basic(t4, t3, z); + ep8_mul_basic(t5, t4, z); + ep8_mul_basic(t6, t5, z); + ep8_mul_basic(t7, t6, z); + + ep8_sub(t7, t7, t6); + ep8_sub(t7, t7, p); + + ep8_sub(t6, t6, t5); + ep8_frb(t6, t6, 1); + + ep8_sub(t5, t5, t4); + ep8_frb(t5, t5, 2); + + ep8_sub(t4, t4, t3); + ep8_frb(t4, t4, 3); + + ep8_sub(t3, t3, t2); + ep8_frb(t3, t3, 4); + + ep8_sub(t2, t2, t1); + ep8_frb(t2, t2, 5); + + ep8_sub(t1, t1, t0); + ep8_frb(t1, t1, 6); + + ep8_sub(t0, t0, p); + ep8_frb(t0, t0, 7); + + ep8_dbl(r, p); + ep8_frb(r, r, 8); + ep8_add(r, r, t0); + ep8_add(r, r, t1); + ep8_add(r, r, t2); + ep8_add(r, r, t3); + ep8_add(r, r, t4); + ep8_add(r, r, t5); + ep8_add(r, r, t6); + ep8_add(r, r, t7); + + ep8_norm(r, r); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + ep8_free(t0); + ep8_free(t1); + ep8_free(t2); + ep8_free(t3); + ep8_free(t4); + ep8_free(t5); + ep8_free(t6); + ep8_free(t7); + bn_free(z); + } +} diff --git a/src/epx/relic_ep8_mul_fix.c b/src/epx/relic_ep8_mul_fix.c new file mode 100644 index 000000000..94e80748e --- /dev/null +++ b/src/epx/relic_ep8_mul_fix.c @@ -0,0 +1,407 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 + * + * Implementation of fixed point multiplication on a prime elliptic curve over + * a quartic extension. + * + * @ingroup epx + */ + +#include "relic_core.h" + +/*============================================================================*/ +/* Private definitions */ +/*============================================================================*/ + +#if EP_FIX == LWNAF || !defined(STRIP) + +/** + * Precomputes a table for a point multiplication on an ordinary curve. + * + * @param[out] t - the destination table. + * @param[in] p - the point to multiply. + */ +static void ep8_mul_pre_ordin(ep8_t *t, const ep8_t p) { + ep8_dbl(t[0], p); +#if defined(EP_MIXED) + ep8_norm(t[0], t[0]); +#endif + +#if RLC_DEPTH > 2 + ep8_add(t[1], t[0], p); + for (int i = 2; i < (1 << (RLC_DEPTH - 2)); i++) { + ep8_add(t[i], t[i - 1], t[0]); + } + +#if defined(EP_MIXED) + for (int i = 1; i < (1 << (RLC_DEPTH - 2)); i++) { + ep8_norm(t[i], t[i]); + } +#endif + +#endif + ep8_copy(t[0], p); +} + +/** + * Multiplies a binary elliptic curve point by an integer using the w-NAF + * method. + * + * @param[out] r - the result. + * @param[in] p - the point to multiply. + * @param[in] k - the integer. + */ +static void ep8_mul_fix_ordin(ep8_t r, const ep8_t *table, const bn_t k) { + int8_t naf[2 * RLC_FP_BITS + 1], *t; + size_t len; + int n; + + if (bn_is_zero(k)) { + ep8_set_infty(r); + return; + } + + /* Compute the w-TNAF representation of k. */ + len = 2 * RLC_FP_BITS + 1; + bn_rec_naf(naf, &len, k, RLC_DEPTH); + + t = naf + len - 1; + ep8_set_infty(r); + for (int i = len - 1; i >= 0; i--, t--) { + ep8_dbl(r, r); + + n = *t; + if (n > 0) { + ep8_add(r, r, table[n / 2]); + } + if (n < 0) { + ep8_sub(r, r, table[-n / 2]); + } + } + /* Convert r to affine coordinates. */ + ep8_norm(r, r); + if (bn_sign(k) == RLC_NEG) { + ep8_neg(r, r); + } +} + +#endif /* EP_FIX == LWNAF */ + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +#if EP_FIX == BASIC || !defined(STRIP) + +void ep8_mul_pre_basic(ep8_t *t, const ep8_t p) { + bn_t n; + + bn_null(n); + + RLC_TRY { + bn_new(n); + + ep8_curve_get_ord(n); + + ep8_copy(t[0], p); + for (int i = 1; i < bn_bits(n); i++) { + ep8_dbl(t[i], t[i - 1]); + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + bn_free(n); + } +} + +void ep8_mul_fix_basic(ep8_t r, const ep8_t *t, const bn_t k) { + bn_t n, _k; + + if (bn_is_zero(k)) { + ep8_set_infty(r); + return; + } + + bn_null(n); + bn_null(_k); + + RLC_TRY { + bn_new(n); + bn_new(_k); + + ep8_curve_get_ord(n); + bn_mod(_k, k, n); + + ep8_set_infty(r); + for (int i = 0; i < bn_bits(_k); i++) { + if (bn_get_bit(_k, i)) { + ep8_add(r, r, t[i]); + } + } + ep8_norm(r, r); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + bn_free(n); + bn_free(_k); + } +} + +#endif + +#if EP_FIX == COMBS || !defined(STRIP) + +void ep8_mul_pre_combs(ep8_t *t, const ep8_t p) { + int i, j, l; + bn_t n; + + bn_null(n); + + RLC_TRY { + bn_new(n); + + ep8_curve_get_ord(n); + l = bn_bits(n); + l = ((l % RLC_DEPTH) == 0 ? (l / RLC_DEPTH) : (l / RLC_DEPTH) + 1); + + ep8_set_infty(t[0]); + + ep8_copy(t[1], p); + for (j = 1; j < RLC_DEPTH; j++) { + ep8_dbl(t[1 << j], t[1 << (j - 1)]); + for (i = 1; i < l; i++) { + ep8_dbl(t[1 << j], t[1 << j]); + } +#if defined(EP_MIXED) + ep8_norm(t[1 << j], t[1 << j]); +#endif + for (i = 1; i < (1 << j); i++) { + ep8_add(t[(1 << j) + i], t[i], t[1 << j]); + } + } +#if defined(EP_MIXED) + for (i = 1; i < RLC_EP_TABLE_COMBS; i++) { + ep8_norm(t[i], t[i]); + } +#endif + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + bn_free(n); + } +} + +void ep8_mul_fix_combs(ep8_t r, const ep8_t *t, const bn_t k) { + int i, j, l, w, n0, p0, p1; + bn_t n, _k; + + if (bn_is_zero(k)) { + ep8_set_infty(r); + return; + } + + bn_null(n); + bn_null(_k); + + RLC_TRY { + bn_new(n); + bn_new(_k); + + ep8_curve_get_ord(n); + l = bn_bits(n); + l = ((l % RLC_DEPTH) == 0 ? (l / RLC_DEPTH) : (l / RLC_DEPTH) + 1); + + bn_mod(_k, k, n); + n0 = bn_bits(_k); + + p0 = (RLC_DEPTH) * l - 1; + + w = 0; + p1 = p0--; + for (j = RLC_DEPTH - 1; j >= 0; j--, p1 -= l) { + w = w << 1; + if (p1 < n0 && bn_get_bit(_k, p1)) { + w = w | 1; + } + } + ep8_copy(r, t[w]); + + for (i = l - 2; i >= 0; i--) { + ep8_dbl(r, r); + + w = 0; + p1 = p0--; + for (j = RLC_DEPTH - 1; j >= 0; j--, p1 -= l) { + w = w << 1; + if (p1 < n0 && bn_get_bit(_k, p1)) { + w = w | 1; + } + } + if (w > 0) { + ep8_add(r, r, t[w]); + } + } + ep8_norm(r, r); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + bn_free(n); + bn_free(_k); + } +} + +#endif + +#if EP_FIX == COMBD || !defined(STRIP) + +void ep8_mul_pre_combd(ep8_t *t, const ep8_t p) { + int i, j, d, e; + bn_t n; + + bn_null(n); + + RLC_TRY { + bn_new(n); + + ep8_curve_get_ord(n); + d = bn_bits(n); + d = ((d % RLC_DEPTH) == 0 ? (d / RLC_DEPTH) : (d / RLC_DEPTH) + 1); + e = (d % 2 == 0 ? (d / 2) : (d / 2) + 1); + + ep8_set_infty(t[0]); + ep8_copy(t[1], p); + for (j = 1; j < RLC_DEPTH; j++) { + ep8_dbl(t[1 << j], t[1 << (j - 1)]); + for (i = 1; i < d; i++) { + ep8_dbl(t[1 << j], t[1 << j]); + } +#if defined(EP_MIXED) + ep8_norm(t[1 << j], t[1 << j]); +#endif + for (i = 1; i < (1 << j); i++) { + ep8_add(t[(1 << j) + i], t[i], t[1 << j]); + } + } + ep8_set_infty(t[1 << RLC_DEPTH]); + for (j = 1; j < (1 << RLC_DEPTH); j++) { + ep8_dbl(t[(1 << RLC_DEPTH) + j], t[j]); + for (i = 1; i < e; i++) { + ep8_dbl(t[(1 << RLC_DEPTH) + j], t[(1 << RLC_DEPTH) + j]); + } + } +#if defined(EP_MIXED) + for (i = 1; i < RLC_EP_TABLE_COMBD; i++) { + ep8_norm(t[i], t[i]); + } +#endif + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + bn_free(n); + } +} + +void ep8_mul_fix_combd(ep8_t r, const ep8_t *t, const bn_t k) { + int i, j, d, e, w0, w1, n0, p0, p1; + bn_t n; + + if (bn_is_zero(k)) { + ep8_set_infty(r); + return; + } + + bn_null(n); + + RLC_TRY { + bn_new(n); + + ep8_curve_get_ord(n); + d = bn_bits(n); + d = ((d % RLC_DEPTH) == 0 ? (d / RLC_DEPTH) : (d / RLC_DEPTH) + 1); + e = (d % 2 == 0 ? (d / 2) : (d / 2) + 1); + + ep8_set_infty(r); + n0 = bn_bits(k); + + p1 = (e - 1) + (RLC_DEPTH - 1) * d; + for (i = e - 1; i >= 0; i--) { + ep8_dbl(r, r); + + w0 = 0; + p0 = p1; + for (j = RLC_DEPTH - 1; j >= 0; j--, p0 -= d) { + w0 = w0 << 1; + if (p0 < n0 && bn_get_bit(k, p0)) { + w0 = w0 | 1; + } + } + + w1 = 0; + p0 = p1-- + e; + for (j = RLC_DEPTH - 1; j >= 0; j--, p0 -= d) { + w1 = w1 << 1; + if (i + e < d && p0 < n0 && bn_get_bit(k, p0)) { + w1 = w1 | 1; + } + } + + ep8_add(r, r, t[w0]); + ep8_add(r, r, t[(1 << RLC_DEPTH) + w1]); + } + ep8_norm(r, r); + if (bn_sign(k) == RLC_NEG) { + ep8_neg(r, r); + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + bn_free(n); + } +} + +#endif + +#if EP_FIX == LWNAF || !defined(STRIP) + +void ep8_mul_pre_lwnaf(ep8_t *t, const ep8_t p) { + ep8_mul_pre_ordin(t, p); +} + +void ep8_mul_fix_lwnaf(ep8_t r, const ep8_t *t, const bn_t k) { + ep8_mul_fix_ordin(r, t, k); +} + +#endif diff --git a/src/epx/relic_ep8_mul_sim.c b/src/epx/relic_ep8_mul_sim.c new file mode 100644 index 000000000..db08c8cbc --- /dev/null +++ b/src/epx/relic_ep8_mul_sim.c @@ -0,0 +1,619 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 + * + * Implementation of simultaneous point multiplication on a prime elliptic + * curve over a quartic extension. + * + * @ingroup epx + */ + +#include "relic_core.h" + +/*============================================================================*/ +/* Private definitions */ +/*============================================================================*/ + +#if EP_SIM == INTER || !defined(STRIP) + +/** + * Multiplies and adds two prime elliptic curve points simultaneously, + * optionally choosing the first point as the generator depending on an optional + * table of precomputed points. + * + * @param[out] r - the result. + * @param[in] p - the first point to multiply. + * @param[in] k - the first integer. + * @param[in] q - the second point to multiply. + * @param[in] m - the second integer. + * @param[in] t - the pointer to the precomputed table. + */ +static void ep8_mul_sim_plain(ep8_t r, const ep8_t p, const bn_t k, + const ep8_t q, const bn_t m, ep8_t *t) { + int i, n0, n1, w, gen = (t == NULL ? 0 : 1); + int8_t naf0[2 * RLC_FP_BITS + 1], naf1[2 * RLC_FP_BITS + 1], *_k, *_m; + ep8_t t0[1 << (RLC_WIDTH - 2)]; + ep8_t t1[1 << (RLC_WIDTH - 2)]; + size_t l, l0, l1; + + RLC_TRY { + if (!gen) { + for (i = 0; i < (1 << (RLC_WIDTH - 2)); i++) { + ep8_null(t0[i]); + ep8_new(t0[i]); + } + ep8_tab(t0, p, RLC_WIDTH); + t = (ep8_t *)t0; + } + + /* Prepare the precomputation table. */ + for (i = 0; i < (1 << (RLC_WIDTH - 2)); i++) { + ep8_null(t1[i]); + ep8_new(t1[i]); + } + /* Compute the precomputation table. */ + ep8_tab(t1, q, RLC_WIDTH); + + /* Compute the w-TNAF representation of k. */ + if (gen) { + w = RLC_DEPTH; + } else { + w = RLC_WIDTH; + } + l0 = l1 = 2 * RLC_FP_BITS + 1; + bn_rec_naf(naf0, &l0, k, w); + bn_rec_naf(naf1, &l1, m, RLC_WIDTH); + + l = RLC_MAX(l0, l1); + _k = naf0 + l - 1; + _m = naf1 + l - 1; + if (bn_sign(k) == RLC_NEG) { + for (i = 0; i < l0; i++) { + naf0[i] = -naf0[i]; + } + } + if (bn_sign(m) == RLC_NEG) { + for (i = 0; i < l1; i++) { + naf1[i] = -naf1[i]; + } + } + + ep8_set_infty(r); + for (i = l - 1; i >= 0; i--, _k--, _m--) { + ep8_dbl(r, r); + + n0 = *_k; + n1 = *_m; + if (n0 > 0) { + ep8_add(r, r, t[n0 / 2]); + } + if (n0 < 0) { + ep8_sub(r, r, t[-n0 / 2]); + } + if (n1 > 0) { + ep8_add(r, r, t1[n1 / 2]); + } + if (n1 < 0) { + ep8_sub(r, r, t1[-n1 / 2]); + } + } + /* Convert r to affine coordinates. */ + ep8_norm(r, r); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + /* Free the precomputation tables. */ + if (!gen) { + for (i = 0; i < (1 << (RLC_WIDTH - 2)); i++) { + ep8_free(t0[i]); + } + } + for (i = 0; i < (1 << (RLC_WIDTH - 2)); i++) { + ep8_free(t1[i]); + } + } +} + +#endif /* EP_SIM == INTER */ + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +#if EP_SIM == BASIC || !defined(STRIP) + +void ep8_mul_sim_basic(ep8_t r, const ep8_t p, const bn_t k, const ep8_t q, + const bn_t l) { + ep8_t t; + + ep8_null(t); + + RLC_TRY { + ep8_new(t); + ep8_mul(t, q, l); + ep8_mul(r, p, k); + ep8_add(t, t, r); + ep8_norm(r, t); + + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + ep8_free(t); + } +} + +#endif + +#if EP_SIM == TRICK || !defined(STRIP) + +void ep8_mul_sim_trick(ep8_t r, const ep8_t p, const bn_t k, const ep8_t q, + const bn_t m) { + ep8_t t0[1 << (RLC_WIDTH / 2)]; + ep8_t t1[1 << (RLC_WIDTH / 2)]; + ep8_t t[1 << RLC_WIDTH]; + bn_t n; + size_t l0, l1, w = RLC_WIDTH / 2; + uint8_t w0[2 * RLC_FP_BITS], w1[2 * RLC_FP_BITS]; + + bn_null(n); + + if (bn_is_zero(k) || ep8_is_infty(p)) { + ep8_mul(r, q, m); + return; + } + if (bn_is_zero(m) || ep8_is_infty(q)) { + ep8_mul(r, p, k); + return; + } + + RLC_TRY { + bn_new(n); + + ep8_curve_get_ord(n); + + for (int i = 0; i < (1 << w); i++) { + ep8_null(t0[i]); + ep8_null(t1[i]); + ep8_new(t0[i]); + ep8_new(t1[i]); + } + for (int i = 0; i < (1 << RLC_WIDTH); i++) { + ep8_null(t[i]); + ep8_new(t[i]); + } + + ep8_set_infty(t0[0]); + ep8_copy(t0[1], p); + if (bn_sign(k) == RLC_NEG) { + ep8_neg(t0[1], t0[1]); + } + for (int i = 2; i < (1 << w); i++) { + ep8_add(t0[i], t0[i - 1], t0[1]); + } + + ep8_set_infty(t1[0]); + ep8_copy(t1[1], q); + if (bn_sign(m) == RLC_NEG) { + ep8_neg(t1[1], t1[1]); + } + for (int i = 1; i < (1 << w); i++) { + ep8_add(t1[i], t1[i - 1], t1[1]); + } + + for (int i = 0; i < (1 << w); i++) { + for (int j = 0; j < (1 << w); j++) { + ep8_add(t[(i << w) + j], t0[i], t1[j]); + } + } + +#if defined(EP_MIXED) + ep8_norm_sim(t + 1, t + 1, (1 << (RLC_WIDTH)) - 1); +#endif + + l0 = l1 = RLC_CEIL(2 * RLC_FP_BITS, w); + bn_rec_win(w0, &l0, k, w); + bn_rec_win(w1, &l1, m, w); + + ep8_set_infty(r); + for (int i = RLC_MAX(l0, l1) - 1; i >= 0; i--) { + for (int j = 0; j < w; j++) { + ep8_dbl(r, r); + } + ep8_add(r, r, t[(w0[i] << w) + w1[i]]); + } + ep8_norm(r, r); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + bn_free(n); + for (int i = 0; i < (1 << w); i++) { + ep8_free(t0[i]); + ep8_free(t1[i]); + } + for (int i = 0; i < (1 << RLC_WIDTH); i++) { + ep8_free(t[i]); + } + } +} +#endif + +#if EP_SIM == INTER || !defined(STRIP) + +void ep8_mul_sim_inter(ep8_t r, const ep8_t p, const bn_t k, const ep8_t q, + const bn_t m) { + if (bn_is_zero(k) || ep8_is_infty(p)) { + ep8_mul(r, q, m); + return; + } + if (bn_is_zero(m) || ep8_is_infty(q)) { + ep8_mul(r, p, k); + return; + } + + ep8_mul_sim_plain(r, p, k, q, m, NULL); +} + +#endif + +#if EP_SIM == JOINT || !defined(STRIP) + +void ep8_mul_sim_joint(ep8_t r, const ep8_t p, const bn_t k, const ep8_t q, + const bn_t m) { + ep8_t t[5]; + int i, u_i, offset; + int8_t jsf[4 * (RLC_FP_BITS + 1)]; + size_t l; + + if (bn_is_zero(k) || ep8_is_infty(p)) { + ep8_mul(r, q, m); + return; + } + if (bn_is_zero(m) || ep8_is_infty(q)) { + ep8_mul(r, p, k); + return; + } + + RLC_TRY { + for (i = 0; i < 5; i++) { + ep8_null(t[i]); + ep8_new(t[i]); + } + + ep8_set_infty(t[0]); + ep8_copy(t[1], q); + if (bn_sign(m) == RLC_NEG) { + ep8_neg(t[1], t[1]); + } + ep8_copy(t[2], p); + if (bn_sign(k) == RLC_NEG) { + ep8_neg(t[2], t[2]); + } + ep8_add(t[3], t[2], t[1]); + ep8_sub(t[4], t[2], t[1]); +#if defined(EP_MIXED) + ep8_norm_sim(t + 3, t + 3, 2); +#endif + + l = 4 * (RLC_FP_BITS + 1); + bn_rec_jsf(jsf, &l, k, m); + + ep8_set_infty(r); + + offset = RLC_MAX(bn_bits(k), bn_bits(m)) + 1; + for (i = l - 1; i >= 0; i--) { + ep8_dbl(r, r); + if (jsf[i] != 0 && jsf[i] == -jsf[i + offset]) { + u_i = jsf[i] * 2 + jsf[i + offset]; + if (u_i < 0) { + ep8_sub(r, r, t[4]); + } else { + ep8_add(r, r, t[4]); + } + } else { + u_i = jsf[i] * 2 + jsf[i + offset]; + if (u_i < 0) { + ep8_sub(r, r, t[-u_i]); + } else { + ep8_add(r, r, t[u_i]); + } + } + } + ep8_norm(r, r); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + for (i = 0; i < 5; i++) { + ep8_free(t[i]); + } + } +} + +#endif + +void ep8_mul_sim_gen(ep8_t r, const bn_t k, const ep8_t q, const bn_t m) { + ep8_t gen; + + ep8_null(gen); + + if (bn_is_zero(k)) { + ep8_mul(r, q, m); + return; + } + if (bn_is_zero(m) || ep8_is_infty(q)) { + ep8_mul_gen(r, k); + return; + } + + RLC_TRY { + ep8_new(gen); + + ep8_curve_get_gen(gen); +#if EP_FIX == LWNAF && defined(EP_PRECO) + ep8_mul_sim_plain(r, gen, k, q, m, ep8_curve_get_tab()); +#else + ep8_mul_sim(r, gen, k, q, m); +#endif + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + ep8_free(gen); + } +} + +void ep8_mul_sim_dig(ep8_t r, const ep8_t p[], const dig_t k[], size_t len) { + ep8_t t; + int max; + + ep8_null(t); + + max = util_bits_dig(k[0]); + for (int i = 1; i < len; i++) { + max = RLC_MAX(max, util_bits_dig(k[i])); + } + + RLC_TRY { + ep8_new(t); + + ep8_set_infty(t); + for (int i = max - 1; i >= 0; i--) { + ep8_dbl(t, t); + for (int j = 0; j < len; j++) { + if (k[j] & ((dig_t)1 << i)) { + ep8_add(t, t, p[j]); + } + } + } + + ep8_norm(r, t); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + ep8_free(t); + } +} + +void ep8_mul_sim_lot(ep8_t r, const ep8_t p[], const bn_t k[], size_t n) { + const size_t len = RLC_FP_BITS + 1; + int i, j, m; + bn_t _k[8], q, x; + int8_t *naf = RLC_ALLOCA(int8_t, 8 * n * len); + size_t l, *_l = RLC_ALLOCA(size_t, 8 * n); + + bn_null(q); + bn_null(x); + + if (n <= 10) { + ep8_t *_p = RLC_ALLOCA(ep8_t, 8 * n); + + RLC_TRY { + bn_new(q); + bn_new(x); + for (j = 0; j < 8; j++) { + bn_null(_k[j]); + bn_new(_k[j]); + for (i = 0; i < n; i++) { + ep8_null(_p[8*i + j]); + ep8_new(_p[8*i + j]); + } + } + + for (int i = 0; i < n; i++) { + ep8_norm(_p[8*i], p[i]); + ep8_frb(_p[8*i + 1], _p[8*i], 1); + ep8_frb(_p[8*i + 2], _p[8*i + 1], 1); + ep8_frb(_p[8*i + 3], _p[8*i + 2], 1); + ep8_frb(_p[8*i + 4], _p[8*i + 3], 1); + ep8_frb(_p[8*i + 5], _p[8*i + 4], 1); + ep8_frb(_p[8*i + 6], _p[8*i + 5], 1); + ep8_frb(_p[8*i + 7], _p[8*i + 6], 1); + } + + ep_curve_get_ord(q); + fp_prime_get_par(x); + + l = 0; + for (i = 0; i < n; i++) { + bn_rec_frb(_k, 8, k[i], q, x, ep_curve_is_pairf() == EP_BN); + for (j = 0; j < 8; j++) { + _l[8*i + j] = len; + bn_rec_naf(&naf[(8*i + j)*len], &_l[8*i + j], _k[j], 2); + if (bn_sign(_k[j]) == RLC_NEG) { + ep8_neg(_p[8*i + j], _p[8*i + j]); + } + l = RLC_MAX(l, _l[8*i + j]); + } + } + + ep8_set_infty(r); + for (i = l - 1; i >= 0; i--) { + ep8_dbl(r, r); + for (j = 0; j < n; j++) { + for (m = 0; m < 8; m++) { + if (naf[(8*j + m)*len + i] > 0) { + ep8_add(r, r, _p[8*j + m]); + } + if (naf[(8*j + m)*len + i] < 0) { + ep8_sub(r, r, _p[8*j + m]); + } + } + } + } + + /* Convert r to affine coordinates. */ + ep8_norm(r, r); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + bn_free(q); + bn_free(x); + for (j = 0; j < 8; j++) { + bn_free(_k[j]); + for (i = 0; i < n; i++) { + ep8_free(_p[8*i + j]); + } + } + RLC_FREE(_l); + RLC_FREE(_p); + RLC_FREE(naf); + } + } else { + const int w = RLC_MAX(2, util_bits_dig(n) - 2), c = (1 << (w - 2)); + ep8_t s, t, u, v, *_p = RLC_ALLOCA(ep8_t, 8 * c); + int8_t ptr; + + ep8_null(s); + ep8_null(t); + ep8_null(u); + ep8_null(v); + + RLC_TRY { + bn_new(q); + bn_new(x); + ep8_new(s); + ep8_new(t); + ep8_new(u); + ep8_new(v); + for (i = 0; i < 8; i++) { + bn_null(_k[i]); + bn_new(_k[i]); + for (j = 0; j < c; j++) { + ep8_null(_p[i*c + j]); + ep8_new(_p[i*c + j]); + ep8_set_infty(_p[i*c + j]); + } + } + + ep_curve_get_ord(q); + fp_prime_get_par(x); + + l = 0; + for (i = 0; i < n; i++) { + bn_rec_frb(_k, 8, k[i], q, x, ep_curve_is_pairf() == EP_BN); + for (j = 0; j < 8; j++) { + _l[8*i + j] = len; + bn_rec_naf(&naf[(8*i + j)*len], &_l[8*i + j], _k[j], w); + l = RLC_MAX(l, _l[8*i + j]); + } + } + + for (i = 0; i < n; i++) { + for (j = 0; j < 8; j++) { + for (m = _l[8*i + j]; m < l; m++) { + naf[(8*i + j)*len + m] = 0; + } + } + } + + ep8_set_infty(s); + for (i = l - 1; i >= 0; i--) { + for (j = 0; j < n; j++) { + for (m = 0; m < 8; m++) { + ptr = naf[(8*j + m)*len + i]; + if (ptr != 0) { + ep8_copy(t, p[j]); + if (ptr < 0) { + ptr = -ptr; + ep8_neg(t, t); + } + if (bn_sign(_k[m]) == RLC_NEG) { + ep8_neg(t, t); + } + ep8_add(_p[m*c + (ptr/2)], _p[m*c + (ptr/2)], t); + } + } + } + + ep8_set_infty(t); + for (m = 3; m >= 0; m--) { + ep8_frb(t, t, 1); + ep8_set_infty(u); + ep8_set_infty(v); + for (j = c - 1; j >= 0; j--) { + ep8_add(u, u, _p[m*c + j]); + if (j == 0) { + ep8_dbl(v, v); + } + ep8_add(v, v, u); + ep8_set_infty(_p[m*c + j]); + } + ep8_add(t, t, v); + } + ep8_dbl(s, s); + ep8_add(s, s, t); + } + + /* Convert r to affine coordinates. */ + ep8_norm(r, s); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + bn_free(q); + bn_free(x); + ep8_free(s); + ep8_free(t); + ep8_free(u); + ep8_free(v); + for (i = 0; i < 8; i++) { + bn_free(_k[i]); + for (j = 0; j < c; j++) { + ep8_free(_p[i*c + j]); + } + } + RLC_FREE(_l); + RLC_FREE(_p); + RLC_FREE(naf); + } + } +} diff --git a/src/epx/relic_ep8_neg.c b/src/epx/relic_ep8_neg.c new file mode 100644 index 000000000..3f0f3061e --- /dev/null +++ b/src/epx/relic_ep8_neg.c @@ -0,0 +1,53 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 + * + * Implementation of point negation on elliptic prime curves over quartic + * extensions. + * + * @ingroup epx + */ + +#include "relic_core.h" + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +void ep8_neg(ep8_t r, const ep8_t p) { + if (ep8_is_infty(p)) { + ep8_set_infty(r); + return; + } + + if (r != p) { + fp8_copy(r->x, p->x); + fp8_copy(r->z, p->z); + } + + fp8_neg(r->y, p->y); + + r->coord = p->coord; +} diff --git a/src/epx/relic_ep8_norm.c b/src/epx/relic_ep8_norm.c new file mode 100644 index 000000000..1fe215a1a --- /dev/null +++ b/src/epx/relic_ep8_norm.c @@ -0,0 +1,138 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 + * + * Implementation of point normalization on prime elliptic curves over octic + * extensions. + * + * @ingroup epx + */ + +#include "relic_core.h" + +/*============================================================================*/ +/* Private definitions */ +/*============================================================================*/ + +#if EP_ADD == PROJC || !defined(STRIP) + +/** + * Normalizes a point represented in projective coordinates. + * + * @param r - the result. + * @param p - the point to normalize. + */ +static void ep8_norm_imp(ep8_t r, const ep8_t p, int inverted) { + if (p->coord != BASIC) { + fp8_t t0, t1; + + fp8_null(t0); + fp8_null(t1); + + RLC_TRY { + + fp8_new(t0); + fp8_new(t1); + + if (inverted) { + fp8_copy(t1, p->z); + } else { + fp8_inv(t1, p->z); + } + 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); + } + } + + r->coord = BASIC; +} + +#endif /* EP_ADD == PROJC */ + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +void ep8_norm(ep8_t r, const ep8_t p) { + if (ep8_is_infty(p)) { + ep8_set_infty(r); + return; + } + + if (p->coord == BASIC) { + /* If the point is represented in affine coordinates, we just copy it. */ + ep8_copy(r, p); + } +#if EP_ADD == PROJC || !defined(STRIP) + ep8_norm_imp(r, p, 0); +#endif +} + +void ep8_norm_sim(ep8_t *r, const ep8_t *t, int n) { + int i; + fp8_t *a = RLC_ALLOCA(fp8_t, n); + + RLC_TRY { + if (a == NULL) { + RLC_THROW(ERR_NO_MEMORY); + } + for (i = 0; i < n; i++) { + fp8_null(a[i]); + fp8_new(a[i]); + fp8_copy(a[i], t[i]->z); + } + + fp8_inv_sim(a, 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]); + } + + for (i = 0; i < n; i++) { + ep8_norm_imp(r[i], r[i], 1); + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + for (i = 0; i < n; i++) { + fp8_free(a[i]); + } + RLC_FREE(a); + } +} diff --git a/src/epx/relic_ep8_util.c b/src/epx/relic_ep8_util.c new file mode 100644 index 000000000..2f4952563 --- /dev/null +++ b/src/epx/relic_ep8_util.c @@ -0,0 +1,328 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 + * + * Implementation of comparison for points on prime elliptic curves over + * quartic extensions. + * + * @ingroup epx + */ + +#include "relic_core.h" + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +int ep8_is_infty(const ep8_t p) { + return (fp8_is_zero(p->z) == 1); +} + +void ep8_set_infty(ep8_t p) { + fp8_zero(p->x); + fp8_zero(p->y); + fp8_zero(p->z); + p->coord = BASIC; +} + +void ep8_copy(ep8_t r, const ep8_t p) { + fp8_copy(r->x, p->x); + fp8_copy(r->y, p->y); + fp8_copy(r->z, p->z); + r->coord = p->coord; +} + +void ep8_rand(ep8_t p) { + bn_t n, k; + + bn_null(k); + bn_null(n); + + RLC_TRY { + bn_new(k); + bn_new(n); + + ep8_curve_get_ord(n); + bn_rand_mod(k, n); + + ep8_mul_gen(p, k); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + bn_free(k); + bn_free(n); + } +} + +void ep8_blind(ep8_t r, const ep8_t p) { + fp8_t rand; + + fp8_null(rand); + + RLC_TRY { + fp8_new(rand); + fp8_rand(rand); +#if EP_ADD == BASIC + (void)rand; + ep8_copy(r, p); +#else + 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; +#endif + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp8_free(rand); + } +} + +void ep8_rhs(fp8_t rhs, const ep8_t p) { + fp8_t t0, t1; + + fp8_null(t0); + fp8_null(t1); + + RLC_TRY { + fp8_new(t0); + fp8_new(t1); + + fp8_sqr(t0, p->x); /* x1^2 */ + + switch (ep8_curve_opt_a()) { + case RLC_ZERO: + break; +#if FP_RDC != MONTY + case RLC_MIN3: + fp_sub_dig(t0[0][0][0], t0[0][0][0], 3); + break; + case RLC_ONE: + fp_add_dig(t0[0][0][0], t0[0][0][0], 1); + break; + case RLC_TWO: + 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]); + fp_mul_dig(t0[0][0][1], t0[0][0][1], t1[0][0][0]); + fp_mul_dig(t0[0][1][0], t0[0][1][0], t1[0][0][0]); + fp_mul_dig(t0[0][1][1], t0[0][1][1], t1[0][0][0]); + fp_mul_dig(t0[1][0][0], t0[1][0][0], t1[0][0][0]); + fp_mul_dig(t0[1][0][1], t0[1][0][1], t1[0][0][0]); + fp_mul_dig(t0[1][1][0], t0[1][1][0], t1[0][0][0]); + fp_mul_dig(t0[1][1][1], t0[1][1][1], t1[0][0][0]); + break; +#endif + default: + ep8_curve_get_a(t1); + fp8_add(t0, t0, t1); + break; + } + + fp8_mul(t0, t0, p->x); /* x1^3 + a * x */ + + switch (ep8_curve_opt_b()) { + case RLC_ZERO: + break; +#if FP_RDC != MONTY + case RLC_MIN3: + fp_sub_dig(t0[0][0], t0[0][0], 3); + break; + case RLC_ONE: + fp_add_dig(t0[0][0], t0[0][0], 1); + break; + case RLC_TWO: + fp_add_dig(t0[0][0], t0[0][0], 2); + break; + case RLC_TINY: + ep8_curve_get_b(t1); + fp_mul_dig(t0[0][0], t0[0][0], t1[0][0][0]); + fp_mul_dig(t0[0][1], t0[0][1], t1[0][0][0]); + fp_mul_dig(t0[1][0], t0[0][0], t1[0][0][0]); + fp_mul_dig(t0[1][1], t0[1][1], t1[0][0][0]); + break; +#endif + default: + ep8_curve_get_b(t1); + fp8_add(t0, t0, t1); + break; + } + + fp8_copy(rhs, t0); + } RLC_CATCH_ANY { + 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; + + ep8_null(t); + + RLC_TRY { + ep8_new(t); + + ep8_norm(t, p); + + ep8_rhs(t->x, t); + fp8_sqr(t->y, t->y); + + r = (fp8_cmp(t->x, t->y) == RLC_EQ) || ep8_is_infty(p); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + ep8_free(t); + } + return r; +} + +void ep8_tab(ep8_t *t, const ep8_t p, int w) { + if (w > 2) { + ep8_dbl(t[0], p); +#if defined(EP_MIXED) + ep8_norm(t[0], t[0]); +#endif + ep8_add(t[1], t[0], p); + for (int i = 2; i < (1 << (w - 2)); i++) { + ep8_add(t[i], t[i - 1], t[0]); + } +#if defined(EP_MIXED) + ep8_norm_sim(t + 1, t + 1, (1 << (w - 2)) - 1); +#endif + } + ep8_copy(t[0], p); +} + +void ep8_print(const ep8_t p) { + fp8_print(p->x); + fp8_print(p->y); + fp8_print(p->z); +} + +int ep8_size_bin(const ep8_t a, int pack) { + ep8_t t; + int size = 0; + + ep8_null(t); + + if (ep8_is_infty(a)) { + return 1; + } + + RLC_TRY { + ep8_new(t); + + ep8_norm(t, a); + + size = 1 + 16 * RLC_FP_BYTES; + //TODO: implement compression properly + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + ep8_free(t); + } + + return size; +} + +void ep8_read_bin(ep8_t a, const uint8_t *bin, size_t len) { + if (len == 1) { + if (bin[0] == 0) { + ep8_set_infty(a); + return; + } else { + RLC_THROW(ERR_NO_BUFFER); + return; + } + } + + if (len != (16 * RLC_FP_BYTES + 1)) { + RLC_THROW(ERR_NO_BUFFER); + return; + } + + a->coord = BASIC; + fp8_set_dig(a->z, 1); + fp8_read_bin(a->x, bin + 1, 8 * RLC_FP_BYTES); + + if (len == 16 * RLC_FP_BYTES + 1) { + if (bin[0] == 4) { + fp8_read_bin(a->y, bin + 8 * RLC_FP_BYTES + 1, 8 * RLC_FP_BYTES); + } else { + RLC_THROW(ERR_NO_VALID); + return; + } + } + + if (!ep8_on_curve(a)) { + RLC_THROW(ERR_NO_VALID); + } +} + +void ep8_write_bin(uint8_t *bin, size_t len, const ep8_t a, int pack) { + ep8_t t; + + ep8_null(t); + + memset(bin, 0, len); + + if (ep8_is_infty(a)) { + if (len < 1) { + RLC_THROW(ERR_NO_BUFFER); + return; + } else { + return; + } + } + + RLC_TRY { + ep8_new(t); + + ep8_norm(t, a); + + if (len < 16 * RLC_FP_BYTES + 1) { + 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); + } + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + ep8_free(t); + } +} diff --git a/src/fp/relic_fp_crt.c b/src/fp/relic_fp_crt.c new file mode 100644 index 000000000..140f64683 --- /dev/null +++ b/src/fp/relic_fp_crt.c @@ -0,0 +1,216 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2010 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 + * + * Implementation of the cube root function. + * + * @ingroup bn + */ + +#include "relic_core.h" + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +int fp_is_cub(const fp_t a) { + bn_t t; + int r = 0; + + bn_null(t); + + if (fp_is_zero(a) || (fp_prime_get_mod18() % 3 == 2)) { + return 1; + } + + RLC_TRY { + bn_new(t); + + /* t = (b - 1)/3. */ + t->sign = RLC_POS; + t->used = RLC_FP_DIGS; + dv_copy(t->dp, fp_prime_get(), RLC_FP_DIGS); + bn_sub_dig(t, t, 1); + bn_div_dig(t, t, 3); + + fp_exp(t->dp, a, t); + r = (fp_cmp_dig(t->dp, 1) == RLC_EQ); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + bn_free(t); + } + return r; +} + +int fp_crt(fp_t c, const fp_t a) { + bn_t e; + fp_t t0, t1, t2, t3, t4, t5; + int f = 0, r = 0; + + bn_null(e); + fp_null(t0); + fp_null(t1); + fp_null(t2); + fp_null(t3); + fp_null(t4); + fp_null(t5); + + if (fp_is_zero(a)) { + fp_zero(c); + return 1; + } + + RLC_TRY { + bn_new(e); + fp_new(t0); + fp_new(t1); + fp_new(t2); + fp_new(t3); + fp_new(t4); + fp_new(t5); + + /* Make e = p. */ + e->used = RLC_FP_DIGS; + dv_copy(e->dp, fp_prime_get(), RLC_FP_DIGS); + + /* Special cases and algorithm taken from "New Cube Root Algorithm Based + * on Third Order Linear Recurrence Relation in Finite Field" + * https://eprint.iacr.org/2013/024.pdf + */ + if (fp_prime_get_mod18() % 3 == 2) { + /* Easy case, compute a^((2q - 1)/3). */ + bn_dbl(e, e); + bn_sub_dig(e, e, 1); + bn_div_dig(e, e, 3); + + fp_exp(t0, a, e); + fp_sqr(t1, t0); + fp_mul(t1, t1, t0); + r = (fp_cmp(t1, a) == RLC_EQ); + fp_copy(c, t0); + } else if (fp_prime_get_mod18() % 9 == 4) { + /* Easy case, compute a^((2q + 1)/9). */ + bn_dbl(e, e); + bn_add_dig(e, e, 1); + bn_div_dig(e, e, 9); + + fp_exp(t0, a, e); + fp_sqr(t1, t0); + fp_mul(t1, t1, t0); + r = (fp_cmp(t1, a) == RLC_EQ); + fp_copy(c, t0); + } else if (fp_prime_get_mod18() % 9 == 7) { + /* Easy case, compute a^((q + 2)/9). */ + bn_add_dig(e, e, 2); + bn_div_dig(e, e, 9); + + fp_exp(t0, a, e); + fp_sqr(t1, t0); + fp_mul(t1, t1, t0); + r = (fp_cmp(t1, a) == RLC_EQ); + fp_copy(c, t0); + } else { + dig_t rem; + + /* First check that a is a square. */ + r = fp_is_cub(a); + + /* Compute progenitor as x^(p-1-3^f)/3^(f+1) where 3^f|(p-1). */ + + /* Write p - 1 as (e * 3^f), with e = 3l \pm 1. */ + bn_sub_dig(e, e, 1); + bn_mod_dig(&rem, e, 3); + while (rem == 0) { + bn_div_dig(e, e, 3); + bn_mod_dig(&rem, e, 3); + f++; + } + + /* Make it e = (p - 1 - 3^f)/3^(f + 1), compute t0 = a^e. */ + bn_mod_dig(&rem, e, 3); + bn_div_dig(e, e, 3); + fp_exp(t0, a, e); + + /* Recover 3^f-root of unity, and continue algorithm. */ + fp_copy(t3, fp_prime_get_crt()); + + fp_copy(c, t3); + for (int i = 0; i < f - 1; i++) { + fp_sqr(t4, c); + fp_mul(c, c, t4); + } + fp_sqr(t1, t0); + fp_mul(t1, t1, t0); + fp_mul(t1, t1, a); + if (rem == 2) { + fp_mul(t0, t0, a); + fp_mul(t1, t1, a); + } + fp_set_dig(t5, 1); + for (int j = f; j > 1; j--) { + fp_copy(t2, t1); + for (int i = 1; i < j - 1; i++) { + fp_sqr(t4, t2); + fp_mul(t2, t2, t4); + } + if (fp_cmp(t2, c) == RLC_EQ) { + fp_sqr(t4, t3); + fp_mul(t5, t5, t4); + fp_mul(t4, t4, t3); + fp_sqr(t4, t4); + fp_mul(t1, t1, t4); + } else if (fp_cmp_dig(t2, 1) != RLC_EQ) { + fp_mul(t5, t5, t3); + fp_sqr(t4, t3); + fp_mul(t4, t4, t3); + fp_mul(t1, t1, t4); + } + fp_sqr(t4, t3); + fp_mul(t3, t3, t4); + } + + fp_mul(c, t0, t5); + if (rem == 1) { + fp_inv(c, c); + } + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + bn_free(e); + fp_free(t0); + fp_free(t1); + fp_free(t2); + fp_free(t3); + fp_free(t4); + fp_free(t5); + } + return r; +} diff --git a/src/fp/relic_fp_exp.c b/src/fp/relic_fp_exp.c index 947807f59..de847ba78 100644 --- a/src/fp/relic_fp_exp.c +++ b/src/fp/relic_fp_exp.c @@ -189,3 +189,34 @@ void fp_exp_monty(fp_t c, const fp_t a, const bn_t b) { } #endif + +void fp_exp_dig(fp_t c, const fp_t a, dig_t b) { + fp_t t; + + if (b == 0) { + fp_set_dig(c, 1); + return; + } + + fp_null(t); + + RLC_TRY { + fp_new(t); + + fp_copy(t, a); + for (int i = util_bits_dig(b) - 2; i >= 0; i--) { + fp_sqr(t, t); + if (b & ((dig_t)1 << i)) { + fp_mul(t, t, a); + } + } + + fp_copy(c, t); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + fp_free(t); + } +} diff --git a/src/fp/relic_fp_inv.c b/src/fp/relic_fp_inv.c index 6ec85f98a..3d94594f2 100644 --- a/src/fp/relic_fp_inv.c +++ b/src/fp/relic_fp_inv.c @@ -33,6 +33,71 @@ #include "relic_fp_low.h" #include "relic_bn_low.h" +/*============================================================================*/ +/* Private definitions */ +/*============================================================================*/ + +#if FP_INV == JMPDS || !defined(STRIP) + +/** + * Conditionally negate a digit vector using two's complement representation. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to conditionally negate. + * @param[in] sa - the sign of the digit vector. + * @param[in] n - the number of digits to conditionally negate. + */ +static void bn_negs_low(dig_t c[], const dig_t a[], dig_t sa, size_t n) { + dig_t carry = sa & 1; + + sa = -sa; + for (int i = 0; i < n; i++) { + c[i] = (a[i] ^ sa) + carry; + carry = (c[i] < carry); + } +} + +static void bn_mul2_low(dig_t *c, const dig_t *a, dis_t digit, int size) { + int sd = digit >> (RLC_DIG - 1); + digit = (digit ^ sd) - sd; + c[size] = bn_mul1_low(c, a, digit, size); +} + +static dis_t jumpdivstep(dis_t m[4], dis_t delta, dig_t f, dig_t g, int s) { + dig_t u = 1, v = 0, q = 0, r = 1, c0, c1; + + /* This is actually faster than my previous version, several tricks from + * https://github.com/bitcoin-core/secp256k1/blob/master/src/modinv64_impl.h + */ + for (s--; s >= 0; s--) { + /* First handle the else part: if delta < 0, compute -(f,u,v). */ + c0 = delta >> (RLC_DIG - 1); + c1 = -(g & 1); + c0 &= c1; + /* Conditionally add -(f,u,v) to (g,q,r) */ + g += ((f ^ c0) - c0) & c1; + q += ((u ^ c0) - c0) & c1; + r += ((v ^ c0) - c0) & c1; + /* Now handle the 'if' part, so c0 will be (delta < 0) && (g & 1)) */ + /* delta = RLC_SEL(delta, -delta, c0 & 1) - 2 (for half-divstep), thus + * delta = - delta - 2 or delta - 1 */ + delta = (delta ^ c0) - 1; + f = f + (g & c0); + u = u + (q & c0); + v = v + (r & c0); + g >>= 1; + u += u; + v += v; + } + m[0] = u; + m[1] = v; + m[2] = q; + m[3] = r; + return delta; +} + +#endif + /*============================================================================*/ /* Public definitions */ /*============================================================================*/ @@ -404,9 +469,9 @@ void fp_inv_exgcd(fp_t c, const fp_t a) { void fp_inv_divst(fp_t c, const fp_t a) { /* Compute number of iterations based on modulus size. */ #if FP_PRIME < 46 - int d = (49 * FP_PRIME + 80) / 17; + const int d = (49 * FP_PRIME + 80) / 17; #else - int d = (49 * FP_PRIME + 57) / 17; + const int d = (49 * FP_PRIME + 57) / 17; #endif int g0, d0; dig_t fs, gs, delta = 1; @@ -511,52 +576,14 @@ void fp_inv_divst(fp_t c, const fp_t a) { #if FP_INV == JMPDS || !defined(STRIP) -static dis_t jumpdivstep(dis_t m[4], dis_t delta, dig_t f, dig_t g, int s) { - dig_t u = 1, v = 0, q = 0, r = 1, c0, c1; - - /* This is actually faster than my previous version, several tricks from - * https://github.com/bitcoin-core/secp256k1/blob/master/src/modinv64_impl.h - */ - for (s--; s >= 0; s--) { - /* First handle the else part: if delta < 0, compute -(f,u,v). */ - c0 = delta >> (RLC_DIG - 1); - c1 = -(g & 1); - c0 &= c1; - /* Conditionally add -(f,u,v) to (g,q,r) */ - g += ((f ^ c0) - c0) & c1; - q += ((u ^ c0) - c0) & c1; - r += ((v ^ c0) - c0) & c1; - /* Now handle the 'if' part, so c0 will be (delta < 0) && (g & 1)) */ - /* delta = RLC_SEL(delta, -delta, c0 & 1) - 2 (for half-divstep), thus - * delta = - delta - 2 or delta - 1 */ - delta = (delta ^ c0) - 1; - f = f + (g & c0); - u = u + (q & c0); - v = v + (r & c0); - g >>= 1; - u += u; - v += v; - } - m[0] = u; - m[1] = v; - m[2] = q; - m[3] = r; - return delta; -} - -static inline void bn_mul2_low(dig_t *c, const dig_t *a, dis_t digit, int size) { - int sd = digit >> (RLC_DIG - 1); - digit = (digit ^ sd) - sd; - c[size] = bn_mul1_low(c, a, digit, size); -} - void fp_inv_jmpds(fp_t c, const fp_t a) { - dis_t m[4]; + dis_t m[4], d = -1; /* Compute number of iterations based on modulus size. */ - int i, d = -1, s = RLC_DIG - 2; /* Iterations taken directly from https://github.com/sipa/safegcd-bounds */ - int iterations = (45907 * FP_PRIME + 26313) / 19929; + const int iterations = (45907 * FP_PRIME + 26313) / 19929; + int loops, i, s = RLC_DIG - 2; dv_t f, g, t, p, t0, t1, u0, u1, v0, v1, p01, p11; + dig_t sf, sg; fp_t pre; if (fp_is_zero(a)) { @@ -593,7 +620,7 @@ void fp_inv_jmpds(fp_t c, const fp_t a) { dv_new(p11); fp_new(pre); -#if (FP_PRIME % WSIZE) != 0 +#ifdef RLC_FP_ROOM int j = 0; fp_copy(pre, core_get()->inv.dp); #else @@ -601,7 +628,6 @@ void fp_inv_jmpds(fp_t c, const fp_t a) { fp_mul(pre, pre, core_get()->conv.dp); fp_mul(pre, pre, core_get()->inv.dp); #endif - f[RLC_FP_DIGS] = g[RLC_FP_DIGS] = 0; dv_zero(t, 2 * RLC_FP_DIGS); dv_zero(p, 2 * RLC_FP_DIGS); @@ -644,25 +670,28 @@ void fp_inv_jmpds(fp_t c, const fp_t a) { dv_copy(p01, v1, 2 * RLC_FP_DIGS); dv_copy(p11, u1, 2 * RLC_FP_DIGS); - int loops = iterations / s; + loops = iterations / s; loops = (iterations % s == 0 ? loops - 1 : loops); for (i = 1; i < loops; i++) { d = jumpdivstep(m, d, f[0] & RLC_MASK(s), g[0] & RLC_MASK(s), s); - t0[RLC_FP_DIGS] = bn_muls_low(t0, f, RLC_SIGN(f[RLC_FP_DIGS]), m[0], RLC_FP_DIGS); - t1[RLC_FP_DIGS] = bn_muls_low(t1, g, RLC_SIGN(g[RLC_FP_DIGS]), m[1], RLC_FP_DIGS); - bn_addn_low(t0, t0, t1, RLC_FP_DIGS + 1); - - f[RLC_FP_DIGS] = bn_muls_low(f, f, RLC_SIGN(f[RLC_FP_DIGS]), m[2], RLC_FP_DIGS); - t1[RLC_FP_DIGS] = bn_muls_low(t1, g, RLC_SIGN(g[RLC_FP_DIGS]), m[3], RLC_FP_DIGS); - bn_addn_low(t1, t1, f, RLC_FP_DIGS + 1); + sf = RLC_SIGN(f[RLC_FP_DIGS]); + sg = RLC_SIGN(g[RLC_FP_DIGS]); + bn_negs_low(u0, f, sf, RLC_FP_DIGS); + bn_negs_low(u1, g, sg, RLC_FP_DIGS); - /* Update f and g. */ + t0[RLC_FP_DIGS] = bn_muls_low(t0, u0, sf, m[0], RLC_FP_DIGS); + t1[RLC_FP_DIGS] = bn_muls_low(t1, u1, sg, m[1], RLC_FP_DIGS); + bn_addn_low(t0, t0, t1, RLC_FP_DIGS + 1); bn_rshs_low(f, t0, RLC_FP_DIGS + 1, s); + + t0[RLC_FP_DIGS] = bn_muls_low(t0, u0, sf, m[2], RLC_FP_DIGS); + t1[RLC_FP_DIGS] = bn_muls_low(t1, u1, sg, m[3], RLC_FP_DIGS); + bn_addn_low(t1, t1, t0, RLC_FP_DIGS + 1); bn_rshs_low(g, t1, RLC_FP_DIGS + 1, s); -#if (FP_PRIME % WSIZE) != 0 +#ifdef RLC_FP_ROOM p[j] = 0; dv_copy(p + j + 1, fp_prime_get(), RLC_FP_DIGS); @@ -727,23 +756,25 @@ void fp_inv_jmpds(fp_t c, const fp_t a) { s = iterations - loops * s; d = jumpdivstep(m, d, f[0] & RLC_MASK(s), g[0] & RLC_MASK(s), s); - t0[RLC_FP_DIGS] = bn_muls_low(t0, f, RLC_SIGN(f[RLC_FP_DIGS]), m[0], RLC_FP_DIGS); - t1[RLC_FP_DIGS] = bn_muls_low(t1, g, RLC_SIGN(g[RLC_FP_DIGS]), m[1], RLC_FP_DIGS); - bn_addn_low(t0, t0, t1, RLC_FP_DIGS + 1); - - f[RLC_FP_DIGS] = bn_muls_low(f, f, RLC_SIGN(f[RLC_FP_DIGS]), m[2], RLC_FP_DIGS); - t1[RLC_FP_DIGS] = bn_muls_low(t1, g, RLC_SIGN(g[RLC_FP_DIGS]), m[3], RLC_FP_DIGS); - bn_addn_low(t1, t1, f, RLC_FP_DIGS + 1); + sf = RLC_SIGN(f[RLC_FP_DIGS]); + sg = RLC_SIGN(g[RLC_FP_DIGS]); + bn_negs_low(u0, f, sf, RLC_FP_DIGS); + bn_negs_low(u1, g, sg, RLC_FP_DIGS); - /* Update f and g. */ + t0[RLC_FP_DIGS] = bn_muls_low(t0, u0, sf, m[0], RLC_FP_DIGS); + t1[RLC_FP_DIGS] = bn_muls_low(t1, u1, sg, m[1], RLC_FP_DIGS); + bn_addn_low(t0, t0, t1, RLC_FP_DIGS + 1); bn_rshs_low(f, t0, RLC_FP_DIGS + 1, s); + + t0[RLC_FP_DIGS] = bn_muls_low(t0, u0, sf, m[2], RLC_FP_DIGS); + t1[RLC_FP_DIGS] = bn_muls_low(t1, u1, sg, m[3], RLC_FP_DIGS); + bn_addn_low(t1, t1, t0, RLC_FP_DIGS + 1); bn_rshs_low(g, t1, RLC_FP_DIGS + 1, s); -#if (FP_PRIME % WSIZE) != 0 +#ifdef RLC_FP_ROOM p[j] = 0; dv_copy(p + j + 1, fp_prime_get(), RLC_FP_DIGS); - /* Update column vector below. */ /* Update column vector below. */ bn_mul2_low(v0, p01, m[0], RLC_FP_DIGS + j); fp_subd_low(t, p, v0); diff --git a/src/fp/relic_fp_param.c b/src/fp/relic_fp_param.c index 2c8b7e557..da5424883 100644 --- a/src/fp/relic_fp_param.c +++ b/src/fp/relic_fp_param.c @@ -37,7 +37,6 @@ /*============================================================================*/ #if FP_PRIME == 255 - /** * Primes with high 2-adicity for curves Tweedledum and Tweedledee. */ @@ -47,7 +46,13 @@ /** * Random prime modulus for the Brainpool P256r1. */ -#define STR_P256 "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377" +#define STR_P256 "AA9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377" + +#elif FP_PRIME == 511 +/** + * CTIDH prime with 511 bits. + */ +#define STR_P511 "65B48E8F740F89BFFC8AB0D15E3E4C4AB42D083AEDC88C425AFBFCC69322C9CDA7AAC6C567F35507516730CC1F0B4F25C2721BF457ACA8351B81B90533C6C87B" #elif FP_PRIME == 544 /** @@ -55,18 +60,35 @@ */ #define STR_P544 "BB9DFD549299F1C803DDD5D7C05E7CC0373D9B1AC15B47AA5AA84626F33E58FE66943943049031AE4CA1D2719B3A84FA363BCD2539A5CD02C6F4B6B645A58C1085E14411" +#elif FP_PRIME == 1024 +/** + * CTIDH prime with 1024 bits. + */ +#define STR_P1024 "ECE55ED427012A9D89DEC879007EBD7216C22BC86F21A080683CF25DB31AD5BF06DE2471CF9386E4D6C594A8AD82D2DF811D9C419EC83297611AD4F90441C800978DBEED90A2B58B97C56D1DE81EDE56B317C5431541F40642ACA4D5A313709C2CAB6A0E287F1BD514BA72CB8D89FD3A1D81EEBBC3D344DDBE34C5460E36453" + #elif FP_PRIME == 1536 /** * Cofactor description of 1536-bit prime modulus. */ #define STR_P1536 "83093742908D4D529CEF06C72191A05D5E6073FE861E637D7747C3E52FBB92DAA5DDF3EF1C61F5F70B256802481A36CAFE995FE33CD54014B846751364C0D3B8327D9E45366EA08F1B3446AC23C9D4B656886731A8D05618CFA1A3B202A2445ABA0E77C5F4F00CA1239975A05377084F256DEAA07D21C4CF2A4279BC117603ACB7B10228C3AB8F8C1742D674395701BB02071A88683041D9C4231E8EE982B8DA" -#elif FP_PRIME == 3072 +#elif FP_PRIME == 2048 +/** + * CTIDH prime with 2048 bits. + */ +#define STR_P2048 "438EFCAB10254C6497FEFC90E8196ED94D8854E8B3E19C53DDFFDCF1AEE53F12DBD1FC2133770253584EB12932F72ABB33A8779A1EC8B8C2B8523D6A302ABF284DD6024BF2F8FEAB6557EBE96D91AEDDC68049793337525393E73ABD17E3AA46095AC8A9F3CE2B0C30D2EDFE50198C647D84F102B5FDE2EAE33586D1208A10179844E5C09BAF59EC0DA1783672767ABB88C691B2D452A8AC7C4CB419996F45E75377D53E856CC9A39796620B3AD8A5D458E89497EF35BBB92842BBE4DBACC65E44084E1A73C76CB244454E851CF305ABA7BEC86FABAF787F6478407D7A9A56EEE111B0D22AB8ECAA95A98036C813C788DC703F0CD8C4D9187790D615EA034943" +#elif FP_PRIME == 3072 /** * Cofactor description of 3072-bit prime modulus. */ -#define STR_P3072 "D2DECB54BA1C33C49BD7B174FBC6E56AD9B05D1B2B4100708AA3B6AA620B5CD167F66D33818B608FC25C9F56A0C685129B9DDAA342ADB37B2CEA7E09DEB49F3BC85B467801ED7507149CF025A021D8109926CAC3C774AD8E3C0B4D175CF1C94A6641A8E5BBBE63FB40EC52B206315D20C074B538785E63174FB8A72C912F51B6A3D132A185FD95B067B817AB9F4C01ABA6CC7BF1546D94FD79AC2D0183814FD8" +#define STR_P3072 "E4C6467513F6DA5D303FCF2C5285C33206AC48901ADBE523D00F9F3B9E4895075BEB07DD1AAEEBF957F2DCBBEC4FB900E2ADE744AA7206BC2A60709BA08CA540" + +#elif FP_PRIME == 4096 +/** + * SQALE prime with 4096 bits. + */ +#define STR_P4096 "5E7717415B4CA2B9C447D91852630BDD26650A3BB26C86B690F049B4591045979B3908337C3FCE9453BDAD5DB6E3F21009C117DD6D5390FBF3924E59A2AFFCB043640CDA1CD63586511586409A8B182FB61117429E0FAD42661F279E970400FFC4BCEFE6A5B783100DAC14812B370ACFF9D051A0FB768F71FB7997BE77856D9284530ADB4A502D6EC3249D4EEA4683A8985A6B47BE6E7821DEF1AD022E6ECAB6CBA7B9B3710891E6757B7B0EA38391F577E88B3F5AADC520FB7E8F8314D444512BA4A0C4C2765F310A825D48E93D16A3B848542F632F95EF18B06DAC453EE68530A8AD864CE7CFEA2ABEADC289712A45C37A2496D6A0643ADBF7269D993760ED6855D97BA9DB63D9D28976E599D8F92E19D841ED1C3B26FCD527B24495B02AC1B19C8D8A6BFE007C68E6C44B4D5D26C6262D87B73F4A55FD9E324EE60EC15289442AE0D0EB23485C9760DB220C5F584BBD9A5671A61D5E08938F4FDC64215E5B3F9D2D3E15ED1B60E2C9D7F2E2DBDA4B10C1665D7FB1B9C76B02F4FD9D35FD9EB061D95CAFC1292BCCE8116D756C8905973DC84CFF577C5B68D30CA59CE3425CFB2F371E06C9D3AACF8DC03746E8A12DD786E8EDD70F9D4F1D32B79F32E14CD64D59D8DEC8B88D8AEE6235F05176385C0EA561D56AF87D0146535D892DB5C5F6D4A09051509BF0ECB893B4DADA515DABD369B93E277B867FD1FCF47604E79BCB" #endif @@ -99,7 +121,13 @@ void fp_param_set(int param) { core_get()->fp_id = param; switch (param) { -#if FP_PRIME == 158 +#if FP_PRIME == 127 + case MP_127: + f[0] = -1; + f[1] = 127; + fp_prime_set_pmers(f, 2); + break; +#elif FP_PRIME == 158 case BN_158: /* x = 0x4000000031. */ bn_set_2b(t0, 38); @@ -295,6 +323,18 @@ void fp_param_set(int param) { bn_set_bit(t0, 15, 1); fp_prime_set_pairf(t0, EP_B24); break; +#elif FP_PRIME == 330 + case K16_330: + /* x = 2^34-2^30+2^26+2^23+2^14-2^5+1. */ + bn_set_2b(t0, 34); + bn_set_2b(t1, 30); + bn_sub(t0, t0, t1); + bn_set_bit(t0, 26, 1); + bn_set_bit(t0, 23, 1); + bn_set_bit(t0, 14, 1); + bn_sub_dig(t0, t0, 31); + fp_prime_set_pairf(t0, EP_K16); + break; #elif FP_PRIME == 377 case B12_377: /* x = 2^63 + 2^58 + 2^56 + 2^51 + 2^47 + 2^46 + 1. */ @@ -400,7 +440,7 @@ void fp_param_set(int param) { fp_prime_set_pairf(t0, EP_B12); break; #elif FP_PRIME == 508 - case KSS_508: + case K508: /* x = -(2^64 + 2^51 - 2^46 - 2^12). */ bn_set_2b(t0, 64); bn_set_2b(t1, 51); @@ -410,34 +450,7 @@ void fp_param_set(int param) { bn_set_2b(t1, 12); bn_sub(t0, t0, t1); bn_neg(t0, t0); - /* h = (49*u^2 + 245 * u + 343)/3 */ - bn_mul_dig(p, t0, 245); - bn_add_dig(p, p, 200); - bn_add_dig(p, p, 143); - bn_sqr(t1, t0); - bn_mul_dig(t2, t1, 49); - bn_add(p, p, t2); - bn_div_dig(p, p, 3); - /* n = (u^6 + 37 * u^3 + 343)/343. */ - bn_mul(t1, t1, t0); - bn_mul_dig(t2, t1, 37); - bn_sqr(t1, t1); - bn_add(t2, t2, t1); - bn_add_dig(t2, t2, 200); - bn_add_dig(t2, t2, 143); - bn_div_dig(t2, t2, 49); - bn_div_dig(t2, t2, 7); - bn_mul(p, p, t2); - /* t = (u^4 + 16 * u + 7)/7. */ - bn_mul_dig(t1, t0, 16); - bn_add_dig(t1, t1, 7); - bn_sqr(t2, t0); - bn_sqr(t2, t2); - bn_add(t2, t2, t1); - bn_div_dig(t2, t2, 7); - bn_add(p, p, t2); - bn_sub_dig(p, p, 1); - fp_prime_set_dense(p); + fp_prime_set_pairf(t0, EP_K18); break; #elif FP_PRIME == 509 case B24_509: @@ -452,11 +465,9 @@ void fp_param_set(int param) { fp_prime_set_pairf(t0, EP_B24); break; #elif FP_PRIME == 511 - case OT_511: - bn_set_2b(t0, 52); - bn_add_dig(t0, t0, 0xAB); - bn_lsh(t0, t0, 12); - fp_prime_set_pairf(t0, EP_OT8); + case CTIDH_511: + bn_read_str(p, STR_P511, strlen(STR_P511), 16); + fp_prime_set_dense(p); break; case PRIME_511187: bn_set_2b(p, 511); @@ -557,6 +568,36 @@ void fp_param_set(int param) { bn_neg(t0, t0); 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; +#elif FP_PRIME == 766 + case K16_766: + /* u = 2^78-2^76-2^28+2^14+2^7+1 */ + bn_set_2b(t0, 78); + bn_set_2b(t1, 76); + bn_sub(t0, t0, t1); + bn_set_2b(t1, 28); + bn_sub(t0, t0, t1); + bn_set_2b(t1, 14); + bn_add(t0, t0, t1); + bn_add_dig(t0, t0, 128); + bn_add_dig(t0, t0, 1); + fp_prime_set_pairf(t0, EP_K16); + break; +#elif FP_PRIME == 1024 + case CTIDH_1024: + bn_read_str(p, STR_P1024, strlen(STR_P1024), 16); + fp_prime_set_dense(p); + break; #elif FP_PRIME == 1536 case SS_1536: /* x = 2^255 + 2^41 + 1. */ @@ -570,18 +611,30 @@ void fp_param_set(int param) { fp_prime_set_dense(p); fp_prime_set_pairf(t0, EP_SS2); break; +#elif FP_PRIME == 2048 + case CTIDH_2048: + bn_read_str(p, STR_P2048, strlen(STR_P2048), 16); + fp_prime_set_dense(p); + break; #elif FP_PRIME == 3072 - case SS_3072: + case K1_3072: /* x = 2^256 + 2^96 - 1. */ bn_set_2b(t0, 256); - bn_set_bit(t0, 96, 1); + bn_set_2b(p, 96); + bn_add(t0, t0, p); bn_sub_dig(t0, t0, 1); bn_read_str(p, STR_P3072, strlen(STR_P3072), 16); + bn_lsh(p, p, 768); bn_mul(p, p, t0); bn_sqr(p, p); bn_add_dig(p, p, 1); fp_prime_set_dense(p); - fp_prime_set_pairf(t0, EP_SS1); + fp_prime_set_pairf(t0, EP_K1); + break; +#elif FP_PRIME == 4096 + case SQALE_4096: + bn_read_str(p, STR_P4096, strlen(STR_P4096), 16); + fp_prime_set_dense(p); break; #else default: @@ -630,7 +683,7 @@ int fp_param_set_any_dense(void) { #ifdef FP_QNRES do { bn_gen_prime(p, RLC_FP_BITS); - } while ((p->dp[0] & 0x7) != 3); + } while ((p->dp[0] % 8) != 3); #else bn_gen_prime(p, RLC_FP_BITS); #endif @@ -650,7 +703,9 @@ int fp_param_set_any_dense(void) { } int fp_param_set_any_pmers(void) { -#if FP_PRIME == 160 +#if FP_PRIME == 127 + fp_param_set(MP_127); +#elif FP_PRIME == 160 fp_param_set(SECG_160); #elif FP_PRIME == 192 fp_param_set(NIST_192); @@ -692,6 +747,8 @@ int fp_param_set_any_tower(void) { fp_param_set(B24_315); #elif FP_PRIME == 317 fp_param_set(B24_317); +#elif FP_PRIME == 330 + fp_param_set(K16_330); #elif FP_PRIME == 377 fp_param_set(B12_377); #elif FP_PRIME == 381 @@ -709,11 +766,11 @@ int fp_param_set_any_tower(void) { #elif FP_PRIME == 455 fp_param_set(B12_455); #elif FP_PRIME == 508 - fp_param_set(KSS_508); + fp_param_set(K18_508); #elif FP_PRIME == 509 fp_param_set(B24_509); #elif FP_PRIME == 511 - fp_param_set(OT_511); + fp_param_set(CTIDH_511); #elif FP_PRIME == 544 fp_param_set(GMT8_544); #elif FP_PRIME == 569 @@ -728,13 +785,22 @@ int fp_param_set_any_tower(void) { fp_param_set(K18_638); //fp_param_set(SG18_638); #endif +#elif FP_PRIME == 765 + fp_param_set(N16_765); +#elif FP_PRIME == 766 + fp_param_set(K16_766); #elif FP_PRIME == 1536 fp_param_set(SS_1536); +#elif FP_PRIME == 3072 + fp_param_set(K1_3072); +#elif FP_PRIME == 4096 + fp_param_set(SQALE_4096); #else do { /* Since we have to generate a prime number, pick a nice towering. */ fp_param_set_any_dense(); - } while (fp_prime_get_mod8() == 1 || fp_prime_get_mod8() == 5); + } while (fp_prime_get_mod8() == 1 || fp_prime_get_mod8() == 5 + || fp_prime_get_mod18() % 3 == 2); #endif return RLC_OK; @@ -743,9 +809,5 @@ int fp_param_set_any_tower(void) { void fp_param_print(void) { util_banner("Prime modulus:", 0); util_print(" "); -#if ALLOC == AUTO - fp_print(fp_prime_get()); -#else - fp_print((const fp_t)fp_prime_get()); -#endif + bn_print(&(core_get()->prime)); } diff --git a/src/fp/relic_fp_prime.c b/src/fp/relic_fp_prime.c index 44335f3bd..c18319e98 100644 --- a/src/fp/relic_fp_prime.c +++ b/src/fp/relic_fp_prime.c @@ -48,6 +48,7 @@ static void fp_prime_set(const bn_t p) { bn_t t; fp_t r; ctx_t *ctx = core_get(); + dig_t rem; if (p->used != RLC_FP_DIGS) { RLC_THROW(ERR_NO_VALID); @@ -101,7 +102,7 @@ static void fp_prime_set(const bn_t p) { #if FP_RDC == MONTY -#if (FP_PRIME % WSIZE) != 0 +#ifdef RLC_FP_ROOM fp_mul(ctx->inv.dp, ctx->inv.dp, ctx->conv.dp); fp_mul(ctx->inv.dp, ctx->inv.dp, ctx->conv.dp); @@ -129,40 +130,60 @@ static void fp_prime_set(const bn_t p) { break; case 7: ctx->qnr = -1; + /* Try this one, pick another later if not a CNR. */ ctx->cnr = -2; - /* TODO: implement cube root to handle this better. */ -#if FP_PRIME == 638 - ctx->cnr = -3; -#endif break; case 1: case 5: ctx->qnr = -2; ctx->cnr = 2; - /* TODO: implement cube root to handle this better. */ #if FP_PRIME == 638 - ctx->qnr = -6; - ctx->cnr = 3; + if (fp_param_get() == K18_638) { + ctx->qnr = -6; + } else { + ctx->qnr = -7; + } #endif + break; + } - /* Check if it is a quadratic non-residue or find another. */ - fp_set_dig(r, -ctx->qnr); + /* Check if qnr is a quadratic non-residue or find another. */ + fp_set_dig(r, -ctx->qnr); + fp_neg(r, r); + while (fp_is_sqr(r)) { + ctx->qnr--; + fp_set_dig(r, -ctx->qnr); + fp_neg(r, r); + }; + + /* Check if cnr is a cubic non-residue or find another. */ + if (ctx->mod18 % 3 == 1) { + if (ctx->cnr > 0) { + fp_set_dig(r, ctx->cnr); + while (fp_is_cub(r)) { + ctx->cnr++; + fp_set_dig(r, ctx->cnr); + }; + } else { + fp_set_dig(r, -ctx->cnr); fp_neg(r, r); - while (fp_srt(r, r) == 1) { - ctx->qnr--; - fp_set_dig(r, -ctx->qnr); + while (fp_is_cub(r)) { + ctx->cnr--; + fp_set_dig(r, -ctx->cnr); fp_neg(r, r); - /* We cannot guarantee a cubic extension anymore. */ - ctx->cnr = 0; }; - break; + } + } else { + ctx->cnr = 0; } + #ifdef FP_QNRES if (ctx->mod8 != 3) { RLC_THROW(ERR_NO_VALID); } #endif + /* Compute root of unity by computing QNR to (p - 1)/2^f. */ ctx->ad2 = 0; bn_sub_dig(t, p, 1); while (bn_is_even(t)) { @@ -170,6 +191,30 @@ static void fp_prime_set(const bn_t p) { bn_hlv(t, t); } + ctx->srt.used = RLC_FP_DIGS; + if (ctx->qnr < 0) { + fp_set_dig(ctx->srt.dp, -ctx->qnr); + } else { + fp_set_dig(ctx->srt.dp, ctx->qnr); + } + fp_exp(ctx->srt.dp, ctx->srt.dp, t); + + /* Write p - 1 as (e * 3^f), with e = 3l \pm 1. */ + bn_sub_dig(t, p, 1); + bn_mod_dig(&rem, t, 3); + while (rem == 0) { + bn_div_dig(t, t, 3); + bn_mod_dig(&rem, t, 3); + } + + /* Compute root of unity by computing CNR to (p - 1)/3^f. */ + if (ctx->cnr < 0) { + fp_set_dig(ctx->crt.dp, -fp_prime_get_cnr()); + } else { + fp_set_dig(ctx->crt.dp, fp_prime_get_cnr()); + } + fp_exp(ctx->crt.dp, ctx->crt.dp, t); + fp_prime_calc(); } RLC_CATCH_ANY { @@ -201,6 +246,8 @@ void fp_prime_init(void) { #if FP_INV == JUMPDS || !defined(STRIP) bn_make(&(ctx->inv), RLC_FP_DIGS); #endif /* FP_INV */ + bn_make(&(ctx->srt), RLC_FP_DIGS); + bn_make(&(ctx->crt), RLC_FP_DIGS); } void fp_prime_clean(void) { @@ -218,6 +265,8 @@ void fp_prime_clean(void) { #if FP_INV == JUMPDS || !defined(STRIP) bn_clean(&(ctx->inv)); #endif /* FP_INV */ + bn_clean(&(ctx->srt)); + bn_clean(&(ctx->crt)); bn_clean(&(ctx->prime)); bn_clean(&(ctx->par)); } @@ -276,6 +325,14 @@ const dig_t *fp_prime_get_conv(void) { #endif } +const dig_t *fp_prime_get_srt(void) { + return core_get()->srt.dp; +} + +const dig_t *fp_prime_get_crt(void) { + return core_get()->crt.dp; +} + dig_t fp_prime_get_mod8(void) { return core_get()->mod8; } @@ -354,29 +411,69 @@ void fp_prime_set_pairf(const bn_t x, int pairf) { bn_add(p, p, t0); fp_prime_set_dense(p); break; - case EP_OT8: - /* p = (x^8 + x^6 + 5*x^4 + x^2 + 4*x + 4) / 4. */ - bn_set_dig(p, 4); - bn_mul_dig(t1, t0, 4); - bn_add(p, p, t1); - bn_sqr(t0, t0); - bn_add(p, p, t0); - bn_sqr(t1, t0); - bn_add(p, p, t1); - bn_add(p, p, t1); - bn_add(p, p, t1); - bn_add(p, p, t1); - bn_add(p, p, t1); - bn_mul(t1, t1, t0); - bn_add(p, p, t1); - bn_mul(t1, t1, t0); - bn_add(p, p, t1); + case EP_N16: + /* p = (x^16 + 2*x^13 + x^10 + 5*x^8 + 6*x^5 + x^2 + 4)/4 */ + bn_sqr(p, t0); + bn_mul(p, p, t0); + bn_add_dig(p, p, 2); + bn_mul(p, p, t0); + bn_mul(p, p, t0); + bn_mul(p, p, t0); + bn_add_dig(p, p, 1); + bn_mul(p, p, t0); + bn_mul(p, p, t0); + bn_add_dig(p, p, 5); + bn_mul(p, p, t0); + bn_mul(p, p, t0); + bn_mul(p, p, t0); + bn_add_dig(p, p, 6); + bn_mul(p, p, t0); + bn_mul(p, p, t0); + bn_mul(p, p, t0); + bn_add_dig(p, p, 1); + bn_mul(p, p, t0); + bn_mul(p, p, t0); + bn_add_dig(p, p, 4); bn_div_dig(p, p, 4); fp_prime_set_dense(p); break; + case EP_K16: + /* p = (u^10 + 2*u^9 + 5*u^8 + 48*u^6 + 152*u^5 + 240*u^4 + + 625*u^2 + 2398*u + 3125) div 980 */ + bn_add_dig(p, t0, 2); + bn_mul(p, p, t0); + bn_add_dig(p, p, 5); + bn_mul(p, p, t0); + bn_mul(p, p, t0); + bn_add_dig(p, p, 48); + bn_mul(p, p, t0); + bn_add_dig(p, p, 152); + bn_mul(p, p, t0); + bn_add_dig(p, p, 240); + bn_mul(p, p, t0); + bn_mul(p, p, t0); + bn_add_dig(p, p, 256); + bn_add_dig(p, p, 256); + bn_add_dig(p, p, 113); + bn_mul(p, p, t0); + bn_set_dig(t1, 9); + bn_lsh(t1, t1, 8); + bn_add_dig(t1, t1, 94); + bn_add(p, p, t1); + bn_mul(p, p, t0); + bn_set_dig(t0, 12); + bn_lsh(t0, t0, 8); + bn_add_dig(t0, t0, 53); + bn_add(p, p, t0); + bn_set_dig(t1, 3); + bn_lsh(t1, t1, 8); + bn_add_dig(t1, t1, 212); + bn_div(p, p, t1); + fp_prime_set_dense(p); + break; case EP_K18: - /* (x^8 + 5x^7 + 7x^6 + 37x^5 + 188x^4 + 259x^3 + 343x^2 + - 1763x + 2401)/21 */ + /* p = (x^8 + 5x^7 + 7x^6 + 37x^5 + 188x^4 + 259x^3 + 343x^2 + + 1763x + 2401)/21 */ bn_add_dig(p, t0, 5); bn_mul(p, p, t0); bn_add_dig(p, p, 7); @@ -404,8 +501,8 @@ void fp_prime_set_pairf(const bn_t x, int pairf) { fp_prime_set_dense(p); break; case EP_SG18: - /* 243x^10 - 162x^8 + 81*x^7 + 27x^6 - 54x^5 + 9x^4 + 9x^3 - - 3x^2 + 1 */ + /* p = 243x^10 - 162x^8 + 81*x^7 + 27x^6 - 54x^5 + 9x^4 + 9x^3 - + 3x^2 + 1 */ bn_sqr(p, t0); bn_mul_dig(p, p, 243); bn_sub_dig(p, p, 162); @@ -456,7 +553,8 @@ void fp_prime_set_pairf(const bn_t x, int pairf) { fp_prime_set_dense(p); break; case EP_SG54: - /* p = (1+3*x+3*x^2+(3^5)*x^9+(3^5)*x^10+(3^6)*x^10+(3^6)*x^11+(3^9)*x^18+(3^10)*x^19+(3^10)*x^20) */ + /* p = (1+3*x+3*x^2+(3^5)*x^9+(3^5)*x^10+(3^6)*x^10+(3^6)*x^11+ + (3^9)*x^18+(3^10)*x^19+(3^10)*x^20) */ bn_set_dig(p, 1); bn_mul_dig(t1, t0, 3); bn_add(p, p, t1); @@ -577,6 +675,7 @@ void fp_prime_calc(void) { if (fp_prime_get_qnr() != 0) { fp2_field_init(); fp4_field_init(); + fp8_field_init(); } if (fp_prime_get_cnr() != 0) { fp3_field_init(); diff --git a/src/fp/relic_fp_smb.c b/src/fp/relic_fp_smb.c index ee42147a5..54a4c42ad 100644 --- a/src/fp/relic_fp_smb.c +++ b/src/fp/relic_fp_smb.c @@ -33,6 +33,98 @@ #include "relic_bn_low.h" #include "relic_fp_low.h" +/*============================================================================*/ +/* Private definitions */ +/*============================================================================*/ + +#if FP_SMB == JMPDS || !defined(STRIP) + +/** + * Conditionally negate a digit vector using two's complement representation. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to conditionally negate. + * @param[in] sa - the sign of the digit vector. + * @param[in] n - the number of digits to conditionally negate. + */ +static void bn_negs_low(dig_t c[], const dig_t a[], dig_t sa, size_t n) { + dig_t carry = sa & 1; + + sa = -sa; + for (int i = 0; i < n; i++) { + c[i] = (a[i] ^ sa) + carry; + carry = (c[i] < carry); + } +} + +static dis_t jumpdivstep(dis_t m[4], dig_t *k, dis_t delta, dis_t y, dis_t x, + int s) { + dig_t d0, t0, t1, t2, c0, c1, yi, ai = 1, bi = 0, ci = 0, di = 1, u = 0; + + /* Unrolling twice makes it faster. */ + for (s -= 2; s >= 0; s -= 2) { + yi = y; + + d0 = (delta >= 0); + c1 = -(x & 1); + c0 = (-d0) & c1; + + t0 = (y ^ -d0) + d0; + t1 = (ci ^ -d0) + d0; + t2 = (di ^ -d0) + d0; + x += t0 & c1; + ai += t1 & c1; + bi += t2 & c1; + + /* delta = RLC_SEL(delta + 1, -delta, c0) */ + y += x & c0; + ci += ai & c0; + di += bi & c0; + + x >>= 1; + ci <<= 1; + di <<= 1; + delta = (delta ^ c0) + 1; + + u += ((yi & y) ^ (y >> 1)) & 2; + u += (u & 1) ^ RLC_SIGN(ci); + + yi = y; + + d0 = (delta >= 0); + c1 = -(x & 1); + c0 = (-d0) & c1; + + t0 = (y ^ -d0) + d0; + t1 = (ci ^ -d0) + d0; + t2 = (di ^ -d0) + d0; + x += t0 & c1; + ai += t1 & c1; + bi += t2 & c1; + + /* delta = RLC_SEL(delta + 1, -delta, c0) */ + y += x & c0; + ci += ai & c0; + di += bi & c0; + + x >>= 1; + ci <<= 1; + di <<= 1; + delta = (delta ^ c0) + 1; + + u += ((yi & y) ^ (y >> 1)) & 2; + u += (u & 1) ^ RLC_SIGN(ci); + } + m[0] = ai; + m[1] = bi; + m[2] = ci; + m[3] = di; + *k = u; + return delta; +} + +#endif + /*============================================================================*/ /* Public definitions */ /*============================================================================*/ @@ -76,13 +168,14 @@ int fp_smb_basic(const fp_t a) { int fp_smb_divst(const fp_t a) { /* Compute number of iterations based on modulus size. */ #if FP_PRIME < 46 - int r, d = (49 * FP_PRIME + 80)/17; + const int d = (49 * FP_PRIME + 80) / 17; #else - int r, d = (49 * FP_PRIME + 57)/17; + const int d = (49 * FP_PRIME + 57) / 17; #endif dig_t delta = 1, g0, d0, fs, gs, k, mask, s; bn_t _t; dv_t f, g, t; + int r = 0; bn_null(_t); dv_null(f); @@ -114,8 +207,6 @@ int fp_smb_divst(const fp_t a) { d0 = g[0] & ((int)delta > 0); /* Conditionally negate delta if d0 is set. */ delta = (delta ^ -d0) + d0; - k ^= (((g[0] >> (dig_t)1) & ((f[0] >> (dig_t)1) ^ 1)) ^ (~fs & gs)) & d0; - /* Conditionally swap and negate based on d0. */ mask = -d0; s = (fs ^ gs) & mask; @@ -128,6 +219,7 @@ int fp_smb_divst(const fp_t a) { } fp_add1_low(g, g, d0); + k ^= (((g[0] & f[0]) >> (dig_t)1) ^ (fs & gs)) & d0; k ^= (f[0] >> 1) ^ (f[0] >> 2); k &= 1; @@ -145,16 +237,18 @@ int fp_smb_divst(const fp_t a) { g[RLC_FP_DIGS - 1] |= (dig_t)gs << (RLC_DIG - 1); } + k = (2*k) % 4; + fp_zero(t); + t[0] = 1; for (int j = 0; j < RLC_FP_DIGS; j++) { - t[j] = 0; f[j] ^= -fs; } - t[0] = 1; fp_add1_low(f, f, fs); - r = !(dv_cmp_const(f, t, RLC_FP_DIGS) == RLC_NE); - r = RLC_SEL(r, -1, (r == 1 && k == 1)); - r = RLC_SEL(r, 1, (r == 1 && k == 0)); + r = RLC_SEL(r, 1 - k, dv_cmp_const(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, fp_is_zero(f)); } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT) } RLC_FINALLY { @@ -170,146 +264,101 @@ int fp_smb_divst(const fp_t a) { #if FP_SMB == JMPDS || !defined(STRIP) -static dis_t jumpdivstep(dis_t m[4], dig_t *k, dis_t delta, dis_t x, dis_t y, int s) { - dig_t c0, c1, yi, ai = 1, bi = 0, ci = 0, di = 1, u = 0; - for (; s > 0; s--) { - yi = y; - - c0 = ~(delta >> (RLC_DIG - 1)); - c1 = -(x & 1); - c0 &= c1; - - x += ((y ^ c0) - c0) & c1; - ai += ((ci ^ c0) - c0) & c1; - bi += ((di ^ c0) - c0) & c1; - - /* delta = RLC_SEL(delta + 1, -delta, c0) */ - delta = (delta ^ c0) + 1; - y = y + (x & c0); - ci = ci + (ai & c0); - di = di + (bi & c0); - x >>= 1; - ci += ci; - di += di; - - u += ((yi & y) ^ (y >> (dig_t)1)) & 2; - u += (u & (dig_t)1) ^ (ci >> (dig_t)(RLC_DIG - 1)); - u %= 4; - } - m[0] = ai; - m[1] = bi; - m[2] = ci; - m[3] = di; - *k = u; - return delta; -} - int fp_smb_jmpds(const fp_t a) { dis_t m[4], d = 0; - int r, i, s = RLC_DIG - 2; /* Iterations taken directly from https://github.com/sipa/safegcd-bounds */ - int loops, iterations = (45907 * FP_PRIME + 26313) / 19929; - dv_t f, g, t, p, t0, t1, u0, u1, v0, v1, p01, p11; - dig_t j, k, mask = RLC_MASK(s + 2); + const int iterations = (45907 * FP_PRIME + 26313) / 19929; + int loops, precision, i, r = 0, s = RLC_DIG - 2; + dv_t f, g, t0, t1, u0, u1; + dig_t sf, sg, j, k; dv_null(f); dv_null(g); - dv_null(t); - dv_null(p); dv_null(t0); dv_null(t1); dv_null(u0); dv_null(u1); - dv_null(v0); - dv_null(v1); - dv_null(p01); - dv_null(p11); RLC_TRY { - dv_new(t0); dv_new(f); - dv_new(t); - dv_new(p); dv_new(g); + dv_new(t0); dv_new(t1); dv_new(u0); dv_new(u1); - dv_new(v0); - dv_new(v1); - dv_new(p01); - dv_new(p11); - - f[RLC_FP_DIGS] = g[RLC_FP_DIGS] = 0; - dv_zero(f, 2 * RLC_FP_DIGS); - dv_zero(g, 2 * RLC_FP_DIGS); - dv_zero(t, 2 * RLC_FP_DIGS); - dv_zero(p, 2 * RLC_FP_DIGS); - dv_zero(u0, 2 * RLC_FP_DIGS); - dv_zero(u1, 2 * RLC_FP_DIGS); - dv_zero(v0, 2 * RLC_FP_DIGS); - dv_zero(v1, 2 * RLC_FP_DIGS); - - dv_copy(g, fp_prime_get(), RLC_FP_DIGS); + + dv_copy(f, fp_prime_get(), RLC_FP_DIGS); + f[RLC_FP_DIGS] = 0; + dv_zero(g, RLC_FP_DIGS + 1); + dv_zero(t0 + RLC_FP_DIGS, RLC_FP_DIGS); + #if FP_RDC == MONTY /* Convert a from Montgomery form. */ - fp_copy(t, a); - fp_rdcn_low(f, t); + fp_copy(t0, a); + fp_rdcn_low(g, t0); #else - fp_copy(f, a); + fp_copy(g, a); #endif - + precision = RLC_FP_DIGS; loops = iterations / s; loops = (iterations % s == 0 ? loops - 1 : loops); - j = k = 0; - for (i = 0; i <= loops; i++) { - d = jumpdivstep(m, &k, d, f[0] & mask, g[0] & mask, s); - - t0[RLC_FP_DIGS] = bn_muls_low(t0, f, f[RLC_FP_DIGS] >> (RLC_DIG - 1), m[0], RLC_FP_DIGS); - t1[RLC_FP_DIGS] = bn_muls_low(t1, g, g[RLC_FP_DIGS] >> (RLC_DIG - 1), m[1], RLC_FP_DIGS); - bn_addn_low(t0, t0, t1, RLC_FP_DIGS + 1); + for (i = j = k = 0; i < loops; i++) { + d = jumpdivstep(m, &k, d, f[0], g[0], s); - f[RLC_FP_DIGS] = bn_muls_low(f, f, f[RLC_FP_DIGS] >> (RLC_DIG - 1), m[2], RLC_FP_DIGS); - t1[RLC_FP_DIGS] = bn_muls_low(t1, g, g[RLC_FP_DIGS] >> (RLC_DIG - 1), m[3], RLC_FP_DIGS); - bn_addn_low(t1, t1, f, RLC_FP_DIGS + 1); + sf = RLC_SIGN(f[precision]); + sg = RLC_SIGN(g[precision]); + bn_negs_low(u0, f, sf, precision); + bn_negs_low(u1, g, sg, precision); + + t0[precision] = bn_muls_low(t0, u0, sf, m[3], precision); + t1[precision] = bn_muls_low(t1, u1, sg, m[2], precision); + bn_addn_low(t0, t0, t1, precision + 1); + bn_rshs_low(f, t0, precision + 1, s); - /* Update f and g. */ - bn_rshs_low(f, t0, RLC_FP_DIGS + 1, s); - bn_rshs_low(g, t1, RLC_FP_DIGS + 1, s); + t0[precision] = bn_muls_low(t0, u0, sf, m[1], precision); + t1[precision] = bn_muls_low(t1, u1, sg, m[0], precision); + bn_addn_low(t1, t1, t0, precision + 1); + bn_rshs_low(g, t1, precision + 1, s); j = (j + k) % 4; - j = (j + ((j & 1) ^ (g[RLC_FP_DIGS] >> (RLC_DIG - 1)))) % 4; + j = (j + ((j & 1) ^ (RLC_SIGN(f[precision])))) % 4; } - r = 0; + s = iterations - loops * s; + d = jumpdivstep(m, &k, d, f[0], g[0], s); + + sf = RLC_SIGN(f[precision]); + sg = RLC_SIGN(g[precision]); + bn_negs_low(u0, f, sf, precision); + bn_negs_low(u1, g, sg, precision); + + t0[precision] = bn_muls_low(t0, u0, sf, m[3], precision); + t1[precision] = bn_muls_low(t1, u1, sg, m[2], precision); + bn_addn_low(t0, t0, t1, precision + 1); + bn_rshs_low(f, t0, precision + 1, s); + + j = (j + k) % 4; + j = (j + ((j & 1) ^ (RLC_SIGN(f[precision])))) % 4; j = (j + (j & 1)) % 4; fp_zero(t0); + r = RLC_SEL(r, 1 - j, dv_cmp_const(f, t0, RLC_FP_DIGS) == RLC_EQ); t0[0] = 1; - r = RLC_SEL(r, 1 - j, dv_cmp_const(g, t0, RLC_FP_DIGS) == RLC_EQ); - for (i = 0; i < RLC_FP_DIGS; i++) { - g[i] = ~g[i]; - } - bn_add1_low(g, g, 1, RLC_FP_DIGS); - r = RLC_SEL(r, 1 - j, dv_cmp_const(g, t0, RLC_FP_DIGS) == RLC_EQ); - r = RLC_SEL(r, 1 - j, fp_is_zero(g)); + r = RLC_SEL(r, 1 - j, dv_cmp_const(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); } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { - dv_free(t0); dv_free(f); - dv_free(t); - dv_free(p); dv_free(g); + dv_free(t0); dv_free(t1); dv_free(u0); dv_free(u1); - dv_free(v0); - dv_free(v1); - dv_free(p01); - dv_free(p11); } return r; diff --git a/src/fp/relic_fp_srt.c b/src/fp/relic_fp_srt.c index 31bd0a765..c5656be1c 100644 --- a/src/fp/relic_fp_srt.c +++ b/src/fp/relic_fp_srt.c @@ -35,15 +35,24 @@ /* Public definitions */ /*============================================================================*/ +int fp_is_sqr(const fp_t a) { + if (fp_is_zero(a)) { + return 1; + } + + return (fp_smb(a) == 1); +} + int fp_srt(fp_t c, const fp_t a) { bn_t e; - fp_t t0; - fp_t t1; - int r = 0; + fp_t t0, t1, t2, t3; + int f = 0, r = 0; bn_null(e); fp_null(t0); fp_null(t1); + fp_null(t2); + fp_null(t3); if (fp_is_zero(a)) { fp_zero(c); @@ -54,75 +63,64 @@ int fp_srt(fp_t c, const fp_t a) { bn_new(e); fp_new(t0); fp_new(t1); + fp_new(t2); + fp_new(t3); /* Make e = p. */ e->used = RLC_FP_DIGS; dv_copy(e->dp, fp_prime_get(), RLC_FP_DIGS); - if (fp_prime_get_mod8() == 3 || fp_prime_get_mod8() == 7) { - /* Easy case, compute a^((p + 1)/4). */ - bn_add_dig(e, e, 1); - bn_rsh(e, e, 2); - - fp_exp(t0, a, e); - fp_sqr(t1, t0); - r = (fp_cmp(t1, a) == RLC_EQ); - fp_copy(c, t0); - } else { - int f = 0, m = 0; - - /* First, check if there is a root. Compute t1 = a^((p - 1)/2). */ - bn_rsh(e, e, 1); - fp_exp(t0, a, e); - - if (fp_cmp_dig(t0, 1) != RLC_EQ) { - /* Nope, there is no square root. */ - r = 0; - } else { - r = 1; - /* Find a quadratic non-residue modulo p, that is a number t2 - * such that (t2 | p) = t2^((p - 1)/2)!= 1. */ - do { - fp_rand(t1); - fp_exp(t0, t1, e); - } while (fp_cmp_dig(t0, 1) == RLC_EQ); + switch(fp_prime_get_mod8() % 4) { + case 3: + /* Easy case, compute a^((p + 1)/4). */ + bn_add_dig(e, e, 1); + bn_rsh(e, e, 2); - /* Write p - 1 as (e * 2^f), odd e. */ - bn_lsh(e, e, 1); - while (bn_is_even(e)) { - bn_rsh(e, e, 1); - f++; - } + fp_exp(t0, a, e); + fp_sqr(t1, t0); + r = (fp_cmp(t1, a) == RLC_EQ); + fp_copy(c, t0); + break; + default: + /* Implement constant-time version of Tonelli-Shanks algorithm + * as per https://eprint.iacr.org/2020/1497.pdf */ - /* Compute t2 = t2^e. */ - fp_exp(t1, t1, e); + /* First check that a is a square. */ + r = fp_is_sqr(a); - /* Compute t1 = a^e, c = a^((e + 1)/2) = a^(e/2 + 1), odd e. */ + /* Compute progenitor as x^(p-1-2^f)/2^(f+1) where 2^f|(p-1). */ + + /* Write p - 1 as (e * 2^f), odd e. */ + f = fp_prime_get_2ad(); + bn_rsh(e, e, f); + + /* Make it e = (p - 1 - 2^f)/2^(f + 1), compute t0 = a^e. */ bn_rsh(e, e, 1); fp_exp(t0, a, e); - fp_mul(e->dp, t0, a); - fp_sqr(t0, t0); - fp_mul(t0, t0, a); - fp_copy(c, e->dp); - - while (1) { - if (fp_cmp_dig(t0, 1) == RLC_EQ) { - break; - } - fp_copy(e->dp, t0); - for (m = 0; (m < f) && (fp_cmp_dig(t0, 1) != RLC_EQ); m++) { - fp_sqr(t0, t0); - } - fp_copy(t0, e->dp); - for (int i = 0; i < f - m - 1; i++) { - fp_sqr(t1, t1); + + /* Recover 2^f-root of unity, and continue algorithm. */ + fp_copy(t3, fp_prime_get_srt()); + + fp_sqr(t1, t0); + fp_mul(t1, t1, a); + fp_mul(c, t0, a); + for (int j = f; j > 1; j--) { + fp_copy(t2, t1); + for (int i = 1; i < j - 1; i++) { + fp_sqr(t2, t2); } - fp_mul(c, c, t1); - fp_sqr(t1, t1); - fp_mul(t0, t0, t1); - f = m; + fp_mul(t0, c, t3); + dv_copy_cond(c, t0, RLC_FP_DIGS, + 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_neg(t0, c); + dv_copy_cond(c, t0, RLC_FP_DIGS, fp_is_even(c) == 0); + break; } } RLC_CATCH_ANY { @@ -132,6 +130,8 @@ int fp_srt(fp_t c, const fp_t a) { bn_free(e); fp_free(t0); fp_free(t1); + fp_free(t2); + fp_free(t3); } return r; } diff --git a/src/fp/relic_fp_util.c b/src/fp/relic_fp_util.c index 4626b528e..86304f2fe 100644 --- a/src/fp/relic_fp_util.c +++ b/src/fp/relic_fp_util.c @@ -60,10 +60,24 @@ int fp_is_zero(const fp_t a) { } int fp_is_even(const fp_t a) { - if ((a[0] & 0x01) == 0) { - return 1; + int r; + bn_t t; + + bn_null(t); + + RLC_TRY { + bn_new(t); + + fp_prime_back(t, a); + r = bn_is_even(t); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); } - return 0; + RLC_FINALLY { + bn_free(t); + } + + return r; } int fp_get_bit(const fp_t a, uint_t bit) { diff --git a/src/fpx/relic_fp16_mul.c b/src/fpx/relic_fp16_mul.c new file mode 100644 index 000000000..d2ce1447a --- /dev/null +++ b/src/fpx/relic_fp16_mul.c @@ -0,0 +1,321 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 4.1 (or later) of the GNU Lesser General Public License + * as published by the Free Software Foundation; or version 4.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 + * + * Implementation of multiplication in an sextadecic extension of a prime field. + * + * @ingroup fpx + */ + +#include "relic_core.h" +#include "relic_fp_low.h" +#include "relic_fpx_low.h" + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +#if FPX_RDC == BASIC || !defined(STRIP) + +void fp16_mul_basic(fp16_t c, const fp16_t a, const fp16_t b) { + fp8_t t0, t1, t4; + + fp8_null(t0); + fp8_null(t1); + fp8_null(t4); + + RLC_TRY { + fp8_new(t0); + fp8_new(t1); + fp8_new(t4); + + /* Karatsuba algorithm. */ + + /* t0 = a_0 * b_0. */ + fp8_mul(t0, a[0], b[0]); + /* t1 = a_1 * b_1. */ + fp8_mul(t1, a[1], b[1]); + /* t4 = b_0 + b_1. */ + fp8_add(t4, b[0], b[1]); + + /* c_1 = a_0 + a_1. */ + fp8_add(c[1], a[0], a[1]); + + /* c_1 = (a_0 + a_1) * (b_0 + b_1) */ + fp8_mul(c[1], c[1], t4); + fp8_sub(c[1], c[1], t0); + fp8_sub(c[1], c[1], t1); + + /* c_0 = a_0b_0 + v * a_1b_1. */ + fp8_mul_art(t4, t1); + fp8_add(c[0], t0, t4); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp8_free(t0); + fp8_free(t1); + fp8_free(t4); + } +} + +void fp16_mul_dxs_basic(fp16_t c, const fp16_t a, const fp16_t b) { + fp8_t t0, t1, t4; + + fp8_null(t0); + fp8_null(t1); + fp8_null(t4); + + RLC_TRY { + fp8_new(t0); + fp8_new(t1); + fp8_new(t4); + + /* Karatsuba algorithm. */ + + /* t0 = a_0 * b_0. */ + fp8_mul(t0, a[0], b[0]); + + /* t1 = a_1 * b_1. */ + fp4_mul(t1[0], a[1][1], b[1][1]); + fp4_add(t1[1], a[1][0], a[1][1]); + fp4_mul(t1[1], t1[1], b[1][1]); + fp4_sub(t1[1], t1[1], t1[0]); + fp4_mul_art(t1[0], t1[0]); + + /* t4 = b_0 + b_1. */ + fp8_add(t4, b[0], b[1]); + + /* c_1 = a_0 + a_1. */ + fp8_add(c[1], a[0], a[1]); + + /* c_1 = (a_0 + a_1) * (b_0 + b_1) */ + fp8_mul(c[1], c[1], t4); + fp8_sub(c[1], c[1], t0); + fp8_sub(c[1], c[1], t1); + + /* c_0 = a_0b_0 + v * a_1b_1. */ + fp8_mul_art(t4, t1); + fp8_add(c[0], t0, t4); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp8_free(t0); + fp8_free(t1); + fp8_free(t4); + } +} + +#endif + +#if PP_EXT == LAZYR || !defined(STRIP) + +void fp16_mul_unr(dv16_t c, const fp16_t a, const fp16_t b) { + fp8_t t0, t1; + dv8_t u0, u1, u2, u3; + + fp8_null(t0); + fp8_null(t1); + dv8_null(u0); + dv8_null(u1); + dv8_null(u2); + dv8_null(u3); + + RLC_TRY { + fp8_new(t0); + fp8_new(t1); + dv8_new(u0); + dv8_new(u1); + dv8_new(u2); + dv8_new(u3); + + /* Karatsuba algorithm. */ + + /* u0 = a_0 * b_0. */ + fp8_mul_unr(u0, a[0], b[0]); + /* u1 = a_1 * b_1. */ + fp8_mul_unr(u1, a[1], b[1]); + /* t1 = a_0 + a_1. */ + fp8_add(t0, a[0], a[1]); + /* t0 = b_0 + b_1. */ + fp8_add(t1, b[0], b[1]); + /* u2 = (a_0 + a_1) * (b_0 + b_1) */ + fp8_mul_unr(u2, t0, t1); + /* c_1 = u2 - a_0b_0 - a_1b_1. */ + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + fp2_subc_low(c[1][i][j], u2[i][j], u0[i][j]); + fp2_subc_low(c[1][i][j], c[1][i][j], u1[i][j]); + } + } + /* c_0 = a_0b_0 + v * a_1b_1. */ + fp2_nord_low(u2[0][0], u1[1][1]); + dv_copy(u2[0][1][0], u1[1][0][0], 2 * RLC_FP_DIGS); + dv_copy(u2[0][1][1], u1[1][0][1], 2 * RLC_FP_DIGS); + dv_copy(u2[1][0][0], u1[0][0][0], 2 * RLC_FP_DIGS); + dv_copy(u2[1][0][1], u1[0][0][1], 2 * RLC_FP_DIGS); + dv_copy(u2[1][1][0], u1[0][1][0], 2 * RLC_FP_DIGS); + dv_copy(u2[1][1][1], u1[0][1][1], 2 * RLC_FP_DIGS); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + fp2_addc_low(c[0][i][j], u0[i][j], u2[i][j]); + } + } + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp8_free(t0); + fp8_free(t1); + dv8_free(u0); + dv8_free(u1); + dv8_free(u2); + dv8_free(u3); + } +} + +void fp16_mul_lazyr(fp16_t c, const fp16_t a, const fp16_t b) { + dv16_t t; + + dv16_null(t); + + RLC_TRY { + dv16_new(t); + fp16_mul_unr(t, a, b); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 2; k++) { + fp2_rdcn_low(c[i][j][k], t[i][j][k]); + } + } + } + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + dv16_free(t); + } +} + +void fp16_mul_dxs_lazyr(fp16_t c, const fp16_t a, const fp16_t b) { + fp8_t t0, t1; + dv8_t u0, u1, u2, u3; + dv16_t t; + + fp8_null(t0); + fp8_null(t1); + dv8_null(u0); + dv8_null(u1); + dv8_null(u2); + dv8_null(u3); + dv16_null(t); + + RLC_TRY { + fp8_new(t0); + fp8_new(t1); + dv8_new(u0); + dv8_new(u1); + dv8_new(u2); + dv8_new(u3); + dv16_new(t); + + /* Karatsuba algorithm. */ + + /* u0 = a_0 * b_0. */ + fp8_mul_unr(u0, a[0], b[0]); + + /* u1 = a_1 * b_1. */ + fp4_mul_unr(u1[0], a[1][1], b[1][1]); + fp4_add(t1[0], a[1][0], a[1][1]); + fp4_mul_unr(u1[1], t1[0], b[1][1]); + fp2_subc_low(u2[1][0], u1[1][0], u1[0][0]); + fp2_subc_low(u2[1][1], u1[1][1], u1[0][1]); + fp2_nord_low(u2[0][0], u1[0][1]); + dv_copy(u2[0][1][0], u1[0][0][0], 2 * RLC_FP_DIGS); + dv_copy(u2[0][1][1], u1[0][0][1], 2 * RLC_FP_DIGS); + + /* t1 = a_0 + a_1. */ + fp8_add(t0, a[0], a[1]); + /* t0 = b_0 + b_1. */ + fp8_add(t1, b[0], b[1]); + /* u2 = (a_0 + a_1) * (b_0 + b_1) */ + fp8_mul_unr(u1, t0, t1); + /* c_1 = u2 - a_0b_0 - a_1b_1. */ + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + fp2_subc_low(t[1][i][j], u1[i][j], u0[i][j]); + fp2_subc_low(t[1][i][j], t[1][i][j], u2[i][j]); + } + } + /* c_0 = a_0b_0 + v * a_1b_1. */ + fp2_nord_low(u1[0][0], u2[1][1]); + dv_copy(u1[0][1][0], u2[1][0][0], 2 * RLC_FP_DIGS); + dv_copy(u1[0][1][1], u2[1][0][1], 2 * RLC_FP_DIGS); + dv_copy(u1[1][0][0], u2[0][0][0], 2 * RLC_FP_DIGS); + dv_copy(u1[1][0][1], u2[0][0][1], 2 * RLC_FP_DIGS); + dv_copy(u1[1][1][0], u2[0][1][0], 2 * RLC_FP_DIGS); + dv_copy(u1[1][1][1], u2[0][1][1], 2 * RLC_FP_DIGS); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + fp2_addc_low(t[0][i][j], u0[i][j], u1[i][j]); + } + } + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 2; k++) { + fp2_rdcn_low(c[i][j][k], t[i][j][k]); + } + } + } + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp8_free(t0); + fp8_free(t1); + dv8_free(u0); + dv8_free(u1); + dv8_free(u2); + dv8_free(u3); + dv16_free(t); + } +} + +#endif + +void fp16_mul_art(fp16_t c, const fp16_t a) { + fp8_t t0; + + fp8_null(t0); + + RLC_TRY { + fp8_new(t0); + + /* (a_0 + a_1 * v) * v = a_0 * v + a_1 * v^4 */ + fp8_copy(t0, a[0]); + fp8_mul_art(c[0], a[1]); + fp8_copy(c[1], t0); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp8_free(t0); + } +} \ No newline at end of file diff --git a/src/fpx/relic_fp16_sqr.c b/src/fpx/relic_fp16_sqr.c new file mode 100644 index 000000000..8e6f180b3 --- /dev/null +++ b/src/fpx/relic_fp16_sqr.c @@ -0,0 +1,181 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 + * + * Implementation of squaring in an sextadecic extension of a prime field. + * + * @ingroup fpx + */ + +#include "relic_core.h" +#include "relic_fp_low.h" +#include "relic_fpx_low.h" + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +#if FPX_RDC == BASIC || !defined(STRIP) + +void fp16_sqr_basic(fp16_t c, const fp16_t a) { + fp8_t t0, t1; + + fp8_null(t0); + fp8_null(t1); + + RLC_TRY { + fp8_new(t0); + fp8_new(t1); + + fp8_add(t0, a[0], a[1]); + fp8_mul_art(t1, a[1]); + fp8_add(t1, a[0], t1); + fp8_mul(t0, t0, t1); + fp8_mul(c[1], a[0], a[1]); + fp8_sub(c[0], t0, c[1]); + fp8_mul_art(t1, c[1]); + fp8_sub(c[0], c[0], t1); + fp8_dbl(c[1], c[1]); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp8_free(t0); + fp8_free(t1); + } +} + +#endif + +#if PP_EXT == LAZYR || !defined(STRIP) + +void fp16_sqr_unr(dv16_t c, const fp16_t a) { + fp8_t t; + dv8_t u0, u1, u2; + + fp8_null(t); + dv8_null(u0); + dv8_null(u1); + dv8_null(u2); + + RLC_TRY { + fp8_new(t); + dv8_new(u0); + dv8_new(u1); + dv8_new(u2); + + /* t0 = a^2. */ + fp8_sqr_unr(u0, a[0]); + /* t1 = b^2. */ + fp8_sqr_unr(u1, a[1]); + + fp8_add(t, a[0], a[1]); + + /* c = a^2 + b^2 * E. */ + dv_copy(u2[1][0][0], u1[0][0][0], 2 * RLC_FP_DIGS); + dv_copy(u2[1][0][1], u1[0][0][1], 2 * RLC_FP_DIGS); + dv_copy(u2[1][1][0], u1[0][1][0], 2 * RLC_FP_DIGS); + dv_copy(u2[1][1][1], u1[0][1][1], 2 * RLC_FP_DIGS); + fp2_nord_low(u2[0][0], u1[1][1]); + dv_copy(u2[0][1][0], u1[1][0][0], 2 * RLC_FP_DIGS); + dv_copy(u2[0][1][1], u1[1][0][1], 2 * RLC_FP_DIGS); + fp2_addc_low(c[0][0][0], u2[0][0], u0[0][0]); + fp2_addc_low(c[0][0][1], u2[0][1], u0[0][1]); + fp2_addc_low(c[0][1][0], u2[1][0], u0[1][0]); + fp2_addc_low(c[0][1][1], u2[1][1], u0[1][1]); + + /* d = (a + b)^2 - a^2 - b^2 = 2 * a * b. */ + fp2_addc_low(u1[0][0], u1[0][0], u0[0][0]); + fp2_addc_low(u1[0][1], u1[0][1], u0[0][1]); + fp2_addc_low(u1[1][0], u1[1][0], u0[1][0]); + fp2_addc_low(u1[1][1], u1[1][1], u0[1][1]); + + fp8_sqr_unr(u0, t); + fp2_subc_low(c[1][0][0], u0[0][0], u1[0][0]); + fp2_subc_low(c[1][0][1], u0[0][1], u1[0][1]); + fp2_subc_low(c[1][1][0], u0[1][0], u1[1][0]); + fp2_subc_low(c[1][1][1], u0[1][1], u1[1][1]); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp8_free(t); + dv8_free(u0); + dv8_free(u1); + dv8_free(u2); + } +} + +void fp16_sqr_lazyr(fp16_t c, const fp16_t a) { + dv16_t t; + + dv16_null(t); + + RLC_TRY { + dv16_new(t); + fp16_sqr_unr(t, a); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 2; k++) { + fp2_rdcn_low(c[i][j][k], t[i][j][k]); + } + } + } + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + dv16_free(t); + } +} + +#endif + +void fp16_sqr_cyc(fp16_t c, const fp16_t a) { + 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); + + fp8_sqr(t0, a[1]); + fp8_add(t1, a[0], a[1]); + fp8_sqr(t2, t1); + fp8_sub(t2, t2, t0); + fp8_mul_art(c[0], t0); + fp8_sub(c[1], t2, c[0]); + fp8_dbl(c[0], c[0]); + fp_add_dig(c[0][0][0], c[0][0][0], 1); + fp_sub_dig(c[1][0][0], c[1][0][0], 1); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp8_free(t0); + fp8_free(t1); + fp8_free(t2); + } +} diff --git a/src/fpx/relic_fp24_sqr.c b/src/fpx/relic_fp24_sqr.c index 77c850f7e..cef7bacf5 100644 --- a/src/fpx/relic_fp24_sqr.c +++ b/src/fpx/relic_fp24_sqr.c @@ -362,7 +362,6 @@ void fp24_sqr_unr(dv24_t c, const fp24_t a) { fp2_addc_low(c[1][0][j], u4[0][j], u3[0][j]); fp2_addc_low(c[1][1][j], u2[0][j], u3[1][j]); } - } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { @@ -398,13 +397,191 @@ void fp24_sqr_lazyr(fp24_t c, const fp24_t a) { } void fp24_sqr_cyc_lazyr(fp24_t c, const fp24_t a) { - /* TODO: implement lazy reduction. */ - fp24_sqr_cyc_basic(c, a); + fp4_t t0, t1, t2; + dv4_t u0, u1, u2, u3; + + fp4_null(t0); + fp4_null(t1); + fp4_null(t2); + dv4_null(u0); + dv4_null(u1); + dv4_null(u2); + dv4_null(u3); + + RLC_TRY { + fp4_new(t0); + fp4_new(t1); + fp4_new(t2); + dv4_new(u0); + dv4_new(u1); + dv4_new(u2); + dv4_new(u3); + + fp4_sqr_unr(u2, a[0][0]); + fp4_sqr_unr(u3, a[0][1]); + fp4_add(t1, a[0][0], a[0][1]); + + fp2_nord_low(u1[0], u3[1]); + fp2_addc_low(u0[0], u2[0], u1[0]); + fp2_addc_low(u0[1], u2[1], u3[0]); + fp2_rdcn_low(t0[0], u0[0]); + fp2_rdcn_low(t0[1], u0[1]); + + fp4_sqr_unr(u1, t1); + fp2_subc_low(u1[0], u1[0], u2[0]); + fp2_subc_low(u1[1], u1[1], u2[1]); + fp2_subc_low(u1[0], u1[0], u3[0]); + fp2_subc_low(u1[1], u1[1], u3[1]); + fp2_rdcn_low(t1[0], u1[0]); + fp2_rdcn_low(t1[1], u1[1]); + + fp4_sub(c[0][0], t0, a[0][0]); + fp4_add(c[0][0], c[0][0], c[0][0]); + fp4_add(c[0][0], t0, c[0][0]); + + fp4_add(c[0][1], t1, a[0][1]); + fp4_add(c[0][1], c[0][1], c[0][1]); + fp4_add(c[0][1], t1, c[0][1]); + + fp4_sqr_unr(u0, a[2][0]); + fp4_sqr_unr(u1, a[2][1]); + fp4_add(t1, a[2][0], a[2][1]); + fp4_sqr_unr(u2, t1); + + for (int i = 0; i < 2; i++) { + fp2_addc_low(u3[i], u0[i], u1[i]); + fp2_subc_low(u3[i], u2[i], u3[i]); + fp2_rdcn_low(t1[i], u3[i]); + } + + fp4_add(t0, a[1][0], a[1][1]); + fp4_sqr(t2, t0); + fp4_sqr_unr(u2, a[1][0]); + + fp4_mul_art(t0, t1); + fp4_add(t1, t0, a[1][0]); + fp4_dbl(t1, t1); + fp4_add(c[1][0], t1, t0); + + fp2_nord_low(u3[0], u1[1]); + fp2_addc_low(u3[0], u0[0], u3[0]); + fp2_addc_low(u3[1], u0[1], u1[0]); + fp4_sqr_unr(u1, a[1][1]); + fp2_rdcn_low(t1[0], u3[0]); + fp2_rdcn_low(t1[1], u3[1]); + fp4_sub(t0, t1, a[1][1]); + fp4_dbl(t0, t0); + fp4_add(c[1][1], t0, t1); + + fp2_nord_low(u3[0], u1[1]); + fp2_addc_low(u3[0], u2[0], u3[0]); + fp2_addc_low(u3[1], u2[1], u1[0]); + fp2_rdcn_low(t1[0], u3[0]); + fp2_rdcn_low(t1[1], u3[1]); + fp4_sub(t0, t1, a[2][0]); + fp4_dbl(t0, t0); + fp4_add(c[2][0], t0, t1); + + fp2_addc_low(u3[0], u2[0], u1[0]); + fp2_addc_low(u3[1], u2[1], u1[1]); + fp2_rdcn_low(t0[0], u3[0]); + fp2_rdcn_low(t0[1], u3[1]); + fp4_sub(t1, t2, t0); + fp4_add(t0, t1, a[2][1]); + fp4_dbl(t0, t0); + fp4_add(c[2][1], t1, t0); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp4_free(t0); + fp4_free(t1); + fp4_free(t2); + dv4_free(u0); + dv4_free(u1); + dv4_free(u2); + dv4_free(u3); + } } void fp24_sqr_pck_lazyr(fp24_t c, const fp24_t a) { - /* TODO: implement lazy reduction. */ - fp24_sqr_pck_basic(c, a); + fp4_t t0, t1, t2; + dv4_t u0, u1, u2, u3; + + fp4_null(t0); + fp4_null(t1); + fp4_null(t2); + dv4_null(u0); + dv4_null(u1); + dv4_null(u2); + dv4_null(u3); + + RLC_TRY { + fp4_new(t0); + fp4_new(t1); + fp4_new(t2); + dv4_new(u0); + dv4_new(u1); + dv4_new(u2); + dv4_new(u3); + + fp4_sqr_unr(u0, a[2][0]); + fp4_sqr_unr(u1, a[2][1]); + fp4_add(t1, a[2][0], a[2][1]); + fp4_sqr_unr(u2, t1); + + for (int i = 0; i < 2; i++) { + fp2_addc_low(u3[i], u0[i], u1[i]); + fp2_subc_low(u3[i], u2[i], u3[i]); + fp2_rdcn_low(t1[i], u3[i]); + } + + fp4_add(t0, a[1][0], a[1][1]); + fp4_sqr(t2, t0); + fp4_sqr_unr(u2, a[1][0]); + + fp4_mul_art(t0, t1); + fp4_add(t1, t0, a[1][0]); + fp4_dbl(t1, t1); + fp4_add(c[1][0], t1, t0); + + fp2_nord_low(u3[0], u1[1]); + fp2_addc_low(u3[0], u0[0], u3[0]); + fp2_addc_low(u3[1], u0[1], u1[0]); + fp4_sqr_unr(u1, a[1][1]); + fp2_rdcn_low(t1[0], u3[0]); + fp2_rdcn_low(t1[1], u3[1]); + fp4_sub(t0, t1, a[1][1]); + fp4_dbl(t0, t0); + fp4_add(c[1][1], t0, t1); + + fp2_nord_low(u3[0], u1[1]); + fp2_addc_low(u3[0], u2[0], u3[0]); + fp2_addc_low(u3[1], u2[1], u1[0]); + fp2_rdcn_low(t1[0], u3[0]); + fp2_rdcn_low(t1[1], u3[1]); + fp4_sub(t0, t1, a[2][0]); + fp4_dbl(t0, t0); + fp4_add(c[2][0], t0, t1); + + fp2_addc_low(u3[0], u2[0], u1[0]); + fp2_addc_low(u3[1], u2[1], u1[1]); + fp2_rdcn_low(t0[0], u3[0]); + fp2_rdcn_low(t0[1], u3[1]); + fp4_sub(t1, t2, t0); + fp4_add(t0, t1, a[2][1]); + fp4_dbl(t0, t0); + fp4_add(c[2][1], t1, t0); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp4_free(t0); + fp4_free(t1); + fp4_free(t2); + dv4_free(u0); + dv4_free(u1); + dv4_free(u2); + dv4_free(u3); + } } #endif diff --git a/src/fpx/relic_fp3_mul.c b/src/fpx/relic_fp3_mul.c index d02102bc9..88daea8a4 100644 --- a/src/fpx/relic_fp3_mul.c +++ b/src/fpx/relic_fp3_mul.c @@ -178,40 +178,43 @@ void fp3_mul_art(fp3_t c, const fp3_t a) { } void fp3_mul_nor(fp3_t c, const fp3_t a) { - fp3_t t; - bn_t b; + fp3_t t, u; fp3_null(t); - bn_null(b); + fp3_null(u); RLC_TRY { fp3_new(t); - bn_new(b); + fp3_new(u); - int cnr = fp3_field_get_cnr(); + fp3_mul_art(t, a); + int cnr = fp3_field_get_cnr(); switch (fp_prime_get_mod18()) { + case 1: case 7: - /* If p = 7 mod 18, we choose (2^k + j) as a QNR/CNR. */ - fp3_mul_art(t, a); - fp3_copy(c, a); - while (cnr > 1) { - fp3_dbl(c, c); - cnr = cnr >> 1; + if (cnr != 0) { + fp3_copy(u, a); + while (cnr > 1) { + fp3_dbl(u, u); + if (cnr & 1) { + fp3_add(u, u, a); + } + cnr = cnr >> 1; + } + fp3_add(t, t, u); } - fp3_add(c, c, t); - break; - default: - fp3_mul_art(c, a); break; } + + fp3_copy(c, t); } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { fp3_free(t); - bn_free(b); + fp3_free(u); } } @@ -272,15 +275,15 @@ void fp3_mul_frb(fp3_t c, const fp3_t a, int i, int j) { fp_copy(t[0], ctx->fp3_p1[j - 1][0]); fp_copy(t[1], ctx->fp3_p1[j - 1][1]); fp_copy(t[2], ctx->fp3_p1[j - 1][2]); + fp3_mul(c, c, t); break; case 2: fp_copy(t[0], ctx->fp3_p2[j - 1][0]); fp_copy(t[1], ctx->fp3_p2[j - 1][1]); fp_copy(t[2], ctx->fp3_p2[j - 1][2]); + fp3_mul(c, c, t); break; } - - fp3_mul(c, c, t); } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); diff --git a/src/fpx/relic_fp48_mul.c b/src/fpx/relic_fp48_mul.c index 3e2545195..f8019badc 100644 --- a/src/fpx/relic_fp48_mul.c +++ b/src/fpx/relic_fp48_mul.c @@ -86,7 +86,44 @@ void fp48_mul_basic(fp48_t c, const fp48_t a, const fp48_t b) { void fp48_mul_lazyr(fp48_t c, const fp48_t a, const fp48_t b) { /* TODO: implement lazy reduction. */ - fp48_mul_basic(c, a, b); + fp24_t t0, t1, t2; + + fp24_null(t0); + fp24_null(t1); + fp24_null(t2); + + RLC_TRY { + fp24_new(t0); + fp24_new(t1); + fp24_new(t2); + + /* Karatsuba algorithm. */ + + /* t0 = a_0 * b_0. */ + fp24_mul(t0, a[0], b[0]); + /* t1 = a_1 * b_1. */ + fp24_mul(t1, a[1], b[1]); + /* t2 = b_0 + b_1. */ + fp24_add(t2, b[0], b[1]); + + /* c_1 = a_0 + a_1. */ + fp24_add(c[1], a[0], a[1]); + + /* c_1 = (a_0 + a_1) * (b_0 + b_1) */ + fp24_mul(c[1], c[1], t2); + fp24_sub(c[1], c[1], t0); + fp24_sub(c[1], c[1], t1); + + /* c_0 = a_0b_0 + v * a_1b_1. */ + fp24_mul_art(t1, t1); + fp24_add(c[0], t0, t1); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp24_free(t0); + fp24_free(t1); + fp24_free(t2); + } } #endif diff --git a/src/fpx/relic_fp48_sqr.c b/src/fpx/relic_fp48_sqr.c index aec4d9f6d..c7cda8d02 100644 --- a/src/fpx/relic_fp48_sqr.c +++ b/src/fpx/relic_fp48_sqr.c @@ -231,7 +231,30 @@ void fp48_sqr_pck_basic(fp48_t c, const fp48_t a) { void fp48_sqr_lazyr(fp48_t c, const fp48_t a) { /* TODO: implement lazy reduction. */ - fp48_sqr_basic(c, a); + fp24_t t0, t1; + + fp24_null(t0); + fp24_null(t1); + + RLC_TRY { + fp24_new(t0); + fp24_new(t1); + + fp24_add(t0, a[0], a[1]); + fp24_mul_art(t1, a[1]); + fp24_add(t1, a[0], t1); + fp24_mul(t0, t0, t1); + fp24_mul(c[1], a[0], a[1]); + fp24_sub(c[0], t0, c[1]); + fp24_mul_art(t1, c[1]); + fp24_sub(c[0], c[0], t1); + fp24_dbl(c[1], c[1]); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp24_free(t0); + fp24_free(t1); + } } void fp48_sqr_cyc_lazyr(fp48_t c, const fp48_t a) { diff --git a/src/fpx/relic_fp4_mul.c b/src/fpx/relic_fp4_mul.c index 30ee90a93..16904cc59 100644 --- a/src/fpx/relic_fp4_mul.c +++ b/src/fpx/relic_fp4_mul.c @@ -170,12 +170,16 @@ void fp4_mul_frb(fp4_t c, const fp4_t a, int i, int j) { fp_copy(t[1], core_get()->fp4_p1[1]); if (i == 1) { + fp4_copy(c, a); for (int k = 0; k < j; k++) { - fp2_mul(c[0], a[0], t); - fp2_mul(c[1], a[1], t); + fp2_mul(c[0], c[0], t); + fp2_mul(c[1], c[1], t); /* If constant in base field, then second component is zero. */ if (core_get()->frb4 == 1) { fp4_mul_art(c, c); + if (fp_prime_get_mod18() % 3 == 2) { + fp4_mul_art(c, c); + } } } } else { diff --git a/src/fpx/relic_fp54_mul.c b/src/fpx/relic_fp54_mul.c index cd0e0d5a7..d2e96b23e 100644 --- a/src/fpx/relic_fp54_mul.c +++ b/src/fpx/relic_fp54_mul.c @@ -108,7 +108,66 @@ void fp54_mul_basic(fp54_t c, const fp54_t a, const fp54_t b) { void fp54_mul_lazyr(fp54_t c, const fp54_t a, const fp54_t b) { /* TODO: implement lazy reduction. */ - fp54_mul_basic(c, a, b); + fp18_t t0, t1, t2, t3, t4, t5; + + fp18_null(t0); + fp18_null(t1); + fp18_null(t2); + fp18_null(t3); + fp18_null(t4); + fp18_null(t5); + + RLC_TRY { + fp18_new(t0); + fp18_new(t1); + fp18_new(t2); + fp18_new(t3); + fp18_new(t4); + fp18_new(t5); + + /* Karatsuba algorithm. */ + + /* t0 = a_0 * b_0. */ + fp18_mul(t0, a[0], b[0]); + /* t1 = a_1 * b_1. */ + fp18_mul(t1, a[1], b[1]); + /* t2 = a_2 * b_2. */ + fp18_mul(t2, a[2], b[2]); + + fp18_add(t3, a[1], a[2]); + fp18_add(t4, b[1], b[2]); + fp18_mul(t3, t3, t4); + fp18_sub(t3, t3, t1); + fp18_sub(t3, t3, t2); + fp18_mul_art(t3, t3); + fp18_add(t3, t3, t0); + + fp18_add(t4, a[0], a[1]); + fp18_add(t5, b[0], b[1]); + fp18_mul(t4, t4, t5); + fp18_sub(t4, t4, t0); + fp18_sub(t4, t4, t1); + fp18_mul_art(t5, t2); + fp18_add(c[1], t4, t5); + + fp18_add(t4, a[0], a[2]); + fp18_add(t5, b[0], b[2]); + fp18_mul(c[2], t4, t5); + fp18_sub(c[2], c[2], t0); + fp18_add(c[2], c[2], t1); + fp18_sub(c[2], c[2], t2); + + fp18_copy(c[0], t3); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp18_free(t0); + fp18_free(t1); + fp18_free(t2); + fp18_free(t3); + fp18_free(t4); + fp18_free(t5); + } } #endif diff --git a/src/fpx/relic_fp54_sqr.c b/src/fpx/relic_fp54_sqr.c index a08e5b611..2bfc9deb8 100644 --- a/src/fpx/relic_fp54_sqr.c +++ b/src/fpx/relic_fp54_sqr.c @@ -276,12 +276,165 @@ void fp54_sqr_pck_basic(fp54_t c, const fp54_t a) { void fp54_sqr_lazyr(fp54_t c, const fp54_t a) { /* TODO: implement lazy reduction. */ - fp54_sqr_basic(c, a); + fp18_t t0, t1, t2, t3, t4; + + fp18_null(t0); + fp18_null(t1); + fp18_null(t2); + fp18_null(t3); + fp18_null(t4); + + RLC_TRY { + fp18_new(t0); + fp18_new(t1); + fp18_new(t2); + fp18_new(t3); + fp18_new(t4); + + /* t0 = a_0^2 */ + fp18_sqr(t0, a[0]); + + /* t1 = 2 * a_1 * a_2 */ + fp18_mul(t1, a[1], a[2]); + fp18_dbl(t1, t1); + + /* t2 = a_2^2. */ + fp18_sqr(t2, a[2]); + + /* c_2 = a_0 + a_2. */ + fp18_add(c[2], a[0], a[2]); + + /* t3 = (a_0 + a_2 + a_1)^2. */ + fp18_add(t3, c[2], a[1]); + fp18_sqr(t3, t3); + + /* c_2 = (a_0 + a_2 - a_1)^2. */ + fp18_sub(c[2], c[2], a[1]); + fp18_sqr(c[2], c[2]); + + /* c_2 = (c_2 + t3)/2. */ + fp18_add(c[2], c[2], t3); + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + fp_hlv(c[2][0][i][j], c[2][0][i][j]); + fp_hlv(c[2][1][i][j], c[2][1][i][j]); + } + } + + /* t3 = t3 - c_2 - t1. */ + fp18_sub(t3, t3, c[2]); + fp18_sub(t3, t3, t1); + + /* c_2 = c_2 - t0 - t2. */ + fp18_sub(c[2], c[2], t0); + fp18_sub(c[2], c[2], t2); + + /* c_0 = t0 + t1 * E. */ + fp18_mul_art(t4, t1); + fp18_add(c[0], t0, t4); + + /* c_1 = t3 + t2 * E. */ + fp18_mul_art(t4, t2); + fp18_add(c[1], t3, t4); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp18_free(t0); + fp18_free(t1); + fp18_free(t2); + fp18_free(t3); + fp18_free(t4); + } } void fp54_sqr_cyc_lazyr(fp54_t c, const fp54_t a) { /* TODO: implement lazy reduction. */ - fp54_sqr_cyc_basic(c, a); + fp9_t t0, t1, t2, t3, t4, t5, t6; + + fp9_null(t0); + fp9_null(t1); + fp9_null(t2); + fp9_null(t3); + fp9_null(t4); + fp9_null(t5); + fp9_null(t6); + + RLC_TRY { + fp9_new(t0); + fp9_new(t1); + fp9_new(t2); + fp9_new(t3); + fp9_new(t4); + fp9_new(t5); + fp9_new(t6); + + fp9_sqr(t2, a[0][0]); + fp9_sqr(t3, a[0][1]); + fp9_add(t1, a[0][0], a[0][1]); + + fp9_mul_art(t0, t3); + fp9_add(t0, t0, t2); + + fp9_sqr(t1, t1); + fp9_sub(t1, t1, t2); + fp9_sub(t1, t1, t3); + + fp9_sub(c[0][0], t0, a[0][0]); + fp9_add(c[0][0], c[0][0], c[0][0]); + fp9_add(c[0][0], t0, c[0][0]); + + fp9_add(c[0][1], t1, a[0][1]); + fp9_add(c[0][1], c[0][1], c[0][1]); + fp9_add(c[0][1], t1, c[0][1]); + + fp9_sqr(t0, a[2][0]); + fp9_sqr(t1, a[2][1]); + fp9_add(t5, a[2][0], a[2][1]); + fp9_sqr(t2, t5); + + fp9_add(t3, t0, t1); + fp9_sub(t5, t2, t3); + + fp9_add(t6, a[1][0], a[1][1]); + fp9_sqr(t3, t6); + fp9_sqr(t2, a[1][0]); + + fp9_mul_art(t6, t5); + fp9_add(t5, t6, a[1][0]); + fp9_dbl(t5, t5); + fp9_add(c[1][0], t5, t6); + + fp9_mul_art(t4, t1); + fp9_add(t5, t0, t4); + fp9_sub(t6, t5, a[1][1]); + + fp9_sqr(t1, a[1][1]); + + fp9_dbl(t6, t6); + fp9_add(c[1][1], t6, t5); + + fp9_mul_art(t4, t1); + fp9_add(t5, t2, t4); + fp9_sub(t6, t5, a[2][0]); + fp9_dbl(t6, t6); + fp9_add(c[2][0], t6, t5); + + fp9_add(t0, t2, t1); + fp9_sub(t5, t3, t0); + fp9_add(t6, t5, a[2][1]); + fp9_dbl(t6, t6); + fp9_add(c[2][1], t5, t6); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp9_free(t0); + fp9_free(t1); + fp9_free(t2); + fp9_free(t3); + fp9_free(t4); + fp9_free(t5); + fp9_free(t6); + } } void fp54_sqr_pck_lazyr(fp54_t c, const fp54_t a) { diff --git a/src/fpx/relic_fp8_mul.c b/src/fpx/relic_fp8_mul.c index fc587f18c..c2d0587da 100644 --- a/src/fpx/relic_fp8_mul.c +++ b/src/fpx/relic_fp8_mul.c @@ -1,6 +1,6 @@ /* * RELIC is an Efficient LIbrary for Cryptography - * Copyright (c) 4007-4019 RELIC Authors + * Copyright (c) 2019 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 @@ -176,14 +176,13 @@ void fp8_mul_dxs(fp8_t c, const fp8_t a, const fp8_t b) { void fp8_mul_unr(dv8_t c, const fp8_t a, const fp8_t b) { fp4_t t0, t1; - dv4_t u0, u1, u2, u3; + dv4_t u0, u1, u2; fp4_null(t0); fp4_null(t1); dv4_null(u0); dv4_null(u1); dv4_null(u2); - dv4_null(u3); RLC_TRY { fp4_new(t0); @@ -191,7 +190,6 @@ void fp8_mul_unr(dv8_t c, const fp8_t a, const fp8_t b) { dv4_new(u0); dv4_new(u1); dv4_new(u2); - dv4_new(u3); /* Karatsuba algorithm. */ @@ -207,8 +205,8 @@ void fp8_mul_unr(dv8_t c, const fp8_t a, const fp8_t b) { fp4_mul_unr(u2, t0, t1); /* c_1 = u2 - a_0b_0 - a_1b_1. */ for (int i = 0; i < 2; i++) { - fp2_addc_low(u3[i], u0[i], u1[i]); - fp2_subc_low(c[1][i], u2[i], u3[i]); + fp2_subc_low(c[1][i], u2[i], u0[i]); + fp2_subc_low(c[1][i], c[1][i], u1[i]); } /* c_0 = a_0b_0 + v * a_1b_1. */ fp2_nord_low(u2[0], u1[1]); @@ -225,7 +223,6 @@ void fp8_mul_unr(dv8_t c, const fp8_t a, const fp8_t b) { dv4_free(u0); dv4_free(u1); dv4_free(u2); - dv4_free(u3); } } @@ -268,3 +265,36 @@ void fp8_mul_art(fp8_t c, const fp8_t a) { fp4_free(t0); } } + +void fp8_mul_frb(fp8_t c, const fp8_t a, int i, int j) { + fp2_t t; + + fp2_null(t); + + RLC_TRY { + fp4_new(t); + + fp_copy(t[0], core_get()->fp8_p1[0]); + fp_copy(t[1], core_get()->fp8_p1[1]); + + if (i == 1) { + fp8_copy(c, a); + for (int k = 0; k < j; k++) { + fp2_mul(c[0][0], c[0][0], t); + fp2_mul(c[0][1], c[0][1], t); + fp2_mul(c[1][0], c[1][0], t); + fp2_mul(c[1][1], c[1][1], t); + /* If constant in base field, then second component is zero. */ + if (core_get()->frb8 == 1) { + fp8_mul_art(c, c); + } + } + } else { + RLC_THROW(ERR_NO_VALID); + } + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp4_free(t); + } +} diff --git a/src/fpx/relic_fp9_mul.c b/src/fpx/relic_fp9_mul.c index 3d33e7aaa..f03a7ee5a 100644 --- a/src/fpx/relic_fp9_mul.c +++ b/src/fpx/relic_fp9_mul.c @@ -267,7 +267,7 @@ void fp9_mul_art(fp9_t c, const fp9_t a) { RLC_TRY { fp3_new(t0); - /* (a_0 + a_1 * v + a_2 * v^2) * v = a_2 + a_0 * v + a_1 * v^2 */ + /* (a_0 + a_1 * v + a_2 * v^2) * v = a_2 * v^3 + a_0 * v + a_1 * v^2 */ fp3_copy(t0, a[0]); fp3_mul_nor(c[0], a[2]); fp3_copy(c[2], a[1]); diff --git a/src/fpx/relic_fpx_add.c b/src/fpx/relic_fpx_add.c index 96221488d..ff10c0aa4 100644 --- a/src/fpx/relic_fpx_add.c +++ b/src/fpx/relic_fpx_add.c @@ -263,6 +263,26 @@ void fp12_dbl(fp12_t c, const fp12_t a) { fp6_dbl(c[1], a[1]); } +void fp16_add(fp16_t c, const fp16_t a, const fp16_t b) { + fp8_add(c[0], a[0], b[0]); + fp8_add(c[1], a[1], b[1]); +} + +void fp16_sub(fp16_t c, const fp16_t a, const fp16_t b) { + fp8_sub(c[0], a[0], b[0]); + fp8_sub(c[1], a[1], b[1]); +} + +void fp16_dbl(fp16_t c, const fp16_t a) { + fp8_dbl(c[0], a[0]); + fp8_dbl(c[1], a[1]); +} + +void fp16_neg(fp16_t c, const fp16_t a) { + fp8_neg(c[0], a[0]); + fp8_neg(c[1], a[1]); +} + void fp18_add(fp18_t c, const fp18_t a, const fp18_t b) { fp9_add(c[0], a[0], b[0]); fp9_add(c[1], a[1], b[1]); diff --git a/src/fpx/relic_fpx_cmp.c b/src/fpx/relic_fpx_cmp.c index 9655fccd5..e6fbfd48f 100644 --- a/src/fpx/relic_fpx_cmp.c +++ b/src/fpx/relic_fpx_cmp.c @@ -106,6 +106,16 @@ int fp12_cmp_dig(const fp12_t a, const dig_t b) { RLC_EQ : RLC_NE; } +int fp16_cmp(const fp16_t a, const fp16_t b) { + return (fp8_cmp(a[0], b[0]) == RLC_EQ) && (fp8_cmp(a[1], b[1]) == RLC_EQ) ? + RLC_EQ : RLC_NE; +} + +int fp16_cmp_dig(const fp16_t a, const dig_t b) { + return (fp8_cmp_dig(a[0], b) == RLC_EQ) && fp8_is_zero(a[1]) ? + RLC_EQ : RLC_NE; +} + int fp18_cmp(const fp18_t a, const fp18_t b) { return (fp9_cmp(a[0], b[0]) == RLC_EQ) && (fp9_cmp(a[1], b[1]) == RLC_EQ) ? RLC_EQ : RLC_NE; diff --git a/src/fpx/relic_fpx_cyc.c b/src/fpx/relic_fpx_cyc.c index 5011aa2a7..a8ca94b4e 100644 --- a/src/fpx/relic_fpx_cyc.c +++ b/src/fpx/relic_fpx_cyc.c @@ -67,7 +67,7 @@ int fp2_test_cyc(const fp2_t a) { RLC_TRY { fp2_new(t); - fp2_frb(t, a, 1); + fp2_inv_cyc(t, a); fp2_mul(t, t, a); result = ((fp2_cmp_dig(t, 1) == RLC_EQ) ? 1 : 0); } @@ -90,6 +90,14 @@ void fp2_exp_cyc(fp2_t c, const fp2_t a, const bn_t b) { return fp2_set_dig(c, 1); } + if (bn_bits(b) <= RLC_DIG) { + fp2_exp_dig(c, a, b->dp[0]); + if (bn_sign(b) == RLC_NEG) { + fp2_inv_cyc(c, c); + } + return; + } + fp2_null(r); fp2_null(s); @@ -146,6 +154,108 @@ void fp2_exp_cyc(fp2_t c, const fp2_t a, const bn_t b) { } } +void fp2_exp_cyc_sim(fp2_t e, const fp2_t a, const bn_t b, const fp2_t c, + const bn_t d) { + int n0, n1; + int8_t naf0[RLC_FP_BITS + 1], naf1[RLC_FP_BITS + 1], *_k, *_m; + fp2_t r, t0[1 << (RLC_WIDTH - 2)]; + fp2_t s, t1[1 << (RLC_WIDTH - 2)]; + size_t l, l0, l1; + + if (bn_is_zero(b)) { + return fp2_exp_cyc(e, c, d); + } + + if (bn_is_zero(d)) { + return fp2_exp_cyc(e, a, b); + } + + fp2_null(r); + fp2_null(s); + + RLC_TRY { + fp2_new(r); + fp2_new(s); + for (int i = 0; i < (1 << (RLC_WIDTH - 2)); i ++) { + fp2_null(t0[i]); + fp2_null(t1[i]); + fp2_new(t0[i]); + fp2_new(t1[i]); + } + +#if RLC_WIDTH > 2 + fp2_sqr(t0[0], a); + fp2_mul(t0[1], t0[0], a); + for (int i = 2; i < (1 << (RLC_WIDTH - 2)); i++) { + fp2_mul(t0[i], t0[i - 1], t0[0]); + } + + fp2_sqr(t1[0], c); + fp2_mul(t1[1], t1[0], c); + for (int i = 2; i < (1 << (RLC_WIDTH - 2)); i++) { + fp2_mul(t1[i], t1[i - 1], t1[0]); + } +#endif + fp2_copy(t0[0], a); + fp2_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; + + fp2_set_dig(r, 1); + for (int i = l - 1; i >= 0; i--, _k--, _m--) { + fp2_sqr(r, r); + + n0 = *_k; + n1 = *_m; + + if (n0 > 0) { + fp2_mul(r, r, t0[n0 / 2]); + } + if (n0 < 0) { + fp2_inv_cyc(s, t0[-n0 / 2]); + fp2_mul(r, r, s); + } + if (n1 > 0) { + fp2_mul(r, r, t1[n1 / 2]); + } + if (n1 < 0) { + fp2_inv_cyc(s, t1[-n1 / 2]); + fp2_mul(r, r, s); + } + } + + fp2_copy(e, r); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + fp2_free(r); + fp2_free(s); + for (int i = 0; i < (1 << (RLC_WIDTH - 2)); i++) { + fp2_free(t0[i]); + fp2_free(t1[i]); + } + } +} + void fp8_conv_cyc(fp8_t c, const fp8_t a) { fp8_t t; @@ -193,13 +303,17 @@ int fp8_test_cyc(const fp8_t a) { void fp8_exp_cyc(fp8_t c, const fp8_t a, const bn_t b) { fp8_t r, s, t[1 << (RLC_WIDTH - 2)]; - int8_t naf[RLC_FP_BITS + 1], *k; + int8_t naf[RLC_FP_BITS + 1], *k, w = RLC_WIDTH; size_t l; if (bn_is_zero(b)) { return fp8_set_dig(c, 1); } + if (bn_bits(b) <= RLC_DIG) { + w = 2; + } + fp8_null(r); fp8_null(s); @@ -214,7 +328,7 @@ void fp8_exp_cyc(fp8_t c, const fp8_t a, const bn_t b) { #if RLC_WIDTH > 2 fp8_sqr_cyc(t[0], a); fp8_mul(t[1], t[0], a); - for (int i = 2; i < (1 << (RLC_WIDTH - 2)); i++) { + for (int i = 2; i < (1 << (w - 2)); i++) { fp8_mul(t[i], t[i - 1], t[0]); } #endif @@ -222,7 +336,7 @@ void fp8_exp_cyc(fp8_t c, const fp8_t a, const bn_t b) { l = RLC_FP_BITS + 1; fp8_set_dig(r, 1); - bn_rec_naf(naf, &l, b, RLC_WIDTH); + bn_rec_naf(naf, &l, b, w); k = naf + l - 1; @@ -328,26 +442,34 @@ void fp12_back_cyc(fp12_t c, const fp12_t a) { fp2_new(t1); fp2_new(t2); - if (fp2_is_zero(a[1][0])) { - /* If g2 = 0, t0 = 2 * g4 * g5, t1 = g3. */ - fp2_mul(t0, a[0][1], a[1][2]); - fp2_dbl(t0, t0); - fp2_copy(t1, a[0][2]); - } else { - /* t0 = g4^2. */ - fp2_sqr(t0, a[0][1]); - /* t1 = 3 * g4^2 - 2 * g3. */ - fp2_sub(t1, t0, a[0][2]); - fp2_dbl(t1, t1); - fp2_add(t1, t1, t0); - /* t0 = E * g5^2 + t1. */ - fp2_sqr(t2, a[1][2]); - fp2_mul_nor(t0, t2); - fp2_add(t0, t0, t1); - /* t1 = 4 * g2. */ - fp2_dbl(t1, a[1][0]); - fp2_dbl(t1, t1); - } + 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); + /* 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); + /* t1 = 3 * g4^2 - 2 * g3. */ + fp2_sub(t1, t0, a[0][2]); + fp2_dbl(t1, t1); + fp2_add(t1, t1, t0); + /* t0 = E * g5^2 + t1. */ + fp2_sqr(t2, a[1][2]); + fp2_mul_nor(t0, t2); + fp2_add(t0, t0, t1); + /* 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); + /* 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); /* t1 = 1/g3 or 1/(4*g2), depending on the above. */ fp2_inv(t1, t1); @@ -406,31 +528,34 @@ void fp12_back_cyc_sim(fp12_t c[], const fp12_t a[], int n) { } for (int i = 0; i < n; i++) { - /* TODO: make this constant time. */ - if (fp2_is_zero(a[i][1][0])) { - /* t0 = 2 * g4 * g5, t1 = g3. */ - fp2_mul(t0[i], a[i][0][1], a[i][1][2]); - fp2_dbl(t0[i], t0[i]); - fp2_copy(t1[i], a[i][0][2]); - } else { - /* t0 = g4^2. */ - fp2_sqr(t0[i], a[i][0][1]); - /* t1 = 3 * g4^2 - 2 * g3. */ - fp2_sub(t1[i], t0[i], a[i][0][2]); - fp2_dbl(t1[i], t1[i]); - fp2_add(t1[i], t1[i], t0[i]); - /* t0 = E * g5^2 + t1. */ - fp2_sqr(t2[i], a[i][1][2]); - fp2_mul_nor(t0[i], t2[i]); - fp2_add(t0[i], t0[i], t1[i]); - /* t1 = (4 * g2). */ - fp2_dbl(t1[i], a[i][1][0]); - fp2_dbl(t1[i], t1[i]); - } + 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); + /* 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); + /* t1 = 3 * g4^2 - 2 * g3. */ + fp2_sub(t1[i], t0[i], a[i][0][2]); + fp2_dbl(t1[i], t1[i]); + fp2_add(t1[i], t1[i], t0[i]); + /* t0 = E * g5^2 + t1. */ + fp2_sqr(t2[i], a[i][1][2]); + fp2_mul_nor(t0[i], t2[i]); + fp2_add(t0[i], t0[i], t1[i]); + /* 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); /* If unity, decompress to unity as well. */ - if (fp12_cmp_dig(a[i], 1) == RLC_EQ) { - fp2_set_dig(t1[i], 1); - } + 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); } /* t1 = 1 / t1. */ @@ -619,109 +744,8 @@ void fp12_exp_cyc(fp12_t c, const fp12_t a, const bn_t b) { } } -void fp2_exp_cyc_sim(fp2_t e, const fp2_t a, const bn_t b, const fp2_t c, const bn_t d) { - int n0, n1; - int8_t naf0[RLC_FP_BITS + 1], naf1[RLC_FP_BITS + 1], *_k, *_m; - fp2_t r, t0[1 << (RLC_WIDTH - 2)]; - fp2_t s, t1[1 << (RLC_WIDTH - 2)]; - size_t l, l0, l1; - - if (bn_is_zero(b)) { - return fp2_exp_cyc(e, c, d); - } - - if (bn_is_zero(d)) { - return fp2_exp_cyc(e, a, b); - } - - fp2_null(r); - fp2_null(s); - - RLC_TRY { - fp2_new(r); - fp2_new(s); - for (int i = 0; i < (1 << (RLC_WIDTH - 2)); i ++) { - fp2_null(t0[i]); - fp2_null(t1[i]); - fp2_new(t0[i]); - fp2_new(t1[i]); - } - -#if RLC_WIDTH > 2 - fp2_sqr(t0[0], a); - fp2_mul(t0[1], t0[0], a); - for (int i = 2; i < (1 << (RLC_WIDTH - 2)); i++) { - fp2_mul(t0[i], t0[i - 1], t0[0]); - } - - fp2_sqr(t1[0], c); - fp2_mul(t1[1], t1[0], c); - for (int i = 2; i < (1 << (RLC_WIDTH - 2)); i++) { - fp2_mul(t1[i], t1[i - 1], t1[0]); - } -#endif - fp2_copy(t0[0], a); - fp2_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; - - fp2_set_dig(r, 1); - for (int i = l - 1; i >= 0; i--, _k--, _m--) { - fp2_sqr(r, r); - - n0 = *_k; - n1 = *_m; - - if (n0 > 0) { - fp2_mul(r, r, t0[n0 / 2]); - } - if (n0 < 0) { - fp2_inv_cyc(s, t0[-n0 / 2]); - fp2_mul(r, r, s); - } - if (n1 > 0) { - fp2_mul(r, r, t1[n1 / 2]); - } - if (n1 < 0) { - fp2_inv_cyc(s, t1[-n1 / 2]); - fp2_mul(r, r, s); - } - } - - fp2_copy(e, r); - } - RLC_CATCH_ANY { - RLC_THROW(ERR_CAUGHT); - } - RLC_FINALLY { - fp2_free(r); - fp2_free(s); - for (int i = 0; i < (1 << (RLC_WIDTH - 2)); i++) { - fp2_free(t0[i]); - fp2_free(t1[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) { +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; bn_t _b[4], _d[4], n, x; fp12_t t[4], u[4]; @@ -903,6 +927,223 @@ void fp12_exp_cyc_sps(fp12_t c, const fp12_t a, const int *b, size_t len, } } +void fp16_conv_cyc(fp16_t c, const fp16_t a) { + fp16_t t; + + fp16_null(t); + + RLC_TRY { + fp16_new(t); + + /* t = a^{-1}. */ + fp16_inv(t, a); + /* c = a^(p^8). */ + fp16_inv_cyc(c, a); + /* c = a^(p^8 - 1). */ + fp16_mul(c, c, t); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + fp16_free(t); + } +} + +int fp16_test_cyc(const fp16_t a) { + fp16_t t; + int result = 0; + + fp16_null(t); + + RLC_TRY { + fp16_new(t); + fp16_inv_cyc(t, a); + fp16_mul(t, t, a); + result = ((fp16_cmp_dig(t, 1) == RLC_EQ) ? 1 : 0); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + fp16_free(t); + } + + return result; +} + +void fp16_exp_cyc(fp16_t c, const fp16_t a, const bn_t b) { + fp16_t r, s, t[1 << (RLC_WIDTH - 2)]; + int8_t naf[RLC_FP_BITS + 1], *k, w = RLC_WIDTH; + size_t l; + + if (bn_is_zero(b)) { + return fp16_set_dig(c, 1); + } + + if (bn_bits(b) <= RLC_DIG) { + w = 2; + } + + fp16_null(r); + fp16_null(s); + + RLC_TRY { + fp16_new(r); + fp16_new(s); + for (int i = 0; i < (1 << (RLC_WIDTH - 2)); i ++) { + fp16_null(t[i]); + fp16_new(t[i]); + } + +#if RLC_WIDTH > 2 + fp16_sqr_cyc(t[0], a); + fp16_mul(t[1], t[0], a); + for (int i = 2; i < (1 << (w - 2)); i++) { + fp16_mul(t[i], t[i - 1], t[0]); + } +#endif + fp16_copy(t[0], a); + + l = RLC_FP_BITS + 1; + fp16_set_dig(r, 1); + bn_rec_naf(naf, &l, b, w); + + k = naf + l - 1; + + for (int i = l - 1; i >= 0; i--, k--) { + fp16_sqr_cyc(r, r); + + if (*k > 0) { + fp16_mul(r, r, t[*k / 2]); + } + if (*k < 0) { + fp16_inv_cyc(s, t[-*k / 2]); + fp16_mul(r, r, s); + } + } + + if (bn_sign(b) == RLC_NEG) { + fp16_inv_cyc(c, r); + } else { + fp16_copy(c, r); + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + fp16_free(r); + fp16_free(s); + for (int i = 0; i < (1 << (RLC_WIDTH - 2)); 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; + int8_t naf0[RLC_FP_BITS + 1], naf1[RLC_FP_BITS + 1], *_k, *_m; + fp16_t r, t0[1 << (RLC_WIDTH - 2)]; + fp16_t s, t1[1 << (RLC_WIDTH - 2)]; + size_t l, l0, l1; + + if (bn_is_zero(b)) { + return fp16_exp_cyc(e, c, d); + } + + if (bn_is_zero(d)) { + return fp16_exp_cyc(e, a, b); + } + + fp16_null(r); + fp16_null(s); + + RLC_TRY { + fp16_new(r); + fp16_new(s); + for (int i = 0; i < (1 << (RLC_WIDTH - 2)); i ++) { + fp16_null(t0[i]); + fp16_null(t1[i]); + fp16_new(t0[i]); + fp16_new(t1[i]); + } + +#if RLC_WIDTH > 2 + fp16_sqr_cyc(t0[0], a); + fp16_mul(t0[1], t0[0], a); + for (int i = 2; i < (1 << (RLC_WIDTH - 2)); i++) { + fp16_mul(t0[i], t0[i - 1], t0[0]); + } + + fp16_sqr_cyc(t1[0], c); + fp16_mul(t1[1], t1[0], c); + for (int i = 2; i < (1 << (RLC_WIDTH - 2)); i++) { + fp16_mul(t1[i], t1[i - 1], t1[0]); + } +#endif + fp16_copy(t0[0], a); + fp16_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; + + fp16_set_dig(r, 1); + for (int i = l - 1; i >= 0; i--, _k--, _m--) { + fp16_sqr(r, r); + + n0 = *_k; + n1 = *_m; + + if (n0 > 0) { + fp16_mul(r, r, t0[n0 / 2]); + } + if (n0 < 0) { + fp16_inv_cyc(s, t0[-n0 / 2]); + fp16_mul(r, r, s); + } + if (n1 > 0) { + fp16_mul(r, r, t1[n1 / 2]); + } + if (n1 < 0) { + fp16_inv_cyc(s, t1[-n1 / 2]); + fp16_mul(r, r, s); + } + } + + fp16_copy(e, r); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + fp16_free(r); + fp16_free(s); + for (int i = 0; i < (1 << (RLC_WIDTH - 2)); i++) { + fp16_free(t0[i]); + fp16_free(t1[i]); + } + } +} + + void fp18_conv_cyc(fp18_t c, const fp18_t a) { fp18_t t; @@ -975,26 +1216,38 @@ void fp18_back_cyc(fp18_t c, const fp18_t a) { fp3_new(t1); fp3_new(t2); - if (fp3_is_zero(a[1][0])) { - /* If g2 = 0, t0 = 2 * g4 * g5, t1 = g3. */ - fp3_mul(t0, a[0][1], a[1][2]); - fp3_dbl(t0, t0); - fp3_copy(t1, a[0][2]); - } else { - /* t0 = g4^2. */ - fp3_sqr(t0, a[0][1]); - /* t1 = 3 * g4^2 - 2 * g3. */ - fp3_sub(t1, t0, a[0][2]); - fp3_dbl(t1, t1); - fp3_add(t1, t1, t0); - /* t0 = E * g5^2 + t1. */ - fp3_sqr(t2, a[1][2]); - fp3_mul_nor(t0, t2); - fp3_add(t0, t0, t1); - /* t1 = 4 * g2. */ - fp3_dbl(t1, a[1][0]); - fp3_dbl(t1, t1); - } + 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); + /* 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); + /* t1 = 3 * g4^2 - 2 * g3. */ + fp3_sub(t1, t0, a[0][2]); + fp3_dbl(t1, t1); + fp3_add(t1, t1, t0); + /* t0 = E * g5^2 + t1. */ + fp3_sqr(t2, a[1][2]); + fp3_mul_nor(t0, t2); + fp3_add(t0, t0, t1); + /* 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); + /* 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); /* t1 = 1/g3 or 1/(4 * g2), depending on the above. */ fp3_inv(t1, t1); @@ -1053,31 +1306,38 @@ void fp18_back_cyc_sim(fp18_t c[], const fp18_t a[], int n) { } for (int i = 0; i < n; i++) { - /* TODO: make this constant time. */ - if (fp3_is_zero(a[i][1][0])) { - /* t0 = 2 * g4 * g5, t1 = g3. */ - fp3_mul(t0[i], a[i][0][1], a[i][1][2]); - fp3_dbl(t0[i], t0[i]); - fp3_copy(t1[i], a[i][0][2]); - } else { - /* t0 = g4^2. */ - fp3_sqr(t0[i], a[i][0][1]); - /* t1 = 3 * g4^2 - 2 * g3. */ - fp3_sub(t1[i], t0[i], a[i][0][2]); - fp3_dbl(t1[i], t1[i]); - fp3_add(t1[i], t1[i], t0[i]); - /* t0 = E * g5^2 + t1. */ - fp3_sqr(t2[i], a[i][1][2]); - fp3_mul_nor(t0[i], t2[i]); - fp3_add(t0[i], t0[i], t1[i]); - /* t1 = (4 * g2). */ - fp3_dbl(t1[i], a[i][1][0]); - fp3_dbl(t1[i], t1[i]); - } + 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); + /* 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); + /* t1 = 3 * g4^2 - 2 * g3. */ + fp3_sub(t1[i], t0[i], a[i][0][2]); + fp3_dbl(t1[i], t1[i]); + fp3_add(t1[i], t1[i], t0[i]); + /* t0 = E * g5^2 + t1. */ + fp3_sqr(t2[i], a[i][1][2]); + fp3_mul_nor(t0[i], t2[i]); + fp3_add(t0[i], t0[i], t1[i]); + /* 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); /* If unity, decompress to unity as well. */ - if (fp18_cmp_dig(a[i], 1) == RLC_EQ) { - fp3_set_dig(t1[i], 1); - } + 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); } /* t1 = 1 / t1. */ @@ -1126,13 +1386,22 @@ static void fp18_gls(fp18_t c, const fp18_t a) { RLC_TRY { fp18_new(b); - /* 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); + if (ep_curve_is_pairf() == 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); + } else { + /* 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); + } } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); @@ -1146,8 +1415,7 @@ void fp18_exp_cyc(fp18_t c, const fp18_t a, const bn_t b) { int i, j, k, w = bn_ham(b); if (bn_is_zero(b)) { - fp18_set_dig(c, 1); - return; + return fp18_set_dig(c, 1); } if ((bn_bits(b) > RLC_DIG) && ((w << 3) > bn_bits(b))) { @@ -1169,8 +1437,14 @@ void fp18_exp_cyc(fp18_t c, const fp18_t a, const bn_t b) { fp18_new(t[i]); } - ep_curve_get_ord(n); 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_mod(_b[0], b, n); bn_rec_frb(_b, 6, _b[0], x, n, ep_curve_is_pairf() == EP_BN); @@ -1178,26 +1452,32 @@ void fp18_exp_cyc(fp18_t c, const fp18_t a, const bn_t b) { l = 0; fp18_copy(t[0], a); - for (i = 0; i < 6; i++) { - if (i > 0) { - fp18_gls(t[i], t[i - 1]); - } + for (int 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 (int 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 (j = l - 1; j >= 0; j--) { + for (int i = l - 1; i >= 0; i--) { fp18_sqr_cyc(c, c); - for (i = 0; i < 6; i++) { - if (naf[i][j] > 0) { - fp18_mul(c, c, t[i]); + for (int j = 0; j < 6; j++) { + if (naf[j][i] > 0) { + fp18_mul(c, c, t[j]); } - if (naf[i][j] < 0) { - fp18_inv_cyc(t[i], t[i]); - fp18_mul(c, c, t[i]); - fp18_inv_cyc(t[i], t[i]); + 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]); } } } @@ -1289,7 +1569,8 @@ void fp18_exp_cyc(fp18_t c, const fp18_t a, const bn_t b) { } } -void fp18_exp_cyc_sim(fp18_t e, const fp18_t a, const bn_t b, const fp18_t c, const bn_t d) { +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; size_t l, l0, l1; int8_t naf0[RLC_FP_BITS + 1], naf1[RLC_FP_BITS + 1], *_k, *_m; @@ -1390,7 +1671,8 @@ void fp18_exp_cyc_sim(fp18_t e, const fp18_t a, const bn_t b, const fp18_t c, co } } -void fp18_exp_cyc_sps(fp18_t c, const fp18_t a, const int *b, int len, int sign) { +void fp18_exp_cyc_sps(fp18_t c, const fp18_t a, const int *b, int len, + int sign) { int i, j, k, w = len; fp18_t t, *u = RLC_ALLOCA(fp18_t, w); @@ -1541,26 +1823,42 @@ void fp24_back_cyc(fp24_t c, const fp24_t a) { fp4_new(t1); fp4_new(t2); - if (fp4_is_zero(a[1][0])) { - /* If g2 = 0, t0 = 2 * g4 * g5, t1 = g3. */ - fp4_mul(t0, a[2][0], a[2][1]); - fp4_dbl(t0, t0); - fp4_copy(t1, a[1][1]); - } else { - /* t0 = g4^2. */ - fp4_sqr(t0, a[2][0]); - /* t1 = 3 * g4^2 - 2 * g3. */ - fp4_sub(t1, t0, a[1][1]); - fp4_dbl(t1, t1); - fp4_add(t1, t1, t0); - /* t0 = E * g5^2 + t1. */ - fp4_sqr(t2, a[2][1]); - fp4_mul_art(t0, t2); - fp4_add(t0, t0, t1); - /* t1 = 1/(4 * g2). */ - fp4_dbl(t1, a[1][0]); - fp4_dbl(t1, t1); - } + 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); + /* 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); + /* t1 = 3 * g4^2 - 2 * g3. */ + fp4_sub(t1, t0, a[1][1]); + fp4_dbl(t1, t1); + fp4_add(t1, t1, t0); + /* t0 = E * g5^2 + t1. */ + fp4_sqr(t2, a[2][1]); + fp4_mul_art(t0, t2); + fp4_add(t0, t0, t1); + /* 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); + /* 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_inv(t1, t1); /* c_1 = g1. */ @@ -1618,30 +1916,42 @@ void fp24_back_cyc_sim(fp24_t c[], const fp24_t a[], int n) { } for (int i = 0; i < n; i++) { - if (fp4_is_zero(a[i][1][0])) { - /* t0 = 2 * g4 * g5, t1 = g3. */ - fp4_mul(t0[i], a[i][2][0], a[i][2][1]); - fp4_dbl(t0[i], t0[i]); - fp4_copy(t1[i], a[i][1][1]); - } else { - /* t0 = g4^2. */ - fp4_sqr(t0[i], a[i][2][0]); - /* t1 = 3 * g4^2 - 2 * g3. */ - fp4_sub(t1[i], t0[i], a[i][1][1]); - fp4_dbl(t1[i], t1[i]); - fp4_add(t1[i], t1[i], t0[i]); - /* t0 = E * g5^2 + t1. */ - fp4_sqr(t2[i], a[i][2][1]); - fp4_mul_art(t0[i], t2[i]); - fp4_add(t0[i], t0[i], t1[i]); - /* t1 = (4 * g2). */ - fp4_dbl(t1[i], a[i][1][0]); - fp4_dbl(t1[i], t1[i]); - } + 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); + /* 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); + /* t1 = 3 * g4^2 - 2 * g3. */ + fp4_sub(t1[i], t0[i], a[i][1][1]); + fp4_dbl(t1[i], t1[i]); + fp4_add(t1[i], t1[i], t0[i]); + /* t0 = E * g5^2 + t1. */ + fp4_sqr(t2[i], a[i][2][1]); + fp4_mul_art(t0[i], t2[i]); + fp4_add(t0[i], t0[i], t1[i]); + /* 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); /* If unity, decompress to unity as well. */ - if (fp24_cmp_dig(a[i], 1) == RLC_EQ) { - fp4_set_dig(t1[i], 1); - } + 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); } /* t1 = 1 / t1. */ @@ -1834,7 +2144,8 @@ void fp24_exp_cyc(fp24_t c, const fp24_t a, const bn_t b) { } } -void fp24_exp_cyc_sim(fp24_t e, const fp24_t a, const bn_t b, const fp24_t c, const bn_t d) { +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; int8_t naf0[RLC_FP_BITS + 1], naf1[RLC_FP_BITS + 1], *_k, *_m; fp24_t r, t0[1 << (RLC_WIDTH - 2)]; @@ -2087,26 +2398,58 @@ void fp48_back_cyc(fp48_t c, const fp48_t a) { fp8_new(t1); fp8_new(t2); - if (fp8_is_zero(a[1][0])) { - /* If g2 = 0, t0 = 2 * g4 * g5, t1 = g3. */ - fp8_mul(t0, a[0][1], a[1][2]); - fp8_dbl(t0, t0); - fp8_copy(t1, a[0][2]); - } else { - /* t0 = g4^2. */ - fp8_sqr(t0, a[0][1]); - /* t1 = 3 * g4^2 - 2 * g3. */ - fp8_sub(t1, t0, a[0][2]); - fp8_dbl(t1, t1); - fp8_add(t1, t1, t0); - /* t0 = E * g5^2 + t1. */ - fp8_sqr(t2, a[1][2]); - fp8_mul_art(t0, t2); - fp8_add(t0, t0, t1); - /* t1 = 1/(4 * g2). */ - fp8_dbl(t1, a[1][0]); - fp8_dbl(t1, t1); - } + 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); + /* 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); + /* t1 = 3 * g4^2 - 2 * g3. */ + fp8_sub(t1, t0, a[0][2]); + fp8_dbl(t1, t1); + fp8_add(t1, t1, t0); + /* t0 = E * g5^2 + t1. */ + fp8_sqr(t2, a[1][2]); + fp8_mul_art(t0, t2); + fp8_add(t0, t0, t1); + /* 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); + /* 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); /* t1 = 1/g3 or 1/(4 * g2), depending on the above. */ fp8_inv(t1, t1); @@ -2165,30 +2508,58 @@ void fp48_back_cyc_sim(fp48_t c[], const fp48_t a[], int n) { } for (int i = 0; i < n; i++) { - if (fp8_is_zero(a[i][1][0])) { - /* If g2 = 0, t0 = 2 * g4 * g5, t1 = g3. */ - fp8_mul(t0[i], a[i][0][1], a[i][1][2]); - fp8_dbl(t0[i], t0[i]); - fp8_copy(t1[i], a[i][0][2]); - } else { - /* t0 = g4^2. */ - fp8_sqr(t0[i], a[i][0][1]); - /* t1 = 3 * g4^2 - 2 * g3. */ - fp8_sub(t1[i], t0[i], a[i][0][2]); - fp8_dbl(t1[i], t1[i]); - fp8_add(t1[i], t1[i], t0[i]); - /* t0 = E * g5^2 + t1. */ - fp8_sqr(t2[i], a[i][1][2]); - fp8_mul_art(t0[i], t2[i]); - fp8_add(t0[i], t0[i], t1[i]); - /* t1 = (4 * g2). */ - fp8_dbl(t1[i], a[i][1][0]); - fp8_dbl(t1[i], t1[i]); - } + 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); + /* 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); + /* t1[i] = 3 * g4^2 - 2 * g3. */ + fp8_sub(t1[i], t0[i], a[i][0][2]); + fp8_dbl(t1[i], t1[i]); + fp8_add(t1[i], t1[i], t0[i]); + /* t0[i] = E * g5^2 + t1[i]. */ + fp8_sqr(t2[i], a[i][1][2]); + fp8_mul_art(t0[i], t2[i]); + fp8_add(t0[i], t0[i], t1[i]); + /* 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); /* If unity, decompress to unity as well. */ - if (fp48_cmp_dig(a[i], 1) == RLC_EQ) { - fp8_set_dig(t1[i], 1); - } + 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); } /* t1 = 1 / t1. */ @@ -2324,6 +2695,108 @@ void fp48_exp_cyc(fp48_t c, const fp48_t a, const bn_t b) { } } +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; + int8_t naf0[RLC_FP_BITS + 1], naf1[RLC_FP_BITS + 1], *_k, *_m; + fp48_t r, t0[1 << (RLC_WIDTH - 2)]; + fp48_t s, t1[1 << (RLC_WIDTH - 2)]; + size_t l, l0, l1; + + if (bn_is_zero(b)) { + return fp48_exp_cyc(e, c, d); + } + + if (bn_is_zero(d)) { + return fp48_exp_cyc(e, a, b); + } + + fp48_null(r); + fp48_null(s); + + RLC_TRY { + fp48_new(r); + fp48_new(s); + for (int i = 0; i < (1 << (RLC_WIDTH - 2)); i ++) { + fp48_null(t0[i]); + fp48_null(t1[i]); + fp48_new(t0[i]); + fp48_new(t1[i]); + } + +#if RLC_WIDTH > 2 + fp48_sqr(t0[0], a); + fp48_mul(t0[1], t0[0], a); + for (int i = 2; i < (1 << (RLC_WIDTH - 2)); i++) { + fp48_mul(t0[i], t0[i - 1], t0[0]); + } + + fp48_sqr(t1[0], c); + fp48_mul(t1[1], t1[0], c); + for (int i = 2; i < (1 << (RLC_WIDTH - 2)); i++) { + fp48_mul(t1[i], t1[i - 1], t1[0]); + } +#endif + fp48_copy(t0[0], a); + fp48_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; + + fp48_set_dig(r, 1); + for (int i = l - 1; i >= 0; i--, _k--, _m--) { + fp48_sqr(r, r); + + n0 = *_k; + n1 = *_m; + + if (n0 > 0) { + fp48_mul(r, r, t0[n0 / 2]); + } + if (n0 < 0) { + fp48_inv_cyc(s, t0[-n0 / 2]); + fp48_mul(r, r, s); + } + if (n1 > 0) { + fp48_mul(r, r, t1[n1 / 2]); + } + if (n1 < 0) { + fp48_inv_cyc(s, t1[-n1 / 2]); + fp48_mul(r, r, s); + } + } + + fp48_copy(e, r); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + fp48_free(r); + fp48_free(s); + for (int i = 0; i < (1 << (RLC_WIDTH - 2)); i++) { + fp48_free(t0[i]); + fp48_free(t1[i]); + } + } +} + void fp48_exp_cyc_sps(fp48_t c, const fp48_t a, const int *b, size_t len, int sign) { size_t i, j, k, w = len; @@ -2475,8 +2948,22 @@ void fp54_back_cyc(fp54_t c, const fp54_t a) { fp9_new(t1); fp9_new(t2); + 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); + } /* t0 = g4^2. */ - fp9_sqr(t0, a[2][0]); + 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); + } /* t1 = 3 * g4^2 - 2 * g3. */ fp9_sub(t1, t0, a[1][1]); fp9_dbl(t1, t1); @@ -2485,6 +2972,23 @@ void fp54_back_cyc(fp54_t c, const fp54_t a) { fp9_sqr(t2, a[2][1]); fp9_mul_art(t0, t2); fp9_add(t0, t0, t1); + /* 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); + } + /* 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); + } + /* t1 = 1/(4 * g2). */ fp9_dbl(t1, a[1][0]); fp9_dbl(t1, t1); @@ -2544,29 +3048,45 @@ void fp54_back_cyc_sim(fp54_t c[], const fp54_t a[], int n) { } for (int i = 0; i < n; i++) { - if (fp9_is_zero(a[i][1][0])) { - /* t0 = 2 * g4 * g5, t1 = g3. */ - fp9_mul(t0[i], a[i][2][0], a[i][2][1]); - fp9_dbl(t0[i], t0[i]); - fp9_copy(t1[i], a[i][1][1]); - } else { - /* t0 = g4^2. */ - fp9_sqr(t0[i], a[i][2][0]); - /* t1 = 3 * g4^2 - 2 * g3. */ - fp9_sub(t1[i], t0[i], a[i][1][1]); - fp9_dbl(t1[i], t1[i]); - fp9_add(t1[i], t1[i], t0[i]); - /* t0 = E * g5^2 + t1. */ - fp9_sqr(t2[i], a[i][2][1]); - fp9_mul_art(t0[i], t2[i]); - fp9_add(t0[i], t0[i], t1[i]); - /* t1 = (4 * g2). */ - fp9_dbl(t1[i], a[i][1][0]); - fp9_dbl(t1[i], t1[i]); + 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); + } + /* 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); + } + /* t1[i] = 3 * g4^2 - 2 * g3. */ + fp9_sub(t1[i], t0[i], a[i][1][1]); + fp9_dbl(t1[i], t1[i]); + fp9_add(t1[i], t1[i], t0[i]); + /* t0[i] = E * g5^2 + t1[i]. */ + fp9_sqr(t2[i], a[i][2][1]); + fp9_mul_art(t0[i], t2[i]); + fp9_add(t0[i], t0[i], t1[i]); + /* 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); } /* If unity, decompress to unity as well. */ - if (fp54_cmp_dig(a[i], 1) == RLC_EQ) { - fp9_set_dig(t1[i], 1); + 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); } } diff --git a/src/fpx/relic_fpx_exp.c b/src/fpx/relic_fpx_exp.c index fd9d506bd..665087e84 100644 --- a/src/fpx/relic_fpx_exp.c +++ b/src/fpx/relic_fpx_exp.c @@ -249,6 +249,66 @@ void fp8_exp(fp8_t c, const fp8_t a, const bn_t b) { } } +void fp8_exp_dig(fp8_t c, const fp8_t a, dig_t b) { + bn_t _b; + fp8_t t, v; + int8_t u, naf[RLC_DIG + 1]; + size_t l; + + if (b == 0) { + fp8_set_dig(c, 1); + return; + } + + bn_null(_b); + fp8_null(t); + fp8_null(v); + + RLC_TRY { + bn_new(_b); + fp8_new(t); + fp8_new(v); + + fp8_copy(t, a); + + if (fp8_test_cyc(a)) { + fp8_inv_cyc(v, a); + bn_set_dig(_b, b); + + l = RLC_DIG + 1; + bn_rec_naf(naf, &l, _b, 2); + + for (int i = bn_bits(_b) - 2; i >= 0; i--) { + fp8_sqr_cyc(t, t); + + u = naf[i]; + if (u > 0) { + fp8_mul(t, t, a); + } else if (u < 0) { + fp8_mul(t, t, v); + } + } + } else { + for (int i = util_bits_dig(b) - 2; i >= 0; i--) { + fp8_sqr(t, t); + if (b & ((dig_t)1 << i)) { + fp8_mul(t, t, a); + } + } + } + + fp8_copy(c, t); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + bn_free(_b); + fp8_free(t); + fp8_free(v); + } +} + void fp9_exp(fp9_t c, const fp9_t a, const bn_t b) { fp9_t t; @@ -385,6 +445,106 @@ void fp12_exp_dig(fp12_t c, const fp12_t a, dig_t b) { } } +void fp16_exp(fp16_t c, const fp16_t a, const bn_t b) { + fp16_t t; + + if (bn_is_zero(b)) { + fp16_set_dig(c, 1); + return; + } + + fp16_null(t); + + RLC_TRY { + fp16_new(t); + + if (fp16_test_cyc(a)) { + fp16_exp_cyc(c, a, b); + } else { + fp16_copy(t, a); + + for (int i = bn_bits(b) - 2; i >= 0; i--) { + fp16_sqr(t, t); + if (bn_get_bit(b, i)) { + fp16_mul(t, t, a); + } + } + + if (bn_sign(b) == RLC_NEG) { + fp16_inv(c, t); + } else { + fp16_copy(c, t); + } + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + fp16_free(t); + } +} + +void fp16_exp_dig(fp16_t c, const fp16_t a, dig_t b) { + bn_t _b; + fp16_t t, v; + int8_t u, naf[RLC_DIG + 1]; + size_t l; + + if (b == 0) { + fp16_set_dig(c, 1); + return; + } + + bn_null(_b); + fp16_null(t); + fp16_null(v); + + RLC_TRY { + bn_new(_b); + fp16_new(t); + fp16_new(v); + + fp16_copy(t, a); + + if (fp16_test_cyc(a)) { + fp16_inv_cyc(v, a); + bn_set_dig(_b, b); + + l = RLC_DIG + 1; + bn_rec_naf(naf, &l, _b, 2); + + for (int i = bn_bits(_b) - 2; i >= 0; i--) { + fp16_sqr_cyc(t, t); + + u = naf[i]; + if (u > 0) { + fp16_mul(t, t, a); + } else if (u < 0) { + fp16_mul(t, t, v); + } + } + } else { + for (int i = util_bits_dig(b) - 2; i >= 0; i--) { + fp16_sqr(t, t); + if (b & ((dig_t)1 << i)) { + fp16_mul(t, t, a); + } + } + } + + fp16_copy(c, t); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + bn_free(_b); + fp16_free(t); + fp16_free(v); + } +} + void fp18_exp(fp18_t c, const fp18_t a, const bn_t b) { fp18_t t; diff --git a/src/fpx/relic_fpx_field.c b/src/fpx/relic_fpx_field.c index 0f86dfa27..cb05e31ce 100644 --- a/src/fpx/relic_fpx_field.c +++ b/src/fpx/relic_fpx_field.c @@ -49,9 +49,14 @@ int fp2_field_get_qnr() { int fp3_field_get_cnr() { #if FP_PRIME == 638 - return 8; + if (fp_param_get() == K18_638) { + return 8; + } else { + return 3; + } #endif - return 0; + + return core_get()->cnr3; } void fp2_field_init(void) { @@ -77,10 +82,11 @@ void fp2_field_init(void) { fp_zero(t0[0]); fp_set_dig(t0[1], 1); /* If it does not work, attempt (u + 2), otherwise double. */ - if (fp2_srt(t1, t0) == 1) { + /* We cannot used QR test here because Frobenius constants below. */ + if (fp2_srt(t1, t0)) { ctx->qnr2 = 2; fp_set_dig(t0[0], ctx->qnr2); - while (fp2_srt(t1, t0) == 1 && util_bits_dig(ctx->qnr2) < RLC_DIG - 1) { + while (fp2_srt(t1, t0) && util_bits_dig(ctx->qnr2) < RLC_DIG - 1) { /* Pick a power of 2 for efficiency. */ ctx->qnr2 *= 2; fp_set_dig(t0[0], ctx->qnr2); @@ -123,25 +129,35 @@ void fp2_field_init(void) { fp_copy(ctx->fp2_p2[0][0], t0[0]); fp_copy(ctx->fp2_p2[0][1], t0[1]); - /* Compute QNR^(p - (p mod 12))/12. */ + /* Compute QNR^(p - (p mod 8))/8. */ fp2_set_dig(t1, 1); fp2_mul_nor(t0, t1); e->used = RLC_FP_DIGS; dv_copy(e->dp, fp_prime_get(), RLC_FP_DIGS); - bn_div_dig(e, e, 12); + bn_div_dig(e, e, 8); fp2_exp(t0, t0, e); fp_copy(ctx->fp2_p2[1][0], t0[0]); fp_copy(ctx->fp2_p2[1][1], t0[1]); - /* Compute QNR^(p - (p mod 24))/24. */ + /* Compute QNR^(p - (p mod 12))/12. */ fp2_set_dig(t1, 1); fp2_mul_nor(t0, t1); e->used = RLC_FP_DIGS; dv_copy(e->dp, fp_prime_get(), RLC_FP_DIGS); - bn_div_dig(e, e, 24); + bn_div_dig(e, e, 12); fp2_exp(t0, t0, e); fp_copy(ctx->fp2_p2[2][0], t0[0]); fp_copy(ctx->fp2_p2[2][1], t0[1]); + + /* Compute QNR^(p - (p mod 24))/24. */ + fp2_set_dig(t1, 1); + fp2_mul_nor(t0, t1); + e->used = RLC_FP_DIGS; + dv_copy(e->dp, fp_prime_get(), RLC_FP_DIGS); + bn_div_dig(e, e, 24); + fp2_exp(t0, t0, e); + fp_copy(ctx->fp2_p2[3][0], t0[0]); + fp_copy(ctx->fp2_p2[3][1], t0[1]); } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { @@ -165,6 +181,24 @@ void fp3_field_init(void) { fp3_new(t0); fp3_new(t1); + /* Start by trying a trivial quadratic non-residue. */ + ctx->cnr3 = 0; + fp_zero(t0[0]); + fp_set_dig(t0[1], 1); + fp_zero(t0[2]); + /* If it does not work, attempt (u + 1), otherwise double. */ + /* This code will fail if p \neq 1 mod 8 because square root in Fp^3 + * relic on Frobenius. Must implement explicit test for those cases. */ + if (fp3_srt(t1, t0)) { + ctx->cnr3 = 1; + fp_set_dig(t0[0], ctx->cnr3); + while (fp3_srt(t1, t0) && util_bits_dig(ctx->qnr2) < RLC_DIG - 1) { + /* Pick a power of 2 for efficiency. */ + ctx->cnr3 *= 2; + fp_set_dig(t0[0], ctx->cnr3); + } + } + /* Compute t0 = u^((p - (p mod 3))/3). */ if (fp_prime_get_cnr() < 0) { fp_set_dig(ctx->fp3_p0[0], -fp_prime_get_cnr()); @@ -183,7 +217,6 @@ void fp3_field_init(void) { bn_read_raw(e, fp_prime_get(), RLC_FP_DIGS); bn_div_dig(e, e, 6); fp3_exp(t0, t0, e); - if (fp3_field_get_cnr() == 0) { /* Look for a non-trivial subfield element.. */ ctx->frb3[0] = 0; @@ -234,7 +267,9 @@ void fp3_field_init(void) { while (ctx->frb3[1] < 3 && fp_is_zero(t0[ctx->frb3[1]++])); fp_copy(ctx->fp3_p2[0][0], t0[--ctx->frb3[1]]); } else { - fp3_copy(ctx->fp3_p2[0], t0); + fp_copy(ctx->fp3_p2[0][0], t0[0]); + fp_copy(ctx->fp3_p2[0][1], t0[1]); + fp_copy(ctx->fp3_p2[0][2], t0[2]); } /* Compute t0 = u^((p - (p mod 18))/18). */ @@ -249,7 +284,9 @@ void fp3_field_init(void) { while (ctx->frb3[2] < 3 && fp_is_zero(t0[ctx->frb3[2]++])); fp_copy(ctx->fp3_p2[1][0], t0[--ctx->frb3[2]]); } else { - fp3_copy(ctx->fp3_p2[1], t0); + fp_copy(ctx->fp3_p2[1][0], t0[0]); + fp_copy(ctx->fp3_p2[1][1], t0[1]); + fp_copy(ctx->fp3_p2[1][2], t0[2]); } } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); @@ -295,3 +332,39 @@ void fp4_field_init() { fp4_free(t0); } } + +void fp8_field_init() { + bn_t e; + fp8_t t0; + ctx_t *ctx = core_get(); + + bn_null(e); + fp8_null(t0); + + RLC_TRY { + bn_new(e); + fp8_new(t0); + + fp8_set_dig(t0, 1); + fp8_mul_art(t0, t0); + e->used = RLC_FP_DIGS; + dv_copy(e->dp, fp_prime_get(), RLC_FP_DIGS); + bn_sub_dig(e, e, 1); + bn_div_dig(e, e, 6); + fp8_exp(t0, t0, e); + if (fp4_is_zero(t0[1])) { + ctx->frb8 = 0; + fp_copy(ctx->fp8_p1[0], t0[0][0][0]); + fp_copy(ctx->fp8_p1[1], t0[0][0][1]); + } else { + ctx->frb8 = 1; + fp_copy(ctx->fp8_p1[0], t0[1][1][0]); + fp_copy(ctx->fp8_p1[1], t0[1][1][1]); + } + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + bn_free(e); + fp8_free(t0); + } +} diff --git a/src/fpx/relic_fpx_frb.c b/src/fpx/relic_fpx_frb.c index 970671bfe..1578b791b 100644 --- a/src/fpx/relic_fpx_frb.c +++ b/src/fpx/relic_fpx_frb.c @@ -67,7 +67,12 @@ void fp4_frb(fp4_t c, const fp4_t a, int i) { for (; i % 4 > 0; i--) { fp2_frb(c[0], c[0], 1); fp2_frb(c[1], c[1], 1); - fp2_mul_frb(c[1], c[1], 1, 3); + if (fp_prime_get_mod18() % 3 == 1) { + fp2_mul_frb(c[1], c[1], 1, 3); + } else { + fp2_mul_frb(c[1], c[1], 2, 1); + fp2_mul_frb(c[1], c[1], 2, 1); + } } } @@ -91,7 +96,7 @@ void fp8_frb(fp8_t c, const fp8_t a, int i) { fp4_frb(c[1], c[1], 1); fp2_mul_frb(c[1][0], c[1][0], 2, 1); fp2_mul_frb(c[1][1], c[1][1], 2, 1); - if (fp_prime_get_mod8() != 1 && fp_prime_get_mod8() != 5) { + if (fp_prime_get_mod8() % 4 != 1) { fp4_mul_art(c[1], c[1]); } } @@ -123,8 +128,28 @@ void fp12_frb(fp12_t c, const fp12_t a, int i) { } } +void fp16_frb(fp16_t c, const fp16_t a, int i) { + /* Cost of four multiplication in Fp^2 per Frobenius. */ + fp16_copy(c, a); + for (; i % 8 > 0; i--) { + fp8_frb(c[0], c[0], 1); + fp8_frb(c[1], c[1], 1); + fp2_mul_frb(c[1][0][0], c[1][0][0], 2, 2); + fp2_mul_frb(c[1][0][1], c[1][0][1], 2, 2); + fp2_mul_frb(c[1][1][0], c[1][1][0], 2, 2); + fp2_mul_frb(c[1][1][1], c[1][1][1], 2, 2); + if (fp_prime_get_mod8() % 4 != 1) { + fp8_mul_art(c[1], c[1]); + } + if (fp_prime_get_mod8() == 5) { + fp4_mul_art(c[1][0], c[1][0]); + fp4_mul_art(c[1][1], c[1][1]); + } + } +} + void fp18_frb(fp18_t c, const fp18_t a, int i) { - /* Cost of five multiplication in Fp^2 per Frobenius. */ + /* Cost of five multiplication in Fp^3 per Frobenius. */ fp18_copy(c, a); for (; i % 18 > 0; i--) { fp9_frb(c[0], c[0], 1); @@ -146,7 +171,7 @@ void fp24_frb(fp24_t c, const fp24_t a, int i) { fp8_frb(c[2], c[2], 1); for (int j = 0; j < 2; j++) { for (int l = 0; l < 2; l++) { - fp2_mul_frb(c[1][j][l], c[1][j][l], 2, 2); + fp2_mul_frb(c[1][j][l], c[1][j][l], 2, 3); fp2_mul_frb(c[2][j][l], c[2][j][l], 1, 1); } if ((fp_prime_get_mod8() % 4) == 3) { @@ -165,7 +190,7 @@ void fp48_frb(fp48_t c, const fp48_t a, int i) { for (int j = 0; j < 3; j++) { for (int k = 0; k < 2; k++) { for (int l = 0; l < 2; l++) { - fp2_mul_frb(c[1][j][k][l], c[1][j][k][l], 2, 3); + fp2_mul_frb(c[1][j][k][l], c[1][j][k][l], 2, 4); } if (fp_prime_get_mod8() == 3) { fp4_mul_art(c[1][j][k], c[1][j][k]); @@ -187,7 +212,7 @@ void fp54_frb(fp54_t c, const fp54_t a, int i) { fp18_frb(c[2], c[2], 1); for (int j = 0; j < 2; j++) { for (int l = 0; l < 3; l++) { - fp3_mul_frb(c[1][j][l], c[1][j][l], 2, 2); + fp3_mul_frb(c[1][j][l], c[1][j][l], 2, 3); fp3_mul_frb(c[2][j][l], c[2][j][l], 2, 1); } /* This is not genreal enough, so hard code parameters needing the diff --git a/src/fpx/relic_fpx_inv.c b/src/fpx/relic_fpx_inv.c index 1ffe85d37..d99c4ace3 100644 --- a/src/fpx/relic_fpx_inv.c +++ b/src/fpx/relic_fpx_inv.c @@ -609,6 +609,82 @@ void fp12_inv_cyc(fp12_t c, const fp12_t a) { fp6_neg(c[1], a[1]); } +void fp16_inv_cyc(fp16_t c, const fp16_t a) { + fp8_copy(c[0], a[0]); + fp8_neg(c[1], a[1]); +} + +void fp16_inv(fp16_t c, const fp16_t a) { + fp8_t t0; + fp8_t t1; + + fp8_null(t0); + fp8_null(t1); + + RLC_TRY { + fp8_new(t0); + fp8_new(t1); + + fp8_sqr(t0, a[0]); + fp8_sqr(t1, a[1]); + fp8_mul_art(t1, t1); + fp8_sub(t0, t0, t1); + fp8_inv(t0, t0); + + fp8_mul(c[0], a[0], t0); + fp8_neg(c[1], a[1]); + fp8_mul(c[1], c[1], t0); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp8_free(t0); + fp8_free(t1); + } +} + +void fp16_inv_sim(fp16_t *c, const fp16_t *a, int n) { + int i; + fp16_t u, *t = RLC_ALLOCA(fp16_t, n); + + for (i = 0; i < n; i++) { + fp16_null(t[i]); + } + fp16_null(u); + + RLC_TRY { + for (i = 0; i < n; i++) { + fp16_new(t[i]); + } + fp16_new(u); + + fp16_copy(c[0], a[0]); + fp16_copy(t[0], a[0]); + + for (i = 1; i < n; i++) { + fp16_copy(t[i], a[i]); + fp16_mul(c[i], c[i - 1], t[i]); + } + + fp16_inv(u, c[n - 1]); + + for (i = n - 1; i > 0; i--) { + fp16_mul(c[i], c[i - 1], u); + fp16_mul(u, u, t[i]); + } + fp16_copy(c[0], u); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + for (i = 0; i < n; i++) { + fp16_free(t[i]); + } + fp16_free(u); + RLC_FREE(t); + } +} + void fp18_inv(fp18_t c, const fp18_t a) { fp9_t t0; fp9_t t1; diff --git a/src/fpx/relic_fpx_pck.c b/src/fpx/relic_fpx_pck.c index 490e8607a..aeeec25f6 100644 --- a/src/fpx/relic_fpx_pck.c +++ b/src/fpx/relic_fpx_pck.c @@ -155,46 +155,46 @@ int fp12_upk_max(fp12_t c, const fp12_t a) { } } -void fp24_pck(fp24_t c, const fp24_t a) { - fp24_copy(c, a); - if (fp24_test_cyc(c)) { - fp4_zero(c[0][0]); - fp4_zero(c[0][1]); +void fp18_pck(fp18_t c, const fp18_t a) { + fp18_copy(c, a); + if (fp18_test_cyc(c)) { + fp2_zero(c[0][0]); + fp2_zero(c[1][1]); } } -int fp24_upk(fp24_t c, const fp24_t a) { - if (fp4_is_zero(a[0][0]) && fp4_is_zero(a[0][1])) { - fp24_back_cyc(c, a); - if (fp24_test_cyc(c)) { +int fp18_upk(fp18_t c, const fp18_t a) { + if (fp2_is_zero(a[0][0]) && fp2_is_zero(a[1][1])) { + fp18_back_cyc(c, a); + if (fp18_test_cyc(c)) { return 1; } else { return 0; } } else { - fp24_copy(c, a); + fp18_copy(c, a); return 1; } } -void fp18_pck(fp18_t c, const fp18_t a) { - fp18_copy(c, a); - if (fp18_test_cyc(c)) { - fp2_zero(c[0][0]); - fp2_zero(c[1][1]); +void fp24_pck(fp24_t c, const fp24_t a) { + fp24_copy(c, a); + if (fp24_test_cyc(c)) { + fp4_zero(c[0][0]); + fp4_zero(c[0][1]); } } -int fp18_upk(fp18_t c, const fp18_t a) { - if (fp2_is_zero(a[0][0]) && fp2_is_zero(a[1][1])) { - fp18_back_cyc(c, a); - if (fp18_test_cyc(c)) { +int fp24_upk(fp24_t c, const fp24_t a) { + if (fp4_is_zero(a[0][0]) && fp4_is_zero(a[0][1])) { + fp24_back_cyc(c, a); + if (fp24_test_cyc(c)) { return 1; } else { return 0; } } else { - fp18_copy(c, a); + fp24_copy(c, a); return 1; } } diff --git a/src/fpx/relic_fpx_srt.c b/src/fpx/relic_fpx_srt.c index 5a08cd827..574e36825 100644 --- a/src/fpx/relic_fpx_srt.c +++ b/src/fpx/relic_fpx_srt.c @@ -36,6 +36,31 @@ /* Public definitions */ /*============================================================================*/ +int fp2_is_sqr(const fp2_t a) { + fp2_t t; + int r = 0; + + fp2_null(t); + + /* QR testing in extension fields from "Square root computation over + * even extension fields", by Gora Adj and Francisco Rodríguez-Henríquez. + * https://eprint.iacr.org/2012/685 */ + + RLC_TRY { + fp2_new(t); + + fp2_frb(t, a, 1); + fp2_mul(t, t, a); + r = fp_is_sqr(t[0]); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp2_free(t); + } + + return r; +} + int fp2_srt(fp2_t c, const fp2_t a) { int r = 0; fp_t t0; @@ -60,7 +85,8 @@ int fp2_srt(fp2_t c, const fp2_t a) { /* special case: either a[0] is square and sqrt is purely 'real' * or a[0] is non-square and sqrt is purely 'imaginary' */ r = 1; - if (fp_srt(t0, a[0])) { + if (fp_is_sqr(a[0])) { + fp_srt(t0, a[0]); fp_copy(c[0], t0); fp_zero(c[1]); } else { @@ -92,20 +118,18 @@ int fp2_srt(fp2_t c, const fp2_t a) { } fp_add(t0, t0, t1); - if (fp_srt(t1, t0)) { + if (fp_is_sqr(t0)) { + fp_srt(t1, t0); /* t0 = (a_0 + sqrt(t0)) / 2 */ fp_add(t0, a[0], t1); fp_hlv(t0, t0); + /* 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)); - if (!fp_srt(t2, t0)) { - /* t0 = (a_0 - sqrt(t0)) / 2 */ - fp_sub(t0, a[0], t1); - fp_hlv(t0, t0); - if (!fp_srt(t2, t0)) { - /* should never happen! */ - RLC_THROW(ERR_NO_VALID); - } - } + /* Should always be a quadratic residue. */ + fp_srt(t2, t0); /* c_0 = sqrt(t0) */ fp_copy(c[0], t2); /* c_1 = a_1 / (2 * sqrt(t0)) */ @@ -127,15 +151,44 @@ int fp2_srt(fp2_t c, const fp2_t a) { return r; } +int fp3_is_sqr(const fp3_t a) { + fp3_t t, u; + int r; + + fp3_null(t); + fp3_null(u); + + RLC_TRY { + fp3_new(t); + fp3_new(u); + + fp3_frb(u, a, 1); + fp3_mul(t, u, a); + fp3_frb(u, u, 1); + fp3_mul(t, t, u); + r = fp_is_sqr(t[0]); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp2_free(t); + fp2_free(u); + } + + return r; +} + int fp3_srt(fp3_t c, const fp3_t a) { - int r = 0; + int f = 0, r = 0; + fp_t root; fp3_t t0, t1, t2, t3; - bn_t e; + bn_t d, e; + fp_null(root); fp3_null(t0); fp3_null(t1); fp3_null(t2); fp3_null(t3); + bn_null(d); bn_null(e); if (fp3_is_zero(a)) { @@ -144,13 +197,72 @@ int fp3_srt(fp3_t c, const fp3_t a) { } RLC_TRY { + fp_new(root); fp3_new(t0); fp3_new(t1); fp3_new(t2); fp3_new(t3); + bn_new(d); bn_new(e); + e->used = RLC_FP_DIGS; + dv_copy(e->dp, fp_prime_get(), RLC_FP_DIGS); + switch (fp_prime_get_mod8()) { + case 1: + /* Implement constant-time version of Tonelli-Shanks algorithm + * as per https://eprint.iacr.org/2020/1497.pdf */ + + /* Compute progenitor as x^(p^3-1-2^f)/2^(f+1) for 2^f|(p-1). + * Let q = (p-1)/2^f. We will write the exponent in p and q. + * Write (p^3-1-2^f)/2^(f+1) as (q*(p^2+p))/2 + (q - 1)/2 */ + bn_sqr(d, e); + bn_add(d, d, e); + bn_rsh(d, d, 1); + /* Compute (q - 1)/2 = (p-1)/2^(f+1).*/ + f = fp_prime_get_2ad(); + bn_sub_dig(e, e, 1); + bn_rsh(e, e, f + 1); + fp3_exp(t1, a, e); + /* Now compute the power (q*(p^2+p))/2. */ + fp3_sqr(t0, t1); + fp3_mul(t0, t0, a); + fp3_exp(t0, t0, d); + fp3_mul(t0, t0, t1); + + /* Generate root of unity, and continue algorithm. */ + dv_copy(root, fp_prime_get_srt(), RLC_FP_DIGS); + + fp3_sqr(t1, t0); + fp3_mul(t1, t1, a); + fp3_mul(t3, t0, a); + fp3_copy(t2, t1); + for (int j = f; j > 1; j--) { + for (int i = 1; i < j - 1; i++) { + fp3_sqr(t2, t2); + } + 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); + 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(t2, t1); + } + break; case 5: fp3_dbl(t3, a); fp3_frb(t0, t3, 1); @@ -163,8 +275,6 @@ int fp3_srt(fp3_t c, const fp3_t a) { fp3_mul(t3, t3, t1); fp3_mul(t0, t0, t3); - e->used = RLC_FP_DIGS; - dv_copy(e->dp, fp_prime_get(), RLC_FP_DIGS); bn_div_dig(e, e, 8); fp3_exp(t0, t0, e); @@ -175,7 +285,7 @@ int fp3_srt(fp3_t c, const fp3_t a) { fp3_mul(t0, t0, a); fp_sub_dig(t1[0], t1[0], 1); - fp3_mul(c, t0, t1); + fp3_mul(t3, t0, t1); break; case 3: case 7: @@ -186,38 +296,69 @@ int fp3_srt(fp3_t c, const fp3_t a) { fp3_mul(t3, t2, a); fp3_mul(t0, t0, t3); - e->used = RLC_FP_DIGS; - dv_copy(e->dp, fp_prime_get(), RLC_FP_DIGS); bn_div_dig(e, e, 4); fp3_exp(t0, t0, e); fp3_mul(t0, t0, a); - fp3_mul(c, t0, t1); + fp3_mul(t3, t0, t1); break; default: fp3_zero(c); break; } - - fp3_sqr(t0, c); - if (fp3_cmp(t0, a) == RLC_EQ) { - r = 1; - } + /* Assume it is a square and test at the end. */ + /* We cannot use QR test because it depends on Frobenius constants. */ + 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); } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { + fp_free(root); fp3_free(t0); fp3_free(t1); fp3_free(t2); fp3_free(t3); + bn_free(d); bn_free(e); } return r; } +int fp4_is_sqr(const fp4_t a) { + fp4_t t, u; + int r; + + fp4_null(t); + fp4_null(u); + + RLC_TRY { + fp4_new(t); + fp4_new(u); + + fp4_frb(u, a, 1); + fp4_mul(t, u, a); + for (int i = 2; i < 4; i++) { + fp4_frb(u, u, 1); + fp4_mul(t, t, u); + } + r = fp_is_sqr(t[0][0]); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp4_free(t); + fp4_free(u); + } + + return r; +} + int fp4_srt(fp4_t c, const fp4_t a) { - int r = 0; + int c0, r = 0; fp2_t t0, t1, t2; fp2_null(t0); @@ -238,8 +379,8 @@ int fp4_srt(fp4_t c, const fp4_t a) { /* special case: either a[0] is square and sqrt is purely 'real' * or a[0] is non-square and sqrt is purely 'imaginary' */ r = 1; - if (fp2_srt(t0, a[0])) { - fp2_copy(c[0], t0); + if (fp2_is_sqr(a[0])) { + fp2_srt(c[0], a[0]); fp2_zero(c[1]); } else { /* Compute a[0]/s^2. */ @@ -259,22 +400,22 @@ int fp4_srt(fp4_t c, const fp4_t a) { fp2_sqr(t1, a[1]); fp2_mul_nor(t2, t1); fp2_sub(t0, t0, t2); - if (fp2_srt(t1, t0)) { + + if (fp2_is_sqr(t0)) { + fp2_srt(t1, t0); /* t0 = (a_0 + sqrt(t0)) / 2 */ fp2_add(t0, a[0], t1); fp_hlv(t0[0], t0[0]); fp_hlv(t0[1], t0[1]); - - if (!fp2_srt(t2, t0)) { - /* t0 = (a_0 - sqrt(t0)) / 2 */ - fp2_sub(t0, a[0], t1); - fp_hlv(t0[0], t0[0]); - fp_hlv(t0[1], t0[1]); - if (!fp2_srt(t2, t0)) { - /* should never happen! */ - RLC_THROW(ERR_NO_VALID); - } - } + c0 = fp2_is_sqr(t0); + /* t0 = (a_0 - sqrt(t0)) / 2 */ + 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); + /* Should always be a quadratic residue. */ + fp2_srt(t2, t0); /* c_0 = sqrt(t0) */ fp2_copy(c[0], t2); @@ -294,3 +435,234 @@ int fp4_srt(fp4_t c, const fp4_t a) { } return r; } + +int fp8_is_sqr(const fp8_t a) { + fp8_t t, u; + int r; + + fp8_null(t); + fp8_null(u); + + RLC_TRY { + fp8_new(t); + fp8_new(u); + + fp8_frb(u, a, 1); + fp8_mul(t, u, a); + for (int i = 2; i < 8; i++) { + fp8_frb(u, u, 1); + fp8_mul(t, t, u); + } + r = fp_is_sqr(t[0][0][0]); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp8_free(t); + fp8_free(u); + } + + return r; +} + +int fp8_srt(fp8_t c, const fp8_t a) { + int c0, r = 0; + fp4_t t0, t1, t2; + + fp4_null(t0); + fp4_null(t1); + fp4_null(t2); + + if (fp8_is_zero(a)) { + fp8_zero(c); + return 1; + } + + RLC_TRY { + fp4_new(t0); + fp4_new(t1); + fp4_new(t2); + + if (fp4_is_zero(a[1])) { + /* special case: either a[0] is square and sqrt is purely 'real' + * or a[0] is non-square and sqrt is purely 'imaginary' */ + r = 1; + if (fp4_is_sqr(a[0])) { + fp4_srt(c[0], a[0]); + fp4_zero(c[1]); + } else { + /* Compute a[0]/s^2. */ + fp4_set_dig(t0, 1); + fp4_mul_art(t0, t0); + fp4_inv(t0, t0); + fp4_mul(t0, a[0], t0); + fp4_zero(c[0]); + if (!fp4_srt(c[1], t0)) { + /* should never happen! */ + RLC_THROW(ERR_NO_VALID); + } + } + } else { + /* t0 = a[0]^2 - s^2 * a[1]^2 */ + fp4_sqr(t0, a[0]); + fp4_sqr(t1, a[1]); + fp4_mul_art(t2, t1); + fp4_sub(t0, t0, t2); + + if (fp4_is_sqr(t0)) { + fp4_srt(t1, t0); + /* t0 = (a_0 + sqrt(t0)) / 2 */ + fp4_add(t0, a[0], t1); + fp_hlv(t0[0][0], t0[0][0]); + fp_hlv(t0[0][1], t0[0][1]); + fp_hlv(t0[1][0], t0[1][0]); + fp_hlv(t0[1][1], t0[1][1]); + c0 = fp4_is_sqr(t0); + /* t0 = (a_0 - sqrt(t0)) / 2 */ + fp4_sub(t1, a[0], t1); + fp_hlv(t1[0][0], t1[0][0]); + 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); + /* Should always be a quadratic residue. */ + fp4_srt(t2, t0); + /* c_0 = sqrt(t0) */ + fp4_copy(c[0], t2); + + /* c_1 = a_1 / (2 * sqrt(t0)) */ + fp4_dbl(t2, t2); + fp4_inv(t2, t2); + fp4_mul(c[1], a[1], t2); + r = 1; + } + } + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp4_free(t0); + fp4_free(t1); + fp4_free(t2); + } + return r; +} + +int fp16_is_sqr(const fp16_t a) { + fp16_t t, u; + int r; + + fp16_null(t); + fp16_null(u); + + RLC_TRY { + fp16_new(t); + fp16_new(u); + + fp16_frb(u, a, 1); + fp16_mul(t, u, a); + for (int i = 2; i < 16; i++) { + fp16_frb(u, u, 1); + fp16_mul(t, t, u); + } + r = fp_is_sqr(t[0][0][0][0]); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp16_free(t); + fp16_free(u); + } + + return r; +} + +int fp16_srt(fp16_t c, const fp16_t a) { + int c0, r = 0; + fp8_t t0, t1, t2; + + fp8_null(t0); + fp8_null(t1); + fp8_null(t2); + + if (fp16_is_zero(a)) { + fp16_zero(c); + return 1; + } + + RLC_TRY { + fp8_new(t0); + fp8_new(t1); + fp8_new(t2); + + if (fp8_is_zero(a[1])) { + /* special case: either a[0] is square and sqrt is purely 'real' + * or a[0] is non-square and sqrt is purely 'imaginary' */ + r = 1; + if (fp8_is_sqr(a[0])) { + fp8_srt(c[0], a[0]); + fp8_zero(c[1]); + } else { + /* Compute a[0]/s^2. */ + fp8_set_dig(t0, 1); + fp8_mul_art(t0, t0); + fp8_inv(t0, t0); + fp8_mul(t0, a[0], t0); + fp8_zero(c[0]); + if (!fp8_srt(c[1], t0)) { + /* should never happen! */ + RLC_THROW(ERR_NO_VALID); + } + } + } else { + /* t0 = a[0]^2 - s^2 * a[1]^2 */ + fp8_sqr(t0, a[0]); + fp8_sqr(t1, a[1]); + fp8_mul_art(t2, t1); + fp8_sub(t0, t0, t2); + + if (fp8_is_sqr(t0)) { + fp8_srt(t1, t0); + /* t0 = (a_0 + sqrt(t0)) / 2 */ + fp8_add(t0, a[0], t1); + fp_hlv(t0[0][0][0], t0[0][0][0]); + fp_hlv(t0[0][0][1], t0[0][0][1]); + fp_hlv(t0[0][1][0], t0[0][1][0]); + fp_hlv(t0[0][1][1], t0[0][1][1]); + fp_hlv(t0[1][0][0], t0[1][0][0]); + fp_hlv(t0[1][0][1], t0[1][0][1]); + fp_hlv(t0[1][1][0], t0[1][1][0]); + fp_hlv(t0[1][1][1], t0[1][1][1]); + c0 = fp8_is_sqr(t0); + /* t0 = (a_0 - sqrt(t0)) / 2 */ + fp8_sub(t1, a[0], t1); + for (int i = 0; i < 2; i++) { + 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); + } + } + } + /* Should always be a quadratic residue. */ + fp8_srt(t2, t0); + /* c_0 = sqrt(t0) */ + fp8_copy(c[0], t2); + + /* c_1 = a_1 / (2 * sqrt(t0)) */ + fp8_dbl(t2, t2); + fp8_inv(t2, t2); + fp8_mul(c[1], a[1], t2); + r = 1; + } + } + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp8_free(t0); + fp8_free(t1); + fp8_free(t2); + } + return r; +} diff --git a/src/fpx/relic_fpx_util.c b/src/fpx/relic_fpx_util.c index cc171850f..bbc946c41 100644 --- a/src/fpx/relic_fpx_util.c +++ b/src/fpx/relic_fpx_util.c @@ -504,6 +504,65 @@ void fp12_set_dig(fp12_t a, const dig_t b) { fp6_zero(a[1]); } +void fp16_copy(fp16_t c, const fp16_t a) { + fp8_copy(c[0], a[0]); + fp8_copy(c[1], a[1]); +} + +void fp16_zero(fp16_t a) { + fp8_zero(a[0]); + fp8_zero(a[1]); +} + +int fp16_is_zero(const fp16_t a) { + return fp8_is_zero(a[0]) && fp8_is_zero(a[1]); +} + +void fp16_rand(fp16_t a) { + fp8_rand(a[0]); + fp8_rand(a[1]); +} + +void fp16_print(const fp16_t a) { + fp8_print(a[0]); + fp8_print(a[1]); +} + +int fp16_size_bin(fp16_t a, int pack) { + if (pack) { + if (fp16_test_cyc(a)) { + return 8 * RLC_FP_BYTES; + } else { + return 16 * RLC_FP_BYTES; + } + } else { + return 16 * RLC_FP_BYTES; + } +} + +void fp16_read_bin(fp16_t a, const uint8_t *bin, size_t len) { + if (len != 16 * RLC_FP_BYTES) { + RLC_THROW(ERR_NO_BUFFER); + return; + } + fp8_read_bin(a[0], bin, 8 * RLC_FP_BYTES); + fp8_read_bin(a[1], bin + 8 * RLC_FP_BYTES, 8 * RLC_FP_BYTES); +} + +void fp16_write_bin(uint8_t *bin, size_t len, const fp16_t a, int pack) { + if (len != 16 * RLC_FP_BYTES) { + 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]); +} + +void fp16_set_dig(fp16_t a, const dig_t b) { + fp8_set_dig(a[0], b); + fp8_zero(a[1]); +} + void fp18_copy(fp18_t c, const fp18_t a) { fp9_copy(c[0], a[0]); fp9_copy(c[1], a[1]); diff --git a/src/low/easy/relic_bn_mul_low.c b/src/low/easy/relic_bn_mul_low.c index 0e4c67e4d..4233d2eb5 100644 --- a/src/low/easy/relic_bn_mul_low.c +++ b/src/low/easy/relic_bn_mul_low.c @@ -64,24 +64,21 @@ dig_t bn_mul1_low(dig_t *c, const dig_t *a, dig_t digit, int size) { return carry; } -dig_t bn_muls_low(dig_t *c, const dig_t *a, dig_t sa, dis_t digit, int size) { - dig_t r, _a, _c, c0, c1, c2, sign, sd = digit >> (RLC_DIG - 1); +dig_t bn_muls_low(dig_t *c, const dig_t *a, dig_t sa, dis_t digit, + int size) { + dig_t r, _c, c0, c1, sign, sd = digit >> (RLC_DIG - 1); sa = -sa; sign = sa ^ sd; digit = (digit ^ sd) - sd; - _a = (a[0] ^ sa) - sa; - c2 = (_a < (a[0] ^ sa)); - RLC_MUL_DIG(r, _c, _a, (dig_t)digit); + RLC_MUL_DIG(r, _c, a[0], (dig_t)digit); _c ^= sign; c[0] = _c - sign; c1 = (c[0] < _c); c0 = r; for (int i = 1; i < size; i++) { - _a = (a[i] ^ sa) + c2; - c2 = (_a < c2); - RLC_MUL_DIG(r, _c, _a, (dig_t)digit); + RLC_MUL_DIG(r, _c, a[i], (dig_t)digit); _c += c0; c0 = r + (_c < c0); _c ^= sign; diff --git a/src/low/easy/relic_fpx_add_low.c b/src/low/easy/relic_fpx_add_low.c index 378c5b279..b24055cf1 100755 --- a/src/low/easy/relic_fpx_add_low.c +++ b/src/low/easy/relic_fpx_add_low.c @@ -286,12 +286,14 @@ void fp3_dblm_low(fp3_t c, fp3_t a) { } void fp3_nord_low(dv3_t c, dv3_t a) { - dv3_t t; + dv3_t t, u; dv3_null(t); + dv3_null(u); RLC_TRY { dv3_new(t); + dv3_new(u); dv_copy(t[0], a[2], 2 * RLC_FP_DIGS); for (int i = 1; i < fp_prime_get_cnr(); i++) { @@ -305,26 +307,30 @@ void fp3_nord_low(dv3_t c, dv3_t a) { int cnr = fp3_field_get_cnr(); switch (fp_prime_get_mod18()) { + case 1: case 7: - /* If p = 7 mod 8, (2^k + i) is a QNR/CNR. */ - dv_copy(c[0], a[0], 2 * RLC_FP_DIGS); - dv_copy(c[1], a[1], 2 * RLC_FP_DIGS); - dv_copy(c[2], a[2], 2 * RLC_FP_DIGS); - while (cnr > 1) { - fp3_addc_low(c, c, c); - cnr = cnr >> 1; + if (cnr != 0) { + dv_copy(u[0], a[0], 2 * RLC_FP_DIGS); + dv_copy(u[1], a[1], 2 * RLC_FP_DIGS); + dv_copy(u[2], a[2], 2 * RLC_FP_DIGS); + while (cnr > 1) { + fp3_addc_low(u, u, u); + if (cnr & 1) { + fp3_addc_low(u, u, a); + } + cnr = cnr >> 1; + } + fp3_addc_low(t, t, u); } - fp3_addc_low(c, c, t); break; - default: - dv_copy(c[0], t[0], 2 * RLC_FP_DIGS); - dv_copy(c[1], t[1], 2 * RLC_FP_DIGS); - dv_copy(c[2], t[2], 2 * RLC_FP_DIGS); - break; - } + } + dv_copy(c[0], t[0], 2 * RLC_FP_DIGS); + dv_copy(c[1], t[1], 2 * RLC_FP_DIGS); + dv_copy(c[2], t[2], 2 * RLC_FP_DIGS); } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { dv3_free(t); + dv3_free(u); } } diff --git a/src/low/gmp-sec/relic_bn_mul_low.c b/src/low/gmp-sec/relic_bn_mul_low.c index 5fa5d265e..082815ede 100644 --- a/src/low/gmp-sec/relic_bn_mul_low.c +++ b/src/low/gmp-sec/relic_bn_mul_low.c @@ -61,11 +61,7 @@ dig_t bn_muls_low(dig_t *c, const dig_t *a, dig_t sa, dis_t digit, int size) { sign = sa ^ sd; digit = (digit ^ sd) - sd; - for (size_t i = 0; i < size; i++) { - _a[i] = a[i] ^ sa; - } - bn_add1_low(_a, _a, -sa, size); - carry = bn_mul1_low(c, _a, (dig_t)digit, size); + carry = bn_mul1_low(c, a, (dig_t)digit, size); for (size_t i = 0; i < size; i++) { c[i] = c[i] ^ sign; } diff --git a/src/low/gmp/relic_bn_mul_low.c b/src/low/gmp/relic_bn_mul_low.c index a6806a55f..6b88f9c12 100644 --- a/src/low/gmp/relic_bn_mul_low.c +++ b/src/low/gmp/relic_bn_mul_low.c @@ -49,17 +49,13 @@ dig_t bn_mul1_low(dig_t *c, const dig_t *a, dig_t digit, int size) { } dig_t bn_muls_low(dig_t *c, const dig_t *a, dig_t sa, dis_t digit, int size) { - dig_t _a[size], carry, sign, sd = digit >> (RLC_DIG - 1); + dig_t carry, sign, sd = digit >> (RLC_DIG - 1); sa = -sa; sign = sa ^ sd; digit = (digit ^ sd) - sd; - for (size_t i = 0; i < size; i++) { - _a[i] = a[i] ^ sa; - } - mpn_add_1(_a, _a, size, -sa); - carry = mpn_mul_1(c, _a, size, digit); + carry = mpn_mul_1(c, a, size, digit); for (size_t i = 0; i < size; i++) { c[i] = c[i] ^ sign; } diff --git a/src/low/gmp/relic_fp_add_low.c b/src/low/gmp/relic_fp_add_low.c index b5c6dc505..535cb8116 100644 --- a/src/low/gmp/relic_fp_add_low.c +++ b/src/low/gmp/relic_fp_add_low.c @@ -111,7 +111,7 @@ dig_t fp_dbln_low(dig_t *c, const dig_t *a) { void fp_dblm_low(dig_t *c, const dig_t *a) { dig_t carry = mpn_add_n(c, a, a, RLC_FP_DIGS); if (carry || (dv_cmp(c, fp_prime_get(), RLC_FP_DIGS) != RLC_LT)) { - carry = fp_subn_low(c, c, fp_prime_get()); + carry = mpn_sub_n(c, c, fp_prime_get(), RLC_FP_DIGS); } } diff --git a/src/low/x64-asm-8l/relic_fp_smb_low.c b/src/low/gmp/relic_fp_smb_low.c similarity index 97% rename from src/low/x64-asm-8l/relic_fp_smb_low.c rename to src/low/gmp/relic_fp_smb_low.c index d25200282..7c4b9b654 100644 --- a/src/low/x64-asm-8l/relic_fp_smb_low.c +++ b/src/low/gmp/relic_fp_smb_low.c @@ -1,6 +1,6 @@ /* * RELIC is an Efficient LIbrary for Cryptography - * Copyright (c) 2021 RELIC Authors + * Copyright (c) 2023 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 @@ -61,6 +61,7 @@ int fp_smbm_low(const dig_t *a) { res = mpz_jacobi(n, p); + (void)t; mpz_clear(n); mpz_clear(p); return res; diff --git a/src/low/x64-asm-10l/relic_fp_add_low.s b/src/low/x64-asm-10l/relic_fp_add_low.s index 3905176d3..70ab7b72c 100644 --- a/src/low/x64-asm-10l/relic_fp_add_low.s +++ b/src/low/x64-asm-10l/relic_fp_add_low.s @@ -455,6 +455,21 @@ cdecl(fp_subc_low): ret cdecl(fp_negm_low): + push %rbx + push %rbp + push %r12 + push %r13 + + xorq %r9, %r9 + xorq %r10, %r10 + xorq %r11, %r11 + xorq %r12, %r12 + xorq %r13, %r13 + xorq %rbx, %rbx + xorq %rbp, %rbp + xorq %rax, %rax + xorq %rcx, %rcx + movq 0(%rsi) , %r8 or 8(%rsi) , %r8 or 16(%rsi), %r8 @@ -464,37 +479,43 @@ cdecl(fp_negm_low): or 48(%rsi), %r8 or 56(%rsi), %r8 or 64(%rsi), %r8 + or 72(%rsi), %r8 test %r8, %r8 cmovnz p0(%rip), %r8 + cmovnz p1(%rip), %r9 + cmovnz p2(%rip), %r10 + cmovnz p3(%rip), %r11 + cmovnz p4(%rip), %rbx + cmovnz p5(%rip), %rbp + cmovnz p6(%rip), %r12 + cmovnz p7(%rip), %r13 + cmovnz p8(%rip), %rax + cmovnz p9(%rip), %rcx subq 0(%rsi) , %r8 movq %r8 , 0(%rdi) - cmovnz p1(%rip), %r8 - sbbq 8(%rsi) , %r8 - movq %r8 , 8(%rdi) - cmovnz p2(%rip), %r8 - sbbq 16(%rsi), %r8 - movq %r8 , 16(%rdi) - cmovnz p3(%rip), %r8 - sbbq 24(%rsi), %r8 - movq %r8 , 24(%rdi) - cmovnz p4(%rip), %r8 - sbbq 32(%rsi), %r8 - movq %r8 , 32(%rdi) - cmovnz p5(%rip), %r8 - sbbq 40(%rsi), %r8 - movq %r8 , 40(%rdi) - cmovnz p6(%rip), %r8 - sbbq 48(%rsi), %r8 - movq %r8 , 48(%rdi) - cmovnz p7(%rip), %r8 - sbbq 56(%rsi), %r8 - movq %r8 , 56(%rdi) - cmovnz p8(%rip), %r8 - sbbq 64(%rsi), %r8 - movq %r8 , 64(%rdi) - cmovnz p9(%rip), %r8 - sbbq 72(%rsi), %r8 - movq %r8 , 72(%rdi) + sbbq 8(%rsi) , %r9 + movq %r9 , 8(%rdi) + sbbq 16(%rsi), %r10 + movq %r10 , 16(%rdi) + sbbq 24(%rsi), %r11 + movq %r11 , 24(%rdi) + sbbq 32(%rsi), %rbx + movq %rbx , 32(%rdi) + sbbq 40(%rsi), %rbp + movq %rbp , 40(%rdi) + sbbq 48(%rsi), %r12 + movq %r12 , 48(%rdi) + sbbq 56(%rsi), %r13 + movq %r13 , 56(%rdi) + sbbq 64(%rsi), %rax + movq %rax , 64(%rdi) + sbbq 72(%rsi), %rcx + movq %rcx , 72(%rdi) + + pop %r13 + pop %r12 + pop %rbp + pop %rbx ret cdecl(fp_dbln_low): @@ -670,7 +691,7 @@ cdecl(fp_hlvm_low): adcq %rdx , %r15 movq 64(%rsi), %rdx adcq %rdx , %rbp - mov 72(%rsi), %rdx + movq 72(%rsi), %rdx adcq %rdx ,%rbx rcrq $1, %rbx @@ -714,6 +735,10 @@ cdecl(fp_hlvd_low): xorq %rdx, %rdx + movq $1 ,%rbp + movq 0(%rsi),%rcx + andq %rcx ,%rbp + movq $P0, %r8 movq $P1, %r9 movq $P2, %r10 @@ -725,10 +750,6 @@ cdecl(fp_hlvd_low): movq $P8, %rax movq $P9, %rbx - movq $1 ,%rbp - movq 0(%rsi),%rcx - andq %rcx ,%rbp - cmovz %rdx, %r8 cmovz %rdx, %r9 cmovz %rdx, %r10 diff --git a/src/low/x64-asm-12l/CMakeLists.txt b/src/low/x64-asm-12l/CMakeLists.txt new file mode 100644 index 000000000..ecca66b65 --- /dev/null +++ b/src/low/x64-asm-12l/CMakeLists.txt @@ -0,0 +1,6 @@ +set(INHERIT "gmp") +include(../cmake/gmp.cmake) +if(GMP_FOUND) + include_directories(${GMP_INCLUDE_DIR}) + set(ARITH_LIBS ${GMP_LIBRARIES}) +endif(GMP_FOUND) diff --git a/src/low/x64-asm-12l/macro.s b/src/low/x64-asm-12l/macro.s new file mode 100644 index 000000000..a33c14129 --- /dev/null +++ b/src/low/x64-asm-12l/macro.s @@ -0,0 +1,332 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 . + */ + +#include "relic_fp_low.h" + +/** + * @file + * + * Implementation of low-level prime field multiplication. + * + * @ingroup fp + */ + +#if FP_PRIME == 766 +/* KSS16-P766 */ +#define P0 0xB955C8905EF99F8D +#define P1 0x7D1C278139EFCE97 +#define P2 0xB72041F5E8174021 +#define P3 0xBC0E3DEC45049335 +#define P4 0xB2CBF189D4D4B3CB +#define P5 0x941663A5AAF69407 +#define P6 0x74C81A64B9FAAE0C +#define P7 0xB691EBF6CC4A8A9B +#define P8 0x24FB15165CCAB927 +#define P9 0x91D2481C864D19F7 +#define P10 0xD1F39E5F37AEACB3 +#define P11 0x3C410B7E6EC19106 +#define U0 0xC18CA908C52344BB +#elif FP_PRIME == 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 +#endif + +#if defined(__APPLE__) +#define cdecl(S) _PREFIX(,S) +#else +#define cdecl(S) S +#endif + +.text + +.macro ADD1 i, j + movq 8*\i(%rsi), %r10 + adcq $0, %r10 + movq %r10, 8*\i(%rdi) + .if \i - \j + ADD1 "(\i + 1)", \j + .endif +.endm + +.macro ADDN i, j + movq 8*\i(%rdx), %r11 + adcq 8*\i(%rsi), %r11 + movq %r11, 8*\i(%rdi) + .if \i - \j + ADDN "(\i + 1)", \j + .endif +.endm + +.macro SUB1 i, j + movq 8*\i(%rsi),%r10 + sbbq $0, %r10 + movq %r10,8*\i(%rdi) + .if \i - \j + SUB1 "(\i + 1)", \j + .endif +.endm + +.macro SUBN i, j + movq 8*\i(%rsi), %r8 + sbbq 8*\i(%rdx), %r8 + movq %r8, 8*\i(%rdi) + .if \i - \j + SUBN "(\i + 1)", \j + .endif +.endm + +.macro DBLN i, j + movq 8*\i(%rsi), %r8 + adcq %r8, %r8 + movq %r8, 8*\i(%rdi) + .if \i - \j + DBLN "(\i + 1)", \j + .endif +.endm + +.macro MULN i, j, k, C, R0, R1, R2, A, B + .if \j > \k + movq 8*\i(\A), %rax + mulq 8*\j(\B) + addq %rax , \R0 + adcq %rdx , \R1 + adcq $0 , \R2 + MULN "(\i + 1)", "(\j - 1)", \k, \C, \R0, \R1, \R2, \A, \B + .else + movq 8*\i(\A), %rax + mulq 8*\j(\B) + addq %rax , \R0 + movq \R0 , 8*(\i+\j)(\C) + adcq %rdx , \R1 + adcq $0 , \R2 + .endif +.endm + +.macro FP_MULN_LOW C, R0, R1, R2, A, B + movq 0(\A),%rax + mulq 0(\B) + movq %rax ,0(\C) + movq %rdx ,\R0 + + xorq \R1,\R1 + xorq \R2,\R2 + MULN 0, 1, 0, \C, \R0, \R1, \R2, \A, \B + xorq \R0,\R0 + MULN 0, 2, 0, \C, \R1, \R2, \R0, \A, \B + xorq \R1,\R1 + MULN 0, 3, 0, \C, \R2, \R0, \R1, \A, \B + xorq \R2,\R2 + MULN 0, 4, 0, \C, \R0, \R1, \R2, \A, \B + xorq \R0,\R0 + MULN 0, 5, 0, \C, \R1, \R2, \R0, \A, \B + xorq \R1,\R1 + MULN 0, 6, 0, \C, \R2, \R0, \R1, \A, \B + xorq \R2,\R2 + MULN 0, 7, 0, \C, \R0, \R1, \R2, \A, \B + xorq \R0,\R0 + MULN 0, 8, 0, \C, \R1, \R2, \R0, \A, \B + xorq \R1,\R1 + MULN 0, 9, 0, \C, \R2, \R0, \R1, \A, \B + xorq \R2,\R2 + MULN 0,10, 0, \C, \R0, \R1, \R2, \A, \B + xorq \R0,\R0 + MULN 0,11, 0, \C, \R1, \R2, \R0, \A, \B + xorq \R1,\R1 + MULN 1,11, 1, \C, \R2, \R0, \R1, \A, \B + xorq \R2,\R2 + MULN 2,11, 2, \C, \R0, \R1, \R2, \A, \B + xorq \R0,\R0 + MULN 3,11, 3, \C, \R1, \R2, \R0, \A, \B + xorq \R1,\R1 + MULN 4,11, 4, \C, \R2, \R0, \R1, \A, \B + xorq \R2,\R2 + MULN 5,11, 5, \C, \R0, \R1, \R2, \A, \B + xorq \R0,\R0 + MULN 6,11, 6, \C, \R1, \R2, \R0, \A, \B + xorq \R1,\R1 + MULN 7,11, 7, \C, \R2, \R0, \R1, \A, \B + xorq \R2,\R2 + MULN 8,11, 8, \C, \R0, \R1, \R2, \A, \B + xorq \R0,\R0 + MULN 9,11, 9, \C, \R1, \R2, \R0, \A, \B + xorq \R1,\R1 + MULN 10,11,10, \C, \R2, \R0, \R1, \A, \B + + movq 88(\A),%rax + mulq 88(\B) + addq %rax ,\R0 + movq \R0 ,176(\C) + adcq %rdx ,\R1 + movq \R1 ,184(\C) +.endm + +.macro _RDCN0 i, j, k, R0, R1, R2 A, P + movq 8*\i(\A), %rax + mulq 8*\j(\P) + addq %rax, \R0 + adcq %rdx, \R1 + adcq $0, \R2 + .if \j > 1 + _RDCN0 "(\i + 1)", "(\j - 1)", \k, \R0, \R1, \R2, \A, \P + .else + addq 8*\k(\A), \R0 + adcq $0, \R1 + adcq $0, \R2 + movq \R0, %rax + mulq %rcx + movq %rax, 8*\k(\A) + mulq 0(\P) + addq %rax , \R0 + adcq %rdx , \R1 + adcq $0 , \R2 + xorq \R0, \R0 + .endif +.endm + +.macro RDCN0 i, j, R0, R1, R2, A, P + _RDCN0 \i, \j, \j, \R0, \R1, \R2, \A, \P +.endm + +.macro _RDCN1 i, j, k, l, R0, R1, R2 A, P + movq 8*\i(\A), %rax + mulq 8*\j(\P) + addq %rax, \R0 + adcq %rdx, \R1 + adcq $0, \R2 + .if \j > \l + _RDCN1 "(\i + 1)", "(\j - 1)", \k, \l, \R0, \R1, \R2, \A, \P + .else + addq 8*\k(\A), \R0 + adcq $0, \R1 + adcq $0, \R2 + movq \R0, 8*\k(\A) + xorq \R0, \R0 + .endif +.endm + +.macro RDCN1 i, j, R0, R1, R2, A, P + _RDCN1 \i, \j, "(\i + \j)", \i, \R0, \R1, \R2, \A, \P +.endm + +// r8, r9, r10, r11, r12, r13, r14, r15, rbp, rbx, rsp, //rsi, rdi, //rax, rcx, rdx +.macro FP_RDCN_LOW C, R0, R1, R2, A, P + xorq \R1, \R1 + movq $U0, %rcx + + movq 0(\A), \R0 + movq \R0 , %rax + mulq %rcx + movq %rax , 0(\A) + mulq 0(\P) + addq %rax , \R0 + adcq %rdx , \R1 + xorq \R2 , \R2 + xorq \R0 , \R0 + + RDCN0 0, 1, \R1, \R2, \R0, \A, \P + RDCN0 0, 2, \R2, \R0, \R1, \A, \P + RDCN0 0, 3, \R0, \R1, \R2, \A, \P + RDCN0 0, 4, \R1, \R2, \R0, \A, \P + RDCN0 0, 5, \R2, \R0, \R1, \A, \P + RDCN0 0, 6, \R0, \R1, \R2, \A, \P + RDCN0 0, 7, \R1, \R2, \R0, \A, \P + RDCN0 0, 8, \R2, \R0, \R1, \A, \P + RDCN0 0, 9, \R0, \R1, \R2, \A, \P + RDCN0 0,10, \R1, \R2, \R0, \A, \P + RDCN0 0,11, \R2, \R0, \R1, \A, \P + RDCN1 1,11, \R0, \R1, \R2, \A, \P + RDCN1 2,11, \R1, \R2, \R0, \A, \P + RDCN1 3,11, \R2, \R0, \R1, \A, \P + RDCN1 4,11, \R0, \R1, \R2, \A, \P + RDCN1 5,11, \R1, \R2, \R0, \A, \P + RDCN1 6,11, \R2, \R0, \R1, \A, \P + RDCN1 7,11, \R0, \R1, \R2, \A, \P + RDCN1 8,11, \R1, \R2, \R0, \A, \P + RDCN1 9,11, \R2, \R0, \R1, \A, \P + RDCN1 10,11,\R0, \R1, \R2, \A, \P + RDCN1 11,11,\R1, \R2, \R0, \A, \P + addq 184(\A), \R2 + movq \R2, 184(\A) + + movq 96(\A), %r11 + movq 104(\A), %r12 + movq 112(\A), %r13 + movq 120(\A), %r14 + movq 128(\A), %r15 + movq 136(\A), %rcx + movq 144(\A), %rbp + movq 152(\A), %rdx + movq 160(\A), %r8 + movq 168(\A), %r9 + movq 176(\A), %r10 + movq 184(\A), %rax + + subq p0(%rip), %r11 + sbbq p1(%rip), %r12 + sbbq p2(%rip), %r13 + sbbq p3(%rip), %r14 + sbbq p4(%rip), %r15 + sbbq p5(%rip), %rcx + sbbq p6(%rip), %rbp + sbbq p7(%rip), %rdx + sbbq p8(%rip), %r8 + sbbq p9(%rip), %r9 + sbbq p10(%rip), %r10 + sbbq p11(%rip), %rax + + cmovc 96(\A), %r11 + cmovc 104(\A), %r12 + cmovc 112(\A), %r13 + cmovc 120(\A), %r14 + cmovc 128(\A), %r15 + cmovc 136(\A), %rcx + cmovc 144(\A), %rbp + cmovc 152(\A), %rdx + cmovc 160(\A), %r8 + cmovc 168(\A), %r9 + cmovc 176(\A), %r10 + cmovc 184(\A), %rax + movq %r11,0(\C) + movq %r12,8(\C) + movq %r13,16(\C) + movq %r14,24(\C) + movq %r15,32(\C) + movq %rcx,40(\C) + movq %rbp,48(\C) + movq %rdx,56(\C) + movq %r8,64(\C) + movq %r9,72(\C) + movq %r10,80(\C) + movq %rax,88(\C) +.endm diff --git a/src/low/x64-asm-12l/relic_fp_add_low.s b/src/low/x64-asm-12l/relic_fp_add_low.s new file mode 100644 index 000000000..d5e418c5e --- /dev/null +++ b/src/low/x64-asm-12l/relic_fp_add_low.s @@ -0,0 +1,977 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2017 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 . + */ + +#include "relic_fp_low.h" + +/** + * @file + * + * Implementation of the low-level prime field addition and subtraction + * functions. + * + * @ingroup fp + */ + +#include "macro.s" + +.data + +p0: .quad P0 +p1: .quad P1 +p2: .quad P2 +p3: .quad P3 +p4: .quad P4 +p5: .quad P5 +p6: .quad P6 +p7: .quad P7 +p8: .quad P8 +p9: .quad P9 +p10:.quad P10 +p11:.quad P11 + +.global p0 +.global p1 +.global p2 +.global p3 +.global p4 +.global p5 +.global p6 +.global p7 +.global p8 +.global p9 +.global p10 +.global p11 + +.hidden p0 +.hidden p1 +.hidden p2 +.hidden p3 +.hidden p4 +.hidden p5 +.hidden p6 +.hidden p7 +.hidden p8 +.hidden p9 +.global p10 +.global p11 + +.text + +.global cdecl(fp_add1_low) +.global cdecl(fp_addn_low) +.global cdecl(fp_addm_low) +.global cdecl(fp_addd_low) +.global cdecl(fp_addc_low) +.global cdecl(fp_sub1_low) +.global cdecl(fp_subn_low) +.global cdecl(fp_subm_low) +.global cdecl(fp_subd_low) +.global cdecl(fp_subc_low) +.global cdecl(fp_negm_low) +.global cdecl(fp_dbln_low) +.global cdecl(fp_dblm_low) +.global cdecl(fp_hlvm_low) +.global cdecl(fp_hlvd_low) + +cdecl(fp_add1_low): + movq 0(%rsi), %r10 + addq %rdx , %r10 + movq %r10 , 0(%rdi) + + ADD1 1, (RLC_FP_DIGS - 1) + + ret + +cdecl(fp_addn_low): + movq 0(%rdx), %r10 + addq 0(%rsi), %r10 + movq %r10 , 0(%rdi) + + ADDN 1, (RLC_FP_DIGS - 1) + + xorq %rax, %rax + + ret + +cdecl(fp_addm_low): + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + push %rdi + + movq 0(%rdx), %r8 + addq 0(%rsi), %r8 + movq 8(%rdx), %r9 + adcq 8(%rsi), %r9 + movq 16(%rdx), %r10 + adcq 16(%rsi), %r10 + movq 24(%rdx), %r11 + adcq 24(%rsi), %r11 + movq 32(%rdx), %r12 + adcq 32(%rsi), %r12 + movq 40(%rdx), %r13 + adcq 40(%rsi), %r13 + movq 48(%rdx), %r14 + adcq 48(%rsi), %r14 + movq 56(%rdx), %r15 + adcq 56(%rsi), %r15 + movq %r15 , 0(%rdi) + movq %r15 , 8(%rdi) + movq 64(%rdx), %rax + adcq 64(%rsi), %rax + movq %rax , 16(%rdi) + movq %rax , 24(%rdi) + movq 72(%rdx), %rcx + adcq 72(%rsi), %rcx + movq %rcx , 32(%rdi) + movq %rcx , 40(%rdi) + movq 80(%rdx), %rax + adcq 80(%rsi), %rax + movq %rax , 48(%rdi) + movq %rax , 56(%rdi) + movq 88(%rdx), %rcx + adcq 88(%rsi), %rcx + movq %rcx , 64(%rdi) + movq %rcx , 72(%rdi) + + movq %rdi, %r15 + + movq %r8 , %rax + movq %r9 , %rcx + movq %r10, %rdx + movq %r11, %rsi + movq %r12, %rbx + movq %r13, %rbp + movq %r14, %rdi + + subq p0(%rip), %rax + sbbq p1(%rip), %rcx + sbbq p2(%rip), %rdx + sbbq p3(%rip), %rsi + sbbq p4(%rip), %rbx + sbbq p5(%rip), %rbp + sbbq p6(%rip), %rdi + + push %rdi + + movq %r15, %rdi + movq 8(%rdi), %r15 + sbbq p7(%rip), %r15 + movq %r15, 8(%rdi) + movq 24(%rdi), %r15 + sbbq p8(%rip), %r15 + movq %r15, 24(%rdi) + movq 40(%rdi), %r15 + sbbq p9(%rip), %r15 + movq %r15, 40(%rdi) + movq 56(%rdi) , %r15 + sbbq p10(%rip), %r15 + movq %r15, 56(%rdi) + movq 72(%rdi) , %r15 + sbbq p11(%rip), %r15 + movq %r15, 72(%rdi) + + pop %rdi + cmovnc %rax, %r8 + cmovnc %rcx, %r9 + cmovnc %rdx, %r10 + cmovnc %rsi, %r11 + cmovnc %rbx, %r12 + cmovnc %rbp, %r13 + cmovnc %rdi, %r14 + pop %rdi + movq 0(%rdi) , %r15 + movq 16(%rdi), %rax + movq 32(%rdi), %rcx + movq 48(%rdi), %rbx + movq 64(%rdi), %rbp + cmovnc 8(%rdi) , %r15 + cmovnc 24(%rdi), %rax + cmovnc 40(%rdi), %rcx + cmovnc 56(%rdi), %rbx + cmovnc 72(%rdi), %rbp + + movq %r8 , 0(%rdi) + movq %r9 , 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 32(%rdi) + movq %r13, 40(%rdi) + movq %r14, 48(%rdi) + movq %r15, 56(%rdi) + movq %rax, 64(%rdi) + movq %rcx, 72(%rdi) + movq %rbx, 80(%rdi) + movq %rbp, 88(%rdi) + xorq %rax, %rax + + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + ret + +cdecl(fp_addd_low): + movq 0(%rdx), %r11 + addq 0(%rsi), %r11 + movq %r11 , 0(%rdi) + + ADDN 1, (2 * RLC_FP_DIGS - 1) + + xorq %rax, %rax + + ret + +cdecl(fp_addc_low): + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + push %rdi + + movq 0(%rsi), %r8 + addq 0(%rdx), %r8 + movq %r8 , 0(%rdi) + + ADDN 1, (RLC_FP_DIGS - 1) + + movq 96(%rsi), %r8 + adcq 96(%rdx), %r8 + movq 104(%rsi), %r9 + adcq 104(%rdx), %r9 + movq 112(%rsi), %r10 + adcq 112(%rdx), %r10 + movq 120(%rsi), %r11 + adcq 120(%rdx), %r11 + movq 128(%rsi), %r12 + adcq 128(%rdx), %r12 + movq 136(%rsi), %r13 + adcq 136(%rdx), %r13 + movq 144(%rsi), %r14 + adcq 144(%rdx), %r14 + movq 152(%rsi), %r15 + adcq 152(%rdx), %r15 + movq %r15 , 96(%rdi) + movq %r15 ,104(%rdi) + movq 160(%rdx), %rax + adcq 160(%rsi), %rax + movq %rax , 112(%rdi) + movq %rax , 120(%rdi) + movq 168(%rdx), %rcx + adcq 168(%rsi), %rcx + movq %rcx , 128(%rdi) + movq %rcx , 136(%rdi) + movq 176(%rdx), %rax + adcq 176(%rsi), %rax + movq %rax , 144(%rdi) + movq %rax , 152(%rdi) + movq 184(%rdx), %rcx + adcq 184(%rsi), %rcx + movq %rcx , 160(%rdi) + movq %rcx , 168(%rdi) + + movq %rdi, %r15 + + movq %r8 , %rax + movq %r9 , %rcx + movq %r10, %rdx + movq %r11, %rsi + movq %r12, %rbx + movq %r13, %rbp + movq %r14, %rdi + + subq p0(%rip), %rax + sbbq p1(%rip), %rcx + sbbq p2(%rip), %rdx + sbbq p3(%rip), %rsi + sbbq p4(%rip), %rbx + sbbq p5(%rip), %rbp + sbbq p6(%rip), %rdi + + push %rdi + + movq %r15, %rdi + movq 104(%rdi), %r15 + sbbq p7(%rip), %r15 + movq %r15, 104(%rdi) + movq 120(%rdi), %r15 + sbbq p8(%rip), %r15 + movq %r15, 120(%rdi) + movq 136(%rdi), %r15 + sbbq p9(%rip), %r15 + movq %r15, 136(%rdi) + movq 152(%rdi), %r15 + sbbq p10(%rip), %r15 + movq %r15, 152(%rdi) + movq 168(%rdi), %r15 + sbbq p11(%rip), %r15 + movq %r15, 168(%rdi) + + pop %rdi + + cmovnc %rax, %r8 + cmovnc %rcx, %r9 + cmovnc %rdx, %r10 + cmovnc %rsi, %r11 + cmovnc %rbx, %r12 + cmovnc %rbp, %r13 + cmovnc %rdi, %r14 + + pop %rdi + movq 96(%rdi), %r15 + movq 112(%rdi), %rax + movq 128(%rdi), %rcx + movq 144(%rdi), %rbx + movq 160(%rdi), %rbp + cmovnc 104(%rdi), %r15 + cmovnc 120(%rdi), %rax + cmovnc 136(%rdi), %rcx + cmovnc 152(%rdi), %rbx + cmovnc 168(%rdi), %rbp + + movq %r8 , 96(%rdi) + movq %r9 , 104(%rdi) + movq %r10, 112(%rdi) + movq %r11, 120(%rdi) + movq %r12, 128(%rdi) + movq %r13, 136(%rdi) + movq %r14, 144(%rdi) + movq %r15, 152(%rdi) + movq %rax, 160(%rdi) + movq %rcx, 168(%rdi) + movq %rbx, 176(%rdi) + movq %rbp, 184(%rdi) + xorq %rax, %rax + + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + ret + +cdecl(fp_sub1_low): + movq 0(%rsi), %r10 + subq %rdx , %r10 + movq %r10 , 0(%rdi) + + SUB1 1, (RLC_FP_DIGS - 1) + + ret + +cdecl(fp_subn_low): + xorq %rax , %rax + movq 0(%rsi), %r11 + subq 0(%rdx), %r11 + movq %r11 , 0(%rdi) + + SUBN 1, (RLC_FP_DIGS - 1) + + adcq $0, %rax + + ret + +cdecl(fp_subm_low): + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + xorq %rax, %rax + xorq %rcx, %rcx + + movq 0(%rsi), %r8 + subq 0(%rdx), %r8 + movq %r8 , 0(%rdi) + + SUBN 1, (RLC_FP_DIGS - 1) + + movq $0, %r8 + movq $0, %r9 + movq $0, %r10 + movq $0, %r11 + movq $0, %rdx + movq $0, %rsi + movq $0, %r12 + movq $0, %r13 + movq $0, %r14 + movq $0, %r15 + + cmovc p0(%rip), %rax + cmovc p1(%rip), %rcx + cmovc p2(%rip), %r8 + cmovc p3(%rip), %r9 + cmovc p4(%rip), %r10 + cmovc p5(%rip), %r11 + cmovc p6(%rip), %rdx + cmovc p7(%rip), %rsi + cmovc p8(%rip), %r12 + cmovc p9(%rip), %r13 + cmovc p10(%rip), %r14 + cmovc p11(%rip), %r15 + + addq %rax, 0(%rdi) + adcq %rcx, 8(%rdi) + adcq %r8, 16(%rdi) + adcq %r9, 24(%rdi) + adcq %r10, 32(%rdi) + adcq %r11, 40(%rdi) + adcq %rdx, 48(%rdi) + adcq %rsi, 56(%rdi) + adcq %r12, 64(%rdi) + adcq %r13, 72(%rdi) + adcq %r14, 80(%rdi) + adcq %r15, 88(%rdi) + + pop %r15 + pop %r14 + pop %r13 + pop %r12 + ret + +cdecl(fp_subd_low): + movq 0(%rsi), %r8 + subq 0(%rdx), %r8 + movq %r8, 0(%rdi) + + SUBN 1, (2 * RLC_FP_DIGS - 1) + + ret + +cdecl(fp_subc_low): + push %r12 + push %r13 + push %r14 + push %r15 + xorq %rax,%rax + xorq %rcx,%rcx + + movq 0(%rsi), %r8 + subq 0(%rdx), %r8 + movq %r8, 0(%rdi) + + SUBN 1, (2 * RLC_FP_DIGS - 1) + + movq $0, %r8 + movq $0, %r9 + movq $0, %r10 + movq $0, %r11 + movq $0, %rsi + movq $0, %rdx + movq $0, %r12 + movq $0, %r13 + movq $0, %r14 + movq $0, %r15 + + cmovc p0(%rip), %rax + cmovc p1(%rip), %rcx + cmovc p2(%rip), %r8 + cmovc p3(%rip), %r9 + cmovc p4(%rip), %r10 + cmovc p5(%rip), %r11 + cmovc p6(%rip), %rsi + cmovc p7(%rip), %rdx + cmovc p8(%rip), %r12 + cmovc p9(%rip), %r13 + cmovc p10(%rip), %r14 + cmovc p11(%rip), %r15 + + addq %rax, 96(%rdi) + adcq %rcx, 104(%rdi) + adcq %r8, 112(%rdi) + adcq %r9, 120(%rdi) + adcq %r10, 128(%rdi) + adcq %r11, 136(%rdi) + adcq %rsi, 144(%rdi) + adcq %rdx, 152(%rdi) + adcq %r12, 160(%rdi) + adcq %r13, 168(%rdi) + adcq %r14, 176(%rdi) + adcq %r15, 184(%rdi) + + pop %r15 + pop %r14 + pop %r13 + pop %r12 + ret + +cdecl(fp_negm_low): + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + xorq %r9, %r9 + xorq %r10, %r10 + xorq %r11, %r11 + xorq %r12, %r12 + xorq %r13, %r13 + xorq %r14, %r14 + xorq %r15, %r15 + xorq %rbx, %rbx + xorq %rbp, %rbp + xorq %rax, %rax + xorq %rcx, %rcx + + movq 0(%rsi) , %r8 + or 8(%rsi) , %r8 + or 16(%rsi), %r8 + or 24(%rsi), %r8 + or 32(%rsi), %r8 + or 40(%rsi), %r8 + or 48(%rsi), %r8 + or 56(%rsi), %r8 + or 64(%rsi), %r8 + or 72(%rsi), %r8 + or 80(%rsi), %r8 + or 88(%rsi), %r8 + test %r8, %r8 + cmovnz p0(%rip), %r8 + cmovnz p1(%rip), %r9 + cmovnz p2(%rip), %r10 + cmovnz p3(%rip), %r11 + cmovnz p4(%rip), %rbx + cmovnz p5(%rip), %rbp + cmovnz p6(%rip), %r12 + cmovnz p7(%rip), %r13 + cmovnz p8(%rip), %r14 + cmovnz p9(%rip), %r15 + cmovnz p10(%rip),%rax + cmovnz p11(%rip),%rcx + subq 0(%rsi) , %r8 + movq %r8 , 0(%rdi) + sbbq 8(%rsi) , %r9 + movq %r9 , 8(%rdi) + sbbq 16(%rsi), %r10 + movq %r10 , 16(%rdi) + sbbq 24(%rsi), %r11 + movq %r11 , 24(%rdi) + sbbq 32(%rsi), %rbx + movq %rbx , 32(%rdi) + sbbq 40(%rsi), %rbp + movq %rbp , 40(%rdi) + sbbq 48(%rsi), %r12 + movq %r12 , 48(%rdi) + sbbq 56(%rsi), %r13 + movq %r13 , 56(%rdi) + sbbq 64(%rsi), %r14 + movq %r14 , 64(%rdi) + sbbq 72(%rsi), %r15 + movq %r15 , 72(%rdi) + sbbq 80(%rsi), %rax + movq %rax , 80(%rdi) + sbbq 88(%rsi), %rcx + movq %rcx , 88(%rdi) + + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + ret + +cdecl(fp_dbln_low): + movq 0(%rsi), %r8 + addq %r8 , %r8 + movq %r8 , 0(%rdi) + + DBLN 1, (RLC_FP_DIGS - 1) + + xorq %rax,%rax + ret + +cdecl(fp_dblm_low): + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + push %rdi + + xorq %rax, %rax + xorq %rcx, %rcx + xorq %rdx, %rdx + + movq 0(%rsi) , %r8 + addq %r8 , %r8 + movq 8(%rsi) , %r9 + adcq %r9 , %r9 + movq 16(%rsi), %r10 + adcq %r10 , %r10 + movq 24(%rsi), %r11 + adcq %r11 , %r11 + movq 32(%rsi), %r12 + adcq %r12 , %r12 + movq 40(%rsi), %r13 + adcq %r13 , %r13 + movq 48(%rsi), %r14 + adcq %r14 , %r14 + movq 56(%rsi), %r15 + adcq %r15 , %r15 + movq %r15 , 0(%rdi) + movq %r15 , 8(%rdi) + movq 64(%rsi), %rax + adcq %rax , %rax + movq %rax , 16(%rdi) + movq %rax , 24(%rdi) + movq 72(%rsi), %rcx + adcq %rcx , %rcx + movq %rcx , 32(%rdi) + movq %rcx , 40(%rdi) + movq 80(%rsi), %rax + adcq %rax , %rax + movq %rax , 48(%rdi) + movq %rax , 56(%rdi) + movq 88(%rsi), %rcx + adcq %rcx , %rcx + movq %rcx , 64(%rdi) + movq %rcx , 72(%rdi) + + movq %rdi, %r15 + + movq %r8 , %rax + movq %r9 , %rcx + movq %r10, %rdx + movq %r11, %rsi + movq %r12, %rbx + movq %r13, %rbp + movq %r14, %rdi + + subq p0(%rip), %rax + sbbq p1(%rip), %rcx + sbbq p2(%rip), %rdx + sbbq p3(%rip), %rsi + sbbq p4(%rip), %rbx + sbbq p5(%rip), %rbp + sbbq p6(%rip), %rdi + + push %rdi + movq %r15, %rdi + + movq 8(%rdi), %r15 + sbbq p7(%rip), %r15 + movq %r15, 8(%rdi) + movq 24(%rdi), %r15 + sbbq p8(%rip), %r15 + movq %r15, 24(%rdi) + movq 40(%rdi), %r15 + sbbq p9(%rip), %r15 + movq %r15, 40(%rdi) + movq 56(%rdi), %r15 + sbbq p10(%rip), %r15 + movq %r15, 56(%rdi) + movq 72(%rdi), %r15 + sbbq p11(%rip), %r15 + movq %r15, 72(%rdi) + + pop %rdi + + cmovnc %rax, %r8 + cmovnc %rcx, %r9 + cmovnc %rdx, %r10 + cmovnc %rsi, %r11 + cmovnc %rbx, %r12 + cmovnc %rbp, %r13 + cmovnc %rdi, %r14 + + pop %rdi + + movq 0(%rdi), %r15 + movq 16(%rdi), %rax + movq 32(%rdi), %rcx + movq 48(%rdi), %rbx + movq 64(%rdi), %rbp + cmovnc 8(%rdi), %r15 + cmovnc 24(%rdi), %rax + cmovnc 40(%rdi), %rcx + cmovnc 56(%rdi), %rbx + cmovnc 72(%rdi), %rbp + + movq %r8 , 0(%rdi) + movq %r9 , 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 32(%rdi) + movq %r13, 40(%rdi) + movq %r14, 48(%rdi) + movq %r15, 56(%rdi) + movq %rax, 64(%rdi) + movq %rcx, 72(%rdi) + movq %rbx, 80(%rdi) + movq %rbp, 88(%rdi) + xorq %rax, %rax + + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + ret + +cdecl(fp_hlvm_low): + push %r12 + push %r13 + push %r14 + push %r15 + push %rbp + push %rbx + + xorq %rdx, %rdx + + movq $1 ,%rax + andq 0(%rsi),%rax + + movq $P0, %r8 + movq $P1, %r9 + movq $P2, %r10 + movq $P3, %r11 + movq $P4, %r12 + movq $P5, %r13 + movq $P6, %r14 + movq $P7, %r15 + movq $P8, %rbp + movq $P9, %rbx + movq $P10, %rcx + movq $P11, %rax + + cmovz %rdx, %r8 + cmovz %rdx, %r9 + cmovz %rdx, %r10 + cmovz %rdx, %r11 + cmovz %rdx, %r12 + cmovz %rdx, %r13 + cmovz %rdx, %r14 + cmovz %rdx, %r15 + cmovz %rdx, %rbp + cmovz %rdx, %rbx + cmovz %rdx, %rcx + cmovz %rdx, %rax + + addq 0(%rsi) , %r8 + movq 8(%rsi) , %rdx + adcq %rdx , %r9 + movq 16(%rsi), %rdx + adcq %rdx , %r10 + movq 24(%rsi), %rdx + adcq %rdx , %r11 + movq 32(%rsi), %rdx + adcq %rdx , %r12 + movq 40(%rsi), %rdx + adcq %rdx , %r13 + movq 48(%rsi), %rdx + adcq %rdx , %r14 + movq 56(%rsi), %rdx + adcq %rdx , %r15 + movq 64(%rsi), %rdx + adcq %rdx , %rbp + movq 72(%rsi), %rdx + adcq %rdx , %rbx + movq 80(%rsi), %rdx + adcq %rdx , %rcx + movq 88(%rsi), %rdx + adcq %rdx , %rax + + rcrq $1, %rax + rcrq $1, %rcx + rcrq $1, %rbx + rcrq $1, %rbp + rcrq $1, %r15 + rcrq $1, %r14 + rcrq $1, %r13 + rcrq $1, %r12 + rcrq $1, %r11 + rcrq $1, %r10 + rcrq $1, %r9 + rcrq $1, %r8 + + movq %r8 , 0(%rdi) + movq %r9 , 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 32(%rdi) + movq %r13, 40(%rdi) + movq %r14, 48(%rdi) + movq %r15, 56(%rdi) + movq %rbp, 64(%rdi) + movq %rbx, 72(%rdi) + movq %rcx, 80(%rdi) + movq %rax, 88(%rdi) + xorq %rax, %rax + + pop %rbx + pop %rbp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + ret + +cdecl(fp_hlvd_low): + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + xorq %rbp, %rbp + movq $1 ,%rdx + andq 0(%rsi),%rdx + + movq $P0, %r8 + movq $P1, %r9 + movq $P2, %r10 + movq $P3, %r11 + movq $P4, %r12 + movq $P5, %r13 + movq $P6, %r14 + movq $P7, %r15 + movq $P8, %rax + movq $P9, %rbx + movq $P10, %rcx + movq $P11, %rdx + + cmovz %rbp, %r8 + cmovz %rbp, %r9 + cmovz %rbp, %r10 + cmovz %rbp, %r11 + cmovz %rbp, %r12 + cmovz %rbp, %r13 + cmovz %rbp, %r14 + cmovz %rbp, %r15 + cmovz %rbp, %rax + cmovz %rbp, %rbx + cmovz %rbp, %rcx + cmovz %rbp, %rdx + + addq 0(%rsi) , %r8 + adcq 8(%rsi) , %r9 + adcq 16(%rsi) , %r10 + adcq 24(%rsi) , %r11 + adcq 32(%rsi) , %r12 + adcq 40(%rsi) , %r13 + adcq 48(%rsi) , %r14 + adcq 56(%rsi) , %r15 + adcq 64(%rsi) , %rax + adcq 72(%rsi) , %rbx + adcq 80(%rsi) , %rcx + adcq 88(%rsi) , %rdx + movq 96(%rsi) , %rbp + adcq $0 , %rbp + + push %rbp + + movq 104(%rsi), %rbp + adcq $0 , %rbp + movq %rbp , 104(%rdi) + movq 112(%rsi), %rbp + adcq $0 , %rbp + movq %rbp , 112(%rdi) + movq 120(%rsi), %rbp + adcq $0 , %rbp + movq %rbp , 120(%rdi) + movq 128(%rsi), %rbp + adcq $0 , %rbp + movq %rbp , 128(%rdi) + movq 136(%rsi), %rbp + adcq $0 , %rbp + movq %rbp , 136(%rdi) + movq 144(%rsi), %rbp + adcq $0 , %rbp + movq %rbp , 144(%rdi) + movq 152(%rsi), %rbp + adcq $0 , %rbp + movq %rbp , 152(%rdi) + movq 160(%rsi), %rbp + adcq $0 , %rbp + movq %rbp , 160(%rdi) + movq 168(%rsi), %rbp + adcq $0 , %rbp + movq %rbp , 168(%rdi) + movq 176(%rsi), %rbp + adcq $0 , %rbp + movq %rbp , 176(%rdi) + movq 184(%rsi), %rbp + adcq $0 , %rbp + movq %rbp , 184(%rdi) + + pop %rbp + + rcrq $1, 184(%rdi) + rcrq $1, 176(%rdi) + rcrq $1, 168(%rdi) + rcrq $1, 160(%rdi) + rcrq $1, 152(%rdi) + rcrq $1, 144(%rdi) + rcrq $1, 136(%rdi) + rcrq $1, 128(%rdi) + rcrq $1, 120(%rdi) + rcrq $1, 112(%rdi) + rcrq $1, 104(%rdi) + rcrq $1, %rbp + rcrq $1, %rdx + rcrq $1, %rcx + rcrq $1, %rbx + rcrq $1, %rax + rcrq $1, %r15 + rcrq $1, %r14 + rcrq $1, %r13 + rcrq $1, %r12 + rcrq $1, %r11 + rcrq $1, %r10 + rcrq $1, %r9 + rcrq $1, %r8 + + movq %rbp, 96(%rdi) + movq %rdx, 88(%rdi) + movq %rcx, 80(%rdi) + movq %rbx, 72(%rdi) + movq %rax, 64(%rdi) + movq %r15, 56(%rdi) + movq %r14, 48(%rdi) + movq %r13, 40(%rdi) + movq %r12, 32(%rdi) + movq %r11, 24(%rdi) + movq %r10, 16(%rdi) + movq %r9 , 8(%rdi) + movq %r8 , 0(%rdi) + + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + ret diff --git a/src/low/x64-asm-12l/relic_fp_mul_low.c b/src/low/x64-asm-12l/relic_fp_mul_low.c new file mode 100644 index 000000000..4d5e493d5 --- /dev/null +++ b/src/low/x64-asm-12l/relic_fp_mul_low.c @@ -0,0 +1,47 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2017 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 + * + * Implementation of the low-level prime field multiplication functions. + * + * @ingroup bn + */ + +#include "gmp.h" + +#include "relic_fp.h" +#include "relic_fp_low.h" + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +dig_t fp_mula_low(dig_t *c, const dig_t *a, dig_t digit) { + return mpn_addmul_1(c, a, RLC_FP_DIGS, digit); +} + +dig_t fp_mul1_low(dig_t *c, const dig_t *a, dig_t digit) { + return mpn_mul_1(c, a, RLC_FP_DIGS, digit); +} diff --git a/src/low/x64-asm-12l/relic_fp_mul_low.s b/src/low/x64-asm-12l/relic_fp_mul_low.s new file mode 100644 index 000000000..ced58a821 --- /dev/null +++ b/src/low/x64-asm-12l/relic_fp_mul_low.s @@ -0,0 +1,68 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2017 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 + * + * Implementation of the low-level prime field multiplication functions. + * + * @ingroup bn + */ + +#include "macro.s" + +.text + +.global cdecl(fp_muln_low) +.global cdecl(fp_mulm_low) + +cdecl(fp_muln_low): + movq %rdx,%rcx + FP_MULN_LOW %rdi, %r8, %r9, %r10, %rsi, %rcx + ret + +cdecl(fp_mulm_low): + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + push %rbp + subq $240, %rsp + + movq %rdx,%rcx + leaq p0(%rip), %rbx + + FP_MULN_LOW %rsp, %r8, %r9, %r10, %rsi, %rcx + + FP_RDCN_LOW %rdi, %r8, %r9, %r10, %rsp, %rbx + + addq $240, %rsp + + pop %rbp + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + ret diff --git a/src/low/x64-asm-12l/relic_fp_rdc_low.c b/src/low/x64-asm-12l/relic_fp_rdc_low.c new file mode 100644 index 000000000..620678a13 --- /dev/null +++ b/src/low/x64-asm-12l/relic_fp_rdc_low.c @@ -0,0 +1,111 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2017 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 + * + * Implementation of the low-level prime field modular reduction functions. + * + * @ingroup fp + */ + +#include "relic_core.h" +#include "relic_fp.h" +#include "relic_fp_low.h" +#include "relic_bn_low.h" + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +void fp_rdcs_low(dig_t *c, const dig_t *a, const dig_t *m) { + rlc_align dig_t q[2 * RLC_FP_DIGS], _q[2 * RLC_FP_DIGS], t[2 * RLC_FP_DIGS], r[RLC_FP_DIGS]; + const int *sform; + int len, first, i, j, k, b0, d0, b1, d1; + + sform = fp_prime_get_sps(&len); + + RLC_RIP(b0, d0, sform[len - 1]); + first = (d0) + (b0 == 0 ? 0 : 1); + + /* q = floor(a/b^k) */ + dv_zero(q, 2 * RLC_FP_DIGS); + dv_rshd(q, a, 2 * RLC_FP_DIGS, d0); + if (b0 > 0) { + bn_rshb_low(q, q, 2 * RLC_FP_DIGS, b0); + } + + /* r = a - qb^k. */ + dv_copy(r, a, first); + if (b0 > 0) { + r[first - 1] &= RLC_MASK(b0); + } + + k = 0; + while (!fp_is_zero(q)) { + dv_zero(_q, 2 * RLC_FP_DIGS); + for (i = len - 2; i > 0; i--) { + j = (sform[i] < 0 ? -sform[i] : sform[i]); + RLC_RIP(b1, d1, j); + dv_zero(t, 2 * RLC_FP_DIGS); + dv_lshd(t, q, RLC_FP_DIGS, d1); + if (b1 > 0) { + bn_lshb_low(t, t, 2 * RLC_FP_DIGS, b1); + } + /* Check if these two have the same sign. */ + if ((sform[len - 2] ^ sform[i]) >= 0) { + bn_addn_low(_q, _q, t, 2 * RLC_FP_DIGS); + } else { + bn_subn_low(_q, _q, t, 2 * RLC_FP_DIGS); + } + } + /* Check if these two have the same sign. */ + if ((sform[len - 2] ^ sform[0]) >= 0) { + bn_addn_low(_q, _q, q, 2 * RLC_FP_DIGS); + } else { + bn_subn_low(_q, _q, q, 2 * RLC_FP_DIGS); + } + dv_rshd(q, _q, 2 * RLC_FP_DIGS, d0); + if (b0 > 0) { + bn_rshb_low(q, q, 2 * RLC_FP_DIGS, b0); + } + if (b0 > 0) { + _q[first - 1] &= RLC_MASK(b0); + } + if (sform[len - 2] < 0) { + fp_add(r, r, _q); + } else { + if (k++ % 2 == 0) { + if (fp_subn_low(r, r, _q)) { + fp_addn_low(r, r, m); + } + } else { + fp_addn_low(r, r, _q); + } + } + } + while (dv_cmp(r, m, RLC_FP_DIGS) != RLC_LT) { + fp_subn_low(r, r, m); + } + fp_copy(c, r); +} diff --git a/src/low/x64-asm-12l/relic_fp_rdc_low.s b/src/low/x64-asm-12l/relic_fp_rdc_low.s new file mode 100644 index 000000000..4e8e69b71 --- /dev/null +++ b/src/low/x64-asm-12l/relic_fp_rdc_low.s @@ -0,0 +1,62 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2017 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 + * + * Implementation of low-level prime field modular reduction. + * + * @ingroup fp + */ + +#include "relic_fp_low.h" + +#include "macro.s" + +.text + +.global cdecl(fp_rdcn_low) + +/* + * Function: fp_rdcn_low + * Inputs: rdi = c, rsi = a + * Output: rax + */ +cdecl(fp_rdcn_low): + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + push %rbp + leaq p0(%rip), %rbx + + FP_RDCN_LOW %rdi, %r8, %r9, %r10, %rsi, %rbx + + pop %rbp + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + ret diff --git a/src/low/x64-asm-12l/relic_fp_sqr_low.c b/src/low/x64-asm-12l/relic_fp_sqr_low.c new file mode 100644 index 000000000..f0c879cd5 --- /dev/null +++ b/src/low/x64-asm-12l/relic_fp_sqr_low.c @@ -0,0 +1,48 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2017 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 + * + * Implementation of low-level prime field squaring functions. + * + * @version $Id: relic_fp_sqr_low.c 677 2011-03-05 22:19:43Z dfaranha $ + * @ingroup fp + */ + +#include + +#include "relic_fp.h" +#include "relic_fp_low.h" + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +void fp_sqrn_low(dig_t *c, const dig_t *a) { + fp_muln_low(c, a, a); +} + +void fp_sqrm_low(dig_t *c, const dig_t *a) { + fp_mulm_low(c, a, a); +} diff --git a/src/low/x64-asm-12l/relic_fpx_rdc_low.c b/src/low/x64-asm-12l/relic_fpx_rdc_low.c new file mode 100755 index 000000000..536c40ca8 --- /dev/null +++ b/src/low/x64-asm-12l/relic_fpx_rdc_low.c @@ -0,0 +1,50 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2017 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 + * + * Implementation of the low-level extension field modular reduction functions. + * + * @ingroup fpx + */ + +#include "relic_core.h" +#include "relic_fp_low.h" +#include "relic_fpx_low.h" + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +void fp3_rdcn_low(fp3_t c, dv3_t a) { +#if FP_RDC == MONTY + fp_rdcn_low(c[0], a[0]); + fp_rdcn_low(c[1], a[1]); + fp_rdcn_low(c[2], a[2]); +#else + fp_rdc(c[0], a[0]); + fp_rdc(c[1], a[1]); + fp_rdc(c[2], a[2]); +#endif +} diff --git a/src/low/x64-asm-12l/relic_fpx_rdc_low.s b/src/low/x64-asm-12l/relic_fpx_rdc_low.s new file mode 100644 index 000000000..8a3c436ff --- /dev/null +++ b/src/low/x64-asm-12l/relic_fpx_rdc_low.s @@ -0,0 +1,65 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2017 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 + * + * Implementation of low-level prime field modular reduction. + * + * @ingroup fp + */ + +#include "relic_dv_low.h" + +#include "macro.s" + +.text + +.global cdecl(fp2_rdcn_low) + +/* + * Function: fp_rdcn_low + * Inputs: rdi = c, rsi = a + * Output: rax + */ +cdecl(fp2_rdcn_low): + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + push %rbp + leaq p0(%rip), %rbx + + FP_RDCN_LOW %rdi, %r8, %r9, %r10, %rsi, %rbx + addq $(8*RLC_FP_DIGS), %rdi + addq $(8*RLC_DV_DIGS), %rsi + FP_RDCN_LOW %rdi, %r8, %r9, %r10, %rsi, %rbx + + pop %rbp + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + ret diff --git a/src/low/x64-asm-6l/macro.s b/src/low/x64-asm-6l/macro.s index bdf23114d..615677d31 100644 --- a/src/low/x64-asm-6l/macro.s +++ b/src/low/x64-asm-6l/macro.s @@ -32,7 +32,15 @@ * @ingroup fp */ -#if FP_PRIME == 377 +#if FP_PRIME == 330 +#define P0 0x523E67A53D5C40AD +#define P1 0x27BBEC8F954D9613 +#define P2 0xF12A1C4947A0784F +#define P3 0x5BF00BAF1EE31FEC +#define P4 0x0832E1406555615B +#define P5 0x24C +#define U0 0x9876AE34F480DCDB +#elif FP_PRIME == 377 #define P0 0x8508C00000000001 #define P1 0x170B5D4430000000 #define P2 0x1EF3622FBA094800 diff --git a/src/low/x64-asm-6l/relic_bn_mul_low.c b/src/low/x64-asm-6l/relic_bn_mul_low.c new file mode 100644 index 000000000..2229b6d2e --- /dev/null +++ b/src/low/x64-asm-6l/relic_bn_mul_low.c @@ -0,0 +1,60 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2009 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 + * + * Implementation of the multiple precision integer arithmetic multiplication + * functions. + * + * @ingroup bn + */ + +#include + +#include "relic_bn.h" +#include "relic_bn_low.h" +#include "relic_util.h" + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +dig_t bn_mula_low(dig_t *c, const dig_t *a, dig_t digit, int size) { + return mpn_addmul_1(c, a, size, digit); +} + +dig_t bn_mul1_low(dig_t *c, const dig_t *a, dig_t digit, int size) { + return mpn_mul_1(c, a, size, digit); +} + +void bn_muln_low(dig_t *c, const dig_t *a, const dig_t *b, int size) { + mpn_mul_n(c, a, b, size); +} + +void bn_muld_low(dig_t *c, const dig_t *a, int sizea, const dig_t *b, int sizeb, + int low, int high) { + (void)low; + (void)high; + mpn_mul(c, a, sizea, b, sizeb); +} diff --git a/src/low/x64-asm-6l/relic_bn_mul_low.s b/src/low/x64-asm-6l/relic_bn_mul_low.s new file mode 100644 index 000000000..fbd535a07 --- /dev/null +++ b/src/low/x64-asm-6l/relic_bn_mul_low.s @@ -0,0 +1,97 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2009 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 + * + * Implementation of the multiple precision integer arithmetic multiplication + * functions in ASM. + * + * @ingroup bn + */ + +.text +.global bn_muls_low + +/** + * c = rdi, a = rsi, sa = rdx, digit = rcx, size = RLC_FP_DIGS + */ +bn_muls_low: + pushq %r12 + pushq %r13 + pushq %r14 + movq %rcx, %rax + shrq $63, %rax + xorq %rdx, %rax # sign = sa ^ sd; + movq %rcx, %rdx + negq %rcx + cmovns %rcx, %rdx # rdx = (digit < 0 ? -digit : digit); + xorq %rcx, %rcx # clear flags, create zero + + mulxq 0(%rsi), %r8, %r9 + + mulxq 8(%rsi), %r11, %r10 + adcx %r11, %r9 + + mulxq 16(%rsi), %r12, %r11 + adcx %r12, %r10 + + mulxq 24(%rsi), %r13, %r12 + adcx %r13, %r11 + + mulxq 32(%rsi), %r14, %r13 + adcx %r14, %r12 + + mulxq 40(%rsi), %rsi, %r14 + adcx %rsi, %r13 + adcx %rcx, %r14 + + negq %rax + xorq %rax, %r8 + xorq %rax, %r9 + xorq %rax, %r10 + xorq %rax, %r11 + xorq %rax, %r12 + xorq %rax, %r13 + xorq %rax, %r14 + + negq %rax + addq %rax, %r8 + adcx %rcx, %r9 + adcx %rcx, %r10 + adcx %rcx, %r11 + adcx %rcx, %r12 + adcx %rcx, %r13 + adcx %rcx, %r14 + movq %r8, 0(%rdi) + movq %r9, 8(%rdi) + movq %r10,16(%rdi) + movq %r11,24(%rdi) + movq %r12,32(%rdi) + movq %r13,40(%rdi) + movq %r14, %rax + + popq %r14 + popq %r13 + popq %r12 + ret diff --git a/src/low/x64-asm-6l/relic_bn_shift_low.c b/src/low/x64-asm-6l/relic_bn_shift_low.c new file mode 100644 index 000000000..0445b5ab8 --- /dev/null +++ b/src/low/x64-asm-6l/relic_bn_shift_low.c @@ -0,0 +1,58 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2009 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 + * + * Implementation of the low-level multiple precision bit shifting functions. + * + * @ingroup bn + */ + +#include +#include +#include +#include + +#include "relic_bn.h" +#include "relic_bn_low.h" + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +dig_t bn_lsh1_low(dig_t *c, const dig_t *a, int size) { + return mpn_lshift(c, a, size, 1); +} + +dig_t bn_lshb_low(dig_t *c, const dig_t *a, int size, int bits) { + return mpn_lshift(c, a, size, bits); +} + +dig_t bn_rsh1_low(dig_t *c, const dig_t *a, int size) { + return mpn_rshift(c, a, size, 1); +} + +dig_t bn_rshb_low(dig_t *c, const dig_t *a, int size, int bits) { + return mpn_rshift(c, a, size, bits); +} diff --git a/src/low/x64-asm-6l/relic_bn_shift_low.s b/src/low/x64-asm-6l/relic_bn_shift_low.s new file mode 100644 index 000000000..563e2603e --- /dev/null +++ b/src/low/x64-asm-6l/relic_bn_shift_low.s @@ -0,0 +1,57 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2009 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 + * + * Implementation of the ASM multiple precision bit shifting functions. + * + * @ingroup bn + */ + +.text +.global bn_rshs_low + +bn_rshs_low: + movq 0(%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + movq 32(%rsi), %rax + movq 40(%rsi), %rcx + movq 48(%rsi), %rsi + shrd $62, %r9, %r8 + shrd $62, %r10, %r9 + shrd $62, %r11, %r10 + shrd $62, %rax, %r11 + shrd $62, %rcx, %rax + shrd $62, %rsi, %rcx + sar $62, %rsi + movq %r8,0(%rdi) + movq %r9,8(%rdi) + movq %r10,16(%rdi) + movq %r11,24(%rdi) + movq %rax,32(%rdi) + movq %rcx,40(%rdi) + movq %rsi,48(%rdi) + ret diff --git a/src/low/x64-asm-6l/relic_fp_add_low.s b/src/low/x64-asm-6l/relic_fp_add_low.s index d49e8438f..4e51dcdc1 100644 --- a/src/low/x64-asm-6l/relic_fp_add_low.s +++ b/src/low/x64-asm-6l/relic_fp_add_low.s @@ -363,6 +363,12 @@ fp_subc_low: ret fp_negm_low: + xorq %r9, %r9 + xorq %r10, %r10 + xorq %r11, %r11 + xorq %rax, %rax + xorq %rcx, %rcx + movq 0(%rsi) , %r8 or 8(%rsi) , %r8 or 16(%rsi), %r8 @@ -371,24 +377,24 @@ fp_negm_low: or 40(%rsi), %r8 test %r8, %r8 cmovnz p0(%rip), %r8 + cmovnz p1(%rip), %r9 + cmovnz p2(%rip), %r10 + cmovnz p3(%rip), %r11 + cmovnz p4(%rip), %rax + cmovnz p5(%rip), %rcx subq 0(%rsi) , %r8 movq %r8 , 0(%rdi) - cmovnz p1(%rip), %r8 - sbbq 8(%rsi) , %r8 - movq %r8 , 8(%rdi) - cmovnz p2(%rip), %r8 - sbbq 16(%rsi), %r8 - movq %r8 , 16(%rdi) - cmovnz p3(%rip), %r8 - sbbq 24(%rsi), %r8 - movq %r8 , 24(%rdi) - cmovnz p4(%rip), %r8 - sbbq 32(%rsi), %r8 - movq %r8 , 32(%rdi) - cmovnz p5(%rip), %r8 - sbbq 40(%rsi), %r8 - movq %r8 , 40(%rdi) - ret + sbbq 8(%rsi) , %r9 + movq %r9 , 8(%rdi) + sbbq 16(%rsi), %r10 + movq %r10 , 16(%rdi) + sbbq 24(%rsi), %r11 + movq %r11 , 24(%rdi) + sbbq 32(%rsi), %rax + movq %rax , 32(%rdi) + sbbq 40(%rsi), %rcx + movq %rcx , 40(%rdi) + ret fp_dbln_low: movq 0(%rsi), %r8 diff --git a/src/low/x64-asm-6l/relic_fp_mul_low.s b/src/low/x64-asm-6l/relic_fp_mul_low.s index 20e20f650..3fd3f3dba 100644 --- a/src/low/x64-asm-6l/relic_fp_mul_low.s +++ b/src/low/x64-asm-6l/relic_fp_mul_low.s @@ -42,6 +42,7 @@ fp_muln_low: FP_MULN_LOW %rdi, %r8, %r9, %r10, %rsi, %rcx ret +#if FP_PRIME != 381 fp_mulm_low: push %r12 push %r13 @@ -67,3 +68,9 @@ fp_mulm_low: pop %r13 pop %r12 ret + +#else + +#include "relic_fp_mul_low_cryptopt.s" + +#endif \ No newline at end of file diff --git a/src/low/x64-asm-6l/relic_fp_mul_low_cryptopt.s b/src/low/x64-asm-6l/relic_fp_mul_low_cryptopt.s new file mode 100644 index 000000000..5d9e7ed8e --- /dev/null +++ b/src/low/x64-asm-6l/relic_fp_mul_low_cryptopt.s @@ -0,0 +1,473 @@ +.text +.intel_syntax noprefix + +fp_mulm_low: +sub rsp, 352 +mov rax, rdx +mov rdx, [ rsi + 0x8 ] +mulx r11, r10, [ rax + 0x8 ] +mov rdx, [ rsi + 0x10 ] +mulx r8, rcx, [ rax + 0x10 ] +mov rdx, [ rax + 0x0 ] +mov [ rsp - 0x80 ], rbx +mulx rbx, r9, [ rsi + 0x10 ] +mov rdx, [ rax + 0x10 ] +mov [ rsp - 0x78 ], rbp +mov [ rsp - 0x70 ], r12 +mulx r12, rbp, [ rsi + 0x28 ] +mov rdx, [ rax + 0x0 ] +mov [ rsp - 0x68 ], r13 +mov [ rsp - 0x60 ], r14 +mulx r14, r13, [ rsi + 0x8 ] +mov rdx, [ rax + 0x0 ] +mov [ rsp - 0x58 ], r15 +mov [ rsp - 0x50 ], rdi +mulx rdi, r15, [ rsi + 0x18 ] +test al, al +adox r10, r14 +mov rdx, [ rax + 0x10 ] +mov [ rsp - 0x48 ], r15 +mulx r15, r14, [ rsi + 0x8 ] +mov rdx, [ rsi + 0x8 ] +mov [ rsp - 0x40 ], r9 +mov [ rsp - 0x38 ], r10 +mulx r10, r9, [ rax + 0x18 ] +adox r14, r11 +adox r9, r15 +mov rdx, [ rsi + 0x10 ] +mulx r15, r11, [ rax + 0x8 ] +adcx r11, rbx +mov rdx, [ rsi + 0x8 ] +mov [ rsp - 0x30 ], r11 +mulx r11, rbx, [ rax + 0x20 ] +adcx rcx, r15 +mov rdx, [ rsi + 0x10 ] +mov [ rsp - 0x28 ], rcx +mulx rcx, r15, [ rax + 0x18 ] +mov rdx, [ rsi + 0x8 ] +mov [ rsp - 0x20 ], r9 +mov [ rsp - 0x18 ], r14 +mulx r14, r9, [ rax + 0x28 ] +adox rbx, r10 +adox r9, r11 +mov rdx, [ rax + 0x20 ] +mulx r11, r10, [ rsi + 0x10 ] +adcx r15, r8 +adcx r10, rcx +mov rdx, [ rax + 0x28 ] +mulx rcx, r8, [ rsi + 0x10 ] +adcx r8, r11 +mov rdx, [ rsi + 0x18 ] +mov [ rsp - 0x10 ], r8 +mulx r8, r11, [ rax + 0x8 ] +mov rdx, [ rax + 0x18 ] +mov [ rsp - 0x8 ], r10 +mov [ rsp + 0x0 ], r15 +mulx r15, r10, [ rsi + 0x18 ] +mov rdx, 0x0 +adcx rcx, rdx +mov rdx, [ rax + 0x10 ] +mov [ rsp + 0x8 ], rcx +mov [ rsp + 0x10 ], r9 +mulx r9, rcx, [ rsi + 0x18 ] +clc +adcx r11, rdi +adcx rcx, r8 +mov rdx, 0x0 +adox r14, rdx +adcx r10, r9 +mov rdx, [ rax + 0x20 ] +mulx r8, rdi, [ rsi + 0x18 ] +adcx rdi, r15 +mov rdx, [ rax + 0x8 ] +mulx r9, r15, [ rsi + 0x28 ] +mov rdx, [ rax + 0x28 ] +mov [ rsp + 0x18 ], rdi +mov [ rsp + 0x20 ], r10 +mulx r10, rdi, [ rsi + 0x18 ] +adcx rdi, r8 +mov rdx, [ rsi + 0x0 ] +mov [ rsp + 0x28 ], rdi +mulx rdi, r8, [ rax + 0x0 ] +adc r10, 0x0 +mov rdx, [ rax + 0x0 ] +mov [ rsp + 0x30 ], r10 +mov [ rsp + 0x38 ], rcx +mulx rcx, r10, [ rsi + 0x28 ] +mov rdx, 0x89f3fffcfffcfffd +mov [ rsp + 0x40 ], r10 +mov [ rsp + 0x48 ], r11 +mulx r11, r10, r8 +xor r11, r11 +adox r15, rcx +adox rbp, r9 +mov rdx, [ rax + 0x18 ] +mulx rcx, r9, [ rsi + 0x28 ] +mov rdx, [ rax + 0x8 ] +mov [ rsp + 0x50 ], rbp +mulx rbp, r11, [ rsi + 0x0 ] +adox r9, r12 +mov rdx, [ rsi + 0x0 ] +mov [ rsp + 0x58 ], r9 +mulx r9, r12, [ rax + 0x10 ] +mov rdx, [ rax + 0x20 ] +mov [ rsp + 0x60 ], r15 +mov [ rsp + 0x68 ], r14 +mulx r14, r15, [ rsi + 0x28 ] +mov rdx, [ rsi + 0x28 ] +mov [ rsp + 0x70 ], rbx +mov [ rsp + 0x78 ], r13 +mulx r13, rbx, [ rax + 0x28 ] +adox r15, rcx +adox rbx, r14 +mov rdx, [ rsi + 0x0 ] +mulx r14, rcx, [ rax + 0x20 ] +adcx r11, rdi +mov rdx, [ rsi + 0x0 ] +mov [ rsp + 0x80 ], rbx +mulx rbx, rdi, [ rax + 0x18 ] +adcx r12, rbp +adcx rdi, r9 +mov rdx, [ rax + 0x28 ] +mulx r9, rbp, [ rsi + 0x0 ] +adcx rcx, rbx +adcx rbp, r14 +mov rdx, 0x0 +adox r13, rdx +adc r9, 0x0 +mov r14, 0xb9feffffffffaaab +mov rdx, r10 +mulx rbx, r10, r14 +mov r14, 0x1eabfffeb153ffff +mov [ rsp + 0x88 ], r13 +mov [ rsp + 0x90 ], r15 +mulx r15, r13, r14 +test al, al +adox r10, r8 +adcx r13, rbx +adox r13, r11 +mov r10, 0x6730d2a0f6b0f624 +mulx r11, r8, r10 +adcx r8, r15 +adox r8, r12 +mov r12, 0x4b1ba7b6434bacd7 +mulx r15, rbx, r12 +mov r12, 0x64774b84f38512bf +mulx r14, r10, r12 +adcx r10, r11 +adcx rbx, r14 +adox r10, rdi +adox rbx, rcx +mov rdi, 0x1a0111ea397fe69a +mulx r11, rcx, rdi +adcx rcx, r15 +mov rdx, 0x0 +adcx r11, rdx +adox rcx, rbp +clc +adcx r13, [ rsp + 0x78 ] +adox r11, r9 +adcx r8, [ rsp - 0x38 ] +mov rdx, [ rsi + 0x20 ] +mulx r9, rbp, [ rax + 0x18 ] +adcx r10, [ rsp - 0x18 ] +adcx rbx, [ rsp - 0x20 ] +adcx rcx, [ rsp + 0x70 ] +adcx r11, [ rsp + 0x10 ] +mov rdx, [ rsi + 0x20 ] +mulx r14, r15, [ rax + 0x0 ] +mov rdx, [ rax + 0x10 ] +mulx r12, rdi, [ rsi + 0x20 ] +mov rdx, [ rax + 0x8 ] +mov [ rsp + 0x98 ], r15 +mov [ rsp + 0xa0 ], r11 +mulx r11, r15, [ rsi + 0x20 ] +setc dl +clc +adcx r15, r14 +adcx rdi, r11 +adcx rbp, r12 +movzx rdx, dl +movzx r14, dl +adox r14, [ rsp + 0x68 ] +mov rdx, 0x89f3fffcfffcfffd +mulx r11, r12, r13 +mov rdx, [ rsi + 0x20 ] +mov [ rsp + 0xa8 ], rbp +mulx rbp, r11, [ rax + 0x20 ] +mov rdx, [ rax + 0x28 ] +mov [ rsp + 0xb0 ], rdi +mov [ rsp + 0xb8 ], r15 +mulx r15, rdi, [ rsi + 0x20 ] +adcx r11, r9 +mov rdx, 0xb9feffffffffaaab +mov [ rsp + 0xc0 ], r11 +mulx r11, r9, r12 +adcx rdi, rbp +setc bpl +clc +adcx r9, r13 +mov r9, 0x1eabfffeb153ffff +mov rdx, r12 +mulx r13, r12, r9 +movzx r9, bpl +lea r9, [ r9 + r15 ] +seto r15b +mov rbp, -0x2 +inc rbp +adox r12, r11 +mov r11, 0x6730d2a0f6b0f624 +mov [ rsp + 0xc8 ], r9 +mulx r9, rbp, r11 +adox rbp, r13 +adcx r12, r8 +adcx rbp, r10 +mov r8, 0x64774b84f38512bf +mulx r13, r10, r8 +mov r8, 0x4b1ba7b6434bacd7 +mov [ rsp + 0xd0 ], rdi +mulx rdi, r11, r8 +adox r10, r9 +adox r11, r13 +adcx r10, rbx +mov rbx, 0x1a0111ea397fe69a +mulx r13, r9, rbx +adox r9, rdi +adcx r11, rcx +mov rcx, 0x0 +adox r13, rcx +adcx r9, [ rsp + 0xa0 ] +adcx r13, r14 +movzx r14, r15b +adc r14, 0x0 +xor r15, r15 +adox r12, [ rsp - 0x40 ] +adox rbp, [ rsp - 0x30 ] +adox r10, [ rsp - 0x28 ] +adox r11, [ rsp + 0x0 ] +mov rcx, 0x89f3fffcfffcfffd +mov rdx, rcx +mulx rdi, rcx, r12 +adox r9, [ rsp - 0x8 ] +mov rdi, 0x1eabfffeb153ffff +mov rdx, rdi +mulx r15, rdi, rcx +adox r13, [ rsp - 0x10 ] +mov rbx, 0xb9feffffffffaaab +mov rdx, rcx +mulx r8, rcx, rbx +adcx rdi, r8 +adox r14, [ rsp + 0x8 ] +seto r8b +mov rbx, -0x2 +inc rbx +adox rcx, r12 +adox rdi, rbp +mov rcx, 0x6730d2a0f6b0f624 +mulx rbp, r12, rcx +adcx r12, r15 +adox r12, r10 +mov r10, 0x64774b84f38512bf +mulx rbx, r15, r10 +adcx r15, rbp +mov rbp, 0x4b1ba7b6434bacd7 +mulx rcx, r10, rbp +adox r15, r11 +adcx r10, rbx +mov r11, 0x1a0111ea397fe69a +mulx rbp, rbx, r11 +adcx rbx, rcx +mov rdx, 0x0 +adcx rbp, rdx +clc +adcx rdi, [ rsp - 0x48 ] +adcx r12, [ rsp + 0x48 ] +mov rcx, 0x89f3fffcfffcfffd +mov rdx, rdi +mulx r11, rdi, rcx +adox r10, r9 +adox rbx, r13 +mov r11, 0xb9feffffffffaaab +xchg rdx, rdi +mulx r13, r9, r11 +adox rbp, r14 +adcx r15, [ rsp + 0x38 ] +adcx r10, [ rsp + 0x20 ] +adcx rbx, [ rsp + 0x18 ] +adcx rbp, [ rsp + 0x28 ] +seto r14b +mov r11, -0x2 +inc r11 +adox r9, rdi +movzx r9, r14b +movzx r8, r8b +lea r9, [ r9 + r8 ] +mov r8, 0x1eabfffeb153ffff +mulx r14, rdi, r8 +adcx r9, [ rsp + 0x30 ] +setc r11b +clc +adcx rdi, r13 +adox rdi, r12 +mov r12, 0x6730d2a0f6b0f624 +mulx r8, r13, r12 +adcx r13, r14 +adox r13, r15 +mov r15, 0x64774b84f38512bf +mulx r12, r14, r15 +adcx r14, r8 +adox r14, r10 +mov r10, 0x4b1ba7b6434bacd7 +mulx r15, r8, r10 +adcx r8, r12 +adox r8, rbx +mov rbx, 0x1a0111ea397fe69a +mulx r10, r12, rbx +adcx r12, r15 +adox r12, rbp +setc dl +clc +adcx rdi, [ rsp + 0x98 ] +adcx r13, [ rsp + 0xb8 ] +movzx rbp, dl +lea rbp, [ rbp + r10 ] +adox rbp, r9 +adcx r14, [ rsp + 0xb0 ] +mov rdx, rcx +mulx r9, rcx, rdi +mov r9, 0xb9feffffffffaaab +mov rdx, r9 +mulx r15, r9, rcx +movzx r10, r11b +mov rbx, 0x0 +adox r10, rbx +mov r11, 0x6730d2a0f6b0f624 +mov rdx, rcx +mulx rbx, rcx, r11 +adcx r8, [ rsp + 0xa8 ] +adcx r12, [ rsp + 0xc0 ] +adcx rbp, [ rsp + 0xd0 ] +mov r11, -0x2 +inc r11 +adox r9, rdi +mov r9, 0x1eabfffeb153ffff +mulx r11, rdi, r9 +adcx r10, [ rsp + 0xc8 ] +setc r9b +clc +adcx rdi, r15 +adcx rcx, r11 +adox rdi, r13 +adox rcx, r14 +mov r13, 0x64774b84f38512bf +mulx r15, r14, r13 +adcx r14, rbx +mov rbx, 0x4b1ba7b6434bacd7 +mulx r13, r11, rbx +adox r14, r8 +adcx r11, r15 +mov r8, 0x1a0111ea397fe69a +mulx rbx, r15, r8 +adcx r15, r13 +mov rdx, 0x0 +adcx rbx, rdx +adox r11, r12 +adox r15, rbp +adox rbx, r10 +movzx r12, r9b +adox r12, rdx +xor rbp, rbp +adox rdi, [ rsp + 0x40 ] +adox rcx, [ rsp + 0x60 ] +mov rdx, 0x89f3fffcfffcfffd +mulx r10, r9, rdi +mov r10, 0x1eabfffeb153ffff +mov rdx, r9 +mulx r13, r9, r10 +adox r14, [ rsp + 0x50 ] +adox r11, [ rsp + 0x58 ] +adox r15, [ rsp + 0x90 ] +mov rbp, 0xb9feffffffffaaab +mulx r10, r8, rbp +adox rbx, [ rsp + 0x80 ] +adox r12, [ rsp + 0x88 ] +adcx r9, r10 +seto r10b +mov rbp, -0x2 +inc rbp +adox r8, rdi +adox r9, rcx +mov r8, 0x6730d2a0f6b0f624 +mulx rcx, rdi, r8 +adcx rdi, r13 +mov r13, 0x64774b84f38512bf +mulx r8, rbp, r13 +adcx rbp, rcx +adox rdi, r14 +mov r14, 0x4b1ba7b6434bacd7 +mulx r13, rcx, r14 +adcx rcx, r8 +adox rbp, r11 +mov r11, 0x1a0111ea397fe69a +mulx r14, r8, r11 +adcx r8, r13 +adox rcx, r15 +mov rdx, 0x0 +adcx r14, rdx +adox r8, rbx +adox r14, r12 +movzx r15, r10b +adox r15, rdx +mov rbx, r9 +mov r10, 0xb9feffffffffaaab +sub rbx, r10 +mov r12, rdi +mov r13, 0x1eabfffeb153ffff +sbb r12, r13 +mov rdx, rbp +mov r11, 0x6730d2a0f6b0f624 +sbb rdx, r11 +mov r11, rcx +mov r13, 0x64774b84f38512bf +sbb r11, r13 +mov r13, r8 +mov r10, 0x4b1ba7b6434bacd7 +sbb r13, r10 +mov r10, r14 +mov [ rsp + 0xd8 ], rdx +mov rdx, 0x1a0111ea397fe69a +sbb r10, rdx +sbb r15, 0x00000000 +cmovc rbx, r9 +cmovc r11, rcx +cmovc r13, r8 +mov r15, [ rsp - 0x50 ] +mov [ r15 + 0x20 ], r13 +mov [ r15 + 0x0 ], rbx +cmovc r12, rdi +cmovc r10, r14 +mov [ r15 + 0x8 ], r12 +mov [ r15 + 0x28 ], r10 +mov [ r15 + 0x18 ], r11 +mov r9, [ rsp + 0xd8 ] +cmovc r9, rbp +mov [ r15 + 0x10 ], r9 +mov rbx, [ rsp - 0x80 ] +mov rbp, [ rsp - 0x78 ] +mov r12, [ rsp - 0x70 ] +mov r13, [ rsp - 0x68 ] +mov r14, [ rsp - 0x60 ] +mov r15, [ rsp - 0x58 ] +add rsp, 352 +ret +// cpu Intel(R) Core(TM) i9-10900K CPU @ 3.70GHz +// ratio 1.8980 +// seed 2910039682142008 +// CC / CFLAGS clang / -march=native -mtune=native -O3 +// time needed: 5268392 ms on 180000 evaluations. +// Time spent for assembling and measuring (initial batch_size=31, initial num_batches=31): 132796 ms +// number of used evaluations: 180000 +// Ratio (time for assembling + measure)/(total runtime for 180000 evals): 0.025206172965109658 +// number reverted permutation / tried permutation: 69492 / 89703 =77.469% +// number reverted decision / tried decision: 62053 / 90296 =68.722% +// validated in 51.361s \ No newline at end of file diff --git a/src/low/x64-asm-6l/relic_fp_smb_low.c b/src/low/x64-asm-6l/relic_fp_smb_low.c index d25200282..118a053df 100644 --- a/src/low/x64-asm-6l/relic_fp_smb_low.c +++ b/src/low/x64-asm-6l/relic_fp_smb_low.c @@ -41,27 +41,5 @@ /*============================================================================*/ int fp_smbm_low(const dig_t *a) { - mpz_t n, p; - rlc_align dig_t t[2 * RLC_FP_DIGS], u[RLC_FP_DIGS]; - int res; - - mpz_init(n); - mpz_init(p); - -#if FP_RDC == MONTY - dv_zero(t + RLC_FP_DIGS, RLC_FP_DIGS); - dv_copy(t, a, RLC_FP_DIGS); - fp_rdcn_low(u, t); -#else - fp_copy(u, a); -#endif - - mpz_import(n, RLC_FP_DIGS, -1, sizeof(dig_t), 0, 0, u); - mpz_import(p, RLC_FP_DIGS, -1, sizeof(dig_t), 0, 0, fp_prime_get()); - - res = mpz_jacobi(n, p); - - mpz_clear(n); - mpz_clear(p); - return res; + return (fp_is_zero(a) ? 0 : (ct_is_square_mod_384(a, fp_prime_get()) ? 1 : -1)); } diff --git a/src/low/x64-asm-6l/relic_fp_smb_low.s b/src/low/x64-asm-6l/relic_fp_smb_low.s new file mode 100644 index 000000000..4d6195845 --- /dev/null +++ b/src/low/x64-asm-6l/relic_fp_smb_low.s @@ -0,0 +1,479 @@ +.text + +.globl ct_is_square_mod_384 +.type ct_is_square_mod_384,@function +.align 32 +ct_is_square_mod_384: +.cfi_startproc + .byte 0xf3,0x0f,0x1e,0xfa + + + pushq %rbp +.cfi_adjust_cfa_offset 8 +.cfi_offset %rbp,-16 + pushq %rbx +.cfi_adjust_cfa_offset 8 +.cfi_offset %rbx,-24 + pushq %r12 +.cfi_adjust_cfa_offset 8 +.cfi_offset %r12,-32 + pushq %r13 +.cfi_adjust_cfa_offset 8 +.cfi_offset %r13,-40 + pushq %r14 +.cfi_adjust_cfa_offset 8 +.cfi_offset %r14,-48 + pushq %r15 +.cfi_adjust_cfa_offset 8 +.cfi_offset %r15,-56 + subq $536,%rsp +.cfi_adjust_cfa_offset 536 + + + leaq 24+255(%rsp),%rax + andq $-256,%rax + + movq 0(%rdi),%r8 + movq 8(%rdi),%r9 + movq 16(%rdi),%r10 + movq 24(%rdi),%r11 + movq 32(%rdi),%r12 + movq 40(%rdi),%r13 + + movq 0(%rsi),%r14 + movq 8(%rsi),%r15 + movq 16(%rsi),%rbx + movq 24(%rsi),%rcx + movq 32(%rsi),%rdx + movq 40(%rsi),%rdi + movq %rax,%rsi + + movq %r8,0(%rax) + movq %r9,8(%rax) + movq %r10,16(%rax) + movq %r11,24(%rax) + movq %r12,32(%rax) + movq %r13,40(%rax) + + movq %r14,48(%rax) + movq %r15,56(%rax) + movq %rbx,64(%rax) + movq %rcx,72(%rax) + movq %rdx,80(%rax) + movq %rdi,88(%rax) + + xorq %rbp,%rbp + movl $24,%ecx + jmp .Loop_is_square + +.align 32 +.Loop_is_square: + movl %ecx,16(%rsp) + + call __ab_approximation_30 + movq %rax,0(%rsp) + movq %rbx,8(%rsp) + + movq $128+48,%rdi + xorq %rsi,%rdi + call __smulq_384_n_shift_by_30 + + movq 0(%rsp),%rdx + movq 8(%rsp),%rcx + leaq -48(%rdi),%rdi + call __smulq_384_n_shift_by_30 + + movl 16(%rsp),%ecx + xorq $128,%rsi + + andq 48(%rdi),%r14 + shrq $1,%r14 + addq %r14,%rbp + + subl $1,%ecx + jnz .Loop_is_square + + + + + movq 48(%rsi),%r9 + call __inner_loop_48 + + movq $1,%rax + andq %rbp,%rax + xorq $1,%rax + + leaq 536(%rsp),%r8 + movq 0(%r8),%r15 +.cfi_restore %r15 + movq 8(%r8),%r14 +.cfi_restore %r14 + movq 16(%r8),%r13 +.cfi_restore %r13 + movq 24(%r8),%r12 +.cfi_restore %r12 + movq 32(%r8),%rbx +.cfi_restore %rbx + movq 40(%r8),%rbp +.cfi_restore %rbp + leaq 48(%r8),%rsp +.cfi_adjust_cfa_offset -536-8*6 + + .byte 0xf3,0xc3 +.cfi_endproc +.size ct_is_square_mod_384,.-ct_is_square_mod_384 + +.type __smulq_384_n_shift_by_30,@function +.align 32 +__smulq_384_n_shift_by_30: +.cfi_startproc + .byte 0xf3,0x0f,0x1e,0xfa + + movq 0(%rsi),%r8 + movq 8(%rsi),%r9 + movq 16(%rsi),%r10 + movq 24(%rsi),%r11 + movq 32(%rsi),%r12 + movq 40(%rsi),%r13 + + movq %rdx,%rbx + sarq $63,%rdx + xorq %rax,%rax + subq %rdx,%rax + + xorq %rdx,%rbx + addq %rax,%rbx + + xorq %rdx,%r8 + xorq %rdx,%r9 + xorq %rdx,%r10 + xorq %rdx,%r11 + xorq %rdx,%r12 + xorq %rdx,%r13 + addq %r8,%rax + adcq $0,%r9 + adcq $0,%r10 + adcq $0,%r11 + adcq $0,%r12 + adcq $0,%r13 + + movq %rdx,%r14 + andq %rbx,%r14 + mulq %rbx + movq %rax,%r8 + movq %r9,%rax + movq %rdx,%r9 + mulq %rbx + addq %rax,%r9 + movq %r10,%rax + adcq $0,%rdx + movq %rdx,%r10 + mulq %rbx + addq %rax,%r10 + movq %r11,%rax + adcq $0,%rdx + movq %rdx,%r11 + mulq %rbx + addq %rax,%r11 + movq %r12,%rax + adcq $0,%rdx + movq %rdx,%r12 + mulq %rbx + addq %rax,%r12 + movq %r13,%rax + adcq $0,%rdx + movq %rdx,%r13 + negq %r14 + mulq %rbx + addq %rax,%r13 + adcq %rdx,%r14 + leaq 48(%rsi),%rsi + movq %rcx,%rdx + + movq %r8,0(%rdi) + movq %r9,8(%rdi) + movq %r10,16(%rdi) + movq %r11,24(%rdi) + movq %r12,32(%rdi) + movq %r13,40(%rdi) + movq 0(%rsi),%r8 + movq 8(%rsi),%r9 + movq 16(%rsi),%r10 + movq 24(%rsi),%r11 + movq 32(%rsi),%r12 + movq 40(%rsi),%r13 + + movq %rdx,%rbx + sarq $63,%rdx + xorq %rax,%rax + subq %rdx,%rax + + xorq %rdx,%rbx + addq %rax,%rbx + + xorq %rdx,%r8 + xorq %rdx,%r9 + xorq %rdx,%r10 + xorq %rdx,%r11 + xorq %rdx,%r12 + xorq %rdx,%r13 + addq %r8,%rax + adcq $0,%r9 + adcq $0,%r10 + adcq $0,%r11 + adcq $0,%r12 + adcq $0,%r13 + + movq %rdx,%r15 + andq %rbx,%r15 + mulq %rbx + movq %rax,%r8 + movq %r9,%rax + movq %rdx,%r9 + mulq %rbx + addq %rax,%r9 + movq %r10,%rax + adcq $0,%rdx + movq %rdx,%r10 + mulq %rbx + addq %rax,%r10 + movq %r11,%rax + adcq $0,%rdx + movq %rdx,%r11 + mulq %rbx + addq %rax,%r11 + movq %r12,%rax + adcq $0,%rdx + movq %rdx,%r12 + mulq %rbx + addq %rax,%r12 + movq %r13,%rax + adcq $0,%rdx + movq %rdx,%r13 + negq %r15 + mulq %rbx + addq %rax,%r13 + adcq %rdx,%r15 + leaq -48(%rsi),%rsi + + addq 0(%rdi),%r8 + adcq 8(%rdi),%r9 + adcq 16(%rdi),%r10 + adcq 24(%rdi),%r11 + adcq 32(%rdi),%r12 + adcq 40(%rdi),%r13 + adcq %r15,%r14 + + shrdq $30,%r9,%r8 + shrdq $30,%r10,%r9 + shrdq $30,%r11,%r10 + shrdq $30,%r12,%r11 + shrdq $30,%r13,%r12 + shrdq $30,%r14,%r13 + + sarq $63,%r14 + xorq %rbx,%rbx + subq %r14,%rbx + + xorq %r14,%r8 + xorq %r14,%r9 + xorq %r14,%r10 + xorq %r14,%r11 + xorq %r14,%r12 + xorq %r14,%r13 + addq %rbx,%r8 + adcq $0,%r9 + adcq $0,%r10 + adcq $0,%r11 + adcq $0,%r12 + adcq $0,%r13 + + movq %r8,0(%rdi) + movq %r9,8(%rdi) + movq %r10,16(%rdi) + movq %r11,24(%rdi) + movq %r12,32(%rdi) + movq %r13,40(%rdi) + + .byte 0xf3,0xc3 +.cfi_endproc +.size __smulq_384_n_shift_by_30,.-__smulq_384_n_shift_by_30 +.type __ab_approximation_30,@function +.align 32 +__ab_approximation_30: +.cfi_startproc + .byte 0xf3,0x0f,0x1e,0xfa + + movq 88(%rsi),%rbx + movq 80(%rsi),%r15 + movq 72(%rsi),%r14 + + movq %r13,%rax + orq %rbx,%rax + cmovzq %r12,%r13 + cmovzq %r15,%rbx + cmovzq %r11,%r12 + movq 64(%rsi),%r11 + cmovzq %r14,%r15 + + movq %r13,%rax + orq %rbx,%rax + cmovzq %r12,%r13 + cmovzq %r15,%rbx + cmovzq %r10,%r12 + movq 56(%rsi),%r10 + cmovzq %r11,%r15 + + movq %r13,%rax + orq %rbx,%rax + cmovzq %r12,%r13 + cmovzq %r15,%rbx + cmovzq %r9,%r12 + movq 48(%rsi),%r9 + cmovzq %r10,%r15 + + movq %r13,%rax + orq %rbx,%rax + cmovzq %r12,%r13 + cmovzq %r15,%rbx + cmovzq %r8,%r12 + cmovzq %r9,%r15 + + movq %r13,%rax + orq %rbx,%rax + bsrq %rax,%rcx + leaq 1(%rcx),%rcx + cmovzq %r8,%r13 + cmovzq %r9,%rbx + cmovzq %rax,%rcx + negq %rcx + + + shldq %cl,%r12,%r13 + shldq %cl,%r15,%rbx + + movq $0xFFFFFFFF00000000,%rax + movl %r8d,%r8d + movl %r9d,%r9d + andq %rax,%r13 + andq %rax,%rbx + orq %r13,%r8 + orq %rbx,%r9 + + jmp __inner_loop_30 + + .byte 0xf3,0xc3 +.cfi_endproc +.size __ab_approximation_30,.-__ab_approximation_30 +.type __inner_loop_30,@function +.align 32 +__inner_loop_30: +.cfi_startproc + .byte 0xf3,0x0f,0x1e,0xfa + + movq $0x7FFFFFFF80000000,%rbx + movq $0x800000007FFFFFFF,%rcx + leaq -1(%rbx),%r15 + movl $30,%edi + +.Loop_30: + movq %r8,%rax + andq %r9,%rax + shrq $1,%rax + + cmpq %r9,%r8 + movq %r8,%r10 + movq %r9,%r11 + leaq (%rax,%rbp,1),%rax + movq %rbx,%r12 + movq %rcx,%r13 + movq %rbp,%r14 + cmovbq %r9,%r8 + cmovbq %r10,%r9 + cmovbq %rcx,%rbx + cmovbq %r12,%rcx + cmovbq %rax,%rbp + + subq %r9,%r8 + subq %rcx,%rbx + addq %r15,%rbx + + testq $1,%r10 + cmovzq %r10,%r8 + cmovzq %r11,%r9 + cmovzq %r12,%rbx + cmovzq %r13,%rcx + cmovzq %r14,%rbp + + leaq 2(%r9),%rax + shrq $1,%r8 + shrq $2,%rax + addq %rcx,%rcx + leaq (%rax,%rbp,1),%rbp + subq %r15,%rcx + + subl $1,%edi + jnz .Loop_30 + + shrq $32,%r15 + movl %ebx,%eax + shrq $32,%rbx + movl %ecx,%edx + shrq $32,%rcx + subq %r15,%rax + subq %r15,%rbx + subq %r15,%rdx + subq %r15,%rcx + + .byte 0xf3,0xc3 +.cfi_endproc +.size __inner_loop_30,.-__inner_loop_30 + +.type __inner_loop_48,@function +.align 32 +__inner_loop_48: +.cfi_startproc + .byte 0xf3,0x0f,0x1e,0xfa + + movl $48,%edi + +.Loop_48: + movq %r8,%rax + andq %r9,%rax + shrq $1,%rax + + cmpq %r9,%r8 + movq %r8,%r10 + movq %r9,%r11 + leaq (%rax,%rbp,1),%rax + movq %rbp,%r12 + cmovbq %r9,%r8 + cmovbq %r10,%r9 + cmovbq %rax,%rbp + + subq %r9,%r8 + + testq $1,%r10 + cmovzq %r10,%r8 + cmovzq %r11,%r9 + cmovzq %r12,%rbp + + leaq 2(%r9),%rax + shrq $1,%r8 + shrq $2,%rax + addq %rax,%rbp + + subl $1,%edi + jnz .Loop_48 + + .byte 0xf3,0xc3 +.cfi_endproc +.size __inner_loop_48,.-__inner_loop_48 + +.section .note.GNU-stack,"",@progbits +.section .note.gnu.property,"a",@note + .long 4,2f-1f,5 + .byte 0x47,0x4E,0x55,0 +1: .long 0xc0000002,4,3 +.align 8 +2: diff --git a/src/low/x64-asm-7l/relic_fp_add_low.s b/src/low/x64-asm-7l/relic_fp_add_low.s index c53afb457..4f03c6d96 100644 --- a/src/low/x64-asm-7l/relic_fp_add_low.s +++ b/src/low/x64-asm-7l/relic_fp_add_low.s @@ -342,6 +342,15 @@ fp_subc_low: ret fp_negm_low: + push %rbx + + xorq %r9, %r9 + xorq %r10, %r10 + xorq %r11, %r11 + xorq %rbx, %rbx + xorq %rax, %rax + xorq %rcx, %rcx + movq 0(%rsi) , %r8 or 8(%rsi) , %r8 or 16(%rsi), %r8 @@ -357,6 +366,12 @@ fp_negm_low: cmovnz p4(%rip), %rbx cmovnz p5(%rip), %rax cmovnz p6(%rip), %rcx + cmovnz p1(%rip), %r9 + cmovnz p2(%rip), %r10 + cmovnz p3(%rip), %r11 + cmovnz p4(%rip), %rbx + cmovnz p5(%rip),%rax + cmovnz p6(%rip),%rcx subq 0(%rsi) , %r8 movq %r8 , 0(%rdi) sbbq 8(%rsi) , %r9 diff --git a/src/low/x64-asm-8.5l/relic_fp_add_low.s b/src/low/x64-asm-8.5l/relic_fp_add_low.s index b531d1ac7..c7a18e7c3 100644 --- a/src/low/x64-asm-8.5l/relic_fp_add_low.s +++ b/src/low/x64-asm-8.5l/relic_fp_add_low.s @@ -458,6 +458,19 @@ cdecl(fp_subc_low): ret cdecl(fp_negm_low): + push %rbx + push %rbp + push %r12 + + xorq %r9, %r9 + xorq %r10, %r10 + xorq %r11, %r11 + xorq %r12, %r12 + xorq %rbx, %rbx + xorq %rbp, %rbp + xorq %rax, %rax + xorq %rcx, %rcx + movq 0(%rsi) , %r8 or 8(%rsi) , %r8 or 16(%rsi), %r8 @@ -469,33 +482,36 @@ cdecl(fp_negm_low): or 64(%rsi), %r8 test %r8, %r8 cmovnz p0(%rip), %r8 + cmovnz p1(%rip), %r9 + cmovnz p2(%rip), %r10 + cmovnz p3(%rip), %r11 + cmovnz p4(%rip), %rbx + cmovnz p5(%rip), %rbp + cmovnz p6(%rip), %r12 + cmovnz p7(%rip), %rax + cmovnz p8(%rip), %rcx subq 0(%rsi) , %r8 movq %r8 , 0(%rdi) - cmovnz p1(%rip), %r8 - sbbq 8(%rsi) , %r8 - movq %r8 , 8(%rdi) - cmovnz p2(%rip), %r8 - sbbq 16(%rsi), %r8 - movq %r8 , 16(%rdi) - cmovnz p3(%rip), %r8 - sbbq 24(%rsi), %r8 - movq %r8 , 24(%rdi) - cmovnz p4(%rip), %r8 - sbbq 32(%rsi), %r8 - movq %r8 , 32(%rdi) - cmovnz p5(%rip), %r8 - sbbq 40(%rsi), %r8 - movq %r8 , 40(%rdi) - cmovnz p6(%rip), %r8 - sbbq 48(%rsi), %r8 - movq %r8 , 48(%rdi) - cmovnz p7(%rip), %r8 - sbbq 56(%rsi), %r8 - movq %r8 , 56(%rdi) - cmovnz p8(%rip), %r8 - sbbq 64(%rsi), %r8 - movq %r8 , 64(%rdi) - ret + sbbq 8(%rsi) , %r9 + movq %r9 , 8(%rdi) + sbbq 16(%rsi), %r10 + movq %r10 ,16(%rdi) + sbbq 24(%rsi), %r11 + movq %r11 ,24(%rdi) + sbbq 32(%rsi), %rbx + movq %rbx ,32(%rdi) + sbbq 40(%rsi), %rbp + movq %rbp ,40(%rdi) + sbbq 48(%rsi), %r12 + movq %r12 ,48(%rdi) + sbbq 56(%rsi), %rax + movq %rax ,56(%rdi) + sbbq 64(%rsi), %rcx + movq %rcx ,64(%rdi) + + pop %r12 + pop %rbp + pop %rbx cdecl(fp_dbln_low): movq 0(%rsi), %r8 diff --git a/src/low/x64-asm-8l/relic_bn_mul_low.c b/src/low/x64-asm-8l/relic_bn_mul_low.c new file mode 100644 index 000000000..2229b6d2e --- /dev/null +++ b/src/low/x64-asm-8l/relic_bn_mul_low.c @@ -0,0 +1,60 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2009 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 + * + * Implementation of the multiple precision integer arithmetic multiplication + * functions. + * + * @ingroup bn + */ + +#include + +#include "relic_bn.h" +#include "relic_bn_low.h" +#include "relic_util.h" + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +dig_t bn_mula_low(dig_t *c, const dig_t *a, dig_t digit, int size) { + return mpn_addmul_1(c, a, size, digit); +} + +dig_t bn_mul1_low(dig_t *c, const dig_t *a, dig_t digit, int size) { + return mpn_mul_1(c, a, size, digit); +} + +void bn_muln_low(dig_t *c, const dig_t *a, const dig_t *b, int size) { + mpn_mul_n(c, a, b, size); +} + +void bn_muld_low(dig_t *c, const dig_t *a, int sizea, const dig_t *b, int sizeb, + int low, int high) { + (void)low; + (void)high; + mpn_mul(c, a, sizea, b, sizeb); +} diff --git a/src/low/x64-asm-8l/relic_bn_mul_low.s b/src/low/x64-asm-8l/relic_bn_mul_low.s new file mode 100644 index 000000000..4a9161c7a --- /dev/null +++ b/src/low/x64-asm-8l/relic_bn_mul_low.s @@ -0,0 +1,113 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2009 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 + * + * Implementation of the multiple precision integer arithmetic multiplication + * functions in ASM. + * + * @ingroup bn + */ + +.text +.global bn_muls_low + +/** + * c = rdi, a = rsi, sa = rdx, digit = rcx, size = RLC_FP_DIGS + */ +bn_muls_low: + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbp + movq %rcx, %rax + shrq $63, %rax + xorq %rdx, %rax # sign = sa ^ sd; + movq %rcx, %rdx + negq %rcx + cmovns %rcx, %rdx # rdx = (digit < 0 ? -digit : digit); + xorq %rcx, %rcx # clear flags, create zero + + mulxq 0(%rsi), %r8, %r9 + + mulxq 8(%rsi), %r11, %r10 + adcx %r11, %r9 + + mulxq 16(%rsi), %r12, %r11 + adcx %r12, %r10 + + mulxq 24(%rsi), %r13, %r12 + adcx %r13, %r11 + + mulxq 32(%rsi), %r14, %r13 + adcx %r14, %r12 + + mulxq 40(%rsi), %r15, %r14 + adcx %r15, %r13 + + mulxq 48(%rsi), %rbp, %r15 + adcx %rbp, %r14 + + mulxq 56(%rsi), %rsi, %rbp + adcx %rsi, %r15 + adcx %rcx, %rbp + + negq %rax + xorq %rax, %r8 + xorq %rax, %r9 + xorq %rax, %r10 + xorq %rax, %r11 + xorq %rax, %r12 + xorq %rax, %r13 + xorq %rax, %r14 + xorq %rax, %r15 + xorq %rax, %rbp + + negq %rax + addq %rax, %r8 + adcx %rcx, %r9 + adcx %rcx, %r10 + adcx %rcx, %r11 + adcx %rcx, %r12 + adcx %rcx, %r13 + adcx %rcx, %r14 + adcx %rcx, %r15 + adcx %rcx, %rbp + movq %r8, 0(%rdi) + movq %r9, 8(%rdi) + movq %r10,16(%rdi) + movq %r11,24(%rdi) + movq %r12,32(%rdi) + movq %r13,40(%rdi) + movq %r14,48(%rdi) + movq %r15,56(%rdi) + movq %rbp, %rax + + popq %rbp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + ret diff --git a/src/low/x64-asm-8l/relic_fp_add_low.s b/src/low/x64-asm-8l/relic_fp_add_low.s index ded7cb8e3..b34dc0429 100644 --- a/src/low/x64-asm-8l/relic_fp_add_low.s +++ b/src/low/x64-asm-8l/relic_fp_add_low.s @@ -378,6 +378,17 @@ fp_subc_low: ret fp_negm_low: + push %rbx + push %rbp + + xorq %r9, %r9 + xorq %r10, %r10 + xorq %r11, %r11 + xorq %rbx, %rbx + xorq %rbp, %rbp + xorq %rax, %rax + xorq %rcx, %rcx + movq 0(%rsi) , %r8 or 8(%rsi) , %r8 or 16(%rsi), %r8 @@ -388,30 +399,33 @@ fp_negm_low: or 56(%rsi), %r8 test %r8, %r8 cmovnz p0(%rip), %r8 + cmovnz p1(%rip), %r9 + cmovnz p2(%rip), %r10 + cmovnz p3(%rip), %r11 + cmovnz p4(%rip), %rbx + cmovnz p5(%rip), %rbp + cmovnz p6(%rip), %rax + cmovnz p7(%rip), %rcx subq 0(%rsi) , %r8 movq %r8 , 0(%rdi) - cmovnz p1(%rip), %r8 - sbbq 8(%rsi) , %r8 - movq %r8 , 8(%rdi) - cmovnz p2(%rip), %r8 - sbbq 16(%rsi), %r8 - movq %r8 , 16(%rdi) - cmovnz p3(%rip), %r8 - sbbq 24(%rsi), %r8 - movq %r8 , 24(%rdi) - cmovnz p4(%rip), %r8 - sbbq 32(%rsi), %r8 - movq %r8 , 32(%rdi) - cmovnz p5(%rip), %r8 - sbbq 40(%rsi), %r8 - movq %r8 , 40(%rdi) - cmovnz p6(%rip), %r8 - sbbq 48(%rsi), %r8 - movq %r8 , 48(%rdi) - cmovnz p7(%rip), %r8 - sbbq 56(%rsi), %r8 - movq %r8 , 56(%rdi) - ret + sbbq 8(%rsi) , %r9 + movq %r9 , 8(%rdi) + sbbq 16(%rsi), %r10 + movq %r10 , 16(%rdi) + sbbq 24(%rsi), %r11 + movq %r11 , 24(%rdi) + sbbq 32(%rsi), %rbx + movq %rbx , 32(%rdi) + sbbq 40(%rsi), %rbp + movq %rbp , 40(%rdi) + sbbq 48(%rsi), %rax + movq %rax , 48(%rdi) + sbbq 56(%rsi), %rcx + movq %rcx , 56(%rdi) + + pop %rbp + pop %rbx + ret fp_dbln_low: movq 0(%rsi), %r8 diff --git a/src/low/x64-asm-8l/relic_fp_inv_low.s b/src/low/x64-asm-8l/relic_fp_inv_low.s deleted file mode 100644 index 2be825dfd..000000000 --- a/src/low/x64-asm-8l/relic_fp_inv_low.s +++ /dev/null @@ -1,296 +0,0 @@ -/* - * RELIC is an Efficient LIbrary for Cryptography - * Copyright (c) 2019 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 - * - * Implementation of the low-level in&version functions. - * - * @ingroup fp - */ - -#include "macro.s" - - -/*============================================================================*/ -/* Public definitions */ -/*============================================================================*/ - -/* No carry */ -.macro _DBL R, i - movq \i+0(\R), %rdx - addq %rdx, \i+0(\R) - movq \i+8(\R), %rdx - adcq %rdx, \i+8(\R) - movq \i+16(\R), %rdx - adcq %rdx, \i+16(\R) - movq \i+24(\R), %rdx - adcq %rdx, \i+24(\R) - movq \i+32(\R), %rdx - adcq %rdx, \i+32(\R) - movq \i+40(\R), %rdx - adcq %rdx, \i+40(\R) - movq \i+48(\R), %rdx - adcq %rdx, \i+48(\R) - movq \i+56(\R), %rdx - adcq %rdx, \i+56(\R) -.endm - -.global fp_invn_asm - -/** - * rdi = x1, rsi = a - */ -fp_invn_asm: - push %r12 - push %r13 - push %r14 - push %r15 - push %rbp - push %rbx - subq $256, %rsp - - /* v = p. */ - movq $P0, %r8 - movq $P1, %r9 - movq $P2, %r10 - movq $P3, %r11 - movq $P4, %r12 - movq $P5, %r13 - movq $P6, %r14 - movq $P7, %r15 - - /* rsp[0..7] = u = a. */ - movq 0(%rsi),%rax - movq %rax,0(%rsp) - movq 8(%rsi),%rax - movq %rax,8(%rsp) - movq 16(%rsi),%rax - movq %rax,16(%rsp) - movq 24(%rsi),%rax - movq %rax,24(%rsp) - movq 32(%rsi),%rax - movq %rax,32(%rsp) - movq 40(%rsi),%rax - movq %rax,40(%rsp) - movq 48(%rsi),%rax - movq %rax,48(%rsp) - movq 56(%rsi),%rax - movq %rax,56(%rsp) - xorq %rax, %rax - - /* rsp[7..15] = x1 = 1. */ - movq $1,64(%rsp) - movq $0,72(%rsp) - movq $0,80(%rsp) - movq $0,88(%rsp) - movq $0,96(%rsp) - movq $0,104(%rsp) - movq $0,112(%rsp) - movq $0,120(%rsp) - - /* rsp[16..23] = x2 = 0. */ - movq $0,128(%rsp) - movq $0,136(%rsp) - movq $0,144(%rsp) - movq $0,152(%rsp) - movq $0,160(%rsp) - movq $0,168(%rsp) - movq $0,176(%rsp) - movq $0,184(%rsp) - -loop: - movq %r8,%rdx - orq %r9,%rdx - orq %r10,%rdx - orq %r11,%rdx - orq %r12,%rdx - orq %r13,%rdx - orq %r14,%rdx - orq %r15,%rdx - jz end - - inc %rax - test $1, %r8 - jnz v_odd - - /* fp_rsh1_low(v). */ - shrd $1, %r9, %r8 - shrd $1, %r10, %r9 - shrd $1, %r11, %r10 - shrd $1, %r12, %r11 - shrd $1, %r13, %r12 - shrd $1, %r14, %r13 - shrd $1, %r15, %r14 - shr $1, %r15 - - /* fp_dbln_low(x1). */ - _DBL %rsp, 64 - jmp loop -v_odd: - movq 0(%rsp),%rdx - test $1, %rdx - jnz u_odd - - /* fp_rsh1_low(u). */ - movq 8(%rsp), %rdx - shrd $1, %rdx, 0(%rsp) - movq 16(%rsp), %rdx - shrd $1, %rdx, 8(%rsp) - movq 24(%rsp), %rdx - shrd $1, %rdx, 16(%rsp) - movq 32(%rsp), %rdx - shrd $1, %rdx, 24(%rsp) - movq 40(%rsp), %rdx - shrd $1, %rdx, 32(%rsp) - movq 48(%rsp), %rdx - shrd $1, %rdx, 40(%rsp) - movq 56(%rsp), %rdx - shrd $1, %rdx, 48(%rsp) - shr $1, %rdx - movq %rdx, 56(%rsp) - - /* fp_dbln_low(x2). */ - _DBL %rsp, 128 - jmp loop -u_odd: - subq 0(%rsp), %r8 - sbbq 8(%rsp), %r9 - sbbq 16(%rsp), %r10 - sbbq 24(%rsp), %r11 - sbbq 32(%rsp), %r12 - sbbq 40(%rsp), %r13 - sbbq 48(%rsp), %r14 - sbbq 56(%rsp), %r15 - jc cmp_lt - - /* fp_rsh1_low(v). */ - shrd $1, %r9, %r8 - shrd $1, %r10, %r9 - shrd $1, %r11, %r10 - shrd $1, %r12, %r11 - shrd $1, %r13, %r12 - shrd $1, %r14, %r13 - shrd $1, %r15, %r14 - shr $1, %r15 - - movq 64(%rsp), %rdx - addq %rdx, 128(%rsp) - movq 72(%rsp), %rdx - adcq %rdx, 136(%rsp) - movq 80(%rsp), %rdx - adcq %rdx, 144(%rsp) - movq 88(%rsp), %rdx - adcq %rdx, 152(%rsp) - movq 96(%rsp), %rdx - adcq %rdx, 160(%rsp) - movq 104(%rsp), %rdx - adcq %rdx, 168(%rsp) - movq 112(%rsp), %rdx - adcq %rdx, 176(%rsp) - movq 120(%rsp), %rdx - adcq %rdx, 184(%rsp) - - _DBL %rsp, 64 - jmp loop -cmp_lt: - addq 0(%rsp), %r8 - adcq 8(%rsp), %r9 - adcq 16(%rsp), %r10 - adcq 24(%rsp), %r11 - adcq 32(%rsp), %r12 - adcq 40(%rsp), %r13 - adcq 48(%rsp), %r14 - adcq 56(%rsp), %r15 - - subq %r8, 0(%rsp) - sbbq %r9, 8(%rsp) - sbbq %r10, 16(%rsp) - sbbq %r11, 24(%rsp) - sbbq %r12, 32(%rsp) - sbbq %r13, 40(%rsp) - sbbq %r14, 48(%rsp) - sbbq %r15, 56(%rsp) - - movq 8(%rsp), %rdx - shrd $1, %rdx, 0(%rsp) - movq 16(%rsp), %rdx - shrd $1, %rdx, 8(%rsp) - movq 24(%rsp), %rdx - shrd $1, %rdx, 16(%rsp) - movq 32(%rsp), %rdx - shrd $1, %rdx, 24(%rsp) - movq 40(%rsp), %rdx - shrd $1, %rdx, 32(%rsp) - movq 48(%rsp), %rdx - shrd $1, %rdx, 40(%rsp) - movq 56(%rsp), %rdx - shrd $1, %rdx, 48(%rsp) - shr $1, %rdx - movq %rdx, 56(%rsp) - - movq 128(%rsp), %rdx - addq %rdx, 64(%rsp) - movq 136(%rsp), %rdx - adcq %rdx, 72(%rsp) - movq 144(%rsp), %rdx - adcq %rdx, 80(%rsp) - movq 152(%rsp), %rdx - adcq %rdx, 88(%rsp) - movq 160(%rsp), %rdx - adcq %rdx, 96(%rsp) - movq 168(%rsp), %rdx - adcq %rdx, 104(%rsp) - movq 176(%rsp), %rdx - adcq %rdx, 112(%rsp) - movq 184(%rsp), %rdx - adcq %rdx, 120(%rsp) - - _DBL %rsp, 128 - jmp loop -end: - movq 64(%rsp), %r9 - movq %r9, 0(%rdi) - movq 72(%rsp), %r9 - movq %r9, 8(%rdi) - movq 80(%rsp), %r9 - movq %r9, 16(%rdi) - movq 88(%rsp), %r9 - movq %r9, 24(%rdi) - movq 96(%rsp), %r9 - movq %r9, 32(%rdi) - movq 104(%rsp), %r9 - movq %r9, 40(%rdi) - movq 112(%rsp), %r9 - movq %r9, 48(%rdi) - movq 120(%rsp), %r9 - movq %r9, 56(%rdi) -exit: - addq $256, %rsp - pop %rbx - pop %rbp - pop %r15 - pop %r14 - pop %r13 - pop %r12 - ret diff --git a/src/low/x64-asm-9l/relic_fp_add_low.s b/src/low/x64-asm-9l/relic_fp_add_low.s index 8dc4734b8..609e39cc0 100644 --- a/src/low/x64-asm-9l/relic_fp_add_low.s +++ b/src/low/x64-asm-9l/relic_fp_add_low.s @@ -424,6 +424,19 @@ cdecl(fp_subc_low): ret cdecl(fp_negm_low): + push %rbx + push %rbp + push %r12 + + xorq %r9, %r9 + xorq %r10, %r10 + xorq %r11, %r11 + xorq %r12, %r12 + xorq %rbx, %rbx + xorq %rbp, %rbp + xorq %rax, %rax + xorq %rcx, %rcx + movq 0(%rsi) , %r8 or 8(%rsi) , %r8 or 16(%rsi), %r8 @@ -434,34 +447,39 @@ cdecl(fp_negm_low): or 56(%rsi), %r8 or 64(%rsi), %r8 test %r8, %r8 - cmovnz p0(%rip), %r8 - subq 0(%rsi) , %r8 - movq %r8 , 0(%rdi) - cmovnz p1(%rip), %r8 - sbbq 8(%rsi) , %r8 - movq %r8 , 8(%rdi) - cmovnz p2(%rip), %r8 - sbbq 16(%rsi), %r8 - movq %r8 , 16(%rdi) - cmovnz p3(%rip), %r8 - sbbq 24(%rsi), %r8 - movq %r8 , 24(%rdi) - cmovnz p4(%rip), %r8 - sbbq 32(%rsi), %r8 - movq %r8 , 32(%rdi) - cmovnz p5(%rip), %r8 - sbbq 40(%rsi), %r8 - movq %r8 , 40(%rdi) - cmovnz p6(%rip), %r8 - sbbq 48(%rsi), %r8 - movq %r8 , 48(%rdi) - cmovnz p7(%rip), %r8 - sbbq 56(%rsi), %r8 - movq %r8 , 56(%rdi) - cmovnz p8(%rip), %r8 - sbbq 64(%rsi), %r8 - movq %r8 , 64(%rdi) - ret + cmovnz p0(%rip), %r8 + cmovnz p1(%rip), %r9 + cmovnz p2(%rip), %r10 + cmovnz p3(%rip), %r11 + cmovnz p4(%rip), %rbx + cmovnz p5(%rip), %rbp + cmovnz p6(%rip), %r12 + cmovnz p7(%rip), %rax + cmovnz p8(%rip), %rcx + subq 0(%rsi) , %r8 + movq %r8 , 0(%rdi) + sbbq 8(%rsi) , %r9 + movq %r9 , 8(%rdi) + sbbq 16(%rsi), %r10 + movq %r10 , 16(%rdi) + sbbq 24(%rsi), %r11 + movq %r11 , 24(%rdi) + sbbq 32(%rsi), %rbx + movq %rbx , 32(%rdi) + sbbq 40(%rsi), %rbp + movq %rbp , 40(%rdi) + sbbq 48(%rsi), %r12 + movq %r12 , 48(%rdi) + sbbq 56(%rsi), %rax + movq %rax , 56(%rdi) + sbbq 64(%rsi), %rcx + movq %rcx , 64(%rdi) + + pop %r12 + pop %rbp + pop %rbx + ret + cdecl(fp_dbln_low): movq 0(%rsi), %r8 diff --git a/src/pc/relic_pc_exp.c b/src/pc/relic_pc_exp.c index a7c6d8ce7..85b8ebde4 100644 --- a/src/pc/relic_pc_exp.c +++ b/src/pc/relic_pc_exp.c @@ -160,7 +160,11 @@ void gt_exp(gt_t c, const gt_t a, const bn_t b) { pc_get_ord(n); bn_mod(_b, b, n); +#if FP_PRIME <= 1536 RLC_CAT(RLC_GT_LOWER, exp_cyc)(c, a, _b); +#else + RLC_CAT(RLC_GT_LOWER, exp)(c, a, _b); +#endif } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { @@ -202,27 +206,36 @@ void gt_exp_dig(gt_t c, const gt_t a, dig_t b) { void gt_exp_sim(gt_t e, const gt_t a, const bn_t b, const gt_t c, const bn_t d) { bn_t n, _b, _d; + gt_t t; bn_null(n); bn_null(_b); bn_null(_d); + gt_null(t); RLC_TRY { bn_new(n); bn_new(_b); bn_new(_d); + gt_new(t); gt_get_ord(n); bn_mod(_b, b, n); bn_mod(_d, d, n); - +#if FP_PRIME <= 1536 RLC_CAT(RLC_GT_LOWER, exp_cyc_sim)(e, a, _b, c, _d); +#else + gt_exp(t, a, _b); + gt_exp(e, c, _d); + gt_mul(e, e, t); +#endif } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { bn_free(n); bn_free(_b); bn_free(_d); + gt_free(t); } } diff --git a/src/pc/relic_pc_util.c b/src/pc/relic_pc_util.c index e756fdfc3..fddd35d44 100644 --- a/src/pc/relic_pc_util.c +++ b/src/pc/relic_pc_util.c @@ -50,15 +50,23 @@ void gt_rand(gt_t a) { gt_rand_imp(a); #if FP_PRIME < 1536 -#if FP_PRIME == 315 || FP_PRIME == 317 || FP_PRIME == 509 +#if FP_PRIME == 575 + pp_exp_k48(a, a); +#elif FP_PRIME == 315 || FP_PRIME == 317 || FP_PRIME == 509 pp_exp_k24(a, a); -#elif FP_PRIME == 638 && !defined(FP_QNRES) +#elif FP_PRIME == 330 || FP_PRIME == 765 || FP_PRIME == 766 + pp_exp_k16(a, a); +#elif FP_PRIME == 508 || FP_PRIME == 638 && !defined(FP_QNRES) pp_exp_k18(a, a); #else pp_exp_k12(a, a); #endif #else +#if FP_PRIME == 1536 pp_exp_k2(a, a); +#else + pp_exp_k1(a, a); +#endif #endif } @@ -68,7 +76,7 @@ void gt_get_gen(gt_t g) { int g1_is_valid(const g1_t a) { bn_t n, t; - g1_t u, v; + g1_t u, v, w; size_t l0, l1, r = 0; int8_t naf0[RLC_FP_BITS + 1], naf1[RLC_FP_BITS + 1]; @@ -80,12 +88,14 @@ int g1_is_valid(const g1_t a) { bn_null(t); g1_null(u); g1_null(v); + g1_null(w); RLC_TRY { bn_new(n); bn_new(t); g1_new(u); g1_new(v); + g1_new(w); ep_curve_get_cof(n); if (bn_cmp_dig(n, 1) == RLC_EQ) { @@ -99,10 +109,17 @@ int g1_is_valid(const g1_t a) { * Piellard. https://eprint.iacr.org/2022/352.pdf */ case EP_B12: case EP_B24: + case EP_B48: /* Check [\psi(P) == [z^2 - 1]P. */ fp_prime_get_par(n); bn_sqr(n, n); if (ep_curve_is_pairf() == EP_B24) { + /* Check [\psi(P) == [z^4 - 1]P. */ + bn_sqr(n, n); + } + if (ep_curve_is_pairf() == EP_B48) { + /* Check [\psi(P) == [z^8 - 1]P. */ + bn_sqr(n, n); bn_sqr(n, n); } bn_sub_dig(n, n, 1); @@ -110,6 +127,52 @@ int g1_is_valid(const g1_t a) { ep_psi(v, a); r = g1_on_curve(a) && (g1_cmp(v, u) == RLC_EQ); break; + /* if (u % 2) == 0, check (u**4)*\psi(P) == P + * else check (u**4-1)//2 * (\psi(P) - P) == P */ + case EP_N16: + fp_prime_get_par(n); + bn_sqr(n, n); + bn_sqr(n, n); + ep_psi(u, a); + if (!bn_is_even(n)) { + bn_sub_dig(n, n, 1); + bn_hlv(n, n); + g1_sub(u, u, a); + g1_norm(u, u); + } + g1_mul_any(u, u, n); + r = g1_on_curve(a) && (g1_cmp(u, a) == RLC_EQ); + break; + /* Formulas from "Fast Subgroup Membership Testings on Pairing- + * friendly Curves" by Yu Dai, Kaizhan Lin, Chang-An Zhao, + * Zijian Zhou. https://eprint.iacr.org/2022/348.pdf */ + case EP_K16: + /* If u = 25 or 45 mod 70 then a1 = ((u//5)**4 + 5)//14 + * is an integer by definition. */ + fp_prime_get_par(n); + bn_div_dig(n, n, 5); + bn_sqr(n, n); + bn_sqr(n, n); + bn_add_dig(n, n, 5); + bn_div_dig(n, n, 14); + bn_mul_dig(n, n, 17); + bn_neg(n, n); + bn_add_dig(n, n, 6); + /* Compute P1 = a1*P. */ + g1_mul_any(w, a, n); + /* Compute \psi([17]P1) - [31]P1 */ + g1_dbl(u, w); + g1_dbl(u, u); + g1_dbl(u, u); + g1_dbl(v, u); + g1_add(u, v, w); + g1_dbl(v, v); + g1_sub(v, v, w); + ep_psi(u, u); + g1_add(u, u, v); + g1_neg(u, u); + r = g1_on_curve(a) && (g1_cmp(u, a) == RLC_EQ); + break; case EP_K18: /* Check that [a_0]P + [a_1]\psi(P)) == O, for * a_0 = 19a_1 + 1, a_1 = (x/7)^3 */ @@ -146,6 +209,22 @@ int g1_is_valid(const g1_t a) { } r = g1_on_curve(a) && g1_is_infty(u); break; + case EP_SG18: + /* Check that [9u^3+2]\psi(P) == -P. */ + fp_prime_get_par(n); + /* Apply \psi twice to get the other beta. */ + ep_psi(u, a); + ep_psi(u, u); + g1_mul_any(v, u, n); + g1_mul_any(v, v, n); + g1_mul_any(v, v, n); + g1_mul_dig(v, v, 9); + g1_dbl(u, u); + g1_add(v, v, u); + g1_norm(v, v); + g1_neg(v, v); + r = g1_on_curve(a) && (g1_cmp(a, v) == RLC_EQ); + break; #endif default: pc_get_ord(n); @@ -164,34 +243,40 @@ int g1_is_valid(const g1_t a) { bn_free(t); g1_free(u); g1_free(v); + g1_free(w); } return r; } int g2_is_valid(const g2_t a) { + g2_t s, t, u, v, w; + bn_t n; + dig_t rem; + int r = 0; + #if FP_PRIME >= 1536 - if (pc_map_is_type1()) { - return g1_is_valid(a); - } + return g1_is_valid(a); #else if (g2_is_infty(a)) { return 0; } - bn_t n; - g2_t u, v; - int r = 0; - bn_null(n); + g2_null(s); + g2_null(t); g2_null(u); g2_null(v); + g2_null(w); RLC_TRY { bn_new(n); + g2_new(s); + g2_new(t); g2_new(u); g2_new(v); + g2_new(w); switch (ep_curve_is_pairf()) { #if defined(EP_ENDOM) && !defined(STRIP) @@ -200,6 +285,7 @@ int g2_is_valid(const g2_t a) { * Piellard. https://eprint.iacr.org/2022/352.pdf */ case EP_B12: case EP_B24: + case EP_B48: if (core_get()->ep_id == B12_383) { /* Since p mod n = r, we can check instead that * psi^4(P) + P == \psi^2(P). */ @@ -230,18 +316,97 @@ int g2_is_valid(const g2_t a) { g2_dbl(v, v); r = g2_on_curve(a) && (g2_cmp(u, v) == RLC_EQ); break; - case EP_K18: - /* Check that [2z/7]P + \psi(P) + [z/7]\psi^3(P) == O. */ + /* If u is even, check that [u*p^3]P = P + * else check [p^5]P = [u]P. */ + case EP_N16: fp_prime_get_par(n); - bn_div_dig(n, n, 7); g2_mul_any(u, a, n); - g2_frb(v, u, 2); - g2_dbl(u, u); - g2_add(v, v, a); - g2_frb(v, v, 1); - g2_neg(v, v); + if (bn_is_even(n)) { + g2_frb(v, u, 3); + g2_copy(u, a); + } else { + g2_frb(v, a, 5); + } r = g2_on_curve(a) && (g2_cmp(u, v) == RLC_EQ); break; + /* Formulas from "Fast Subgroup Membership Testings for G1, + * G2 and GT on Pairing-friendly Curves" by Dai et al. + * https://eprint.iacr.org/2022/348.pdf + * Paper has u = 45 mod 70, we ran their code for u = 25 mod 70. */ + case EP_K16: + fp_prime_get_par(n); + bn_mod_dig(&rem, n, 70); + if (rem == 45) { + bn_neg(n, n); + } + /* Compute s = (\pm u - 25)/70. */ + bn_sub_dig(n, n, 25); + bn_div_dig(n, n, 70); + /* [11s+4, 9s+3, 3s+1, -(3s+1), -13*u-5, -7*u-3, u, -11s-4] */ + /* or [11s+4, -9s-3, 3s+1, 3s+1, -13*u-5, 7*u+3, u, 11s+4]. */ + g2_mul_any(u, a, n); /* u = a^s*/ + g2_frb(w, u, 6); + g2_dbl(s, u); + g2_add(v, s, a); + g2_add(t, v, u); /* t = a^(3s + 1) */ + g2_copy(u, v); /* u = a^(2s + 1)*/ + g2_frb(v, t, 2); + g2_add(w, w, v); + g2_frb(v, t, 3); + if (rem == 45) { + g2_add(w, w, v); + } else { + g2_sub(w, w, v); + } + g2_dbl(v, t); + g2_add(t, t, v); /* t = a^(9s + 3). */ + g2_frb(v, t, 1); + if (rem == 45) { + g2_neg(v, v); + } + g2_add(w, w, v); + g2_sub(s, t, s); /* s = a^(7s + 3). */ + g2_frb(v, s, 5); + if (rem == 45) { + g2_add(w, w, v); + } else { + g2_sub(w, w, v); + } + g2_add(t, t, u); /* t = a^(11s + 4). */ + g2_add(w, w, t); + g2_frb(v, t, 7); + if (rem == 45) { + g2_add(w, w, v); + } else { + g2_sub(w, w, v); + } + g2_add(t, t, u); /* t = a^(13s + 5). */ + g2_frb(t, t, 4); + r = g2_on_curve(a) && (g2_cmp(w, t) == RLC_EQ); + break; + case EP_K18: + /* Check that P + u*psi2P + 2*psi3P == \mathcal{O}. */ + fp_prime_get_par(n); + g2_frb(u, a, 2); + g2_frb(v, u, 1); + g2_dbl(v, v); + g2_mul_any(u, u, n); + g2_add(v, v, u); + g2_neg(u, v); + r = g2_on_curve(a) && (g2_cmp(u, a) == RLC_EQ); + break; + case EP_SG18: + /* Check that 3u*P + 2\psi^2(P) == \psi^5P] and [3]P \eq O. */ + fp_prime_get_par(n); + bn_mul_dig(n, n, 3); + g2_mul_any(u, a, n); + r = g2_is_infty(a) == 0; + g2_frb(v, a, 2); + g2_add(u, u, v); + g2_add(u, u, v); + g2_frb(v, a, 5); + r &= g2_on_curve(a) && (g2_cmp(u, v) == RLC_EQ); + break; #endif default: pc_get_ord(n); @@ -256,8 +421,11 @@ int g2_is_valid(const g2_t a) { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { bn_free(n); + g2_free(s); + g2_free(t); g2_free(u); g2_free(v); + g2_free(w); } return r; @@ -266,22 +434,29 @@ int g2_is_valid(const g2_t a) { int gt_is_valid(const gt_t a) { bn_t n; - gt_t u, v; + gt_t s, t, u, v, w; int l, r = 0; const int *b; + dig_t rem; if (gt_is_unity(a)) { return 0; } bn_null(n); + gt_null(s); + gt_null(t); gt_null(u); gt_null(v); + gt_null(w); RLC_TRY { bn_new(n); + gt_new(s); + gt_new(t); gt_new(u); gt_new(v); + gt_new(w); fp_prime_get_par(n); b = fp_prime_get_par_sps(&l); @@ -308,6 +483,13 @@ int gt_is_valid(const gt_t a) { r = (gt_cmp(u, v) == RLC_EQ); r &= fp24_test_cyc((void *)a); break; + case EP_B48: + /* Check that a^u = a^p. */ + gt_frb(u, a, 1); + fp48_exp_cyc_sps((void *)v, (void *)a, b, l, bn_sign(n)); + r = (gt_cmp(u, v) == RLC_EQ); + r &= fp48_test_cyc((void *)a); + break; /* Formulas from "Fast Subgroup Membership Testings for G1, * G2 and GT on Pairing-friendly Curves" by Dai et al. * https://eprint.iacr.org/2022/348.pdf */ @@ -324,21 +506,93 @@ int gt_is_valid(const gt_t a) { r = (gt_cmp(u, v) == RLC_EQ); r &= fp12_test_cyc((void *)a); break; + /* If u is even, check that [u*p^3]P = P + * else check [p^5]P = [u]P. */ + case EP_N16: + fp_prime_get_par(n); + gt_exp(u, a, n); + if (bn_is_even(n)) { + gt_frb(v, u, 3); + gt_copy(u, a); + } else { + gt_frb(v, a, 5); + } + r = (gt_cmp(u, v) == RLC_EQ); + r &= fp16_test_cyc((void *)a); + break; + case EP_K16: + fp_prime_get_par(n); + bn_mod_dig(&rem, n, 70); + if (rem == 45) { + bn_neg(n, n); + } + /* Compute s = (u - 25)/70. */ + bn_sub_dig(n, n, 25); + bn_div_dig(n, n, 70); + /* Vectors for u = 25 or 45 mod 70 below, respectively: */ + /* [11s+4, 9s+3, 3s+1, -(3s+1), -13*u-5, -7*u-3, u, -11s-4] */ + /* or [11s+4, -9s-3, 3s+1, 3s+1, -13*u-5, 7*u+3, u, 11s+4]. */ + gt_exp(u, a, n); /* u = a^s*/ + gt_frb(w, u, 6); + gt_sqr(s, u); + gt_mul(v, s, a); + gt_mul(t, v, u); /* t = a^(3s + 1) */ + gt_copy(u, v); /* u = a^(2s + 1)*/ + gt_frb(v, t, 2); + gt_mul(w, w, v); + gt_frb(v, t, 3); + if (rem != 45) { + gt_inv(v, v); + } + gt_mul(w, w, v); + gt_sqr(v, t); + gt_mul(t, t, v); /* t = a^(9s + 3). */ + gt_frb(v, t, 1); + if (rem == 45) { + gt_inv(v, v); + } + gt_mul(w, w, v); + gt_inv(s, s); + gt_mul(s, t, s); /* s = a^(7s + 3). */ + gt_frb(v, s, 5); + if (rem != 45) { + gt_inv(v, v); + } + gt_mul(w, w, v); + gt_mul(t, t, u); /* t = a^(11s + 4). */ + gt_mul(w, w, t); + gt_frb(v, t, 7); + if (rem != 45) { + gt_inv(v, v); + } + gt_mul(w, w, v); + gt_mul(t, t, u); /* t = a^(13s + 5). */ + gt_frb(t, t, 4); + r = (gt_cmp(w, t) == RLC_EQ); + r &= fp16_test_cyc((void *)a); + break; case EP_K18: - /* Check that [2z]P + [z]\psi^3(P) == -7\psi(P). */ - fp18_exp_cyc_sps((void *)u, (void *)a, b, l, bn_sign(n)); - gt_frb(v, u, 3); - gt_sqr(u, u); - gt_mul(u, u, v); - gt_sqr(v, a); - gt_mul(v, v, a); + /* Check that P + u*psi2P + 2*psi3P == \mathcal{O}. */ + gt_frb(u, a, 2); + gt_frb(v, u, 1); gt_sqr(v, v); - gt_mul(v, v, a); - gt_frb(v, v, 1); - gt_inv(v, v); - r = (gt_cmp(u, v) == RLC_EQ); + fp18_exp_cyc_sps((void *)u, (void *)u, b, l, bn_sign(n)); + gt_mul(v, v, u); + gt_inv(u, v); + r = (gt_cmp(u, a) == RLC_EQ); r &= fp18_test_cyc((void *)a); break; + case EP_SG18: + /* Check that 3u*P + 2\psi^2(P) == \psi^5P] and [3]P \eq O. */ + fp_prime_get_par(n); + bn_mul_dig(n, n, 3); + gt_exp(u, a, n); + r = gt_is_unity(a) == 0; + gt_frb(v, a, 2); + gt_mul(u, u, v); + gt_mul(u, u, v); + gt_frb(v, a, 5); + r &= fp18_test_cyc((void *)a); default: /* Common case. */ pc_get_ord(n); @@ -352,8 +606,11 @@ int gt_is_valid(const gt_t a) { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { bn_free(n); + gt_free(s); + gt_free(t); gt_free(u); gt_free(v); + gt_free(w); } return r; diff --git a/src/pp/relic_pp_add_k1.c b/src/pp/relic_pp_add_k1.c new file mode 100644 index 000000000..9d46c155e --- /dev/null +++ b/src/pp/relic_pp_add_k1.c @@ -0,0 +1,174 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 + * + * Implementation of Miller addition for curves of embedding degree 1. + * + * @ingroup pp + */ + +#include "relic_core.h" +#include "relic_pp.h" +#include "relic_fp_low.h" +#include "relic_fpx_low.h" +#include "relic_util.h" + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +#if EP_ADD == BASIC || !defined(STRIP) + +void pp_add_k1_basic(fp_t l, fp_t m, ep_t r, const ep_t p, const ep_t q) { + fp_t s; + + fp_null(s); + + RLC_TRY { + fp_new(s); + + if (fp_cmp(r->x, p->x) == RLC_EQ) { + fp_set_dig(m, 1); + fp_sub(l, q->x, p->x); + } else { + fp_sub(l, q->x, p->x); + ep_add_slp_basic(r, s, r, p); + fp_mul(l, l, s); + fp_sub(l, q->y, l); + fp_sub(l, l, p->y); + if (fp_is_zero(l)) { + fp_set_dig(l, 1); + } + fp_sub(m, q->x, r->x); + } + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp_free(s); + } +} + +#endif + +#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP) + +void pp_add_k1_projc(fp_t l, fp_t m, 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); + + fp_sqr(l, r->z); + fp_mul(l, l, p->x); + if (fp_cmp(l, r->x) == RLC_EQ) { + fp_set_dig(m, 1); + fp_sub(l, q->x, p->x); + } else { + /* t0 = z1^2. */ + fp_sqr(t0, r->z); + + /* t3 = U = x2 * z1^2. */ + fp_mul(t3, p->x, t0); + + /* t1 = S = y2 * z1^3. */ + fp_mul(t1, t0, r->z); + fp_mul(t1, t1, p->y); + + /* t2 = H = U - x1. */ + fp_sub(t2, t3, r->x); + + /* t4 = L = S - y1. */ + fp_sub(t4, t1, r->y); + + /* t5 = H_2 = 2H, t3 = I = 4H^2. */ + fp_dbl(t5, t2); + fp_sqr(t3, t5); + + /* Z3 = (Z1 + H)^2 - Z1^2 - H^2 = 2 * z1 * H. */ + fp_mul(r->z, r->z, t5); + + /* t4 = M = 2L, t5 = M3 = (L + Z3)^2 - L^2 - Z3^2 = 2 * L * Z3. */ + fp_dbl(t4, t4); + fp_mul(t5, t4, r->z); + + /* l = Z3^2 * (yQ - y2) - M3*(xQ - x2). */ + fp_sqr(m, r->z); + fp_sub(l, q->y, p->y); + fp_mul(l, l, m); + fp_sub(t0, q->x, p->x); + fp_mul(t0, t0, t5); + fp_sub(l, l, t0); + if (fp_is_zero(l)) { + fp_set_dig(l, 1); + } + + /* t0 = V = x1 * I, t3 = J = HI, x3 = 4L^2 - J - 2V*/ + fp_mul(t0, r->x, t3); + fp_mul(t3, t3, t2); + fp_sqr(r->x, t4); + fp_sub(r->x, r->x, t3); + fp_sub(r->x, r->x, t0); + fp_sub(r->x, r->x, t0); + + /* y3 = M * (V - X3) - 2y1 * J. */ + fp_mul(r->y, r->y, t3); + fp_dbl(r->y, r->y); + fp_sub(t0, t0, r->x); + fp_mul(t0, t4, t0); + fp_sub(r->y, t0, r->y); + + /* v = Z3^2 * xQ - X3. */ + fp_mul(m, m, q->x); + fp_sub(m, m, r->x); + + 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); + } +} + +#endif diff --git a/src/pp/relic_pp_add_k16.c b/src/pp/relic_pp_add_k16.c new file mode 100644 index 000000000..8c72c67f6 --- /dev/null +++ b/src/pp/relic_pp_add_k16.c @@ -0,0 +1,346 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 + * + * Implementation of Miller addition for curves of embedding degree 16. + * + * @ingroup pp + */ + +#include "relic_core.h" +#include "relic_pp.h" +#include "relic_fp_low.h" +#include "relic_fpx_low.h" +#include "relic_util.h" + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +#if EP_ADD == BASIC || !defined(STRIP) + +void pp_add_k16_basic(fp16_t l, ep4_t r, const ep4_t q, const ep_t p) { + int one = 1, zero = 0; + fp4_t s; + ep4_t t; + + fp4_null(s); + ep4_null(t); + + RLC_TRY { + fp4_new(s); + ep4_new(t); + + ep4_copy(t, r); + ep4_add_slp_basic(r, s, r, q); + + if (ep4_curve_is_twist() == RLC_EP_MTYPE) { + one ^= 1; + zero ^= 1; + } + + fp_mul(l[one][zero][0][0], s[0][0], p->x); + fp_mul(l[one][zero][0][1], s[0][1], p->x); + fp_mul(l[one][zero][1][0], s[1][0], p->x); + fp_mul(l[one][zero][1][1], s[1][1], p->x); + fp4_mul(l[one][one], s, t->x); + fp4_sub(l[one][one], t->y, l[one][one]); + fp_copy(l[zero][zero][0][0], p->y); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + fp4_free(s); + ep4_free(t); + } +} + +#endif + +#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP) + +#if PP_EXT == BASIC || !defined(STRIP) + +void pp_add_k16_projc_basic(fp16_t l, ep4_t r, const ep4_t q, const ep_t p) { + fp4_t t0, t1, t2, t3, t4, t5; + int one = 1, zero = 0; + + fp4_null(t0); + fp4_null(t1); + fp4_null(t2); + fp4_null(t3); + fp4_null(t4); + + RLC_TRY { + fp4_new(t0); + fp4_new(t1); + fp4_new(t2); + fp4_new(t3); + fp4_new(t4); + fp4_new(t5); + + if (ep4_curve_is_twist() == RLC_EP_MTYPE) { + one ^= 1; + zero ^= 1; + } + + /* t0 = A = Z1^2, t1 = B = X2*Z1. */ + fp4_sqr(t0, r->z); + fp4_mul(t1, r->z, q->x); + + /* t0 = C = y2*A, t2 = D = (x1 - B) */ + fp4_mul(t0, t0, q->y); + fp4_sub(t2, r->x, t1); + + /* t3 = E = 2*(y1 - C), t4 = F = 2*D*z1, t2 = G = 4*D*F. */ + fp4_sub(t3, r->y, t0); + fp4_dbl(t3, t3); + fp4_dbl(t2, t2); + fp4_mul(t4, t2, r->z); + fp4_mul(t2, t2, t4); + fp4_dbl(t2, t2); + + /* l = E*X2 - F*Y2 - E*xQ + F*yQ. */ + fp4_mul(l[one][one], t3, q->x); + fp4_mul(t0, t4, q->y); + fp4_sub(l[one][one], l[one][one], t0); + fp_mul(l[one][zero][0][0], t3[0][0], p->x); + fp_mul(l[one][zero][0][1], t3[0][1], p->x); + fp_mul(l[one][zero][1][0], t3[1][0], p->x); + fp_mul(l[one][zero][1][1], t3[1][1], p->x); + fp_mul(l[zero][zero][0][0], t4[0][0], p->y); + fp_mul(l[zero][zero][0][1], t4[0][1], p->y); + fp_mul(l[zero][zero][1][0], t4[1][0], p->y); + fp_mul(l[zero][zero][1][1], t4[1][1], p->y); + + /* z3 = F^2, t4 = (F + E)^2, t3 = E^2. */ + fp4_sqr(r->z, t4); + fp4_add(t4, t4, t3); + fp4_sqr(t4, t4); + fp4_sqr(t3, t3); + + /* t5 = x3 = 2*E^2 - (x1 + B)*G. */ + fp4_add(t1, t1, r->x); + fp4_mul(t1, t1, t2); + fp4_dbl(t5, t3); + fp4_sub(t5, t5, t1); + + /* y3 = ((F + E)^2 - E^2 - F^2)*(x1*G - x3) - y1*G^2. */ + fp4_sub(t4, t4, r->z); + fp4_sub(t4, t4, t3); + fp4_mul(t1, r->x, t2); + fp4_sub(t1, t1, t5); + fp4_mul(t4, t4, t1); + fp4_sqr(t2, t2); + fp4_mul(r->y, r->y, t2); + fp4_sub(r->y, t4, r->y); + + /* Z3 = 2*F^2. */ + fp4_dbl(r->z, r->z); + fp4_copy(r->x, t5); + + 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); + } +} + +#endif + +#if PP_EXT == LAZYR || !defined(STRIP) + +void pp_add_k16_projc_lazyr(fp16_t l, ep4_t r, const ep4_t q, const ep_t p) { + fp4_t t0, t1, t2, t3, t4, t5; + int one = 1, zero = 0; + + fp4_null(t0); + fp4_null(t1); + fp4_null(t2); + fp4_null(t3); + fp4_null(t4); + + RLC_TRY { + fp4_new(t0); + fp4_new(t1); + fp4_new(t2); + fp4_new(t3); + fp4_new(t4); + fp4_new(t5); + + if (ep4_curve_is_twist() == RLC_EP_MTYPE) { + one ^= 1; + zero ^= 1; + } + + /* t0 = A = Z1^2, t1 = B = X2*Z1. */ + fp4_sqr(t0, r->z); + fp4_mul(t1, r->z, q->x); + + /* t0 = C = y2*A, t2 = D = (x1 - B) */ + fp4_mul(t0, t0, q->y); + fp4_sub(t2, r->x, t1); + + /* t3 = E = 2*(y1 - C), t4 = F = 2*D*z1, t2 = G = 4*D*F. */ + fp4_sub(t3, r->y, t0); + fp4_dbl(t3, t3); + fp4_dbl(t2, t2); + fp4_mul(t4, t2, r->z); + fp4_mul(t2, t2, t4); + fp4_dbl(t2, t2); + + /* l = E*X2 - F*Y2 - E*xQ + F*yQ. */ + fp4_mul(l[one][one], t3, q->x); + fp4_mul(t0, t4, q->y); + fp4_sub(l[one][one], l[one][one], t0); + fp_mul(l[one][zero][0][0], t3[0][0], p->x); + fp_mul(l[one][zero][0][1], t3[0][1], p->x); + fp_mul(l[one][zero][1][0], t3[1][0], p->x); + fp_mul(l[one][zero][1][1], t3[1][1], p->x); + fp_mul(l[zero][zero][0][0], t4[0][0], p->y); + fp_mul(l[zero][zero][0][1], t4[0][1], p->y); + fp_mul(l[zero][zero][1][0], t4[1][0], p->y); + fp_mul(l[zero][zero][1][1], t4[1][1], p->y); + + /* z3 = F^2, t4 = (F + E)^2, t3 = E^2. */ + fp4_sqr(r->z, t4); + fp4_add(t4, t4, t3); + fp4_sqr(t4, t4); + fp4_sqr(t3, t3); + + /* t5 = x3 = 2*E^2 - (x1 + B)*G. */ + fp4_add(t1, t1, r->x); + fp4_mul(t1, t1, t2); + fp4_dbl(t5, t3); + fp4_sub(t5, t5, t1); + + /* y3 = ((F + E)^2 - E^2 - F^2)*(x1*G - x3) - y1*G^2. */ + fp4_sub(t4, t4, r->z); + fp4_sub(t4, t4, t3); + fp4_mul(t1, r->x, t2); + fp4_sub(t1, t1, t5); + fp4_mul(t4, t4, t1); + fp4_sqr(t2, t2); + fp4_mul(r->y, r->y, t2); + fp4_sub(r->y, t4, r->y); + + /* Z3 = 2*F^2. */ + fp4_dbl(r->z, r->z); + fp4_copy(r->x, t5); + + 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); + } +} + +#endif + +#endif + +void pp_add_lit_k16(fp16_t l, ep_t r, const ep_t p, const ep4_t q) { + fp_t t0, t1, t2, t3; + int one = 1, zero = 0; + + fp_null(t0); + fp_null(t1); + fp_null(t2); + fp_null(t3); + + RLC_TRY { + fp_new(t0); + fp_new(t1); + fp_new(t2); + fp_new(t3); + + fp_mul(t0, r->z, p->x); + fp_sub(t0, r->x, t0); + fp_mul(t1, r->z, p->y); + fp_sub(t1, r->y, t1); + fp_mul(t2, p->x, t1); + r->coord = PROJC; + + if (ep4_curve_is_twist() == RLC_EP_MTYPE) { + one ^= 1; + zero ^= 1; + } + + fp_mul(l[zero][zero][0][0], t0, p->y); + fp_sub(l[zero][zero][0][0], t2, l[zero][zero][0][0]); + + fp_mul(l[zero][one][0][0], q->x[0][0], t1); + fp_mul(l[zero][one][0][1], q->x[0][1], t1); + fp_mul(l[zero][one][1][0], q->x[1][0], t1); + fp_mul(l[zero][one][1][1], q->x[1][1], t1); + fp4_neg(l[zero][one], l[zero][one]); + + fp_mul(l[one][one][0][0], q->y[0][0], t0); + fp_mul(l[one][one][0][1], q->y[0][1], t0); + fp_mul(l[one][one][1][0], q->y[1][0], t0); + fp_mul(l[one][one][1][1], q->y[1][1], t0); + + fp_sqr(t2, t0); + fp_mul(r->x, t2, r->x); + fp_mul(t2, t0, t2); + fp_sqr(t3, t1); + fp_mul(t3, t3, r->z); + fp_add(t3, t2, t3); + fp_sub(t3, t3, r->x); + fp_sub(t3, t3, r->x); + fp_sub(r->x, r->x, t3); + fp_mul(t1, t1, r->x); + fp_mul(r->y, t2, r->y); + fp_sub(r->y, t1, r->y); + fp_mul(r->x, t0, t3); + fp_mul(r->z, r->z, t2); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + fp_free(t0); + fp_free(t1); + fp_free(t2); + fp_free(t3); + } +} diff --git a/src/pp/relic_pp_add_k18.c b/src/pp/relic_pp_add_k18.c index 29b6030c6..f3616793a 100644 --- a/src/pp/relic_pp_add_k18.c +++ b/src/pp/relic_pp_add_k18.c @@ -24,7 +24,7 @@ /** * @file * - * Implementation of Miller addition for curves of embedding degree 12. + * Implementation of Miller addition for curves of embedding degree 18. * * @ingroup pp */ diff --git a/src/pp/relic_pp_add_k48.c b/src/pp/relic_pp_add_k48.c index 3be9b9dfb..a21b2f9ca 100644 --- a/src/pp/relic_pp_add_k48.c +++ b/src/pp/relic_pp_add_k48.c @@ -33,93 +33,25 @@ #include "relic_pp.h" #include "relic_util.h" -/*============================================================================*/ -/* Private definitions */ -/*============================================================================*/ - -static void ep8_add_basic(fp8_t s, fp8_t rx, fp8_t ry, const fp8_t qx, - const fp8_t qy) { - 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, qx, rx); - /* t1 = y2 - y1. */ - fp8_sub(t1, qy, ry); - - /* 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_basic(s, rx, ry); - RLC_THROW(ERR_NO_VALID); - } else { - /* If t1 is not zero and t0 is zero, q = -p and r = infty. */ - fp8_zero(rx); - fp8_zero(ry); - } - } 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, rx); - fp8_sub(t0, t0, qx); - - /* y3 = lambda * (x1 - x3) - y1. */ - fp8_sub(t1, rx, t0); - fp8_mul(t1, t2, t1); - fp8_sub(ry, t1, ry); - - fp8_copy(rx, t0); - - if (s != NULL) { - fp8_copy(s, t2); - } - } - } - RLC_CATCH_ANY { - RLC_THROW(ERR_CAUGHT); - } - RLC_FINALLY { - fp8_free(t0); - fp8_free(t1); - fp8_free(t2); - } -} - /*============================================================================*/ /* Public definitions */ /*============================================================================*/ #if EP_ADD == BASIC || !defined(STRIP) -void pp_add_k48_basic(fp48_t l, fp8_t rx, fp8_t ry, fp8_t qx, fp8_t qy, const ep_t p) { - fp8_t s, tx, ty; +void pp_add_k48_basic(fp48_t l, ep8_t r, const ep8_t q, const ep_t p) { + fp8_t s; + ep8_t t; fp8_null(s); - fp8_null(tx); - fp8_null(ty); + ep8_null(t); RLC_TRY { fp8_new(s); - fp8_new(tx); - fp8_new(ty); + ep8_new(t); - fp8_copy(tx, rx); - fp8_copy(ty, ry); - ep8_add_basic(s, rx, ry, qx, qy); + ep8_copy(t, r); + ep8_add_slp_basic(r, s, r, q); fp48_zero(l); fp_mul(l[0][1][0][0][0], p->x, s[0][0][0]); @@ -131,8 +63,8 @@ void pp_add_k48_basic(fp48_t l, fp8_t rx, fp8_t ry, fp8_t qx, fp8_t qy, const ep fp_mul(l[0][1][1][1][0], p->x, s[1][1][0]); fp_mul(l[0][1][1][1][1], p->x, s[1][1][1]); - fp8_mul(l[0][0], s, tx); - fp8_sub(l[0][0], ty, l[0][0]); + fp8_mul(l[0][0], s, t->x); + fp8_sub(l[0][0], t->y, l[0][0]); fp_neg(l[1][1][0][0][0], p->y); } @@ -141,8 +73,7 @@ void pp_add_k48_basic(fp48_t l, fp8_t rx, fp8_t ry, fp8_t qx, fp8_t qy, const ep } RLC_FINALLY { fp8_free(s); - fp8_free(tx); - fp8_free(ty); + ep8_free(t); } } @@ -150,8 +81,7 @@ void pp_add_k48_basic(fp48_t l, fp8_t rx, fp8_t ry, fp8_t qx, fp8_t qy, const ep #if EP_ADD == PROJC || !defined(STRIP) -void pp_add_k48_projc(fp48_t l, fp8_t rx, fp8_t ry, fp8_t rz, const fp8_t qx, - const fp8_t qy, const ep_t p) { +void pp_add_k48_projc(fp48_t l, ep8_t r, const ep8_t q, const ep_t p) { fp8_t t0, t1, t2, t3, t4; fp8_null(t0); @@ -168,22 +98,22 @@ void pp_add_k48_projc(fp48_t l, fp8_t rx, fp8_t ry, fp8_t rz, const fp8_t qx, fp8_new(t4); /* B = t0 = x1 - x2 * z1. */ - fp8_mul(t0, rz, qx); - fp8_sub(t0, rx, t0); + fp8_mul(t0, r->z, q->x); + fp8_sub(t0, r->x, t0); /* A = t1 = y1 - y2 * z1. */ - fp8_mul(t1, rz, qy); - fp8_sub(t1, ry, t1); + fp8_mul(t1, r->z, q->y); + fp8_sub(t1, r->y, t1); /* D = B^2. */ fp8_sqr(t2, t0); /* G = x1 * D. */ - fp8_mul(rx, rx, t2); + fp8_mul(r->x, r->x, t2); /* E = B^3. */ fp8_mul(t2, t2, t0); /* C = A^2. */ fp8_sqr(t3, t1); /* F = E + z1 * C. */ - fp8_mul(t3, t3, rz); + fp8_mul(t3, t3, r->z); fp8_add(t3, t2, t3); /* l10 = - (A * xp). */ @@ -198,23 +128,23 @@ void pp_add_k48_projc(fp48_t l, fp8_t rx, fp8_t ry, fp8_t rz, const fp8_t qx, fp_mul(l[0][1][1][1][1], t1[1][1][1], t4[0][0][0]); /* t4 = B * x2. */ - fp8_mul(t4, qx, t1); + fp8_mul(t4, q->x, t1); /* H = E + F - 2 * G. */ - fp8_sub(t3, t3, rx); - fp8_sub(t3, t3, rx); + fp8_sub(t3, t3, r->x); + fp8_sub(t3, t3, r->x); /* y3 = A * (G - H) - y1 * E. */ - fp8_sub(rx, rx, t3); - fp8_mul(t1, t1, rx); - fp8_mul(ry, t2, ry); - fp8_sub(ry, t1, ry); + fp8_sub(r->x, r->x, t3); + fp8_mul(t1, t1, r->x); + fp8_mul(r->y, t2, r->y); + fp8_sub(r->y, t1, r->y); /* x3 = B * H. */ - fp8_mul(rx, t0, t3); + fp8_mul(r->x, t0, t3); /* z3 = z1 * E. */ - fp8_mul(rz, rz, t2); + fp8_mul(r->z, r->z, t2); /* l11 = J = B * x2 - A * y2. */ - fp8_mul(t2, qy, t0); + fp8_mul(t2, q->y, t0); fp8_sub(l[0][0], t4, t2); /* l00 = B * yp. */ diff --git a/src/pp/relic_pp_add_k8.c b/src/pp/relic_pp_add_k8.c index 91fea6f36..cb040b0c6 100644 --- a/src/pp/relic_pp_add_k8.c +++ b/src/pp/relic_pp_add_k8.c @@ -24,7 +24,7 @@ /** * @file * - * Implementation of Miller addition for curves of embedding degree 2. + * Implementation of Miller addition for curves of embedding degree 8. * * @ingroup pp */ diff --git a/src/pp/relic_pp_dbl_k1.c b/src/pp/relic_pp_dbl_k1.c new file mode 100644 index 000000000..0c7667e0e --- /dev/null +++ b/src/pp/relic_pp_dbl_k1.c @@ -0,0 +1,168 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 + * + * Implementation of Miller doubling for curves of embedding degree 1. + * + * @ingroup pp + */ + +#include "relic_core.h" +#include "relic_pp.h" +#include "relic_fp_low.h" +#include "relic_fpx_low.h" +#include "relic_util.h" + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +#if EP_ADD == BASIC || !defined(STRIP) + +/* Formulas from "Generation and Tate Pairing Computation + * of Ordinary Elliptic Curves with Embedding Degree One", by Hu et al. */ + +void pp_dbl_k1_basic(fp_t l, fp_t m, ep_t r, const ep_t p, const ep_t q) { + fp_t s; + + fp_null(s); + + RLC_TRY { + fp_new(s); + + ep_dbl_slp_basic(r, s, p); + fp_sub(m, q->x, r->x); + fp_mul(l, m, s); + fp_sub(l, r->y, l); + fp_add(l, l, q->y); + if (fp_is_zero(l)) { + fp_set_dig(l, 1); + } + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp_free(s); + } +} + +#endif + +#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP) + +void pp_dbl_k1_projc(fp_t l, fp_t m, 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); + + /* dbl-2007-bl formulas 1M + 8S + 1*a + 10add + 2*2 + 1*3 + 1*8 */ + + /* t0 = z1^2. */ + fp_sqr(t0, p->z); + + /* t1 = y1^2. */ + fp_sqr(t1, p->y); + + /* t2 = x1^2. */ + fp_sqr(t2, p->x); + + /* t3 = y1^4.*/ + fp_sqr(t3, t1); + + /* t4 = S = 2*((X1+YY)^2-XX-YYYY). */ + fp_add(t4, p->x, t1); + fp_sqr(t4, t4); + fp_sub(t4, t4, t2); + fp_sub(t4, t4, t3); + fp_dbl(t4, t4); + + /* z3 = (Y1+Z1)^2-YY-ZZ, */ + 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); + + /* t5 = M = 3*XX+a*ZZ^2. */ + fp_dbl(t5, t2); + fp_add(t5, t5, t2); + fp_sqr(t2, t0); + fp_mul(t1, t2, ep_curve_get_a()); + fp_add(t5, t5, t1); + + /* x3 = T = M^2 - 2S. */ + fp_sqr(r->x, t5); + fp_sub(r->x, r->x, t4); + fp_sub(r->x, r->x, t4); + + /* y3 = M*(S-T)-8*YYYY. */ + fp_sub(t1, t4, r->x); + fp_mul(t1, t5, t1); + fp_dbl(t3, t3); + fp_dbl(t3, t3); + fp_dbl(t3, t3); + fp_sub(r->y, t1, t3); + + /* l = z3*z3^2*yQ + y3 − t5*(z3^2*xQ - x3), v = z3*(z3^2*xQ - x3)). */ + fp_sqr(t2, r->z); + fp_mul(l, r->z, t2); + fp_mul(l, l, q->y); + fp_add(l, l, r->y); + fp_mul(t2, t2, q->x); + fp_sub(t2, t2, r->x); + fp_mul(m, r->z, t2); + fp_mul(t2, t2, t5); + fp_sub(l, l, t2); + if (fp_is_zero(l)) { + fp_set_dig(l, 1); + } + + 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); + } +} + +#endif diff --git a/src/pp/relic_pp_dbl_k16.c b/src/pp/relic_pp_dbl_k16.c new file mode 100644 index 000000000..61992eebb --- /dev/null +++ b/src/pp/relic_pp_dbl_k16.c @@ -0,0 +1,415 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 + * + * Implementation of Miller doubling for curves of embedding degree 16. + * + * @ingroup pp + */ + +#include "relic_core.h" +#include "relic_pp.h" +#include "relic_fp_low.h" +#include "relic_fpx_low.h" +#include "relic_util.h" + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +#if EP_ADD == BASIC || !defined(STRIP) + +void pp_dbl_k16_basic(fp16_t l, ep4_t r, const ep4_t q, const ep_t p) { + fp4_t s; + ep4_t t; + int one = 1, zero = 0; + + fp4_null(s); + ep4_null(t); + + RLC_TRY { + fp4_new(s); + ep4_new(t); + ep4_copy(t, q); + ep4_dbl_slp_basic(r, s, q); + + if (ep4_curve_is_twist() == RLC_EP_MTYPE) { + one ^= 1; + zero ^= 1; + } + + fp_mul(l[one][zero][0][0], s[0][0], p->x); + fp_mul(l[one][zero][0][1], s[0][1], p->x); + fp_mul(l[one][zero][1][0], s[1][0], p->x); + fp_mul(l[one][zero][1][1], s[1][1], p->x); + fp4_mul(l[one][one], s, t->x); + fp4_sub(l[one][one], t->y, l[one][one]); + fp_copy(l[zero][zero][0][0], p->y); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + fp4_free(s); + ep4_free(t); + } +} + +#endif + +#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP) + +#if PP_EXT == BASIC || !defined(STRIP) + +void pp_dbl_k16_projc_basic(fp16_t l, ep4_t r, const ep4_t q, const ep_t p) { + fp4_t t0, t1, t2, t3, t4, t5, t6; + int one = 1, zero = 0; + + fp4_null(t0); + fp4_null(t1); + fp4_null(t2); + fp4_null(t3); + fp4_null(t4); + fp4_null(t5); + fp4_null(t6); + + RLC_TRY { + fp4_new(t0); + fp4_new(t1); + fp4_new(t2); + fp4_new(t3); + fp4_new(t4); + fp4_new(t5); + fp4_new(t6); + + if (ep4_curve_is_twist() == RLC_EP_MTYPE) { + one ^= 1; + zero ^= 1; + } + + /* t0 = A = X1^2, t1 = B = Y1^2, t2 = C = Z1^2, t3 = D = a*C. */ + 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); + + /* x3 = (A - D)^2, l11 = (A - D + x1)^2 - x3 - A. */ + fp4_sub(t5, t0, t3); + fp4_add(l[one][one], t5, q->x); + fp4_sqr(r->x, t5); + fp4_sqr(l[one][one], l[one][one]); + fp4_sub(l[one][one], l[one][one], r->x); + fp4_sub(l[one][one], l[one][one], t0); + + /* l10 := -xp*z1*2*(3A + D). */ + fp4_add(t6, t0, t3); + fp4_dbl(t0, t0); + fp4_add(t0, t0, t6); + fp4_dbl(t0, t0); + fp4_mul(l[one][zero], t0, q->z); + fp_mul(l[one][zero][0][0], l[one][zero][0][0], p->x); + fp_mul(l[one][zero][0][1], l[one][zero][0][1], p->x); + fp_mul(l[one][zero][1][0], l[one][zero][1][0], p->x); + fp_mul(l[one][zero][1][1], l[one][zero][1][1], p->x); + + /* l01 = 2*((y1 + z1)^2 - B - C)*yP. */ + fp4_add(l[zero][zero], q->y, q->z); + fp4_sqr(l[zero][zero], l[zero][zero]); + fp4_sub(l[zero][zero], l[zero][zero], t1); + fp4_sub(l[zero][zero], l[zero][zero], t2); + fp4_dbl(l[zero][zero], l[zero][zero]); + fp_mul(l[zero][zero][0][0], l[zero][zero][0][0], p->y); + fp_mul(l[zero][zero][0][1], l[zero][zero][0][1], p->y); + fp_mul(l[zero][zero][1][0], l[zero][zero][1][0], p->y); + fp_mul(l[zero][zero][1][1], l[zero][zero][1][1], p->y); + + /* t4 = E = 2*(A + D)^2 - x3. */ + fp4_sqr(t4, t6); + fp4_dbl(t4, t4); + fp4_sub(t4, t4, r->x); + /* y3 = E * ((A - D + y1)^2 - B - x3). */ + fp4_add(r->y, t5, q->y); + fp4_sqr(r->y, r->y); + fp4_sub(r->y, r->y, t1); + fp4_sub(r->y, r->y, r->x); + fp4_mul(r->y, r->y, t4); + /* z3 = 4*B. */ + fp4_dbl(r->z, t1); + fp4_dbl(r->z, r->z); + + 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 + +#if PP_EXT == LAZYR || !defined(STRIP) + +void pp_dbl_k16_projc_lazyr(fp16_t l, ep4_t r, const ep4_t q, const ep_t p) { + fp4_t t0, t1, t2, t3, t4, t5, t6; + dv4_t u0, u1; + int one = 1, zero = 0; + + fp4_null(t0); + fp4_null(t1); + fp4_null(t2); + fp4_null(t3); + fp4_null(t4); + fp4_null(t5); + fp4_null(t6); + dv4_null(u0); + dv4_null(u1); + + RLC_TRY { + fp4_new(t0); + fp4_new(t1); + fp4_new(t2); + fp4_new(t3); + fp4_new(t4); + fp4_new(t5); + fp4_new(t6); + dv4_new(u0); + dv4_new(u1); + + if (ep4_curve_is_twist() == RLC_EP_MTYPE) { + one ^= 1; + zero ^= 1; + } + + /* t0 = A = X1^2, t1 = B = Y1^2, t2 = C = Z1^2, t3 = D = a*C. */ + 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); + + /* x3 = (A - D)^2, l11 = (A - D + x1)^2 - x3 - A. */ + fp4_sub(t5, t0, t3); + fp4_add(l[one][one], t5, q->x); + fp4_sqr(r->x, t5); + fp4_sqr(l[one][one], l[one][one]); + fp4_sub(l[one][one], l[one][one], r->x); + fp4_sub(l[one][one], l[one][one], t0); + + /* l10 := -xp*z1*2*(3A + D). */ + fp4_add(t6, t0, t3); + fp4_dbl(t0, t0); + fp4_add(t0, t0, t6); + fp4_dbl(t0, t0); + fp4_mul(l[one][zero], t0, q->z); + fp_mul(l[one][zero][0][0], l[one][zero][0][0], p->x); + fp_mul(l[one][zero][0][1], l[one][zero][0][1], p->x); + fp_mul(l[one][zero][1][0], l[one][zero][1][0], p->x); + fp_mul(l[one][zero][1][1], l[one][zero][1][1], p->x); + + /* l01 = 2*((y1 + z1)^2 - B - C)*yP. */ + fp4_add(l[zero][zero], q->y, q->z); + fp4_sqr(l[zero][zero], l[zero][zero]); + fp4_sub(l[zero][zero], l[zero][zero], t1); + fp4_sub(l[zero][zero], l[zero][zero], t2); + fp4_dbl(l[zero][zero], l[zero][zero]); + fp_mul(l[zero][zero][0][0], l[zero][zero][0][0], p->y); + fp_mul(l[zero][zero][0][1], l[zero][zero][0][1], p->y); + fp_mul(l[zero][zero][1][0], l[zero][zero][1][0], p->y); + fp_mul(l[zero][zero][1][1], l[zero][zero][1][1], p->y); + + /* t4 = E = 2*(A + D)^2 - x3. */ + fp4_sqr(t4, t6); + fp4_dbl(t4, t4); + fp4_sub(t4, t4, r->x); + /* y3 = E * ((A - D + y1)^2 - B - x3). */ + fp4_add(r->y, t5, q->y); + fp4_sqr(r->y, r->y); + fp4_sub(r->y, r->y, t1); + fp4_sub(r->y, r->y, r->x); + fp4_mul(r->y, r->y, t4); + /* z3 = 4*B. */ + fp4_dbl(r->z, t1); + fp4_dbl(r->z, r->z); + 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); + dv4_free(u0); + dv4_free(u1); + } +} + +#endif + +#endif + +void pp_dbl_lit_k16(fp16_t l, ep_t r, const ep_t p, const ep4_t q) { + fp_t t0, t1, t2, t3, t4, t5, t6; + int one = 1, zero = 0; + + 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); + + fp_sqr(t0, p->x); + fp_sqr(t1, p->y); + fp_sqr(t2, p->z); + + fp_mul(t4, ep_curve_get_b(), t2); + + fp_dbl(t3, t4); + fp_add(t3, t3, t4); + + fp_add(t4, p->x, p->y); + fp_sqr(t4, t4); + fp_sub(t4, t4, t0); + fp_sub(t4, t4, t1); + fp_add(t5, p->y, p->z); + fp_sqr(t5, t5); + fp_sub(t5, t5, t1); + fp_sub(t5, t5, t2); + fp_dbl(t6, t3); + fp_add(t6, t6, t3); + fp_sub(r->x, t1, t6); + fp_mul(r->x, r->x, t4); + fp_add(r->y, t1, t6); + fp_sqr(r->y, r->y); + fp_sqr(t4, t3); + fp_dbl(t6, t4); + fp_add(t6, t6, t4); + fp_dbl(t6, t6); + fp_dbl(t6, t6); + fp_sub(r->y, r->y, t6); + fp_mul(r->z, t1, t5); + fp_dbl(r->z, r->z); + fp_dbl(r->z, r->z); + r->coord = PROJC; + + if (ep4_curve_is_twist() == RLC_EP_MTYPE) { + one ^= 1; + zero ^= 1; + } + + fp4_dbl(l[zero][one], q->x); + fp4_add(l[zero][one], l[zero][one], q->x); + fp_mul(l[zero][one][0][0], l[zero][one][0][0], t0); + fp_mul(l[zero][one][0][1], l[zero][one][0][1], t0); + fp_mul(l[zero][one][1][0], l[zero][one][1][0], t0); + fp_mul(l[zero][one][1][1], l[zero][one][1][1], t0); + + fp_sub(l[zero][zero][0][0], t3, t1); + + fp_mul(l[one][one][0][0], q->y[0][0], t5); + fp_mul(l[one][one][0][1], q->y[0][1], t5); + fp_mul(l[one][one][1][0], q->y[1][0], t5); + fp_mul(l[one][one][1][1], q->y[1][1], t5); + + } + 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); + } +} diff --git a/src/pp/relic_pp_dbl_k18.c b/src/pp/relic_pp_dbl_k18.c index 9b34ed299..2837eed99 100644 --- a/src/pp/relic_pp_dbl_k18.c +++ b/src/pp/relic_pp_dbl_k18.c @@ -24,7 +24,7 @@ /** * @file * - * Implementation of Miller doubling for curves of embedding degree 12. + * Implementation of Miller doubling for curves of embedding degree 18. * * @ingroup pp */ diff --git a/src/pp/relic_pp_dbl_k24.c b/src/pp/relic_pp_dbl_k24.c index 6057a976e..5dc1e1111 100644 --- a/src/pp/relic_pp_dbl_k24.c +++ b/src/pp/relic_pp_dbl_k24.c @@ -37,7 +37,7 @@ /* Public definitions */ /*============================================================================*/ -#if EP_ADD == PROJC || !defined(STRIP) +#if EP_ADD == BASIC || !defined(STRIP) void pp_dbl_k24_basic(fp24_t l, ep4_t r, const ep4_t q, const ep_t p) { fp4_t s; diff --git a/src/pp/relic_pp_dbl_k48.c b/src/pp/relic_pp_dbl_k48.c index 743518c2b..888efc3ed 100644 --- a/src/pp/relic_pp_dbl_k48.c +++ b/src/pp/relic_pp_dbl_k48.c @@ -33,86 +33,25 @@ #include "relic_pp.h" #include "relic_util.h" -/*============================================================================*/ -/* Private definitions */ -/*============================================================================*/ - -static void ep8_dbl_basic(fp8_t s, fp8_t rx, fp8_t ry) { - 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, ry); - fp8_inv(t0, t0); - - /* t1 = 3 * x1^2 + a. */ - fp8_sqr(t1, rx); - fp8_copy(t2, t1); - fp8_dbl(t1, t1); - fp8_add(t1, t1, t2); - - /* a = 0. */ - /* 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, rx); - fp8_sub(t0, t2, t0); - - /* y3 = t1 * (x1 - x3) - y1. */ - fp8_sub(t2, rx, t0); - fp8_mul(t1, t1, t2); - - fp8_sub(ry, t1, ry); - - fp8_copy(rx, t0); - } - RLC_CATCH_ANY { - RLC_THROW(ERR_CAUGHT); - } - RLC_FINALLY { - fp8_free(t0); - fp8_free(t1); - fp8_free(t2); - } -} - /*============================================================================*/ /* Public definitions */ /*============================================================================*/ #if EP_ADD == BASIC || !defined(STRIP) -void pp_dbl_k48_basic(fp48_t l, fp8_t rx, fp8_t ry, const ep_t p) { - fp8_t s, tx, ty; +void pp_dbl_k48_basic(fp48_t l, ep8_t r, const ep8_t q, const ep_t p) { + fp8_t s; + ep8_t t; fp8_null(s); - fp8_null(tx); - fp8_null(ty); + ep8_null(t); RLC_TRY { fp8_new(s); - fp8_new(tx); - fp8_new(ty); + ep8_new(t); - fp8_copy(tx, rx); - fp8_copy(ty, ry); - ep8_dbl_basic(s, rx, ry); + ep8_copy(t, q); + ep8_dbl_slp_basic(r, s, q); fp48_zero(l); fp_mul(l[0][1][0][0][0], p->x, s[0][0][0]); @@ -124,8 +63,8 @@ void pp_dbl_k48_basic(fp48_t l, fp8_t rx, fp8_t ry, const ep_t p) { fp_mul(l[0][1][1][1][0], p->x, s[1][1][0]); fp_mul(l[0][1][1][1][1], p->x, s[1][1][1]); - fp8_mul(l[0][0], s, tx); - fp8_sub(l[0][0], ty, l[0][0]); + fp8_mul(l[0][0], s, t->x); + fp8_sub(l[0][0], t->y, l[0][0]); fp_copy(l[1][1][0][0][0], p->y); } RLC_CATCH_ANY { @@ -133,8 +72,7 @@ void pp_dbl_k48_basic(fp48_t l, fp8_t rx, fp8_t ry, const ep_t p) { } RLC_FINALLY { fp8_free(s); - fp8_free(tx); - fp8_free(ty); + ep8_free(t); } } @@ -142,7 +80,7 @@ void pp_dbl_k48_basic(fp48_t l, fp8_t rx, fp8_t ry, const ep_t p) { #if EP_ADD == PROJC || !defined(STRIP) -void pp_dbl_k48_projc(fp48_t l, fp8_t rx, fp8_t ry, fp8_t rz, const ep_t p) { +void pp_dbl_k48_projc(fp48_t l, ep8_t r, const ep8_t q, const ep_t p) { fp8_t t0, t1, t2, t3, t4, t5, t6; fp8_null(t0); @@ -163,26 +101,25 @@ void pp_dbl_k48_projc(fp48_t l, fp8_t rx, fp8_t ry, fp8_t rz, const ep_t p) { fp8_new(t6); /* A = x1^2. */ - fp8_sqr(t0, rx); + fp8_sqr(t0, q->x); /* B = y1^2. */ - fp8_sqr(t1, ry); + fp8_sqr(t1, q->y); /* C = z1^2. */ - fp8_sqr(t2, rz); + fp8_sqr(t2, q->z); /* D = 3bC, general b. */ fp8_dbl(t3, t2); fp8_add(t3, t3, t2); - fp8_zero(t4); - fp_copy(t4[1][0][0], ep_curve_get_b()); - + ep8_curve_get_b(t4); fp8_mul(t3, t3, t4); + /* E = (x1 + y1)^2 - A - B. */ - fp8_add(t4, rx, ry); + fp8_add(t4, q->x, q->y); fp8_sqr(t4, t4); fp8_sub(t4, t4, t0); fp8_sub(t4, t4, t1); /* F = (y1 + z1)^2 - B - C. */ - fp8_add(t5, ry, rz); + fp8_add(t5, q->y, q->z); fp8_sqr(t5, t5); fp8_sub(t5, t5, t1); fp8_sub(t5, t5, t2); @@ -192,23 +129,23 @@ void pp_dbl_k48_projc(fp48_t l, fp8_t rx, fp8_t ry, fp8_t rz, const ep_t p) { fp8_add(t6, t6, t3); /* x3 = E * (B - G). */ - fp8_sub(rx, t1, t6); - fp8_mul(rx, rx, t4); + fp8_sub(r->x, t1, t6); + fp8_mul(r->x, r->x, t4); /* y3 = (B + G)^2 -12D^2. */ fp8_add(t6, t6, t1); fp8_sqr(t6, t6); fp8_sqr(t2, t3); - fp8_dbl(ry, t2); - fp8_dbl(t2, ry); - fp8_dbl(ry, t2); - fp8_add(ry, ry, t2); - fp8_sub(ry, t6, ry); + fp8_dbl(r->y, t2); + fp8_dbl(t2, r->y); + fp8_dbl(r->y, t2); + fp8_add(r->y, r->y, t2); + fp8_sub(r->y, t6, r->y); /* z3 = 4B * F. */ - fp8_dbl(rz, t1); - fp8_dbl(rz, rz); - fp8_mul(rz, rz, t5); + fp8_dbl(r->z, t1); + fp8_dbl(r->z, r->z); + fp8_mul(r->z, r->z, t5); /* l11 = D - B. */ fp8_sub(l[0][0], t3, t1); diff --git a/src/pp/relic_pp_dbl_k8.c b/src/pp/relic_pp_dbl_k8.c index a15901b9b..1153f3d04 100644 --- a/src/pp/relic_pp_dbl_k8.c +++ b/src/pp/relic_pp_dbl_k8.c @@ -24,7 +24,7 @@ /** * @file * - * Implementation of Miller doubling for curves of embedding degree 2. + * Implementation of Miller doubling for curves of embedding degree 8. * * @ingroup pp */ diff --git a/src/pp/relic_pp_exp_k1.c b/src/pp/relic_pp_exp_k1.c new file mode 100644 index 000000000..b014a82db --- /dev/null +++ b/src/pp/relic_pp_exp_k1.c @@ -0,0 +1,62 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2019 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 + * + * Implementation of the final exponentiation for curves of embedding degree 1. + * + * @ingroup pp + */ + +#include "relic_core.h" +#include "relic_pp.h" +#include "relic_util.h" + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +void pp_exp_k1(fp_t c, fp_t a) { + bn_t e, n; + + bn_null(n); + bn_null(e); + + RLC_TRY { + bn_new(n); + bn_new(e); + + ep_curve_get_ord(n); + + bn_read_raw(e, fp_prime_get(), RLC_FP_DIGS); + bn_sub_dig(e, e, 1); + bn_div(e, e, n); + fp_exp(c, a, e); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + bn_free(n); + bn_free(e); + } +} diff --git a/src/pp/relic_pp_exp_k16.c b/src/pp/relic_pp_exp_k16.c new file mode 100644 index 000000000..48c71360c --- /dev/null +++ b/src/pp/relic_pp_exp_k16.c @@ -0,0 +1,351 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 + * + * Implementation of the final exponentiation for curves of embedding degree 16. + * + * @ingroup pp + */ + +#include "relic_core.h" +#include "relic_pp.h" +#include "relic_util.h" + +/*============================================================================*/ +/* Private definitions */ +/*============================================================================*/ + +/** + * Computes the final exponentiation of a pairing defined over a KSS curve. + * + * @param[out] c - the result. + * @param[in] a - the extension field element to exponentiate. + */ +static void pp_exp_kss(fp16_t c, fp16_t a) { + fp16_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13; + bn_t x; + + bn_null(x); + fp16_null(t0); + fp16_null(t1); + fp16_null(t2); + fp16_null(t3); + fp16_null(t4); + fp16_null(t5); + fp16_null(t6); + fp16_null(t7); + fp16_null(t8); + fp16_null(t9); + fp16_null(t10); + fp16_null(t11); + fp16_null(t12); + fp16_null(t13); + + RLC_TRY { + bn_new(x); + fp16_new(t0); + fp16_new(t1); + fp16_new(t2); + fp16_new(t3); + fp16_new(t4); + fp16_new(t5); + fp16_new(t6); + fp16_new(t7); + fp16_new(t8); + fp16_new(t9); + fp16_new(t10); + fp16_new(t11); + fp16_new(t12); + fp16_new(t13); + + fp_prime_get_par(x); + + /* First, compute m = f^(p^8 - 1). */ + fp16_conv_cyc(c, a); + + /* Now compute m^((p^8 + 1) / r). */ + fp16_sqr_cyc(t0, c); + fp16_sqr_cyc(t1, t0); + + bn_add_dig(x, x, 1); + fp16_exp_cyc(t2, c, x); + fp16_exp_cyc(t3, t2, x); + fp16_mul(t4, t3, t1); + bn_sub_dig(x, x, 1); + + fp16_exp_cyc(t5, t4, x); + fp16_sqr_cyc(t6, t4); + fp16_sqr_cyc(t6, t6); + fp16_mul(t6, t6, t4); + fp16_sqr_cyc(t7, t1); + fp16_sqr_cyc(t7, t7); + fp16_sqr_cyc(t7, t7); + fp16_sqr_cyc(t8, t7); + fp16_inv_cyc(t9, t1); + fp16_mul(t9, t7, t9); + fp16_sqr_cyc(t10, t9); + fp16_exp_cyc(t11, t5, x); + fp16_exp_cyc(t12, t11, x); + fp16_mul(t13, t12, t10); + + fp16_exp_cyc(t9, t13, x); + fp16_inv_cyc(t2, t9); + fp16_sqr_cyc(t2, t2); + fp16_sqr_cyc(t10, t6); + fp16_sqr_cyc(t10, t10); + fp16_mul(t10, t10, t6); + fp16_sqr_cyc(t0, t10); + fp16_sqr_cyc(t0, t0); + fp16_mul(t10, t10, t0); + fp16_inv_cyc(t0, t10); + fp16_mul(t0, t2, t0); + + fp16_sqr_cyc(t3, t0); + fp16_sqr_cyc(t2, t2); + fp16_sqr_cyc(t2, t2); + fp16_mul(t2, t2, t9); + fp16_mul(t2, t2, t3); + fp16_exp_cyc(t3, t9, x); + fp16_exp_cyc(t6, t3, x); + fp16_exp_cyc(t7, t6, x); + fp16_sqr_cyc(t10, t3); + + fp16_sqr_cyc(t9, t5); + fp16_sqr_cyc(t9, t9); + fp16_mul(t9, t9, t5); + fp16_sqr_cyc(t4, t9); + fp16_sqr_cyc(t4, t4); + fp16_mul(t9, t4, t9); + fp16_sqr_cyc(t4, t9); + fp16_mul(t4, t4, t9); + fp16_mul(t9, t4, t9); + fp16_sqr_cyc(t10, t10); + fp16_mul(c, t10, t4); + fp16_inv_cyc(c, c); + fp16_inv_cyc(t3, t3); + fp16_mul(t3, t3, t10); + fp16_mul(t3, t3, t9); + fp16_sqr_cyc(t9, t11); + fp16_sqr_cyc(t9, t9); + fp16_mul(t11, t11, t9); + fp16_sqr_cyc(t9, t11); + fp16_mul(t4, t9, t6); + + fp16_sqr_cyc(t6, t6); + fp16_sqr_cyc(t10, t9); + fp16_sqr_cyc(t10, t10); + fp16_mul(t9, t9, t10); + fp16_mul(t9, t9, t11); + fp16_mul(t9, t9, t6); + fp16_sqr_cyc(t5, t12); + fp16_mul(t5, t5, t12); + fp16_sqr_cyc(t5, t5); + fp16_sqr_cyc(t5, t5); + fp16_sqr_cyc(t12, t5); + fp16_mul(t5, t7, t12); + fp16_inv_cyc(t5, t5); + fp16_sqr_cyc(t10, t8); + fp16_mul(t8, t8, t10); + fp16_mul(t6, t8, t1); + fp16_mul(t7, t5, t6); + fp16_sqr_cyc(t8, t13); + fp16_mul(t8, t8, t13); + fp16_sqr_cyc(t8, t8); + fp16_mul(t8, t8, t13); + fp16_frb(c, c, 1); + fp16_frb(t7, t7, 3); + fp16_frb(t3, t3, 5); + fp16_frb(t8, t8, 7); + fp16_mul(t1, c, t7); + fp16_mul(t1, t1, t3); + fp16_mul(t1, t1, t8); + fp16_frb(t0, t0, 2); + fp16_frb(t4, t4, 4); + fp16_frb(t2, t2, 6); + fp16_mul(t2, t2, t0); + + fp16_mul(c, t2, t9); + fp16_mul(c, c, t1); + fp16_mul(c, c, t4); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + bn_free(x); + fp16_free(t0); + fp16_free(t1); + fp16_free(t2); + fp16_free(t3); + fp16_free(t4); + fp16_free(t5); + fp16_free(t6); + fp16_free(t7); + fp16_free(t8); + fp16_free(t9); + fp16_free(t10); + fp16_free(t11); + fp16_free(t12); + fp16_free(t13); + } +} + +/** + * Computes the final exponentiation of a pairing defined over a KSS curve. + * + * @param[out] c - the result. + * @param[in] a - the extension field element to exponentiate. + */ +static void pp_exp_new(fp16_t c, fp16_t a) { + fp16_t t0, t1, t2, t3, t4; + bn_t x, x_; + + bn_null(x); + bn_null(x_); + fp16_null(t0); + fp16_null(t1); + fp16_null(t2); + fp16_null(t3); + fp16_null(t4); + + RLC_TRY { + bn_new(x); + bn_new(x_); + fp16_new(t0); + fp16_new(t1); + fp16_new(t2); + fp16_new(t3); + fp16_new(t4); + + fp_prime_get_par(x); + + /* First, compute m = f^(p^8 - 1). */ + fp16_conv_cyc(c, a); + + /* Now compute m^((p^8 + 1) / r). */ + bn_abs(x_, x); + + /* Compute eq t0 = m^(u*p * (1+u*p^3)). */ + fp16_exp_cyc(t0, c, x_); + fp16_frb(t0, t0, 3); + fp16_inv_cyc(t1, c); + if (bn_sign(x) == RLC_POS) { + fp16_mul(t0, t0, c); + } else { + fp16_mul(t0, t0, t1); + } + fp16_exp_cyc(t0, t0, x_); + fp16_frb(t0, t0, 1); + + /* Compute t2 = m^(p^5 + u*(-1 + u^2 * u*p*(1+u*p^3))). */ + fp16_exp_cyc(t2, t0, x_); + fp16_exp_cyc(t2, t2, x_); + fp16_mul(t2, t2, t1); + fp16_exp_cyc(t2, t2, x_); + if (bn_sign(x) == RLC_NEG) { + fp16_inv_cyc(t2, t2); + } + fp16_frb(t3, c, 5); + fp16_mul(t2, t2, t3); + + /* Compute t2 = m2^(((u^2 div 4)*(u^3+1)^2 +1) */ + if (bn_is_even(x_)) { + bn_hlv(x_, x_); + fp16_exp_cyc(t3, t2, x_); + fp16_exp_cyc(t3, t3, x_); + bn_dbl(x_, x_); + if (bn_sign(x) == RLC_NEG) { + fp16_inv_cyc(t4, t3); + } else { + fp16_copy(t4, t3); + } + fp16_exp_cyc(t3, t3, x_); + fp16_exp_cyc(t3, t3, x_); + fp16_exp_cyc(t3, t3, x_); + fp16_mul(t3, t3, t4); + if (bn_sign(x) == RLC_NEG) { + fp16_inv_cyc(t4, t3); + } else { + fp16_copy(t4, t3); + } + fp16_exp_cyc(t3, t3, x_); + fp16_exp_cyc(t3, t3, x_); + fp16_exp_cyc(t3, t3, x_); + fp16_mul(t3, t3, t4); + } else { + fp16_exp_cyc(t3, t2, x_); + fp16_exp_cyc(t3, t3, x_); + bn_sqr(x, x_); + bn_mul(x, x, x_); + bn_add_dig(x, x, 1); + bn_hlv(x, x); + bn_abs(x, x); + fp16_exp_cyc(t3, t3, x); + fp16_exp_cyc(t3, t3, x); + } + fp16_mul(t2, t2, t3); + + /* Compute t2 = (t0 * m2)^((p^2-u^2). */ + fp16_mul(t2, t2, t0); + fp16_frb(t4, t2, 2); + fp16_exp_cyc(t2, t2, x_); + fp16_exp_cyc(t2, t2, x_); + fp16_inv_cyc(t2, t2); + fp16_mul(t2, t4, t2); + + fp16_mul(c, c, t2); + if (!bn_is_even(x_)) { + fp16_sqr_cyc(c, c); + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + bn_free(x); + bn_free(x_); + fp16_free(t0); + fp16_free(t1); + fp16_free(t2); + fp16_free(t3); + fp16_free(t4); + } +} + + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +void pp_exp_k16(fp16_t c, fp16_t a) { + switch (ep_curve_is_pairf()) { + case EP_K16: + pp_exp_kss(c, a); + break; + case EP_N16: + pp_exp_new(c, a); + break; + } +} diff --git a/src/pp/relic_pp_exp_k18.c b/src/pp/relic_pp_exp_k18.c index b096220c0..027398119 100644 --- a/src/pp/relic_pp_exp_k18.c +++ b/src/pp/relic_pp_exp_k18.c @@ -34,10 +34,16 @@ #include "relic_util.h" /*============================================================================*/ -/* Public definitions */ +/* Private definitions */ /*============================================================================*/ -void pp_exp_k18(fp18_t c, fp18_t a) { +/** + * Computes the final exponentiation of a pairing defined over a KSS curve. + * + * @param[out] c - the result. + * @param[in] a - the extension field element to exponentiate. + */ +static void pp_exp_kss(fp18_t c, fp18_t a) { fp18_t t0, t1, t2, t3, t4, t5; const int *b; bn_t x; @@ -155,3 +161,114 @@ void pp_exp_k18(fp18_t c, fp18_t a) { fp18_free(t5); } } + +/** + * Computes the final exponentiation of a pairing defined over a SG curve. + * + * @param[out] c - the result. + * @param[in] a - the extension field element to exponentiate. + */ +void pp_exp_sg(fp18_t c, fp18_t a) { + fp18_t t0, t1, t2, t3; + const int *b; + bn_t x; + int l; + + bn_null(x); + fp18_null(t0); + fp18_null(t1); + fp18_null(t2); + fp18_null(t3); + + RLC_TRY { + bn_new(x); + fp18_new(t0); + fp18_new(t1); + fp18_new(t2); + fp18_new(t3); + + fp_prime_get_par(x); + b = fp_prime_get_par_sps(&l); + /* First, compute m^(p^9 - 1)(p^3 + 1). */ + fp18_conv_cyc(c, a); + + /* t0 = f^(-3p^2), t1 = f^(1 - 3up + p^3). */ + fp18_sqr(t1, c); + fp18_mul(t1, t1, c); + if (bn_sign(x) == RLC_POS) { + fp18_inv_cyc(t1, t1); + fp18_frb(t0, t1, 2); + } else { + fp18_frb(t0, t1, 2); + fp18_inv_cyc(t0, t0); + } + fp18_exp_cyc_sps(t1, t1, b, l, RLC_POS); + fp18_frb(t3, c, 2); + fp18_mul(t1, t1, t3); + fp18_frb(t1, t1, 1); + fp18_mul(t1, t1, c); + + fp18_exp_cyc_sps(t2, t1, b, l, RLC_POS); + fp18_exp_cyc_sps(t2, t2, b, l, RLC_POS); + fp18_sqr_cyc(t3, t2); + fp18_mul(t2, t2, t3); + fp18_frb(t3, t1, 1); + fp18_mul(t2, t2, t3); + fp18_exp_cyc_sps(t2, t2, b, l, RLC_POS); + if (bn_sign(x) == RLC_NEG) { + fp18_inv_cyc(t3, t1); + } else { + fp18_copy(t3, t1); + } + fp18_mul(t2, t2, t3); + fp18_exp_cyc_sps(t2, t2, b, l, RLC_POS); + fp18_sqr_cyc(t3, t2); + fp18_mul(t2, t2, t3); + fp18_frb(t3, t1, 2); + fp18_mul(t2, t2, t3); + fp18_mul(t2, t2, t0); + + /* Compute t2 = t2^(3*u^2-1). */ + fp18_exp_cyc_sps(t3, t2, b, l, RLC_POS); + fp18_exp_cyc_sps(t3, t3, b, l, RLC_POS); + fp18_sqr_cyc(t0, t3); + fp18_mul(t3, t3, t0); + fp18_inv_cyc(t2, t2), + fp18_mul(t2, t2, t3); + + /* Compute t2 = t2^(3*u^2-1). */ + fp18_exp_cyc_sps(t3, t2, b, l, RLC_POS); + fp18_exp_cyc_sps(t3, t3, b, l, RLC_POS); + fp18_sqr_cyc(t0, t3); + fp18_mul(t3, t3, t0); + fp18_inv_cyc(t2, t2), + fp18_mul(t2, t2, t3); + + fp18_mul(c, t1, t2); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + bn_free(x); + fp18_free(t0); + fp18_free(t1); + fp18_free(t2); + fp18_free(t3); + } +} + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +void pp_exp_k18(fp18_t c, fp18_t a) { + switch (ep_curve_is_pairf()) { + case EP_K18: + pp_exp_kss(c, a); + break; + case EP_SG18: + pp_exp_sg(c, a); + break; + } +} diff --git a/src/pp/relic_pp_exp_k8.c b/src/pp/relic_pp_exp_k8.c index 089cdcbc7..7053f6167 100644 --- a/src/pp/relic_pp_exp_k8.c +++ b/src/pp/relic_pp_exp_k8.c @@ -24,7 +24,7 @@ /** * @file * - * Implementation of the final exponentiation for curves of embedding degree 2. + * Implementation of the final exponentiation for curves of embedding degree 8. * * @ingroup pp */ diff --git a/src/pp/relic_pp_map.c b/src/pp/relic_pp_map.c index 7c67182a9..4408feb1d 100644 --- a/src/pp/relic_pp_map.c +++ b/src/pp/relic_pp_map.c @@ -41,10 +41,12 @@ void pp_map_init(void) { ep2_curve_init(); ep3_curve_init(); ep4_curve_init(); + ep8_curve_init(); } void pp_map_clean(void) { ep2_curve_clean(); ep3_curve_clean(); ep4_curve_clean(); + ep8_curve_clean(); } diff --git a/src/pp/relic_pp_map_k1.c b/src/pp/relic_pp_map_k1.c new file mode 100644 index 000000000..39d1786c9 --- /dev/null +++ b/src/pp/relic_pp_map_k1.c @@ -0,0 +1,320 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 + * + * Implementation of pairing computation for curves with embedding degree 1. + * + * @ingroup pp + */ + +#include "relic_core.h" +#include "relic_pp.h" +#include "relic_util.h" + +/*============================================================================*/ +/* Private definitions */ +/*============================================================================*/ + +/** + * Compute the Miller loop for pairings of type G_2 x G_1 over the bits of a + * given parameter. + * + * @param[out] r - the result. + * @param[out] t - the resulting point. + * @param[in] p - the first pairing argument in affine coordinates. + * @param[in] q - the second pairing argument in affine coordinates. + * @param[in] n - the number of pairings to evaluate. + * @param[in] a - the loop parameter. + */ +static void pp_mil_k1(fp_t r, ep_t *t, ep_t *p, ep_t *q, int n, bn_t a) { + fp_t l, m, s; + int i, j; + + fp_null(l); + fp_null(m); + fp_null(s); + + RLC_TRY { + fp_new(l); + fp_new(m); + fp_new(s); + for (j = 0; j < n; j++) { + ep_copy(t[j], p[j]); + } + + fp_set_dig(s, 1); + for (i = bn_bits(a) - 2; i >= 0; i--) { + fp_sqr(r, r); + fp_sqr(s, s); + for (j = 0; j < n; j++) { + pp_dbl_k1(l, m, t[j], t[j], q[j]); + fp_mul(r, r, l); + fp_mul(s, s, m); + if (bn_get_bit(a, i)) { + pp_add_k1(l, m, t[j], p[j], q[j]); + fp_mul(r, r, l); + fp_mul(s, s, m); + } + } + } + + if (!fp_is_zero(s)) { + fp_inv(s, s); + fp_mul(r, r, s); + } else { + fp_set_dig(r, 1); + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + fp_free(l); + fp_free(m); + fp_free(s); + } +} + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +#if PP_MAP == TATEP || PP_MAP == OATEP || !defined(STRIP) + +void pp_map_tatep_k1(fp_t r, const ep_t p, const ep_t q) { + ep_t _p[1], _q[1], t[1]; + bn_t n; + + ep_null(_p[0]); + ep_null(_q[0]); + ep_null(t[0]); + bn_null(n); + + RLC_TRY { + ep_new(t[0]); + bn_new(n); + + ep_norm(_p[0], p); + ep_norm(_q[0], q); + ep_curve_get_ord(n); + fp_set_dig(r, 1); + + if (!ep_is_infty(p) && !ep_is_infty(q)) { + pp_mil_k1(r, t, _p, _q, 1, n); + pp_exp_k1(r, r); + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + ep_free(_p[0]); + ep_free(_q[0]); + ep_free(t[0]); + bn_free(n); + } +} + +void pp_map_sim_tatep_k1(fp_t r, const ep_t *p, const ep_t *q, int m) { + ep_t *_p = RLC_ALLOCA(ep_t, m), + *_q = RLC_ALLOCA(ep_t, m), *t = RLC_ALLOCA(ep_t, m); + bn_t n; + int i, j; + + bn_null(n); + + RLC_TRY { + bn_new(n); + if (_p == NULL || _q == NULL || t == NULL) { + RLC_THROW(ERR_NO_MEMORY); + } + for (i = 0; i < m; i++) { + ep_null(_p[i]); + ep_null(_q[i]); + ep_null(t[i]); + ep_new(_p[i]); + ep_new(_q[i]); + ep_new(t[i]); + } + + j = 0; + for (i = 0; i < m; i++) { + if (!ep_is_infty(p[i]) && !ep_is_infty(q[i])) { + ep_norm(_p[j], p[i]); + ep_norm(_q[j++], q[i]); + } + } + + ep_curve_get_ord(n); + fp_set_dig(r, 1); + if (j > 0) { + pp_mil_k1(r, t, _p, _q, j, n); + pp_exp_k1(r, r); + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + bn_free(n); + for (i = 0; i < m; i++) { + ep_free(_p[i]); + ep_free(_q[i]); + ep_free(t[i]); + } + RLC_FREE(_p); + RLC_FREE(_q); + RLC_FREE(t); + } +} + +#endif + +#if PP_MAP == WEILP || !defined(STRIP) + +void pp_map_weilp_k1(fp_t r, const ep_t p, const ep_t q) { + ep_t _p[1], _q[1], t0[1], t1[1]; + fp_t r0, r1; + bn_t n; + + ep_null(_p[0]); + ep_null(_q[0]); + ep_null(t0[0]); + ep_null(t1[0]); + fp_null(r0); + fp_null(r1); + bn_null(n); + + RLC_TRY { + ep_new(_p[0]); + ep_new(_q[0]); + ep_new(t0[0]); + ep_new(t1[0]); + fp_new(r0); + fp_new(r1); + bn_new(n); + + ep_norm(_p[0], p); + ep_norm(_q[0], q); + ep_curve_get_ord(n); + fp_set_dig(r0, 1); + fp_set_dig(r1, 1); + + if (!ep_is_infty(_p[0]) && !ep_is_infty(_q[0])) { + pp_mil_k1(r0, t0, _p, _q, 1, n); + pp_mil_k1(r1, t1, _q, _p, 1, n); + if (fp_cmp(r0, r1) != RLC_EQ) { + fp_neg(r0, r0); + } + fp_inv(r1, r1); + } + /* Compute r = (-1)^n * r0/r1. */ + fp_mul(r, r0, r1); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + ep_free(_p[0]); + ep_free(_q[0]); + ep_free(t0[0]); + ep_free(t1[0]); + fp_free(r0); + fp_free(r1); + bn_free(n); + } +} + +void pp_map_sim_weilp_k1(fp_t r, const ep_t *p, const ep_t *q, int m) { + ep_t *_p = RLC_ALLOCA(ep_t, m), + *_q = RLC_ALLOCA(ep_t, m), + *t0 = RLC_ALLOCA(ep_t, m), *t1 = RLC_ALLOCA(ep_t, m); + fp_t r0, r1; + bn_t n; + int i, j; + + fp_null(r0); + fp_null(r1); + bn_null(r); + + RLC_TRY { + fp_new(r0); + fp_new(r1); + bn_new(n); + if (_p == NULL || _q == NULL || t0 == NULL || t1 == NULL) { + RLC_THROW(ERR_NO_MEMORY); + } + for (i = 0; i < m; i++) { + ep_null(_p[i]); + ep_null(_q[i]); + ep_null(t0[i]); + ep_null(t1[i]); + ep_new(_p[i]); + ep_new(_q[i]); + ep_new(t0[i]); + ep_new(t1[i]); + } + + j = 0; + for (i = 0; i < m; i++) { + if (!ep_is_infty(p[i]) && !ep_is_infty(q[i])) { + ep_norm(_p[j], p[i]); + ep_norm(_q[j++], q[i]); + } + } + + ep_curve_get_ord(n); + bn_sub_dig(n, n, 1); + fp_set_dig(r0, 1); + fp_set_dig(r1, 1); + + if (j > 0) { + pp_mil_k1(r0, t0, _p, _q, j, n); + pp_mil_k1(r1, t1, _q, _p, j, n); + fp_inv(r1, r1); + } + fp_mul(r, r0, r1); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + fp_free(r0); + fp_free(r1); + bn_free(n); + for (i = 0; i < m; i++) { + ep_free(_p[i]); + ep_free(_q[i]); + ep_free(t0[i]); + ep_free(t1[i]); + } + RLC_FREE(_p); + RLC_FREE(_q); + RLC_FREE(t0); + RLC_FREE(t1); + } +} + +#endif diff --git a/src/pp/relic_pp_map_k16.c b/src/pp/relic_pp_map_k16.c new file mode 100644 index 000000000..bdf0472ad --- /dev/null +++ b/src/pp/relic_pp_map_k16.c @@ -0,0 +1,606 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (c) 2023 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 + * + * Implementation of pairing computation for curves with embedding degree 16. + * + * @ingroup pp + */ + +#include "relic_core.h" +#include "relic_pp.h" +#include "relic_util.h" + +/*============================================================================*/ +/* Private definitions */ +/*============================================================================*/ + +/** + * Compute the Miller loop for pairings of type G_2 x G_1 over the bits of a + * given parameter represented in sparse form. + * + * @param[out] r - the result. + * @param[out] t - the resulting point. + * @param[in] q - the vector of first arguments in affine coordinates. + * @param[in] p - the vector of second arguments in affine coordinates. + * @param[in] n - the number of pairings to evaluate. + * @param[in] a - the loop parameter. + */ +static void pp_mil_k16(fp16_t r, ep4_t *t, ep4_t *q, ep_t *p, int m, bn_t a) { + fp16_t l; + ep_t *_p = RLC_ALLOCA(ep_t, m); + ep4_t *_q = RLC_ALLOCA(ep4_t, m); + int i, j; + size_t len = bn_bits(a) + 1; + int8_t s[RLC_FP_BITS + 1]; + + if (m == 0) { + return; + } + + fp16_null(l); + + RLC_TRY { + fp16_new(l); + if (_p == NULL || _q == NULL) { + RLC_THROW(ERR_NO_MEMORY); + } + + for (j = 0; j < m; j++) { + ep_null(_p[j]); + ep4_null(_q[j]); + ep_new(_p[j]); + ep4_new(_q[j]); + ep4_copy(t[j], q[j]); + ep4_neg(_q[j], q[j]); +#if EP_ADD == BASIC + ep_neg(_p[j], p[j]); +#else + fp_neg(_p[j]->x, p[j]->x); + fp_copy(_p[j]->y, p[j]->y); +#endif + } + + fp16_zero(l); + bn_rec_naf(s, &len, a, 2); + pp_dbl_k16(r, t[0], t[0], _p[0]); + for (j = 1; j < m; j++) { + pp_dbl_k16(l, t[j], t[j], _p[j]); + fp16_mul_dxs(r, r, l); + } + if (s[len - 2] > 0) { + for (j = 0; j < m; j++) { + pp_add_k16(l, t[j], q[j], _p[j]); + fp16_mul_dxs(r, r, l); + } + } + if (s[len - 2] < 0) { + for (j = 0; j < m; j++) { + pp_add_k16(l, t[j], _q[j], _p[j]); + fp16_mul_dxs(r, r, l); + } + } + + for (i = len - 3; i >= 0; i--) { + fp16_sqr(r, r); + for (j = 0; j < m; j++) { + pp_dbl_k16(l, t[j], t[j], _p[j]); + fp16_mul_dxs(r, r, l); + if (s[i] > 0) { + pp_add_k16(l, t[j], q[j], _p[j]); + fp16_mul_dxs(r, r, l); + } + if (s[i] < 0) { + pp_add_k16(l, t[j], _q[j], _p[j]); + fp16_mul_dxs(r, r, l); + } + } + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + fp16_free(l); + for (j = 0; j < m; j++) { + ep_free(_p[j]); + ep4_free(_q[j]); + } + RLC_FREE(_p); + RLC_FREE(_q); + } +} + +/** + * Compute the Miller loop for pairings of type G_1 x G_2 over the bits of a + * given parameter. + * + * @param[out] r - the result. + * @param[out] t - the resulting point. + * @param[in] p - the first pairing argument in affine coordinates. + * @param[in] q - the second pairing argument in affine coordinates. + * @param[in] n - the number of pairings to evaluate. + * @param[in] a - the loop parameter. + */ +static void pp_mil_lit_k16(fp16_t r, ep_t *t, ep_t *p, ep4_t *q, int m, bn_t a) { + fp16_t l; + ep4_t *_q = RLC_ALLOCA(ep4_t, m); + int j; + + fp16_null(l); + + RLC_TRY { + if (_q == NULL) { + RLC_THROW(ERR_NO_MEMORY); + } + fp16_new(l); + + for (j = 0; j < m; j++) { + ep4_null(_q[j]); + ep4_new(_q[j]); + ep_copy(t[j], p[j]); + ep4_neg(_q[j], q[j]); + } + + fp16_zero(l); + for (int i = bn_bits(a) - 2; i >= 0; i--) { + fp16_sqr(r, r); + for (j = 0; j < m; j++) { + pp_dbl_lit_k16(l, t[j], t[j], _q[j]); + fp16_mul(r, r, l); + if (bn_get_bit(a, i)) { + pp_add_lit_k16(l, t[j], p[j], q[j]); + fp16_mul(r, r, l); + } + } + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + fp16_free(l); + for (j = 0; j < m; j++) { + ep4_free(_q[j]); + } + RLC_FREE(_q); + } +} + +/** + * Compute the final lines for optimal ate pairings. + * + * @param[out] r - the result. + * @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_k16_oatep(fp16_t r, ep4_t t, ep4_t q, ep_t p) { + ep4_t q1, q2; + fp16_t tmp; + + fp16_null(tmp); + ep4_null(q1); + ep4_null(q2); + + RLC_TRY { + ep4_new(q1); + ep4_new(q2); + fp16_new(tmp); + fp16_zero(tmp); + +#if EP_ADD == PROJC + fp_neg(p->x, p->x); +#endif + ep4_frb(q1, q, 1); + 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_mul_dxs(r, r, tmp); + } RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } RLC_FINALLY { + fp16_free(tmp); + ep4_free(q1); + ep4_free(q2); + } +} + +/*============================================================================*/ +/* Public definitions */ +/*============================================================================*/ + +#if PP_MAP == TATEP || !defined(STRIP) + +void pp_map_tatep_k16(fp16_t r, const ep_t p, const ep4_t q) { + ep_t _p[1], t[1]; + ep4_t _q[1]; + bn_t n; + + ep_null(_p[0]); + ep_null(t[0]); + ep4_null(_q[0]); + bn_null(n); + + RLC_TRY { + ep_new(_p[0]); + ep_new(t[0]); + ep4_new(_q[0]); + bn_new(n); + + ep_norm(_p[0], p); + ep4_norm(_q[0], q); + ep_curve_get_ord(n); + fp16_set_dig(r, 1); + + if (!ep_is_infty(p) && !ep4_is_infty(q)) { + pp_mil_lit_k16(r, t, _p, _q, 1, n); + pp_exp_k16(r, r); + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + ep_free(_p[0]); + ep_free(t[0]); + ep4_free(_q[0]); + bn_free(n); + } +} + +void pp_map_sim_tatep_k16(fp16_t r, const ep_t *p, const ep4_t *q, int m) { + ep_t *_p = RLC_ALLOCA(ep_t, m), *t = RLC_ALLOCA(ep_t, m); + ep4_t *_q = RLC_ALLOCA(ep4_t, m); + bn_t n; + int i, j; + + bn_null(n); + + RLC_TRY { + bn_new(n); + if (_p == NULL || _q == NULL || t == NULL) { + RLC_THROW(ERR_NO_MEMORY); + } + for (i = 0; i < m; i++) { + ep_null(_p[i]); + ep_null(t[i]); + ep4_null(_q[i]); + ep_new(_p[i]); + ep_new(t[i]); + ep4_new(_q[i]); + } + + j = 0; + for (i = 0; i < m; i++) { + if (!ep_is_infty(p[i]) && !ep4_is_infty(q[i])) { + ep_norm(_p[j], p[i]); + ep4_norm(_q[j], q[i]); + j++; + } + } + + ep_curve_get_ord(n); + fp16_set_dig(r, 1); + if (j > 0) { + pp_mil_lit_k16(r, t, _p, _q, j, n); + pp_exp_k16(r, r); + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + bn_free(n); + for (i = 0; i < m; i++) { + ep_free(_p[i]); + ep_free(t[i]); + ep4_free(_q[i]); + } + RLC_FREE(_p); + RLC_FREE(t); + RLC_FREE(_q); + } +} + +#endif + +#if PP_MAP == WEILP || !defined(STRIP) + +void pp_map_weilp_k16(fp16_t r, const ep_t p, const ep4_t q) { + ep_t _p[1], t0[1]; + ep4_t _q[1], t1[1]; + fp16_t r0, r1; + bn_t n; + + ep_null(_p[0]); + ep_null(t0[0]); + ep4_null(_q[0]); + ep4_null(t1[0]); + fp16_null(r0); + fp16_null(r1); + bn_null(n); + + RLC_TRY { + ep_new(_p[0]); + ep_new(t0[0]); + ep4_new(_q[0]); + ep4_new(t1[0]); + fp16_new(r0); + fp16_new(r1); + bn_new(n); + + ep_norm(_p[0], p); + ep4_norm(_q[0], q); + + ep_curve_get_ord(n); + bn_sub_dig(n, n, 1); + fp16_set_dig(r0, 1); + fp16_set_dig(r1, 1); + + if (!ep_is_infty(_p[0]) && !ep4_is_infty(_q[0])) { + pp_mil_k16(r1, t1, _q, _p, 1, n); + pp_mil_lit_k16(r0, t0, _p, _q, 1, n); + fp16_inv(r1, r1); + fp16_mul(r0, r0, r1); + fp16_inv(r1, r0); + fp16_inv_cyc(r0, r0); + } + fp16_mul(r, r0, r1); + fp16_sqr(r, r); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + ep_free(_p[0]); + ep_free(t0[0]); + ep4_free(_q[0]); + ep4_free(t1[0]); + fp16_free(r0); + fp16_free(r1); + bn_free(n); + } +} + +void pp_map_sim_weilp_k16(fp16_t r, const ep_t *p, const ep4_t *q, int m) { + ep_t *_p = RLC_ALLOCA(ep_t, m), *t0 = RLC_ALLOCA(ep_t, m); + ep4_t *_q = RLC_ALLOCA(ep4_t, m), *t1 = RLC_ALLOCA(ep4_t, m); + fp16_t r0, r1; + bn_t n; + int i, j; + + fp16_null(r0); + fp16_null(r1); + bn_null(n); + + RLC_TRY { + fp16_new(r0); + fp16_new(r1); + bn_new(n); + if (_p == NULL || _q == NULL || t0 == NULL || t1 == NULL) { + RLC_THROW(ERR_NO_MEMORY); + } + for (i = 0; i < m; i++) { + ep_null(_p[i]); + ep_null(t0[i]); + ep4_null(_q[i]); + ep4_null(t1[i]); + ep_new(_p[i]); + ep_new(t0[i]); + ep4_new(_q[i]); + ep4_new(t1[i]); + } + + j = 0; + for (i = 0; i < m; i++) { + if (!ep_is_infty(p[i]) && !ep4_is_infty(q[i])) { + ep_norm(_p[j], p[i]); + ep4_norm(_q[j++], q[i]); + } + } + + ep_curve_get_ord(n); + bn_sub_dig(n, n, 1); + fp16_set_dig(r0, 1); + fp16_set_dig(r1, 1); + + if (j > 0) { + pp_mil_k16(r1, t1, _q, _p, j, n); + pp_mil_lit_k16(r0, t0, _p, _q, j, n); + fp16_inv(r1, r1); + fp16_mul(r0, r0, r1); + fp16_inv(r1, r0); + fp16_inv_cyc(r0, r0); + } + fp16_mul(r, r0, r1); + fp16_sqr(r, r); + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + fp16_free(r0); + fp16_free(r1); + bn_free(n); + for (i = 0; i < m; i++) { + ep_free(_p[i]); + ep_free(t0[i]); + ep4_free(_q[i]); + ep4_free(t1[i]); + } + RLC_FREE(_p); + RLC_FREE(_q); + RLC_FREE(t0); + RLC_FREE(t1); + } +} + +#endif + +#if PP_MAP == OATEP || !defined(STRIP) + +void pp_map_oatep_k16(fp16_t r, const ep_t p, const ep4_t q) { + ep_t _p[1]; + ep4_t t[1], _q[1]; + bn_t a; + + ep_null(_p[0]); + ep4_null(_q[0]); + ep4_null(t[0]); + bn_null(a); + + RLC_TRY { + ep_new(_p[0]); + ep4_new(_q[0]); + ep4_new(t[0]); + bn_new(a); + + fp_prime_get_par(a); + fp16_set_dig(r, 1); + + ep_norm(_p[0], p); + ep4_norm(_q[0], q); + + if (!ep_is_infty(_p[0]) && !ep4_is_infty(_q[0])) { + switch (ep_curve_is_pairf()) { + case EP_N16: + /* r = f_{|a|,Q}(P). */ + pp_mil_k16(r, t, _q, _p, 1, a); + if (bn_sign(a) == RLC_NEG) { + /* f_{-a,Q}(P) = 1/f_{a,Q}(P). */ + fp16_inv_cyc(r, r); + ep4_neg(t[0], t[0]); + } + pp_exp_k16(r, r); + break; + case EP_K16: + /* r = f_{|a|,Q}(P). */ + pp_mil_k16(r, t, _q, _p, 1, a); + if (bn_sign(a) == RLC_NEG) { + /* f_{-a,Q}(P) = 1/f_{a,Q}(P). */ + fp16_inv_cyc(r, r); + ep4_neg(t[0], t[0]); + } + fp16_frb(r, r, 3); + pp_fin_k16_oatep(r, t[0], _q[0], _p[0]); + pp_exp_k16(r, r); + break; + } + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + ep_free(_p[0]); + ep4_free(_q[0]); + ep4_free(t[0]); + bn_free(a); + } +} + +void pp_map_sim_oatep_k16(fp16_t r, const ep_t *p, const ep4_t *q, int m) { + ep_t *_p = RLC_ALLOCA(ep_t, m); + ep4_t *t = RLC_ALLOCA(ep4_t, m), *_q = RLC_ALLOCA(ep4_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]); + ep4_null(_q[i]); + ep4_null(t[i]); + ep_new(_p[i]); + ep4_new(_q[i]); + ep4_new(t[i]); + } + + j = 0; + for (i = 0; i < m; i++) { + if (!ep_is_infty(p[i]) && !ep4_is_infty(q[i])) { + ep_norm(_p[j], p[i]); + ep4_norm(_q[j++], q[i]); + } + } + + fp_prime_get_par(a); + fp16_set_dig(r, 1); + + if (j > 0) { + switch (ep_curve_is_pairf()) { + case EP_N16: + /* r = f_{|a|,Q}(P). */ + pp_mil_k16(r, t, _q, _p, j, a); + if (bn_sign(a) == RLC_NEG) { + /* f_{-a,Q}(P) = 1/f_{a,Q}(P). */ + fp16_inv_cyc(r, r); + } + pp_exp_k16(r, r); + break; + case EP_K16: + /* r = f_{|a|,Q}(P). */ + pp_mil_k16(r, t, _q, _p, j, a); + if (bn_sign(a) == RLC_NEG) { + /* f_{-a,Q}(P) = 1/f_{a,Q}(P). */ + fp16_inv_cyc(r, r); + } + fp16_frb(r, r, 3); + for (i = 0; i < j; i++) { + if (bn_sign(a) == RLC_NEG) { + ep4_neg(t[i], t[i]); + } + pp_fin_k16_oatep(r, t[i], _q[i], _p[i]); + } + pp_exp_k16(r, r); + break; + } + } + } + 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); + } +} + +#endif diff --git a/src/pp/relic_pp_map_k18.c b/src/pp/relic_pp_map_k18.c index 4ec9f6b39..95c61a73e 100644 --- a/src/pp/relic_pp_map_k18.c +++ b/src/pp/relic_pp_map_k18.c @@ -24,7 +24,7 @@ /** * @file * - * Implementation of pairing computation for curves with embedding degree 12. + * Implementation of pairing computation for curves with embedding degree 18. * * @ingroup pp */ @@ -198,7 +198,7 @@ static void pp_mil_lit_k18(fp18_t r, ep_t *t, ep_t *p, ep3_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_k18_oatep(fp18_t r, ep3_t t, ep3_t q, ep_t p) { +static void pp_fin_k18_oatep(fp18_t r, ep3_t t, ep3_t q, ep_t p, int f) { fp18_t u, v; ep3_t _q; ep_t _p; @@ -214,28 +214,41 @@ static void pp_fin_k18_oatep(fp18_t r, ep3_t t, ep3_t q, ep_t p) { ep3_new(_q); ep3_null(_p); - /* _q = 3*p*Q. */ - fp18_zero(u); - fp18_zero(v); + /* Compute additional line function. */ + fp18_zero(u); + fp18_zero(v); - /* Compute additional line function. */ + switch (ep_curve_is_pairf()) { + case EP_K18: #if EP_ADD == BASIC - ep_neg(_p, p); + ep_neg(_p, p); #else - fp_add(_p->x, p->x, p->x); - fp_add(_p->x, _p->x, p->x); - fp_neg(_p->y, p->y); + fp_add(_p->x, p->x, p->x); + fp_add(_p->x, _p->x, p->x); + fp_neg(_p->y, p->y); #endif - - pp_dbl_k18(u, _q, q, _p); - pp_add_k18(v, _q, q, p); - pp_norm_k18(_q, _q); - fp18_mul_dxs(u, u, v); - fp18_frb(u, u, 1); - fp18_mul(r, r, u); - ep3_frb(_q, _q, 1); - pp_add_k18(u, t, _q, p); - fp18_mul_dxs(r, r, u); + /* _q = 3*p*Q. */ + pp_dbl_k18(u, _q, q, _p); + pp_add_k18(v, _q, q, p); + pp_norm_k18(_q, _q); + fp18_mul_dxs(u, u, v); + fp18_frb(u, u, 1); + fp18_mul(r, r, u); + ep3_frb(_q, _q, 1); + pp_add_k18(u, t, _q, p); + fp18_mul_dxs(r, r, u); + break; + case EP_SG18: + if (f == 1) { + fp18_frb(u, r, 3); + fp18_mul(r, r, u); + } + ep3_frb(t, t, 3); + ep3_frb(_q, q, 2); + pp_add_k18(v, t, _q, p); + fp18_mul_dxs(r, r, v); + break; + } } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { @@ -522,7 +535,18 @@ void pp_map_oatep_k18(fp18_t r, const ep_t p, const ep3_t q) { fp18_inv_cyc(r, r); ep3_neg(t[0], t[0]); } - pp_fin_k18_oatep(r, t[0], _q[0], _p[0]); + pp_fin_k18_oatep(r, t[0], _q[0], _p[0], 0); + pp_exp_k18(r, r); + break; + case EP_SG18: + /* r = f_{|a|,Q}(P). */ + pp_mil_k18(r, t, _q, _p, 1, a); + if (bn_sign(a) == RLC_NEG) { + /* f_{-a,Q}(P) = 1/f_{a,Q}(P). */ + fp18_inv_cyc(r, r); + ep3_neg(t[0], t[0]); + } + pp_fin_k18_oatep(r, t[0], _q[0], _p[0], 1); pp_exp_k18(r, r); break; } @@ -584,7 +608,23 @@ void pp_map_sim_oatep_k18(fp18_t r, const ep_t *p, const ep3_t *q, int m) { if (bn_sign(a) == RLC_NEG) { ep3_neg(t[i], t[i]); } - pp_fin_k18_oatep(r, t[i], _q[i], _p[i]); + pp_fin_k18_oatep(r, t[i], _q[i], _p[i], 0); + } + pp_exp_k18(r, r); + break; + case EP_SG18: + /* r = f_{|a|,Q}(P). */ + pp_mil_k18(r, t, _q, _p, j, a); + if (bn_sign(a) == RLC_NEG) { + /* f_{-a,Q}(P) = 1/f_{a,Q}(P). */ + fp18_inv_cyc(r, r); + } + for (i = 0; i < j; i++) { + if (bn_sign(a) == RLC_NEG) { + ep3_neg(t[i], t[i]); + } + /* Apply Frobenius only once. */ + pp_fin_k18_oatep(r, t[i], _q[i], _p[i], i == 0); } pp_exp_k18(r, r); break; diff --git a/src/pp/relic_pp_map_k24.c b/src/pp/relic_pp_map_k24.c index 91701eee0..87e09717e 100644 --- a/src/pp/relic_pp_map_k24.c +++ b/src/pp/relic_pp_map_k24.c @@ -24,7 +24,7 @@ /** * @file * - * Implementation of pairing computation for curves with embedding degree 12. + * Implementation of pairing computation for curves with embedding degree 24. * * @ingroup pp */ @@ -168,7 +168,6 @@ void pp_map_k24(fp24_t r, const ep_t p, const ep4_t q) { pp_mil_k24(r, t, _q, _p, 1, a); if (bn_sign(a) == RLC_NEG) { fp24_inv_cyc(r, r); - ep4_neg(t[0], t[0]); } pp_exp_k24(r, r); break; diff --git a/src/pp/relic_pp_map_k48.c b/src/pp/relic_pp_map_k48.c index e47e5028e..d1da3573d 100644 --- a/src/pp/relic_pp_map_k48.c +++ b/src/pp/relic_pp_map_k48.c @@ -37,55 +37,85 @@ /* Private definitions */ /*============================================================================*/ -static void pp_mil_k48(fp48_t r, const fp8_t qx, const fp8_t qy, const ep_t p, - const bn_t a) { +/** + * Compute the Miller loop for pairings of type G_2 x G_1 over the bits of a + * given parameter represented in sparse form. + * + * @param[out] r - the result. + * @param[out] t - the resulting point. + * @param[in] q - the vector of first arguments in affine coordinates. + * @param[in] p - the vector of second arguments in affine coordinates. + * @param[in] n - the number of pairings to evaluate. + * @param[in] a - the loop parameter. + */ +static void pp_mil_k48(fp48_t r, ep8_t *t, ep8_t *q, ep_t *p, int m, bn_t a) { fp48_t l; - ep_t _p; - fp8_t rx, ry, rz, qn; + ep_t *_p = RLC_ALLOCA(ep_t, m); + ep8_t *_q = RLC_ALLOCA(ep8_t, m); size_t len = bn_bits(a) + 1; - int i; + int i, j; int8_t s[RLC_FP_BITS + 1]; + if (m == 0) { + return; + } + fp48_null(l); - ep_null(_p); - fp8_null(rx); - fp8_null(ry); - fp8_null(rz); - fp8_null(qn); RLC_TRY { fp48_new(l); - ep_new(_p); - fp8_new(rx); - fp8_new(ry); - fp8_new(rz); - fp8_new(qn); - - fp48_zero(l); - fp8_copy(rx, qx); - fp8_copy(ry, qy); - fp8_set_dig(rz, 1); + if (_p == NULL || _q == NULL) { + RLC_THROW(ERR_NO_MEMORY); + } + for (j = 0; j < m; j++) { + ep_null(_p[j]); + ep8_null(_q[j]); + ep_new(_p[j]); + ep8_new(_q[j]); + ep8_copy(t[j], q[j]); + ep8_neg(_q[j], q[j]); #if EP_ADD == BASIC - ep_neg(_p, p); + ep_neg(_p[j], p[j]); #else - fp_add(_p->x, p->x, p->x); - fp_add(_p->x, _p->x, p->x); - fp_neg(_p->y, p->y); + fp_add(_p[j]->x, p[j]->x, p[j]->x); + fp_add(_p[j]->x, _p[j]->x, p[j]->x); + fp_neg(_p[j]->y, p[j]->y); #endif - fp8_neg(qn, qy); + } + fp48_zero(l); bn_rec_naf(s, &len, a, 2); - for (i = len - 2; i >= 0; i--) { - fp48_sqr(r, r); - pp_dbl_k48(l, rx, ry, rz, _p); + pp_dbl_k48(r, t[0], t[0], _p[0]); + for (j = 1; j < m; j++) { + pp_dbl_k48(l, t[j], t[j], _p[j]); fp48_mul_dxs(r, r, l); - if (s[i] > 0) { - pp_add_k48(l, rx, ry, rz, qx, qy, p); + } + if (s[len - 2] > 0) { + for (j = 0; j < m; j++) { + pp_add_k48(l, t[j], q[j], p[j]); + fp48_mul_dxs(r, r, l); + } + } + if (s[len - 2] < 0) { + for (j = 0; j < m; j++) { + pp_add_k48(l, t[j], _q[j], p[j]); fp48_mul_dxs(r, r, l); } - if (s[i] < 0) { - pp_add_k48(l, rx, ry, rz, qx, qn, p); + } + + for (i = len - 3; i >= 0; i--) { + fp48_sqr(r, r); + for (j = 0; j < m; j++) { + pp_dbl_k48(l, t[j], t[j], _p[j]); fp48_mul_dxs(r, r, l); + if (s[i] > 0) { + pp_add_k48(l, t[j], q[j], p[j]); + fp48_mul_dxs(r, r, l); + } + if (s[i] < 0) { + pp_add_k48(l, t[j], _q[j], p[j]); + fp48_mul_dxs(r, r, l); + } } } } @@ -94,11 +124,12 @@ static void pp_mil_k48(fp48_t r, const fp8_t qx, const fp8_t qy, const ep_t p, } RLC_FINALLY { fp48_free(l); - ep_free(_p); - fp8_free(rx); - fp8_free(ry); - fp8_free(rz); - fp8_free(qn); + for (j = 0; j < m; j++) { + ep_free(_p[j]); + ep8_free(_q[j]); + } + RLC_FREE(_p); + RLC_FREE(_q); } } @@ -106,22 +137,91 @@ static void pp_mil_k48(fp48_t r, const fp8_t qx, const fp8_t qy, const ep_t p, /* Public definitions */ /*============================================================================*/ -void pp_map_k48(fp48_t r, const ep_t p, const fp8_t qx, const fp8_t qy) { +#if PP_MAP == OATEP || !defined(STRIP) + +void pp_map_k48(fp48_t r, const ep_t p, const ep8_t q) { + ep_t _p[1]; + ep8_t t[1], _q[1]; bn_t a; + ep_null(_p[0]); + ep8_null(_q[0]); + ep8_null(t[0]); bn_null(a); RLC_TRY { + ep_new(_p[0]); + ep8_new(_q[0]); + ep8_new(t[0]); + bn_new(a); + + fp_prime_get_par(a); + fp48_set_dig(r, 1); + + ep_norm(_p[0], p); + ep8_norm(_q[0], q); + + if (!ep_is_infty(_p[0]) && !ep8_is_infty(_q[0])) { + switch (ep_curve_is_pairf()) { + case EP_B48: + /* r = f_{|a|,Q}(P). */ + pp_mil_k48(r, t, _q, _p, 1, a); + if (bn_sign(a) == RLC_NEG) { + fp48_inv_cyc(r, r); + } + pp_exp_k48(r, r); + break; + } + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + ep_free(_p[0]); + ep8_free(_q[0]); + ep8_free(t[0]); + bn_free(a); + } +} + +void pp_map_sim_k48(fp48_t r, const ep_t *p, const ep8_t *q, int m) { + ep_t *_p = RLC_ALLOCA(ep_t, m); + ep8_t *t = RLC_ALLOCA(ep8_t, m), *_q = RLC_ALLOCA(ep8_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]); + ep8_null(_q[i]); + ep8_null(t[i]); + ep_new(_p[i]); + ep8_new(_q[i]); + ep8_new(t[i]); + } + + j = 0; + for (i = 0; i < m; i++) { + if (!ep_is_infty(p[i]) && !ep8_is_infty(q[i])) { + ep_norm(_p[j], p[i]); + ep8_norm(_q[j++], q[i]); + } + } fp_prime_get_par(a); fp48_set_dig(r, 1); - if (!ep_is_infty(p) && !(fp8_is_zero(qx) && fp8_is_zero(qy))) { + if (j > 0) { switch (ep_curve_is_pairf()) { case EP_B48: /* r = f_{|a|,Q}(P). */ - pp_mil_k48(r, qx, qy, p, a); + pp_mil_k48(r, t, _q, _p, j, a); if (bn_sign(a) == RLC_NEG) { fp48_inv_cyc(r, r); } @@ -135,5 +235,15 @@ void pp_map_k48(fp48_t r, const ep_t p, const fp8_t qx, const fp8_t qy) { } RLC_FINALLY { bn_free(a); + for (i = 0; i < m; i++) { + ep_free(_p[i]); + ep8_free(_q[i]); + ep8_free(t[i]); + } + RLC_FREE(_p); + RLC_FREE(_q); + RLC_FREE(t); } } + +#endif diff --git a/src/pp/relic_pp_norm.c b/src/pp/relic_pp_norm.c index 80ffd8742..e63b0d62c 100644 --- a/src/pp/relic_pp_norm.c +++ b/src/pp/relic_pp_norm.c @@ -39,6 +39,10 @@ /* Public definitions */ /*============================================================================*/ +void pp_norm_k1(ep_t r, const ep_t p) { + ep_norm(r, p); +} + void pp_norm_k2(ep_t r, const ep_t p) { ep_norm(r, p); } @@ -82,6 +86,28 @@ void pp_norm_k12(ep2_t r, const ep2_t p) { #endif } +void pp_norm_k16(ep4_t r, const ep4_t p) { + if (ep4_is_infty(p)) { + ep4_set_infty(r); + return; + } + + if (p->coord == BASIC) { + /* If the point is represented in affine coordinates, we just copy it. */ + ep4_copy(r, p); + } +#if EP_ADD == PROJC || !defined(STRIP) + fp4_inv(r->z, p->z); + fp4_mul(r->x, p->x, r->z); + fp4_mul(r->y, p->y, r->z); + if (ep_curve_opt_b() == RLC_ZERO) { + fp4_mul(r->y, r->y, r->z); + } + fp4_set_dig(r->z, 1); + r->coord = BASIC; +#endif +} + void pp_norm_k18(ep3_t r, const ep3_t p) { if (ep3_is_infty(p)) { ep3_set_infty(r); @@ -119,3 +145,22 @@ void pp_norm_k24(ep4_t r, const ep4_t p) { r->coord = BASIC; #endif } + +void pp_norm_k48(ep8_t r, const ep8_t p) { + if (ep8_is_infty(p)) { + ep8_set_infty(r); + return; + } + + if (p->coord == BASIC) { + /* If the point is represented in affine coordinates, we just copy it. */ + ep8_copy(r, p); + } +#if EP_ADD == PROJC || !defined(STRIP) + fp8_inv(r->z, p->z); + fp8_mul(r->x, p->x, r->z); + fp8_mul(r->y, p->y, r->z); + fp8_set_dig(r->z, 1); + r->coord = BASIC; +#endif +} diff --git a/src/tmpl/relic_tmpl_map.h b/src/tmpl/relic_tmpl_map.h index 311bf144a..2caaef1f7 100644 --- a/src/tmpl/relic_tmpl_map.h +++ b/src/tmpl/relic_tmpl_map.h @@ -172,7 +172,7 @@ * "Fast and simple constant-time hashing to the BLS12-381 Elliptic Curve" */ #define TMPL_MAP_SSWU(CUR, PFX, PTR_TY, COPY_COND) \ - static void CUR##_map_sswu(CUR##_t p, PFX##_t t) { \ + static void CUR##_map_sswu(CUR##_t p, const PFX##_t t) { \ PFX##_t t0, t1, t2, t3; \ ctx_t *ctx = core_get(); \ PTR_TY *mBoverA = ctx->CUR##_map_c[0]; \ @@ -197,40 +197,40 @@ PFX##_sqr(t1, t0); /* t1 = u^2 * t^4 */ \ PFX##_add(t2, t1, t0); /* t2 = u^2 * t^4 + u * t^2 */ \ \ - /* handle the exceptional cases */ \ - /* XXX(rsw) should be done projectively */ \ - { \ - const int e1 = PFX##_is_zero(t2); \ - PFX##_neg(t3, u); /* t3 = -u */ \ - COPY_COND(t2, t3, e1); /* exception: -u instead of u^2t^4 + ut^2 */ \ - PFX##_inv(t2, t2); /* t2 = -1/u or 1/(u^2 * t^4 + u*t^2) */ \ - PFX##_add_dig(t3, t2, 1); /* t3 = 1 + t2 */ \ - COPY_COND(t2, t3, e1 == 0); /* only add 1 if t2 != -1/u */ \ - } \ - /* e1 goes out of scope */ \ - \ - /* compute x1, g(x1) */ \ - PFX##_mul(p->x, t2, mBoverA); /* -B / A * (1 + 1 / (u^2 * t^4 + u * t^2)) */ \ - PFX##_sqr(p->y, p->x); /* x^2 */ \ - PFX##_add(p->y, p->y, a); /* x^2 + a */ \ - PFX##_mul(p->y, p->y, p->x); /* x^3 + a x */ \ - PFX##_add(p->y, p->y, b); /* x^3 + a x + b */ \ - \ - /* compute x2, g(x2) */ \ - PFX##_mul(t2, t0, p->x); /* t2 = u * t^2 * x1 */ \ - PFX##_mul(t1, t0, t1); /* t1 = u^3 * t^6 */ \ - PFX##_mul(t3, t1, p->y); /* t5 = g(t2) = u^3 * t^6 * g(p->x) */ \ - \ - /* XXX(rsw) */ \ - /* This should be done in constant time and without computing 2 sqrts. */ \ - /* Avoiding a second sqrt relies on knowing the 2-adicity of the modulus. */ \ - if (!PFX##_srt(p->y, p->y)) { \ - /* try x2, g(x2) */ \ - PFX##_copy(p->x, t2); \ - if (!PFX##_srt(p->y, t3)) { \ - RLC_THROW(ERR_NO_VALID); \ - } \ - } \ + /* handle the exceptional cases */ \ + /* XXX(rsw) should be done projectively */ \ + { \ + 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); \ + /* 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 */ \ + } \ + /* e1 goes out of scope */ \ + /* compute x1, g(x1) */ \ + /* -B / A * (1 + 1 / (u^2 * t^4 + u * t^2)) */ \ + PFX##_mul(p->x, t2, mBoverA); \ + PFX##_sqr(p->y, p->x); /* x^2 */ \ + PFX##_add(p->y, p->y, a); /* x^2 + a */ \ + PFX##_mul(p->y, p->y, p->x); /* x^3 + a x */ \ + PFX##_add(p->y, p->y, b); /* x^3 + a x + b */ \ + \ + /* compute x2, g(x2) */ \ + PFX##_mul(t2, t0, p->x); /* t2 = u * t^2 * x1 */ \ + PFX##_mul(t1, t0, t1); /* t1 = u^3 * t^6 */ \ + PFX##_mul(t3, t1, p->y); /* t5 = g(t2) = u^3 * t^6 * g(p->x) */ \ + { \ + /* 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); \ + } \ + if (!PFX##_srt(p->y, p->y)) { \ + RLC_THROW(ERR_NO_VALID); \ + } \ PFX##_set_dig(p->z, 1); \ p->coord = BASIC; \ } \ @@ -248,8 +248,15 @@ * draft-irtf-cfrg-hash-to-curve-06, Section 6.6.1 */ #define TMPL_MAP_SVDW(CUR, PFX, PTR_TY, COPY_COND) \ - static void CUR##_map_svdw(CUR##_t p, PFX##_t t) { \ + static void CUR##_map_svdw(CUR##_t p, const PFX##_t t) { \ PFX##_t t1, t2, t3, t4; \ + ctx_t *ctx = core_get(); \ + PTR_TY *gU = ctx->CUR##_map_c[0]; \ + PTR_TY *mUover2 = ctx->CUR##_map_c[1]; \ + PTR_TY *c3 = ctx->CUR##_map_c[2]; \ + PTR_TY *c4 = ctx->CUR##_map_c[3]; \ + PTR_TY *u = ctx->CUR##_map_u; \ + \ PFX##_null(t1); \ PFX##_null(t2); \ PFX##_null(t3); \ @@ -261,13 +268,6 @@ PFX##_new(t3); \ PFX##_new(t4); \ \ - ctx_t *ctx = core_get(); \ - PTR_TY *gU = ctx->CUR##_map_c[0]; \ - PTR_TY *mUover2 = ctx->CUR##_map_c[1]; \ - PTR_TY *c3 = ctx->CUR##_map_c[2]; \ - PTR_TY *c4 = ctx->CUR##_map_c[3]; \ - PTR_TY *u = ctx->CUR##_map_u; \ - \ /* start computing the map */ \ PFX##_sqr(t1, t); \ PFX##_mul(t1, t1, gU); \ @@ -290,26 +290,31 @@ PFX##_mul(t4, t4, t3); \ PFX##_mul(t4, t4, c3); \ \ - /* XXX(rsw) this should be constant time */ \ /* compute x1 and g(x1) */ \ PFX##_sub(p->x, mUover2, t4); \ CUR##_rhs(p->y, p); \ - if (!PFX##_srt(p->y, p->y)) { \ + { \ + const int e0 = PFX##_is_sqr(p->y); \ /* compute x2 and g(x2) */ \ - PFX##_add(p->x, mUover2, t4); \ - CUR##_rhs(p->y, p); \ - if (!PFX##_srt(p->y, p->y)) { \ - /* compute x3 and g(x3) */ \ - PFX##_sqr(p->x, t2); \ - PFX##_mul(p->x, p->x, t3); \ - PFX##_sqr(p->x, p->x); \ - PFX##_mul(p->x, p->x, c4); \ - PFX##_add(p->x, p->x, u); \ - CUR##_rhs(p->y, p); \ - if (!PFX##_srt(p->y, p->y)) { \ - RLC_THROW(ERR_NO_VALID); \ - } \ - } \ + PFX##_add(t4, mUover2, t4); \ + COPY_COND(p->x, t4, e0 == 0); \ + CUR##_rhs(t1, p); \ + COPY_COND(p->y, t1, e0 == 0); \ + } \ + { \ + const int e1 = PFX##_is_sqr(p->y); \ + /* compute x3 and g(x3) */ \ + PFX##_sqr(t1, t2); \ + PFX##_mul(t1, t1, t3); \ + 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); \ + } \ + if (!PFX##_srt(p->y, p->y)) { \ + RLC_THROW(ERR_NO_VALID); \ } \ PFX##_set_dig(p->z, 1); \ p->coord = BASIC; \ diff --git a/test/test_bn.c b/test/test_bn.c index 85d2cf584..c10f08497 100644 --- a/test/test_bn.c +++ b/test/test_bn.c @@ -2251,7 +2251,7 @@ static int recoding(void) { /* Check that subscalars have the right length. */ TEST_ASSERT(bn_bits(b) <= 1 + (bn_bits(v2[0]) >> 1), end); TEST_ASSERT(bn_bits(c) <= 1 + (bn_bits(v2[0]) >> 1), end); - /* Recover lambda parameter. */ + /* Recover two candidates for the lambda parameter. */ if (bn_cmp_dig(v1[2], 1) == RLC_EQ) { bn_gcd_ext(v1[0], v2[1], NULL, v1[1], v2[0]); } else { @@ -2268,17 +2268,16 @@ static int recoding(void) { } bn_mod(v1[0], v1[0], v2[0]); bn_sub(v1[1], v2[0], v1[0]); - if (bn_cmp(v1[1], v1[0]) == RLC_LT) { - bn_copy(v1[0], v1[1]); - } /* Check if b + c * lambda = k (mod n). */ - bn_mul(c, c, v1[0]); - bn_add(b, b, c); - bn_mod(b, b, v2[0]); - if (bn_sign(b) == RLC_NEG) { - bn_add(b, b, v2[0]); - } - TEST_ASSERT(bn_cmp(a, b) == RLC_EQ, end); + bn_mul(v2[1], c, v1[0]); + bn_add(v2[1], v2[1], b); + bn_mod(v2[1], v2[1], v2[0]); + /* Now try the other candidate. */ + bn_mul(v2[2], c, v1[1]); + bn_add(v2[2], v2[2], b); + bn_mod(v2[2], v2[2], v2[0]); + TEST_ASSERT(bn_cmp(a, v2[1]) == RLC_EQ || + bn_cmp(a, v2[2]) == RLC_EQ, end); } } TEST_END; #endif /* WITH_EP && EP_ENDOM */ diff --git a/test/test_cp.c b/test/test_cp.c index 045807d7e..575e695ea 100644 --- a/test/test_cp.c +++ b/test/test_cp.c @@ -1283,9 +1283,7 @@ static int sokaka(void) { cp_sokaka_gen(s); - TEST_CASE - ("sakai-ohgishi-kasahara authenticated key agreement is correct") - { + TEST_CASE("sakai-ohgishi-kasahara auth key agreement is correct") { TEST_ASSERT(cp_sokaka_gen_prv(k, ia, s) == RLC_OK, end); TEST_ASSERT(cp_sokaka_key(k1, l, ia, k, ib) == RLC_OK, end); TEST_ASSERT(cp_sokaka_gen_prv(k, ib, s) == RLC_OK, end); diff --git a/test/test_ep.c b/test/test_ep.c index db23f619f..e01ece13c 100644 --- a/test/test_ep.c +++ b/test/test_ep.c @@ -437,7 +437,7 @@ static int doubling(void) { } TEST_END; #endif -#if EP_ADD == PROJC || !defined(STRIP) +#if EP_ADD == JACOB || !defined(STRIP) TEST_CASE("point doubling in jacobian coordinates is correct") { ep_rand(a); /* a in projective coordinates. */ @@ -525,7 +525,7 @@ static int endomorphism(void) { } TEST_END; -#if EB_ADD == BASIC || !defined(STRIP) +#if EP_ADD == BASIC || !defined(STRIP) TEST_CASE("endomorphism in affine coordinates is correct") { ep_rand(a); ep_psi(b, a); @@ -537,11 +537,24 @@ static int endomorphism(void) { TEST_END; #endif -#if EB_ADD == PROJC || !defined(STRIP) +#if EP_ADD == PROJC || !defined(STRIP) TEST_CASE("endomorphism in projective coordinates is correct") { ep_rand(a); ep_dbl_projc(a, a); ep_psi(b, a); + ep_norm(a, a); + ep_mul(c, a, l); + ep_neg(a, b); + } + TEST_END; +#endif + +#if EP_ADD == JACOB || !defined(STRIP) + TEST_CASE("endomorphism in jacobian coordinates is correct") { + ep_rand(a); + ep_dbl_jacob(a, a); + ep_psi(b, a); + ep_norm(a, a); ep_mul(c, a, l); ep_neg(a, b); TEST_ASSERT(ep_cmp(b, c) == RLC_EQ || @@ -1337,17 +1350,14 @@ static int compression(void) { static int hashing(void) { int code = RLC_ERR; ep_t a; - ep_t b; bn_t n; uint8_t msg[5]; ep_null(a); - ep_null(b); bn_null(n); RLC_TRY { ep_new(a); - ep_new(b); bn_new(n); ep_curve_get_ord(n); @@ -1355,13 +1365,46 @@ static int hashing(void) { TEST_CASE("point hashing is correct") { rand_bytes(msg, sizeof(msg)); ep_map(a, msg, sizeof(msg)); - TEST_ASSERT(ep_is_infty(a) == 0, end); - ep_map_dst(b, msg, sizeof(msg), (const uint8_t *)"RELIC", 5); - TEST_ASSERT(ep_cmp(a, b) == RLC_EQ, end); + 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; + +#if EP_MAP == BASIC || !defined(STRIP) + TEST_CASE("basic point hashing is correct") { + rand_bytes(msg, sizeof(msg)); + ep_map_basic(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; +#endif + +#if EP_MAP == SSWUM || !defined(STRIP) + TEST_CASE("simplified SWU point hashing is correct") { + rand_bytes(msg, sizeof(msg)); + ep_map_sswum(a, msg, sizeof(msg)); + TEST_ASSERT(ep_on_curve(a) && ep_is_infty(a) == 0, end); ep_mul(a, a, n); - TEST_ASSERT(ep_is_infty(a) == 1, end); + TEST_ASSERT(ep_on_curve(a) && ep_is_infty(a) == 1, end); } TEST_END; +#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); + } + TEST_END; +#endif + } } RLC_CATCH_ANY { RLC_ERROR(end); @@ -1369,7 +1412,6 @@ static int hashing(void) { code = RLC_OK; end: ep_free(a); - ep_free(b); bn_free(n); return code; } @@ -1431,6 +1473,7 @@ int test(void) { int main(void) { int r0 = RLC_ERR, r1 = RLC_ERR, r2 = RLC_ERR, r3 = RLC_ERR; + int c0 = 0, c1 = 0, c2 = 0, c3 = 0; if (core_init() != RLC_OK) { core_clean(); @@ -1442,6 +1485,7 @@ int main(void) { #if defined(EP_PLAIN) r0 = ep_param_set_any_plain(); if (r0 == RLC_OK) { + c0 = ep_param_get(); if (test() != RLC_OK) { core_clean(); return 1; @@ -1452,27 +1496,36 @@ int main(void) { #if defined(EP_ENDOM) r1 = ep_param_set_any_endom(); if (r1 == RLC_OK) { - if (test() != RLC_OK) { - core_clean(); - return 1; + c1 = ep_param_get(); + if (c1 != c0) { + if (test() != RLC_OK) { + core_clean(); + return 1; + } } } #endif r2 = ep_param_set_any_pairf(); if (r2 == RLC_OK) { - if (test() != RLC_OK) { - core_clean(); - return 1; + c2 = ep_param_get(); + if (c2 != c1) { + if (test() != RLC_OK) { + core_clean(); + return 1; + } } } #if defined(EP_SUPER) r3 = ep_param_set_any_super(); if (r3 == RLC_OK) { - if (test() != RLC_OK) { - core_clean(); - return 1; + c3 = ep_param_get(); + if (c3 != c2) { + if (test() != RLC_OK) { + core_clean(); + return 1; + } } } #endif @@ -1490,6 +1543,11 @@ int main(void) { } } + (void)c0; + (void)c1; + (void)c2; + (void)c3; + util_banner("All tests have passed.\n", 0); core_clean(); diff --git a/test/test_epx.c b/test/test_epx.c index e63f21856..26c45ab68 100644 --- a/test/test_epx.c +++ b/test/test_epx.c @@ -1096,31 +1096,61 @@ static int compression2(void) { static int hashing2(void) { int code = RLC_ERR; bn_t n; - ep2_t p; - ep2_t q; + ep2_t a; uint8_t msg[5]; bn_null(n); - ep2_null(p); - ep2_null(q); + ep2_null(a); RLC_TRY { bn_new(n); - ep2_new(p); - ep2_new(q); + ep2_new(a); ep2_curve_get_ord(n); TEST_CASE("point hashing is correct") { rand_bytes(msg, sizeof(msg)); - ep2_map(p, msg, sizeof(msg)); - TEST_ASSERT(ep2_is_infty(p) == 0, end); - ep2_map_dst(q, msg, sizeof(msg), (const uint8_t *)"RELIC", 5); - TEST_ASSERT(ep2_cmp(p, q) == RLC_EQ, end); - ep2_mul(p, p, n); - TEST_ASSERT(ep2_is_infty(p) == 1, end); + ep2_map(a, msg, sizeof(msg)); + TEST_ASSERT(ep2_on_curve(a) == 1, end); + ep2_mul(a, a, n); + TEST_ASSERT(ep2_is_infty(a) == 1, end); + } + TEST_END; + +#if EP_MAP == BASIC || !defined(STRIP) + TEST_CASE("basic point hashing is correct") { + rand_bytes(msg, sizeof(msg)); + ep2_map_basic(a, msg, sizeof(msg)); + TEST_ASSERT(ep2_is_infty(a) == 0, end); + ep2_mul(a, a, n); + TEST_ASSERT(ep2_is_infty(a) == 1, end); + } + TEST_END; +#endif + +#if EP_MAP == SSWUM || !defined(STRIP) + TEST_CASE("simplified SWU point hashing is correct") { + rand_bytes(msg, sizeof(msg)); + ep2_map_sswum(a, msg, sizeof(msg)); + TEST_ASSERT(ep2_is_infty(a) == 0, end); + ep2_mul(a, a, n); + TEST_ASSERT(ep2_is_infty(a) == 1, end); } TEST_END; +#endif + + if (ep_curve_is_pairf()) { + #if EP_MAP == SWIFT || !defined(STRIP) + TEST_CASE("swift point hashing is correct") { + rand_bytes(msg, sizeof(msg)); + ep2_map_swift(a, msg, sizeof(msg)); + TEST_ASSERT(ep2_is_infty(a) == 0, end); + ep2_mul(a, a, n); + TEST_ASSERT(ep2_is_infty(a) == 1, end); + } + TEST_END; + #endif + } } RLC_CATCH_ANY { util_print("FATAL ERROR!\n"); @@ -1129,8 +1159,7 @@ static int hashing2(void) { code = RLC_OK; end: bn_free(n); - ep2_free(p); - ep2_free(q); + ep2_free(a); return code; } @@ -2316,23 +2345,25 @@ static int util4(void) { } TEST_END; TEST_CASE("reading and writing a point are consistent") { - ep4_set_infty(a); - l = ep4_size_bin(a, 0); - ep4_write_bin(bin, l, a, 0); - ep4_read_bin(b, bin, l); - TEST_ASSERT(ep4_cmp(a, b) == RLC_EQ, end); - ep4_rand(a); - l = ep4_size_bin(a, 0); - ep4_write_bin(bin, l, a, 0); - ep4_read_bin(b, bin, l); - TEST_ASSERT(ep4_cmp(a, b) == RLC_EQ, end); - ep4_rand(a); - ep4_dbl(a, a); - l = ep4_size_bin(a, 0); - ep4_norm(a, a); - ep4_write_bin(bin, l, a, 0); - ep4_read_bin(b, bin, l); - TEST_ASSERT(ep4_cmp(a, b) == RLC_EQ, end); + for (int j = 0; j < 2; j++) { + ep4_set_infty(a); + l = ep4_size_bin(a, j); + ep4_write_bin(bin, l, a, j); + ep4_read_bin(b, bin, l); + TEST_ASSERT(ep4_cmp(a, b) == RLC_EQ, end); + ep4_rand(a); + l = ep4_size_bin(a, j); + ep4_write_bin(bin, l, a, j); + ep4_read_bin(b, bin, l); + TEST_ASSERT(ep4_cmp(a, b) == RLC_EQ, end); + ep4_rand(a); + ep4_dbl(a, a); + l = ep4_size_bin(a, j); + ep4_norm(a, a); + ep4_write_bin(bin, l, a, j); + ep4_read_bin(b, bin, l); + TEST_ASSERT(ep4_cmp(a, b) == RLC_EQ, end); + } } TEST_END; } @@ -3171,7 +3202,7 @@ static int hashing4(void) { TEST_CASE("point hashing is correct") { rand_bytes(msg, sizeof(msg)); ep4_map(p, msg, sizeof(msg)); - TEST_ASSERT(ep4_is_infty(p) == 0, end); + TEST_ASSERT(ep4_on_curve(p) == 1, end); ep4_mul(p, p, n); TEST_ASSERT(ep4_is_infty(p) == 1, end); } @@ -3232,164 +3263,1193 @@ static int frobenius4(void) { return code; } -int main(void) { - int r0, r1, r2; - - if (core_init() != RLC_OK) { - core_clean(); - return 1; - } +static int memory8(void) { + err_t e = ERR_CAUGHT; + int code = RLC_ERR; + ep8_t a; - util_banner("Tests for the EPX module", 0); + ep8_null(a); - if (ep_param_set_any_pairf() == RLC_ERR) { - RLC_THROW(ERR_NO_CURVE); - core_clean(); - return 0; + RLC_TRY { + TEST_CASE("memory can be allocated") { + ep8_new(a); + ep8_free(a); + } TEST_END; + } RLC_CATCH(e) { + switch (e) { + case ERR_NO_MEMORY: + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + break; + } } + (void)a; + code = RLC_OK; + end: + return code; +} - if ((r0 = ep2_curve_is_twist())) { - ep_param_print(); +static int util8(void) { + int l, code = RLC_ERR; + ep8_t a, b, c; + uint8_t bin[16 * RLC_FP_BYTES + 1]; - util_banner("Utilities:", 1); + ep8_null(a); + ep8_null(b); + ep8_null(c); - if (memory2() != RLC_OK) { - core_clean(); - return 1; - } + RLC_TRY { + ep8_new(a); + ep8_new(b); + ep8_new(c); - if (util2() != RLC_OK) { - core_clean(); - return 1; + TEST_CASE("copy and comparison are consistent") { + ep8_rand(a); + ep8_rand(b); + ep8_rand(c); + /* Compare points in affine coordinates. */ + if (ep8_cmp(a, c) != RLC_EQ) { + ep8_copy(c, a); + TEST_ASSERT(ep8_cmp(c, a) == RLC_EQ, end); + } + if (ep8_cmp(b, c) != RLC_EQ) { + ep8_copy(c, b); + TEST_ASSERT(ep8_cmp(b, c) == RLC_EQ, end); + } + /* Compare with one point in projective. */ + ep8_dbl(c, a); + ep8_norm(c, c); + ep8_dbl(a, a); + TEST_ASSERT(ep8_cmp(c, a) == RLC_EQ, end); + TEST_ASSERT(ep8_cmp(a, c) == RLC_EQ, end); + /* Compare with two points in projective. */ + ep8_dbl(c, c); + ep8_dbl(a, a); + TEST_ASSERT(ep8_cmp(c, a) == RLC_EQ, end); + TEST_ASSERT(ep8_cmp(a, c) == RLC_EQ, end); } + TEST_END; - util_banner("Arithmetic:", 1); - - if (addition2() != RLC_OK) { - core_clean(); - return 1; + TEST_CASE("negation and comparison are consistent") { + ep8_rand(a); + ep8_neg(b, a); + TEST_ASSERT(ep8_cmp(a, b) != RLC_EQ, end); + ep8_neg(b, b); + TEST_ASSERT(ep8_cmp(a, b) == RLC_EQ, end); + ep8_neg(b, a); + ep8_add(a, a, b); + ep8_set_infty(b); + TEST_ASSERT(ep8_cmp(a, b) == RLC_EQ, end); } + TEST_END; - if (subtraction2() != RLC_OK) { - core_clean(); - return 1; + TEST_CASE("assignment to random and comparison are consistent") { + ep8_rand(a); + ep8_set_infty(c); + TEST_ASSERT(ep8_cmp(a, c) != RLC_EQ, end); + TEST_ASSERT(ep8_cmp(c, a) != RLC_EQ, end); } + TEST_END; - if (doubling2() != RLC_OK) { - core_clean(); - return 1; + TEST_CASE("assignment to infinity and infinity test are consistent") { + ep8_set_infty(a); + TEST_ASSERT(ep8_is_infty(a), end); } + TEST_END; - if (multiplication2() != RLC_OK) { - core_clean(); - return 1; + TEST_CASE("validity test is correct") { + ep8_set_infty(a); + TEST_ASSERT(ep8_on_curve(a), end); + ep8_rand(a); + TEST_ASSERT(ep8_on_curve(a), end); + fp8_rand(a->x); + TEST_ASSERT(!ep8_on_curve(a), end); } + TEST_END; - if (fixed2() != RLC_OK) { - core_clean(); - return 1; - } + TEST_CASE("blinding is consistent") { + ep8_rand(a); + ep8_blind(a, a); + TEST_ASSERT(ep8_on_curve(a), end); + } TEST_END; - if (simultaneous2() != RLC_OK) { - core_clean(); - return 1; + TEST_CASE("reading and writing a point are consistent") { + for (int j = 0; j < 2; j++) { + ep8_set_infty(a); + l = ep8_size_bin(a, j); + ep8_write_bin(bin, l, a, j); + ep8_read_bin(b, bin, l); + TEST_ASSERT(ep8_cmp(a, b) == RLC_EQ, end); + ep8_rand(a); + l = ep8_size_bin(a, j); + ep8_write_bin(bin, l, a, j); + ep8_read_bin(b, bin, l); + TEST_ASSERT(ep8_cmp(a, b) == RLC_EQ, end); + ep8_rand(a); + ep8_dbl(a, a); + l = ep8_size_bin(a, j); + ep8_norm(a, a); + ep8_write_bin(bin, l, a, j); + ep8_read_bin(b, bin, l); + TEST_ASSERT(ep8_cmp(a, b) == RLC_EQ, end); + } } + TEST_END; + } + RLC_CATCH_ANY { + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + } + code = RLC_OK; + end: + ep8_free(a); + ep8_free(b); + ep8_free(c); + return code; +} - if (compression2() != RLC_OK) { - core_clean(); - return 1; - } +static int addition8(void) { + int code = RLC_ERR; + ep8_t a, b, c, d, e; - if (hashing2() != RLC_OK) { - core_clean(); - return 1; - } + ep8_null(a); + ep8_null(b); + ep8_null(c); + ep8_null(d); + ep8_null(e); - if (frobenius2() != RLC_OK) { - core_clean(); - return 1; - } - } + RLC_TRY { + ep8_new(a); + ep8_new(b); + ep8_new(c); + ep8_new(d); + ep8_new(e); - if ((r1 = ep3_curve_is_twist())) { - ep_param_print(); + TEST_CASE("point addition is commutative") { + ep8_rand(a); + ep8_rand(b); + ep8_add(d, a, b); + ep8_add(e, b, a); + TEST_ASSERT(ep8_cmp(d, e) == RLC_EQ, end); + } TEST_END; - util_banner("Utilities:", 1); + TEST_CASE("point addition is associative") { + ep8_rand(a); + ep8_rand(b); + ep8_rand(c); + ep8_add(d, a, b); + ep8_add(d, d, c); + ep8_add(e, b, c); + ep8_add(e, e, a); + TEST_ASSERT(ep8_cmp(d, e) == RLC_EQ, end); + } TEST_END; - if (memory3() != RLC_OK) { - core_clean(); - return 1; - } + TEST_CASE("point addition has identity") { + ep8_rand(a); + ep8_set_infty(d); + ep8_add(e, a, d); + TEST_ASSERT(ep8_cmp(e, a) == RLC_EQ, end); + ep8_add(e, d, a); + TEST_ASSERT(ep8_cmp(e, a) == RLC_EQ, end); + } TEST_END; - if (util3() != RLC_OK) { - core_clean(); - return 1; - } + TEST_CASE("point addition has inverse") { + ep8_rand(a); + ep8_neg(d, a); + ep8_add(e, a, d); + TEST_ASSERT(ep8_is_infty(e), end); + } TEST_END; - util_banner("Arithmetic:", 1); +#if EP_ADD == BASIC || !defined(STRIP) + TEST_CASE("point addition in affine coordinates is correct") { + ep8_rand(a); + ep8_rand(b); + ep8_add(d, a, b); + ep8_add_basic(e, a, b); + TEST_ASSERT(ep8_cmp(e, d) == RLC_EQ, end); + } TEST_END; +#endif - if (addition3() != RLC_OK) { - core_clean(); - return 1; - } +#if EP_ADD == PROJC || !defined(STRIP) +#if !defined(EP_MIXED) || !defined(STRIP) + TEST_CASE("point addition in projective coordinates is correct") { + ep8_rand(a); + ep8_rand(b); + ep8_rand(c); + ep8_add_projc(a, a, b); + ep8_add_projc(b, b, c); + /* a and b in projective coordinates. */ + ep8_add_projc(d, a, b); + /* normalize before mixing coordinates. */ + 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 - if (subtraction3() != RLC_OK) { - core_clean(); - return 1; - } + 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_projc(a, a, b); + ep8_add_projc(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; - if (doubling3() != RLC_OK) { - core_clean(); - return 1; - } + TEST_CASE("point addition in mixed coordinates (z1,z2 = 1) is correct") { + ep8_rand(a); + ep8_rand(b); + /* a and b in affine coordinates. */ + ep8_add(d, a, b); + ep8_add_projc(e, a, b); + TEST_ASSERT(ep8_cmp(d, e) == RLC_EQ, end); + } TEST_END; +#endif - if (multiplication3() != RLC_OK) { - core_clean(); - return 1; - } + } + RLC_CATCH_ANY { + RLC_ERROR(end); + } + code = RLC_OK; + end: + ep8_free(a); + ep8_free(b); + ep8_free(c); + ep8_free(d); + ep8_free(e); + return code; +} - if (fixed3() != RLC_OK) { - core_clean(); - return 1; - } +static int subtraction8(void) { + int code = RLC_ERR; + ep8_t a, b, c, d; - if (simultaneous3() != RLC_OK) { - core_clean(); - return 1; + ep8_null(a); + ep8_null(b); + ep8_null(c); + ep8_null(d); + + RLC_TRY { + ep8_new(a); + ep8_new(b); + ep8_new(c); + ep8_new(d); + + TEST_CASE("point subtraction is anti-commutative") { + ep8_rand(a); + ep8_rand(b); + ep8_sub(c, a, b); + ep8_sub(d, b, a); + ep8_neg(d, d); + TEST_ASSERT(ep8_cmp(c, d) == RLC_EQ, end); } + TEST_END; - if (hashing3() != RLC_OK) { - core_clean(); - return 1; + TEST_CASE("point subtraction has identity") { + ep8_rand(a); + ep8_set_infty(c); + ep8_sub(d, a, c); + TEST_ASSERT(ep8_cmp(d, a) == RLC_EQ, end); } + TEST_END; - if (frobenius3() != RLC_OK) { - core_clean(); - return 1; + TEST_CASE("point subtraction has inverse") { + ep8_rand(a); + ep8_sub(c, a, a); + TEST_ASSERT(ep8_is_infty(c), end); } + TEST_END; } + RLC_CATCH_ANY { + RLC_ERROR(end); + } + code = RLC_OK; + end: + ep8_free(a); + ep8_free(b); + ep8_free(c); + ep8_free(d); + return code; +} - if ((r2 = ep4_curve_is_twist())) { - ep_param_print(); - - util_banner("Utilities:", 1); +static int doubling8(void) { + int code = RLC_ERR; + ep8_t a, b, c; - if (memory4() != RLC_OK) { - core_clean(); - return 1; - } + ep8_null(a); + ep8_null(b); + ep8_null(c); - if (util4() != RLC_OK) { - core_clean(); - return 1; - } + RLC_TRY { + ep8_new(a); + ep8_new(b); + ep8_new(c); - util_banner("Arithmetic:", 1); + TEST_CASE("point doubling is correct") { + ep8_rand(a); + ep8_add(b, a, a); + ep8_dbl(c, a); + TEST_ASSERT(ep8_cmp(b, c) == RLC_EQ, end); + } TEST_END; - if (addition4() != RLC_OK) { - core_clean(); - return 1; - } +#if EP_ADD == BASIC || !defined(STRIP) + TEST_CASE("point doubling in affine coordinates is correct") { + ep8_rand(a); + ep8_dbl(b, a); + ep8_dbl_basic(c, a); + TEST_ASSERT(ep8_cmp(b, c) == RLC_EQ, end); + } TEST_END; +#endif + +#if EP_ADD == PROJC || !defined(STRIP) + TEST_CASE("point doubling in projective coordinates is correct") { + ep8_rand(a); + /* a in projective coordinates. */ + ep8_dbl_projc(a, a); + ep8_dbl_projc(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_projc(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); + } + code = RLC_OK; + end: + ep8_free(a); + ep8_free(b); + ep8_free(c); + return code; +} + +static int multiplication8(void) { + int code = RLC_ERR; + bn_t n, k; + ep8_t p, q, r; + + bn_null(n); + bn_null(k); + ep8_null(p); + ep8_null(q); + ep8_null(r); + + RLC_TRY { + bn_new(n); + bn_new(k); + ep8_new(p); + ep8_new(q); + ep8_new(r); + + ep8_curve_get_gen(p); + ep8_curve_get_ord(n); + + TEST_ONCE("generator has the right order") { + TEST_ASSERT(ep8_on_curve(p), end); + ep8_mul(r, p, n); + TEST_ASSERT(ep8_is_infty(r) == 1, end); + } TEST_END; + + TEST_CASE("generator multiplication is correct") { + bn_zero(k); + ep8_mul_gen(r, k); + TEST_ASSERT(ep8_is_infty(r), end); + bn_set_dig(k, 1); + ep8_mul_gen(r, k); + TEST_ASSERT(ep8_cmp(p, r) == RLC_EQ, end); + bn_rand_mod(k, n); + ep8_mul(q, p, k); + ep8_mul_gen(r, k); + TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end); + bn_neg(k, k); + ep8_mul_gen(r, k); + ep8_neg(r, r); + TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end); + bn_rand_mod(k, n); + ep8_mul_gen(q, k); + bn_add(k, k, n); + ep8_mul_gen(r, k); + TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end); + } TEST_END; + +#if EP_MUL == BASIC || !defined(STRIP) + TEST_CASE("binary point multiplication is correct") { + bn_zero(k); + ep8_mul_basic(r, p, k); + TEST_ASSERT(ep8_is_infty(r), end); + bn_set_dig(k, 1); + ep8_mul_basic(r, p, k); + TEST_ASSERT(ep8_cmp(p, r) == RLC_EQ, end); + ep8_rand(p); + ep8_mul(r, p, n); + TEST_ASSERT(ep8_is_infty(r), end); + bn_rand_mod(k, n); + ep8_mul(q, p, k); + ep8_mul_basic(r, p, k); + TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end); + bn_neg(k, k); + ep8_mul_basic(r, p, k); + ep8_neg(r, r); + TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end); + } TEST_END; +#endif + +#if EP_MUL == MONTY || !defined(STRIP) + TEST_CASE("sliding window point multiplication is correct") { + bn_zero(k); + ep8_mul_slide(r, p, k); + TEST_ASSERT(ep8_is_infty(r), end); + bn_set_dig(k, 1); + ep8_mul_slide(r, p, k); + TEST_ASSERT(ep8_cmp(p, r) == RLC_EQ, end); + ep8_rand(p); + ep8_mul(r, p, n); + TEST_ASSERT(ep8_is_infty(r), end); + bn_rand_mod(k, n); + ep8_mul(q, p, k); + ep8_mul_slide(r, p, k); + TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end); + bn_neg(k, k); + ep8_mul_slide(r, p, k); + ep8_neg(r, r); + TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end); + } + TEST_END; +#endif + +#if EP_MUL == MONTY || !defined(STRIP) + TEST_CASE("montgomery ladder point multiplication is correct") { + bn_zero(k); + ep8_mul_monty(r, p, k); + TEST_ASSERT(ep8_is_infty(r), end); + bn_set_dig(k, 1); + ep8_mul_monty(r, p, k); + TEST_ASSERT(ep8_cmp(p, r) == RLC_EQ, end); + ep8_rand(p); + ep8_mul(r, p, n); + TEST_ASSERT(ep8_is_infty(r), end); + bn_rand_mod(k, n); + ep8_mul(q, p, k); + ep8_mul_monty(r, p, k); + TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end); + bn_neg(k, k); + ep8_mul_monty(r, p, k); + ep8_neg(r, r); + TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end); + } + TEST_END; +#endif + +#if EP_MUL == LWNAF || !defined(STRIP) + TEST_CASE("left-to-right w-naf point multiplication is correct") { + bn_zero(k); + ep8_mul_lwnaf(r, p, k); + TEST_ASSERT(ep8_is_infty(r), end); + bn_set_dig(k, 1); + ep8_mul_lwnaf(r, p, k); + TEST_ASSERT(ep8_cmp(p, r) == RLC_EQ, end); + ep8_rand(p); + ep8_mul(r, p, n); + TEST_ASSERT(ep8_is_infty(r), end); + bn_rand_mod(k, n); + ep8_mul(q, p, k); + ep8_mul_lwnaf(r, p, k); + TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end); + bn_neg(k, k); + ep8_mul_lwnaf(r, p, k); + ep8_neg(r, r); + 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); + ep8_mul_dig(r, p, 1); + TEST_ASSERT(ep8_cmp(p, r) == RLC_EQ, end); + bn_rand(k, RLC_POS, RLC_DIG); + ep8_mul(q, p, k); + ep8_mul_dig(r, p, k->dp[0]); + TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end); + } + TEST_END; + } + RLC_CATCH_ANY { + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + } + code = RLC_OK; + end: + bn_free(n); + bn_free(k); + ep8_free(p); + ep8_free(q); + ep8_free(r); + return code; +} + +static int fixed8(void) { + int code = RLC_ERR; + bn_t n, k; + ep8_t p, q, r, t[RLC_EPX_TABLE_MAX]; + + bn_null(n); + bn_null(k); + ep8_null(p); + ep8_null(q); + ep8_null(r); + + for (int i = 0; i < RLC_EPX_TABLE_MAX; i++) { + ep8_null(t[i]); + } + + RLC_TRY { + bn_new(n); + bn_new(k); + ep8_new(p); + ep8_new(q); + ep8_new(r); + + ep8_curve_get_gen(p); + ep8_curve_get_ord(n); + + for (int i = 0; i < RLC_EP_TABLE; i++) { + ep8_new(t[i]); + } + TEST_CASE("fixed point multiplication is correct") { + ep8_rand(p); + ep8_mul_pre(t, p); + bn_zero(k); + ep8_mul_fix(r, t, k); + TEST_ASSERT(ep8_is_infty(r), end); + bn_set_dig(k, 1); + ep8_mul_fix(r, t, k); + TEST_ASSERT(ep8_cmp(p, r) == RLC_EQ, end); + bn_rand_mod(k, n); + ep8_mul(q, p, k); + ep8_mul_fix(q, t, k); + ep8_mul(r, p, k); + TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end); + bn_neg(k, k); + ep8_mul_fix(r, t, k); + ep8_neg(r, r); + TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end); + } TEST_END; + for (int i = 0; i < RLC_EP_TABLE; i++) { + ep8_free(t[i]); + } + +#if EP_FIX == BASIC || !defined(STRIP) + for (int i = 0; i < RLC_EP_TABLE_BASIC; i++) { + ep8_new(t[i]); + } + TEST_CASE("binary fixed point multiplication is correct") { + ep8_rand(p); + ep8_mul_pre_basic(t, p); + bn_zero(k); + ep8_mul_fix_basic(r, t, k); + TEST_ASSERT(ep8_is_infty(r), end); + bn_set_dig(k, 1); + ep8_mul_fix_basic(r, t, k); + TEST_ASSERT(ep8_cmp(p, r) == RLC_EQ, end); + bn_rand_mod(k, n); + ep8_mul(r, p, k); + ep8_mul_fix_basic(q, t, k); + TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end); + bn_neg(k, k); + ep8_mul_fix_basic(r, t, k); + ep8_neg(r, r); + TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end); + } TEST_END; + for (int i = 0; i < RLC_EP_TABLE_BASIC; i++) { + ep8_free(t[i]); + } +#endif + +#if EP_FIX == COMBS || !defined(STRIP) + for (int i = 0; i < RLC_EP_TABLE_COMBS; i++) { + ep8_new(t[i]); + } + TEST_CASE("single-table comb fixed point multiplication is correct") { + ep8_rand(p); + ep8_mul_pre_combs(t, p); + bn_zero(k); + ep8_mul_fix_combs(r, t, k); + TEST_ASSERT(ep8_is_infty(r), end); + bn_set_dig(k, 1); + ep8_mul_fix_combs(r, t, k); + TEST_ASSERT(ep8_cmp(p, r) == RLC_EQ, end); + bn_rand_mod(k, n); + ep8_mul(r, p, k); + ep8_mul_fix_combs(q, t, k); + TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end); + bn_neg(k, k); + ep8_mul_fix_combs(r, t, k); + ep8_neg(r, r); + TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end); + } TEST_END; + for (int i = 0; i < RLC_EP_TABLE_COMBS; i++) { + ep8_free(t[i]); + } +#endif + +#if EP_FIX == COMBD || !defined(STRIP) + for (int i = 0; i < RLC_EP_TABLE_COMBD; i++) { + ep8_new(t[i]); + } + TEST_CASE("double-table comb fixed point multiplication is correct") { + ep8_rand(p); + ep8_mul_pre_combd(t, p); + bn_zero(k); + ep8_mul_fix_combd(r, t, k); + TEST_ASSERT(ep8_is_infty(r), end); + bn_set_dig(k, 1); + ep8_mul_fix_combd(r, t, k); + TEST_ASSERT(ep8_cmp(p, r) == RLC_EQ, end); + bn_rand_mod(k, n); + ep8_mul(r, p, k); + ep8_mul_fix_combd(q, t, k); + TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end); + bn_neg(k, k); + ep8_mul_fix_combd(r, t, k); + ep8_neg(r, r); + TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end); + } TEST_END; + for (int i = 0; i < RLC_EP_TABLE_COMBD; i++) { + ep8_free(t[i]); + } +#endif + +#if EP_FIX == LWNAF || !defined(STRIP) + for (int i = 0; i < RLC_EP_TABLE_LWNAF; i++) { + ep8_new(t[i]); + } + TEST_CASE("left-to-right w-naf fixed point multiplication is correct") { + ep8_rand(p); + ep8_mul_pre_lwnaf(t, p); + bn_zero(k); + ep8_mul_fix_lwnaf(r, t, k); + TEST_ASSERT(ep8_is_infty(r), end); + bn_set_dig(k, 1); + ep8_mul_fix_lwnaf(r, t, k); + TEST_ASSERT(ep8_cmp(p, r) == RLC_EQ, end); + bn_rand_mod(k, n); + ep8_mul(r, p, k); + ep8_mul_fix_lwnaf(q, t, k); + TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end); + bn_neg(k, k); + ep8_mul_fix_lwnaf(r, t, k); + ep8_neg(r, r); + TEST_ASSERT(ep8_cmp(q, r) == RLC_EQ, end); + } TEST_END; + for (int i = 0; i < RLC_EP_TABLE_LWNAF; i++) { + ep8_free(t[i]); + } +#endif + } + RLC_CATCH_ANY { + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + } + code = RLC_OK; + end: + ep8_free(p); + ep8_free(q); + ep8_free(r); + bn_free(n); + bn_free(k); + return code; +} + +static int simultaneous8(void) { + int code = RLC_ERR; + bn_t n, k[2]; + ep8_t p[2], r; + + bn_null(n); + bn_null(k[0]); + bn_null(k[1]); + ep8_null(p[0]); + ep8_null(p[1]); + ep8_null(r); + + RLC_TRY { + bn_new(n); + bn_new(k[0]); + bn_new(k[1]); + ep8_new(p[0]); + ep8_new(p[1]); + ep8_new(r); + + ep8_curve_get_gen(p[0]); + ep8_curve_get_ord(n); + + TEST_CASE("simultaneous point multiplication is correct") { + bn_zero(k[0]); + bn_rand_mod(k[1], n); + ep8_mul(p[1], p[0], k[1]); + ep8_mul_sim(r, p[0], k[0], p[0], k[1]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_rand_mod(k[0], n); + bn_zero(k[1]); + ep8_mul(p[1], p[0], k[0]); + ep8_mul_sim(r, p[0], k[0], p[0], k[1]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_rand_mod(k[0], n); + bn_rand_mod(k[1], n); + ep8_mul_sim(r, p[0], k[0], p[1], k[1]); + ep8_mul(p[0], p[0], k[0]); + ep8_mul(p[1], p[1], k[1]); + ep8_add(p[1], p[1], p[0]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_neg(k[0], k[0]); + ep8_mul_sim(r, p[0], k[0], p[1], k[1]); + ep8_mul(p[0], p[0], k[0]); + ep8_mul(p[1], p[1], k[1]); + ep8_add(p[1], p[1], p[0]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_neg(k[1], k[1]); + ep8_mul_sim(r, p[0], k[0], p[1], k[1]); + ep8_mul(p[0], p[0], k[0]); + ep8_mul(p[1], p[1], k[1]); + ep8_add(p[1], p[1], p[0]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + ep8_mul_sim(r, p[0], k[0], p[1], k[1]); + ep8_mul_sim_lot(p[1], p, k, 2); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + } TEST_END; + +#if EP_SIM == BASIC || !defined(STRIP) + TEST_CASE("basic simultaneous point multiplication is correct") { + bn_zero(k[0]); + bn_rand_mod(k[1], n); + ep8_mul(p[1], p[0], k[1]); + ep8_mul_sim_basic(r, p[0], k[0], p[0], k[1]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_rand_mod(k[0], n); + bn_zero(k[1]); + ep8_mul(p[1], p[0], k[0]); + ep8_mul_sim_basic(r, p[0], k[0], p[0], k[1]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_rand_mod(k[0], n); + bn_rand_mod(k[1], n); + ep8_mul_sim_basic(r, p[0], k[0], p[1], k[1]); + ep8_mul(p[0], p[0], k[0]); + ep8_mul(p[1], p[1], k[1]); + ep8_add(p[1], p[1], p[0]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_neg(k[0], k[0]); + ep8_mul_sim_basic(r, p[0], k[0], p[1], k[1]); + ep8_mul(p[0], p[0], k[0]); + ep8_mul(p[1], p[1], k[1]); + ep8_add(p[1], p[1], p[0]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_neg(k[1], k[1]); + ep8_mul_sim_basic(r, p[0], k[0], p[1], k[1]); + ep8_mul(p[0], p[0], k[0]); + ep8_mul(p[1], p[1], k[1]); + ep8_add(p[1], p[1], p[0]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + } TEST_END; +#endif + +#if EP_SIM == TRICK || !defined(STRIP) + TEST_CASE("shamir's trick for simultaneous multiplication is correct") { + bn_zero(k[0]); + bn_rand_mod(k[1], n); + ep8_mul(p[1], p[0], k[1]); + ep8_mul_sim_trick(r, p[0], k[0], p[0], k[1]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_rand_mod(k[0], n); + bn_zero(k[1]); + ep8_mul(p[1], p[0], k[0]); + ep8_mul_sim_trick(r, p[0], k[0], p[0], k[1]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_rand_mod(k[0], n); + bn_rand_mod(k[1], n); + ep8_mul_sim_trick(r, p[0], k[0], p[1], k[1]); + ep8_mul(p[0], p[0], k[0]); + ep8_mul(p[1], p[1], k[1]); + ep8_add(p[1], p[1], p[0]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_neg(k[0], k[0]); + ep8_mul_sim_trick(r, p[0], k[0], p[1], k[1]); + ep8_mul(p[0], p[0], k[0]); + ep8_mul(p[1], p[1], k[1]); + ep8_add(p[1], p[1], p[0]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_neg(k[1], k[1]); + ep8_mul_sim_trick(r, p[0], k[0], p[1], k[1]); + ep8_mul(p[0], p[0], k[0]); + ep8_mul(p[1], p[1], k[1]); + ep8_add(p[1], p[1], p[0]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + } TEST_END; +#endif + +#if EP_SIM == INTER || !defined(STRIP) + TEST_CASE("interleaving for simultaneous multiplication is correct") { + bn_zero(k[0]); + bn_rand_mod(k[1], n); + ep8_mul(p[1], p[0], k[1]); + ep8_mul_sim_inter(r, p[0], k[0], p[0], k[1]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_rand_mod(k[0], n); + bn_zero(k[1]); + ep8_mul(p[1], p[0], k[0]); + ep8_mul_sim_inter(r, p[0], k[0], p[0], k[1]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_rand_mod(k[0], n); + bn_rand_mod(k[1], n); + ep8_mul_sim_inter(r, p[0], k[0], p[1], k[1]); + ep8_mul(p[0], p[0], k[0]); + ep8_mul(p[1], p[1], k[1]); + ep8_add(p[1], p[1], p[0]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_neg(k[0], k[0]); + ep8_mul_sim_inter(r, p[0], k[0], p[1], k[1]); + ep8_mul(p[0], p[0], k[0]); + ep8_mul(p[1], p[1], k[1]); + ep8_add(p[1], p[1], p[0]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_neg(k[1], k[1]); + ep8_mul_sim_inter(r, p[0], k[0], p[1], k[1]); + ep8_mul(p[0], p[0], k[0]); + ep8_mul(p[1], p[1], k[1]); + ep8_add(p[1], p[1], p[0]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + } TEST_END; +#endif + +#if EP_SIM == JOINT || !defined(STRIP) + TEST_CASE("jsf for simultaneous multiplication is correct") { + bn_zero(k[0]); + bn_rand_mod(k[1], n); + ep8_mul(p[1], p[0], k[1]); + ep8_mul_sim_joint(r, p[0], k[0], p[0], k[1]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_rand_mod(k[0], n); + bn_zero(k[1]); + ep8_mul(p[1], p[0], k[0]); + ep8_mul_sim_joint(r, p[0], k[0], p[0], k[1]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_rand_mod(k[0], n); + bn_rand_mod(k[1], n); + ep8_mul_sim_joint(r, p[0], k[0], p[1], k[1]); + ep8_mul(p[0], p[0], k[0]); + ep8_mul(p[1], p[1], k[1]); + ep8_add(p[1], p[1], p[0]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_neg(k[0], k[0]); + ep8_mul_sim_joint(r, p[0], k[0], p[1], k[1]); + ep8_mul(p[0], p[0], k[0]); + ep8_mul(p[1], p[1], k[1]); + ep8_add(p[1], p[1], p[0]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_neg(k[1], k[1]); + ep8_mul_sim_joint(r, p[0], k[0], p[1], k[1]); + ep8_mul(p[0], p[0], k[0]); + ep8_mul(p[1], p[1], k[1]); + ep8_add(p[1], p[1], p[0]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + } TEST_END; +#endif + + TEST_CASE("simultaneous multiplication with generator is correct") { + bn_zero(k[0]); + bn_rand_mod(k[1], n); + ep8_mul(p[1], p[0], k[1]); + ep8_mul_sim_gen(r, k[0], p[0], k[1]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_rand_mod(k[0], n); + bn_zero(k[1]); + ep8_mul_gen(p[1], k[0]); + ep8_mul_sim_gen(r, k[0], p[0], k[1]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_rand_mod(k[0], n); + bn_rand_mod(k[1], n); + ep8_mul_sim_gen(r, k[0], p[1], k[1]); + ep8_curve_get_gen(p[0]); + ep8_mul_sim(p[1], p[0], k[0], p[1], k[1]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_neg(k[0], k[0]); + ep8_mul_sim_gen(r, k[0], p[1], k[1]); + ep8_curve_get_gen(p[0]); + ep8_mul_sim(p[1], p[0], k[0], p[1], k[1]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + bn_neg(k[1], k[1]); + ep8_mul_sim_gen(r, k[0], p[1], k[1]); + ep8_curve_get_gen(p[0]); + ep8_mul_sim(p[1], p[0], k[0], p[1], k[1]); + TEST_ASSERT(ep8_cmp(p[1], r) == RLC_EQ, end); + } TEST_END; + } + RLC_CATCH_ANY { + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + } + code = RLC_OK; + end: + bn_free(n); + bn_free(k[0]); + bn_free(k[1]); + ep8_free(p[0]); + ep8_free(p[1]); + ep8_free(r); + return code; +} + +static int hashing8(void) { + int code = RLC_ERR; + bn_t n; + ep8_t p; + uint8_t msg[5]; + + bn_null(n); + ep8_null(p); + + RLC_TRY { + bn_new(n); + ep8_new(p); + + ep8_curve_get_ord(n); + + TEST_CASE("point hashing is correct") { + rand_bytes(msg, sizeof(msg)); + ep8_map(p, msg, sizeof(msg)); + TEST_ASSERT(ep8_on_curve(p) == 1, end); + ep8_mul(p, p, n); + TEST_ASSERT(ep8_is_infty(p) == 1, end); + } + TEST_END; + } + RLC_CATCH_ANY { + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + } + code = RLC_OK; + end: + bn_free(n); + ep8_free(p); + return code; +} + +static int frobenius8(void) { + int code = RLC_ERR; + ep8_t a, b, c; + bn_t d, n; + + ep8_null(a); + ep8_null(b); + ep8_null(c); + bn_null(d); + bn_null(n); + + RLC_TRY { + ep8_new(a); + ep8_new(b); + ep8_new(c); + bn_new(d); + bn_new(n); + + ep8_curve_get_ord(n); + + TEST_CASE("frobenius and point multiplication are consistent") { + ep8_rand(a); + ep8_frb(b, a, 1); + d->used = RLC_FP_DIGS; + dv_copy(d->dp, fp_prime_get(), RLC_FP_DIGS); + bn_mod(d, d, n); + ep8_mul(c, a, d); + TEST_ASSERT(ep8_cmp(c, b) == RLC_EQ, end); + } TEST_END; + } + RLC_CATCH_ANY { + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + } + code = RLC_OK; + end: + ep8_free(a); + ep8_free(b); + ep8_free(c); + bn_free(d); + bn_free(n); + return code; +} + +int main(void) { + int r0, r1, r2, r3; + + if (core_init() != RLC_OK) { + core_clean(); + return 1; + } + + util_banner("Tests for the EPX module", 0); + + if (ep_param_set_any_pairf() == RLC_ERR) { + RLC_THROW(ERR_NO_CURVE); + core_clean(); + return 0; + } + + if ((r0 = ep2_curve_is_twist())) { + ep_param_print(); + + util_banner("Utilities:", 1); + + if (memory2() != RLC_OK) { + core_clean(); + return 1; + } + + if (util2() != RLC_OK) { + core_clean(); + return 1; + } + + util_banner("Arithmetic:", 1); + + if (addition2() != RLC_OK) { + core_clean(); + return 1; + } + + if (subtraction2() != RLC_OK) { + core_clean(); + return 1; + } + + if (doubling2() != RLC_OK) { + core_clean(); + return 1; + } + + if (multiplication2() != RLC_OK) { + core_clean(); + return 1; + } + + if (fixed2() != RLC_OK) { + core_clean(); + return 1; + } + + if (simultaneous2() != RLC_OK) { + core_clean(); + return 1; + } + + if (compression2() != RLC_OK) { + core_clean(); + return 1; + } + + if (hashing2() != RLC_OK) { + core_clean(); + return 1; + } + + if (frobenius2() != RLC_OK) { + core_clean(); + return 1; + } + } + + if ((r1 = ep3_curve_is_twist())) { + ep_param_print(); + + util_banner("Utilities:", 1); + + if (memory3() != RLC_OK) { + core_clean(); + return 1; + } + + if (util3() != RLC_OK) { + core_clean(); + return 1; + } + + util_banner("Arithmetic:", 1); + + if (addition3() != RLC_OK) { + core_clean(); + return 1; + } + + if (subtraction3() != RLC_OK) { + core_clean(); + return 1; + } + + if (doubling3() != RLC_OK) { + core_clean(); + return 1; + } + + if (multiplication3() != RLC_OK) { + core_clean(); + return 1; + } + + if (fixed3() != RLC_OK) { + core_clean(); + return 1; + } + + if (simultaneous3() != RLC_OK) { + core_clean(); + return 1; + } + + if (hashing3() != RLC_OK) { + core_clean(); + return 1; + } + + if (frobenius3() != RLC_OK) { + core_clean(); + return 1; + } + } + + if ((r2 = ep4_curve_is_twist())) { + ep_param_print(); + + util_banner("Utilities:", 1); + + if (memory4() != RLC_OK) { + core_clean(); + return 1; + } + + if (util4() != RLC_OK) { + core_clean(); + return 1; + } + + util_banner("Arithmetic:", 1); + + if (addition4() != RLC_OK) { + core_clean(); + return 1; + } if (subtraction4() != RLC_OK) { core_clean(); @@ -3427,7 +4487,65 @@ int main(void) { } } - if (!r0 && !r1 && !r2) { + if ((r3 = ep8_curve_is_twist())) { + ep_param_print(); + + util_banner("Utilities:", 1); + + if (memory8() != RLC_OK) { + core_clean(); + return 1; + } + + if (util8() != RLC_OK) { + core_clean(); + return 1; + } + + util_banner("Arithmetic:", 1); + + if (addition8() != RLC_OK) { + core_clean(); + return 1; + } + + if (subtraction8() != RLC_OK) { + core_clean(); + return 1; + } + + if (doubling8() != RLC_OK) { + core_clean(); + return 1; + } + + if (multiplication8() != RLC_OK) { + core_clean(); + return 1; + } + + if (fixed8() != RLC_OK) { + core_clean(); + return 1; + } + + if (simultaneous8() != RLC_OK) { + core_clean(); + return 1; + } + + if (frobenius8() != RLC_OK) { + core_clean(); + return 1; + } + + if (hashing8() != RLC_OK) { + core_clean(); + return 1; + } + } + + if (!r0 && !r1 && !r2 && !r3) { RLC_THROW(ERR_NO_CURVE); core_clean(); return 0; diff --git a/test/test_fp.c b/test/test_fp.c index 53cddcbfd..a25936fc5 100644 --- a/test/test_fp.c +++ b/test/test_fp.c @@ -799,6 +799,9 @@ static int inversion(void) { fp_inv(b, a); fp_mul(c, a, b); TEST_ASSERT(fp_cmp_dig(c, 1) == RLC_EQ, end); + fp_set_dig(a, 1); + fp_inv(b, a); + TEST_ASSERT(fp_cmp_dig(b, 1) == RLC_EQ, end); } TEST_END; #if FP_INV == BASIC || !defined(STRIP) @@ -935,6 +938,7 @@ static int symbol(void) { TEST_ASSERT(fp_smb(a) == fp_smb_basic(a), end); } TEST_END; #endif + #if FP_SMB == DIVST || !defined(STRIP) TEST_CASE("division step symbol computation is correct") { fp_rand(a); @@ -1060,6 +1064,19 @@ static int square_root(void) { fp_new(b); fp_new(c); + TEST_CASE("quadratic residuosity test is correct") { + fp_zero(a); + TEST_ASSERT(fp_is_sqr(a) == 1, end); + fp_rand(a); + fp_sqr(a, a); + TEST_ASSERT(fp_is_sqr(a) == 1, end); + do { + fp_rand(a); + } while(fp_srt(b, a) == 1); + TEST_ASSERT(fp_is_sqr(a) == 0, end); + } + TEST_END; + TEST_CASE("square root extraction is correct") { fp_rand(a); fp_sqr(c, a); @@ -1071,6 +1088,10 @@ static int square_root(void) { fp_sqr(c, b); TEST_ASSERT(fp_cmp(c, a) == RLC_EQ, end); } + do { + fp_rand(a); + } while(fp_is_sqr(a) == 1); + TEST_ASSERT(fp_srt(b, a) == 0, end); } TEST_END; } @@ -1085,21 +1106,101 @@ static int square_root(void) { return code; } +static int cube_root(void) { + int code = RLC_ERR; + fp_t a, b, c, d; + + fp_null(a); + fp_null(b); + fp_null(c); + fp_null(d); + + RLC_TRY { + fp_new(a); + fp_new(b); + fp_new(c); + fp_new(d); + + TEST_CASE("cubic residuosity test is correct") { + fp_zero(a); + TEST_ASSERT(fp_is_cub(a) == 1, end); + fp_rand(a); + fp_sqr(b, a); + fp_mul(a, a, b); + TEST_ASSERT(fp_is_cub(a) == 1, end); + /* If p = 2 mod 3, all elements are cubic residues. */ + if (fp_prime_get_mod18() % 3 != 2) { + do { + fp_rand(a); + } while(fp_crt(b, a) == 1); + TEST_ASSERT(fp_is_cub(a) == 0, end); + } + } + TEST_END; + + TEST_CASE("cube root extraction is correct") { + int r = 1; + fp_rand(a); + fp_sqr(c, a); + fp_mul(c, c, a); + TEST_ASSERT(fp_crt(b, c), end); + if (fp_prime_get_cnr()) { + fp_copy(d, fp_prime_get_crt()); + while (fp_cmp_dig(d, 1) != RLC_EQ) { + fp_copy(c, d); + fp_sqr(d, d); + fp_mul(d, d, c); + } + if (fp_cmp(b, a) != RLC_EQ) { + fp_mul(b, b, c); + if (fp_cmp(b, a) != RLC_EQ) { + fp_mul(b, b, c); + if (fp_cmp(b, a) != RLC_EQ) { + r = 0; + } + } + } + TEST_ASSERT(r == 1, end); + } + fp_rand(a); + if (fp_crt(b, a)) { + fp_sqr(c, b); + fp_mul(c, c, b); + TEST_ASSERT(fp_cmp(c, a) == RLC_EQ, end); + } + } + TEST_END; + } + RLC_CATCH_ANY { + RLC_ERROR(end); + } + code = RLC_OK; + end: + fp_free(a); + fp_free(b); + fp_free(c); + fp_free(d); + return code; +} + static int digit(void) { int code = RLC_ERR; fp_t a, b, c, d; dig_t g; + bn_t e; fp_null(a); fp_null(b); fp_null(c); fp_null(d); + bn_null(e); RLC_TRY { fp_new(a); fp_new(b); fp_new(c); fp_new(d); + bn_new(e); TEST_CASE("addition of a single digit is consistent") { fp_rand(a); @@ -1130,6 +1231,15 @@ static int digit(void) { fp_mul_dig(d, a, g); TEST_ASSERT(fp_cmp(c, d) == RLC_EQ, end); } TEST_END; + + TEST_CASE("exponentiation by a single digit is consistent") { + fp_rand(a); + bn_rand(e, RLC_POS, RLC_DIG); + fp_exp_dig(b, a, e->dp[0]); + fp_exp(c, a, e); + TEST_ASSERT(fp_cmp(b, c) == RLC_EQ, end); + } TEST_END; + } RLC_CATCH_ANY { RLC_ERROR(end); @@ -1140,6 +1250,7 @@ static int digit(void) { fp_free(b); fp_free(c); fp_free(d); + bn_free(e); return code; } @@ -1226,6 +1337,11 @@ int main(void) { return 1; } + if (cube_root() != RLC_OK) { + core_clean(); + return 1; + } + if (digit() != RLC_OK) { core_clean(); return 1; diff --git a/test/test_fpx.c b/test/test_fpx.c index 378fe9cbb..2bac3ff4e 100644 --- a/test/test_fpx.c +++ b/test/test_fpx.c @@ -783,6 +783,19 @@ static int square_root2(void) { fp2_new(b); fp2_new(c); + TEST_CASE("quadratic residuosity test is correct") { + fp2_zero(a); + TEST_ASSERT(fp2_is_sqr(a) == 1, end); + fp2_rand(a); + fp2_sqr(a, a); + TEST_ASSERT(fp2_is_sqr(a) == 1, end); + do { + fp2_rand(a); + } while(fp2_srt(b, a) == 1); + TEST_ASSERT(fp2_is_sqr(a) == 0, end); + } + TEST_END; + TEST_CASE("square root extraction is correct") { fp2_zero(a); fp2_sqr(c, a); @@ -813,6 +826,10 @@ static int square_root2(void) { TEST_ASSERT(r, end); TEST_ASSERT(fp2_cmp(b, a) == RLC_EQ || fp2_cmp(c, a) == RLC_EQ, end); + do { + fp2_rand(a); + } while(fp2_is_sqr(a) == 1); + TEST_ASSERT(fp2_srt(b, a) == 0, end); } TEST_END; } RLC_CATCH_ANY { @@ -1509,7 +1526,6 @@ static int exponentiation3(void) { static int square_root3(void) { int code = RLC_ERR; fp3_t a, b, c; - int r; fp3_null(a); fp3_null(b); @@ -1520,14 +1536,36 @@ static int square_root3(void) { fp3_new(b); fp3_new(c); + TEST_CASE("quadratic residuosity test is correct") { + fp3_zero(a); + TEST_ASSERT(fp3_is_sqr(a) == 1, end); + fp3_rand(a); + fp3_sqr(a, a); + TEST_ASSERT(fp3_is_sqr(a) == 1, end); + do { + fp3_rand(a); + } while(fp3_srt(b, a) == 1); + TEST_ASSERT(fp3_is_sqr(a) == 0, end); + } + TEST_END; + TEST_CASE("square root extraction is correct") { fp3_rand(a); fp3_sqr(c, a); - r = fp3_srt(b, c); - fp3_sqr(b, b); - TEST_ASSERT(r == 1, end); - TEST_ASSERT(fp3_cmp(b, c) == RLC_EQ, end); - } TEST_END; + TEST_ASSERT(fp3_srt(b, c), end); + fp3_neg(c, b); + TEST_ASSERT(fp3_cmp(b, a) == RLC_EQ || fp3_cmp(c, a) == RLC_EQ, end); + fp3_rand(a); + if (fp3_srt(b, a)) { + fp3_sqr(c, b); + TEST_ASSERT(fp3_cmp(c, a) == RLC_EQ, end); + } + do { + fp3_rand(a); + } while(fp3_is_sqr(a) == 1); + TEST_ASSERT(fp3_srt(b, a) == 0, end); + } + TEST_END; } RLC_CATCH_ANY { util_print("FATAL ERROR!\n"); @@ -2156,6 +2194,19 @@ static int square_root4(void) { fp4_new(b); fp4_new(c); + TEST_CASE("quadratic residuosity test is correct") { + fp4_zero(a); + TEST_ASSERT(fp4_is_sqr(a) == 1, end); + fp4_rand(a); + fp4_sqr(a, a); + TEST_ASSERT(fp4_is_sqr(a) == 1, end); + do { + fp4_rand(a); + } while(fp4_srt(b, a) == 1); + TEST_ASSERT(fp4_is_sqr(a) == 0, end); + } + TEST_END; + TEST_CASE("square root extraction is correct") { fp4_zero(a); fp4_sqr(c, a); @@ -3412,29 +3463,74 @@ static int exponentiation8(void) { return code; } -static int memory12(void) { - err_t e = ERR_CAUGHT; +static int square_root8(void) { int code = RLC_ERR; - fp12_t a; + fp8_t a, b, c; + int r; - fp12_null(a); + fp8_null(a); + fp8_null(b); + fp8_null(c); RLC_TRY { - TEST_CASE("memory can be allocated") { - fp12_new(a); - fp12_free(a); - } TEST_END; - } RLC_CATCH(e) { - switch (e) { - case ERR_NO_MEMORY: - util_print("FATAL ERROR!\n"); - RLC_ERROR(end); - break; + fp8_new(a); + fp8_new(b); + fp8_new(c); + + TEST_CASE("quadratic residuosity test is correct") { + fp8_zero(a); + TEST_ASSERT(fp8_is_sqr(a) == 1, end); + fp8_rand(a); + fp8_sqr(a, a); + TEST_ASSERT(fp8_is_sqr(a) == 1, end); + do { + fp8_rand(a); + } while(fp8_srt(b, a) == 1); + TEST_ASSERT(fp8_is_sqr(a) == 0, end); } + TEST_END; + + TEST_CASE("square root extraction is correct") { + fp8_zero(a); + fp8_sqr(c, a); + r = fp8_srt(b, c); + TEST_ASSERT(r, end); + TEST_ASSERT(fp8_cmp(b, a) == RLC_EQ || + fp8_cmp(c, a) == RLC_EQ, end); + fp4_rand(a[0]); + fp4_zero(a[1]); + fp8_sqr(c, a); + r = fp8_srt(b, c); + fp8_neg(c, b); + TEST_ASSERT(r, end); + TEST_ASSERT(fp8_cmp(b, a) == RLC_EQ || + fp8_cmp(c, a) == RLC_EQ, end); + fp4_zero(a[0]); + fp4_rand(a[1]); + fp8_sqr(c, a); + r = fp8_srt(b, c); + fp8_neg(c, b); + TEST_ASSERT(r, end); + TEST_ASSERT(fp8_cmp(b, a) == RLC_EQ || + fp8_cmp(c, a) == RLC_EQ, end); + fp8_rand(a); + fp8_sqr(c, a); + r = fp8_srt(b, c); + fp8_neg(c, b); + TEST_ASSERT(r, end); + TEST_ASSERT(fp8_cmp(b, a) == RLC_EQ || + fp8_cmp(c, a) == RLC_EQ, end); + } TEST_END; + } + RLC_CATCH_ANY { + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); } - (void)a; code = RLC_OK; end: + fp8_free(a); + fp8_free(b); + fp8_free(c); return code; } @@ -3987,6 +4083,32 @@ static int exponentiation9(void) { return code; } +static int memory12(void) { + err_t e = ERR_CAUGHT; + int code = RLC_ERR; + fp12_t a; + + fp12_null(a); + + RLC_TRY { + TEST_CASE("memory can be allocated") { + fp12_new(a); + fp12_free(a); + } TEST_END; + } RLC_CATCH(e) { + switch (e) { + case ERR_NO_MEMORY: + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + break; + } + } + (void)a; + code = RLC_OK; + end: + return code; +} + static int util12(void) { int code = RLC_ERR; uint8_t bin[12 * RLC_FP_BYTES]; @@ -4761,17 +4883,17 @@ static int compression12(void) { return code; } -static int memory18(void) { +static int memory16(void) { err_t e = ERR_CAUGHT; int code = RLC_ERR; - fp18_t a; + fp16_t a; - fp18_null(a); + fp16_null(a); RLC_TRY { TEST_CASE("memory can be allocated") { - fp18_new(a); - fp18_free(a); + fp16_new(a); + fp16_free(a); } TEST_END; } RLC_CATCH(e) { switch (e) { @@ -4787,110 +4909,99 @@ static int memory18(void) { return code; } -static int util18(void) { +static int util16(void) { int code = RLC_ERR; - uint8_t bin[18 * RLC_FP_BYTES]; - fp18_t a, b, c; + uint8_t bin[16 * RLC_FP_BYTES]; + fp16_t a, b, c; dig_t d; - fp18_null(a); - fp18_null(b); - fp18_null(c); + fp16_null(a); + fp16_null(b); + fp16_null(c); RLC_TRY { - fp18_new(a); - fp18_new(b); - fp18_new(c); + fp16_new(a); + fp16_new(b); + fp16_new(c); TEST_CASE("comparison is consistent") { - fp18_rand(a); - fp18_rand(b); - if (fp18_cmp(a, b) != RLC_EQ) { - TEST_ASSERT(fp18_cmp(b, a) == RLC_NE, end); + fp16_rand(a); + fp16_rand(b); + if (fp16_cmp(a, b) != RLC_EQ) { + TEST_ASSERT(fp16_cmp(b, a) == RLC_NE, end); } } TEST_END; TEST_CASE("copy and comparison are consistent") { - fp18_rand(a); - fp18_rand(b); - fp18_rand(c); - if (fp18_cmp(a, c) != RLC_EQ) { - fp18_copy(c, a); - TEST_ASSERT(fp18_cmp(c, a) == RLC_EQ, end); + fp16_rand(a); + fp16_rand(b); + fp16_rand(c); + if (fp16_cmp(a, c) != RLC_EQ) { + fp16_copy(c, a); + TEST_ASSERT(fp16_cmp(c, a) == RLC_EQ, end); } - if (fp18_cmp(b, c) != RLC_EQ) { - fp18_copy(c, b); - TEST_ASSERT(fp18_cmp(b, c) == RLC_EQ, end); + if (fp16_cmp(b, c) != RLC_EQ) { + fp16_copy(c, b); + TEST_ASSERT(fp16_cmp(b, c) == RLC_EQ, end); } } TEST_END; TEST_CASE("negation is consistent") { - fp18_rand(a); - fp18_neg(b, a); - if (fp18_cmp(a, b) != RLC_EQ) { - TEST_ASSERT(fp18_cmp(b, a) == RLC_NE, end); + fp16_rand(a); + fp16_neg(b, a); + if (fp16_cmp(a, b) != RLC_EQ) { + TEST_ASSERT(fp16_cmp(b, a) == RLC_NE, end); } - fp18_neg(b, b); - TEST_ASSERT(fp18_cmp(a, b) == RLC_EQ, end); - } - TEST_END; - - TEST_CASE("assignment to zero and comparison are consistent") { - do { - fp18_rand(a); - } while (fp18_is_zero(a)); - fp18_zero(c); - TEST_ASSERT(fp18_cmp(a, c) == RLC_NE, end); - TEST_ASSERT(fp18_cmp(c, a) == RLC_NE, end); + fp16_neg(b, b); + TEST_ASSERT(fp16_cmp(a, b) == RLC_EQ, end); } TEST_END; TEST_CASE("assignment to zero and comparison are consistent") { do { - fp18_rand(a); - } while (fp18_is_zero(a)); - fp18_zero(c); - TEST_ASSERT(fp18_cmp(a, c) == RLC_NE, end); - TEST_ASSERT(fp18_cmp(c, a) == RLC_NE, end); + fp16_rand(a); + } while (fp16_is_zero(a)); + fp16_zero(c); + TEST_ASSERT(fp16_cmp(a, c) == RLC_NE, end); + TEST_ASSERT(fp16_cmp(c, a) == RLC_NE, end); } TEST_END; - TEST_CASE("assignment to random and comparison are consistent") { do { - fp18_rand(a); - } while (fp18_is_zero(a)); - fp18_zero(c); - TEST_ASSERT(fp18_cmp(a, c) == RLC_NE, end); + fp16_rand(a); + } while (fp16_is_zero(a)); + fp16_zero(c); + TEST_ASSERT(fp16_cmp(a, c) == RLC_NE, end); } TEST_END; TEST_CASE("assignment to zero and zero test are consistent") { - fp18_zero(a); - TEST_ASSERT(fp18_is_zero(a), end); + fp16_zero(a); + TEST_ASSERT(fp16_is_zero(a), end); } TEST_END; TEST_CASE("assignment to a constant and comparison are consistent") { - rand_bytes((uint8_t *)&d, (RLC_DIG / 8)); - fp18_set_dig(a, d); - TEST_ASSERT(fp18_cmp_dig(a, d) == RLC_EQ, end); + rand_bytes((uint8_t *)&d, (RLC_DIG / 16)); + fp16_set_dig(a, d); + TEST_ASSERT(fp16_cmp_dig(a, d) == RLC_EQ, end); } TEST_END; TEST_CASE("reading and writing a finite field element are consistent") { - fp18_rand(a); - fp18_write_bin(bin, sizeof(bin), a, 0); - fp18_read_bin(b, bin, sizeof(bin)); - TEST_ASSERT(fp18_cmp(a, b) == RLC_EQ, end); + fp16_rand(a); + fp16_write_bin(bin, sizeof(bin), a, 0); + fp16_read_bin(b, bin, sizeof(bin)); + TEST_ASSERT(fp16_cmp(a, b) == RLC_EQ, end); } TEST_END; TEST_CASE("getting the size of a finite field element is correct") { - fp18_rand(a); - TEST_ASSERT(fp18_size_bin(a, 0) == 18 * RLC_FP_BYTES, end); + fp16_rand(a); + TEST_ASSERT(fp16_size_bin(a, 0) == 16 * RLC_FP_BYTES, end); } TEST_END; } @@ -4899,60 +5010,60 @@ static int util18(void) { } code = RLC_OK; end: - fp18_free(a); - fp18_free(b); - fp18_free(c); + fp16_free(a); + fp16_free(b); + fp16_free(c); return code; } -static int addition18(void) { +static int addition16(void) { int code = RLC_ERR; - fp18_t a, b, c, d, e; + fp16_t a, b, c, d, e; - fp18_null(a); - fp18_null(b); - fp18_null(c); - fp18_null(d); - fp18_null(e); + fp16_null(a); + fp16_null(b); + fp16_null(c); + fp16_null(d); + fp16_null(e); RLC_TRY { - fp18_new(a); - fp18_new(b); - fp18_new(c); - fp18_new(d); - fp18_new(e); + fp16_new(a); + fp16_new(b); + fp16_new(c); + fp16_new(d); + fp16_new(e); TEST_CASE("addition is commutative") { - fp18_rand(a); - fp18_rand(b); - fp18_add(d, a, b); - fp18_add(e, b, a); - TEST_ASSERT(fp18_cmp(d, e) == RLC_EQ, end); + fp16_rand(a); + fp16_rand(b); + fp16_add(d, a, b); + fp16_add(e, b, a); + TEST_ASSERT(fp16_cmp(d, e) == RLC_EQ, end); } TEST_END; TEST_CASE("addition is associative") { - fp18_rand(a); - fp18_rand(b); - fp18_rand(c); - fp18_add(d, a, b); - fp18_add(d, d, c); - fp18_add(e, b, c); - fp18_add(e, a, e); - TEST_ASSERT(fp18_cmp(d, e) == RLC_EQ, end); + fp16_rand(a); + fp16_rand(b); + fp16_rand(c); + fp16_add(d, a, b); + fp16_add(d, d, c); + fp16_add(e, b, c); + fp16_add(e, a, e); + TEST_ASSERT(fp16_cmp(d, e) == RLC_EQ, end); } TEST_END; TEST_CASE("addition has identity") { - fp18_rand(a); - fp18_zero(d); - fp18_add(e, a, d); - TEST_ASSERT(fp18_cmp(e, a) == RLC_EQ, end); + fp16_rand(a); + fp16_zero(d); + fp16_add(e, a, d); + TEST_ASSERT(fp16_cmp(e, a) == RLC_EQ, end); } TEST_END; TEST_CASE("addition has inverse") { - fp18_rand(a); - fp18_neg(d, a); - fp18_add(e, a, d); - TEST_ASSERT(fp18_is_zero(e), end); + fp16_rand(a); + fp16_neg(d, a); + fp16_add(e, a, d); + TEST_ASSERT(fp16_is_zero(e), end); } TEST_END; } RLC_CATCH_ANY { @@ -4961,46 +5072,51 @@ static int addition18(void) { } code = RLC_OK; end: - fp18_free(a); - fp18_free(b); - fp18_free(c); - fp18_free(d); - fp18_free(e); + fp16_free(a); + fp16_free(b); + fp16_free(c); + fp16_free(d); + fp16_free(e); return code; } -static int subtraction18(void) { +static int subtraction16(void) { int code = RLC_ERR; - fp18_t a, b, c, d; + fp16_t a, b, c, d; + + fp16_null(a); + fp16_null(b); + fp16_null(c); + fp16_null(d); RLC_TRY { - fp18_new(a); - fp18_new(b); - fp18_new(c); - fp18_new(d); + fp16_new(a); + fp16_new(b); + fp16_new(c); + fp16_new(d); TEST_CASE("subtraction is anti-commutative") { - fp18_rand(a); - fp18_rand(b); - fp18_sub(c, a, b); - fp18_sub(d, b, a); - fp18_neg(d, d); - TEST_ASSERT(fp18_cmp(c, d) == RLC_EQ, end); + fp16_rand(a); + fp16_rand(b); + fp16_sub(c, a, b); + fp16_sub(d, b, a); + fp16_neg(d, d); + TEST_ASSERT(fp16_cmp(c, d) == RLC_EQ, end); } TEST_END; TEST_CASE("subtraction has identity") { - fp18_rand(a); - fp18_zero(c); - fp18_sub(d, a, c); - TEST_ASSERT(fp18_cmp(d, a) == RLC_EQ, end); + fp16_rand(a); + fp16_zero(c); + fp16_sub(d, a, c); + TEST_ASSERT(fp16_cmp(d, a) == RLC_EQ, end); } TEST_END; TEST_CASE("subtraction has inverse") { - fp18_rand(a); - fp18_sub(c, a, a); - TEST_ASSERT(fp18_is_zero(c), end); + fp16_rand(a); + fp16_sub(c, a, a); + TEST_ASSERT(fp16_is_zero(c), end); } TEST_END; } @@ -5010,35 +5126,735 @@ static int subtraction18(void) { } code = RLC_OK; end: - fp18_free(a); - fp18_free(b); - fp18_free(c); - fp18_free(d); + fp16_free(a); + fp16_free(b); + fp16_free(c); + fp16_free(d); return code; } -static int multiplication18(void) { +static int doubling16(void) { int code = RLC_ERR; - fp18_t a, b, c, d, e, f; + fp16_t a, b, c; + + fp16_null(a); + fp16_null(b); + fp16_null(c); RLC_TRY { - fp18_new(a); - fp18_new(b); - fp18_new(c); - fp18_new(d); - fp18_new(e); - fp18_new(f); + fp16_new(a); + fp16_new(b); + fp16_new(c); - TEST_CASE("multiplication is commutative") { - fp18_rand(a); - fp18_rand(b); - fp18_mul(d, a, b); - fp18_mul(e, b, a); - TEST_ASSERT(fp18_cmp(d, e) == RLC_EQ, end); + TEST_CASE("doubling is correct") { + fp16_rand(a); + fp16_dbl(b, a); + fp16_add(c, a, a); + TEST_ASSERT(fp16_cmp(b, c) == RLC_EQ, end); } TEST_END; - - TEST_CASE("multiplication is associative") { - fp18_rand(a); + } + RLC_CATCH_ANY { + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + } + code = RLC_OK; + end: + fp16_free(a); + fp16_free(b); + fp16_free(c); + return code; +} + +static int multiplication16(void) { + int code = RLC_ERR; + fp16_t a, b, c, d, e, f; + + fp16_null(a); + fp16_null(b); + fp16_null(c); + fp16_null(d); + fp16_null(e); + fp16_null(f); + + RLC_TRY { + fp16_new(a); + fp16_new(b); + fp16_new(c); + fp16_new(d); + fp16_new(e); + fp16_new(f); + + TEST_CASE("multiplication is commutative") { + fp16_rand(a); + fp16_rand(b); + fp16_mul(d, a, b); + fp16_mul(e, b, a); + TEST_ASSERT(fp16_cmp(d, e) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("multiplication is associative") { + fp16_rand(a); + fp16_rand(b); + fp16_rand(c); + fp16_mul(d, a, b); + fp16_mul(d, d, c); + fp16_mul(e, b, c); + fp16_mul(e, a, e); + TEST_ASSERT(fp16_cmp(d, e) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("multiplication is distributive") { + fp16_rand(a); + fp16_rand(b); + fp16_rand(c); + fp16_add(d, a, b); + fp16_mul(d, c, d); + fp16_mul(e, c, a); + fp16_mul(f, c, b); + fp16_add(e, e, f); + TEST_ASSERT(fp16_cmp(d, e) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("multiplication has identity") { + fp16_set_dig(d, 1); + fp16_mul(e, a, d); + TEST_ASSERT(fp16_cmp(e, a) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("multiplication has zero property") { + fp16_zero(d); + fp16_mul(e, a, d); + TEST_ASSERT(fp16_is_zero(e), end); + } TEST_END; + + TEST_CASE("multiplication by adjoined root is correct") { + fp16_rand(a); + fp16_zero(b); + fp8_set_dig(b[1], 1); + fp16_mul(c, a, b); + fp16_mul_art(d, a); + TEST_ASSERT(fp16_cmp(c, d) == RLC_EQ, end); + } TEST_END; + +#if FPX_RDC == BASIC | !defined(STRIP) + TEST_CASE("basic multiplication is correct") { + fp16_rand(a); + fp16_rand(b); + fp16_mul(c, a, b); + fp16_mul_basic(d, a, b); + TEST_ASSERT(fp16_cmp(c, d) == RLC_EQ, end); + } TEST_END; +#endif + +#if FPX_RDC == LAZYR || !defined(STRIP) + TEST_CASE("lazy-reduced multiplication is correct") { + fp16_rand(a); + fp16_rand(b); + fp16_mul(c, a, b); + fp16_mul_lazyr(d, a, b); + TEST_ASSERT(fp16_cmp(c, d) == RLC_EQ, end); + } TEST_END; +#endif + } + RLC_CATCH_ANY { + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + } + code = RLC_OK; + end: + fp16_free(a); + fp16_free(b); + fp16_free(c); + fp16_free(d); + fp16_free(e); + fp16_free(f); + return code; +} + +static int squaring16(void) { + int code = RLC_ERR; + fp16_t a, b, c; + + fp16_null(a); + fp16_null(b); + fp16_null(c); + + RLC_TRY { + fp16_new(a); + fp16_new(b); + fp16_new(c); + + TEST_CASE("squaring is correct") { + fp16_rand(a); + fp16_mul(b, a, a); + fp16_sqr(c, a); + TEST_ASSERT(fp16_cmp(b, c) == RLC_EQ, end); + } TEST_END; + +#if FPX_RDC == BASIC | !defined(STRIP) + TEST_CASE("basic squaring is correct") { + fp16_rand(a); + fp16_sqr(b, a); + fp16_sqr_basic(c, a); + TEST_ASSERT(fp16_cmp(b, c) == RLC_EQ, end); + } TEST_END; +#endif + +#if FPX_RDC == LAZYR || !defined(STRIP) + TEST_CASE("lazy-reduced squaring is correct") { + fp16_rand(a); + fp16_sqr(b, a); + fp16_sqr_lazyr(c, a); + TEST_ASSERT(fp16_cmp(b, c) == RLC_EQ, end); + } TEST_END; +#endif + } + RLC_CATCH_ANY { + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + } + code = RLC_OK; + end: + fp16_free(a); + fp16_free(b); + fp16_free(c); + return code; +} + +static int cyclotomic16(void) { + int code = RLC_ERR; + fp16_t a, b, c; + bn_t f; + + fp16_null(a); + fp16_null(b); + fp16_null(c); + bn_null(f); + + RLC_TRY { + fp16_new(a); + fp16_new(b); + fp16_new(c); + bn_new(f); + + TEST_CASE("cyclotomic test is correct") { + fp16_rand(a); + fp16_conv_cyc(a, a); + TEST_ASSERT(fp16_test_cyc(a) == 1, end); + } TEST_END; + + TEST_CASE("cyclotomic squaring is correct") { + fp16_rand(a); + fp16_conv_cyc(a, a); + fp16_sqr(b, a); + fp16_sqr_cyc(c, a); + TEST_ASSERT(fp16_cmp(b, c) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("cyclotomic exponentiation is correct") { + fp16_rand(a); + fp16_conv_cyc(a, a); + bn_zero(f); + fp16_exp_cyc(c, a, f); + TEST_ASSERT(fp16_cmp_dig(c, 1) == RLC_EQ, end); + bn_set_dig(f, 1); + fp16_exp_cyc(c, a, f); + TEST_ASSERT(fp16_cmp(c, a) == RLC_EQ, end); + bn_rand(f, RLC_POS, RLC_FP_BITS); + fp16_exp(b, a, f); + fp16_exp_cyc(c, a, f); + TEST_ASSERT(fp16_cmp(b, c) == RLC_EQ, end); + bn_rand(f, RLC_POS, RLC_FP_BITS); + fp16_exp_cyc(b, a, f); + bn_neg(f, f); + fp16_exp_cyc(c, a, f); + fp16_inv_cyc(c, c); + TEST_ASSERT(fp16_cmp(b, c) == RLC_EQ, end); + } TEST_END; + } + RLC_CATCH_ANY { + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + } + code = RLC_OK; + end: + fp16_free(a); + fp16_free(b); + fp16_free(c); + bn_free(f); + return code; +} + +static int inversion16(void) { + int code = RLC_ERR; + fp16_t a, b, c, d[2]; + + fp16_null(a); + fp16_null(b); + fp16_null(c); + fp16_null(d[0]); + fp16_null(d[1]); + + RLC_TRY { + fp16_new(a); + fp16_new(b); + fp16_new(c); + fp16_new(d[0]); + fp16_new(d[1]); + + TEST_CASE("inversion is correct") { + do { + fp16_rand(a); + } while (fp16_is_zero(a)); + fp16_inv(b, a); + fp16_mul(c, a, b); + TEST_ASSERT(fp16_cmp_dig(c, 1) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("inversion of a unitary element is correct") { + do { + fp16_rand(a); + } while (fp16_is_zero(a)); + fp16_conv_cyc(a, a); + fp16_inv(b, a); + fp16_inv_cyc(c, a); + TEST_ASSERT(fp16_cmp(b, c) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("simultaneous inversion is correct") { + do { + fp16_rand(a); + fp16_rand(b); + } while (fp16_is_zero(a) || fp16_is_zero(b)); + fp16_copy(d[0], a); + fp16_copy(d[1], b); + fp16_inv(a, a); + fp16_inv(b, b); + fp16_inv_sim(d, d, 2); + TEST_ASSERT(fp16_cmp(d[0], a) == RLC_EQ && + fp16_cmp(d[1], b) == RLC_EQ, end); + } TEST_END; + } + RLC_CATCH_ANY { + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + } + code = RLC_OK; + end: + fp16_free(a); + fp16_free(b); + fp16_free(c); + fp16_free(d[0]); + fp16_free(d[1]); + return code; +} + +static int exponentiation16(void) { + int code = RLC_ERR; + fp16_t a, b, c; + bn_t d; + + fp16_null(a); + fp16_null(b); + fp16_null(c); + bn_null(d); + + RLC_TRY { + fp16_new(a); + fp16_new(b); + fp16_new(c); + bn_new(d); + + TEST_CASE("exponentiation is correct") { + fp16_rand(a); + bn_zero(d); + fp16_exp(c, a, d); + TEST_ASSERT(fp16_cmp_dig(c, 1) == RLC_EQ, end); + bn_set_dig(d, 1); + fp16_exp(c, a, d); + TEST_ASSERT(fp16_cmp(c, a) == RLC_EQ, end); + bn_rand(d, RLC_POS, RLC_FP_BITS); + fp16_exp(b, a, d); + bn_neg(d, d); + fp16_exp(c, a, d); + fp16_inv(c, c); + TEST_ASSERT(fp16_cmp(b, c) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("frobenius and exponentiation are consistent") { + fp16_rand(a); + fp16_frb(b, a, 0); + TEST_ASSERT(fp16_cmp(a, b) == RLC_EQ, end); + fp16_frb(b, a, 1); + d->sign = RLC_POS; + d->used = RLC_FP_DIGS; + dv_copy(d->dp, fp_prime_get(), RLC_FP_DIGS); + fp16_exp(c, a, d); + TEST_ASSERT(fp16_cmp(b, c) == RLC_EQ, end); + } TEST_END; + } + RLC_CATCH_ANY { + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + } + code = RLC_OK; + end: + fp16_free(a); + fp16_free(b); + fp16_free(c); + bn_free(d); + return code; +} + +static int square_root16(void) { + int code = RLC_ERR; + fp16_t a, b, c; + int r; + + fp16_null(a); + fp16_null(b); + fp16_null(c); + + RLC_TRY { + fp16_new(a); + fp16_new(b); + fp16_new(c); + + TEST_CASE("quadratic residuosity test is correct") { + fp16_zero(a); + TEST_ASSERT(fp16_is_sqr(a) == 1, end); + fp16_rand(a); + fp16_sqr(a, a); + TEST_ASSERT(fp16_is_sqr(a) == 1, end); + do { + fp16_rand(a); + } while(fp16_srt(b, a) == 1); + TEST_ASSERT(fp16_is_sqr(a) == 0, end); + } + TEST_END; + + TEST_CASE("square root extraction is correct") { + fp16_zero(a); + fp16_sqr(c, a); + r = fp16_srt(b, c); + TEST_ASSERT(r, end); + TEST_ASSERT(fp16_cmp(b, a) == RLC_EQ || + fp16_cmp(c, a) == RLC_EQ, end); + fp8_rand(a[0]); + fp8_zero(a[1]); + fp16_sqr(c, a); + r = fp16_srt(b, c); + fp16_neg(c, b); + TEST_ASSERT(r, end); + TEST_ASSERT(fp16_cmp(b, a) == RLC_EQ || + fp16_cmp(c, a) == RLC_EQ, end); + fp8_zero(a[0]); + fp8_rand(a[1]); + fp16_sqr(c, a); + r = fp16_srt(b, c); + fp16_neg(c, b); + TEST_ASSERT(r, end); + TEST_ASSERT(fp16_cmp(b, a) == RLC_EQ || + fp16_cmp(c, a) == RLC_EQ, end); + fp16_rand(a); + fp16_sqr(c, a); + r = fp16_srt(b, c); + fp16_neg(c, b); + TEST_ASSERT(r, end); + TEST_ASSERT(fp16_cmp(b, a) == RLC_EQ || + fp16_cmp(c, a) == RLC_EQ, end); + } TEST_END; + } + RLC_CATCH_ANY { + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + } + code = RLC_OK; + end: + fp16_free(a); + fp16_free(b); + fp16_free(c); + return code; +} + +static int memory18(void) { + err_t e = ERR_CAUGHT; + int code = RLC_ERR; + fp18_t a; + + fp18_null(a); + + RLC_TRY { + TEST_CASE("memory can be allocated") { + fp18_new(a); + fp18_free(a); + } TEST_END; + } RLC_CATCH(e) { + switch (e) { + case ERR_NO_MEMORY: + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + break; + } + } + (void)a; + code = RLC_OK; + end: + return code; +} + +static int util18(void) { + int code = RLC_ERR; + uint8_t bin[18 * RLC_FP_BYTES]; + fp18_t a, b, c; + dig_t d; + + fp18_null(a); + fp18_null(b); + fp18_null(c); + + RLC_TRY { + fp18_new(a); + fp18_new(b); + fp18_new(c); + + TEST_CASE("comparison is consistent") { + fp18_rand(a); + fp18_rand(b); + if (fp18_cmp(a, b) != RLC_EQ) { + TEST_ASSERT(fp18_cmp(b, a) == RLC_NE, end); + } + } + TEST_END; + + TEST_CASE("copy and comparison are consistent") { + fp18_rand(a); + fp18_rand(b); + fp18_rand(c); + if (fp18_cmp(a, c) != RLC_EQ) { + fp18_copy(c, a); + TEST_ASSERT(fp18_cmp(c, a) == RLC_EQ, end); + } + if (fp18_cmp(b, c) != RLC_EQ) { + fp18_copy(c, b); + TEST_ASSERT(fp18_cmp(b, c) == RLC_EQ, end); + } + } + TEST_END; + + TEST_CASE("negation is consistent") { + fp18_rand(a); + fp18_neg(b, a); + if (fp18_cmp(a, b) != RLC_EQ) { + TEST_ASSERT(fp18_cmp(b, a) == RLC_NE, end); + } + fp18_neg(b, b); + TEST_ASSERT(fp18_cmp(a, b) == RLC_EQ, end); + } + TEST_END; + + TEST_CASE("assignment to zero and comparison are consistent") { + do { + fp18_rand(a); + } while (fp18_is_zero(a)); + fp18_zero(c); + TEST_ASSERT(fp18_cmp(a, c) == RLC_NE, end); + TEST_ASSERT(fp18_cmp(c, a) == RLC_NE, end); + } + TEST_END; + + TEST_CASE("assignment to zero and comparison are consistent") { + do { + fp18_rand(a); + } while (fp18_is_zero(a)); + fp18_zero(c); + TEST_ASSERT(fp18_cmp(a, c) == RLC_NE, end); + TEST_ASSERT(fp18_cmp(c, a) == RLC_NE, end); + } + TEST_END; + + + TEST_CASE("assignment to random and comparison are consistent") { + do { + fp18_rand(a); + } while (fp18_is_zero(a)); + fp18_zero(c); + TEST_ASSERT(fp18_cmp(a, c) == RLC_NE, end); + } + TEST_END; + + TEST_CASE("assignment to zero and zero test are consistent") { + fp18_zero(a); + TEST_ASSERT(fp18_is_zero(a), end); + } + TEST_END; + + TEST_CASE("assignment to a constant and comparison are consistent") { + rand_bytes((uint8_t *)&d, (RLC_DIG / 8)); + fp18_set_dig(a, d); + TEST_ASSERT(fp18_cmp_dig(a, d) == RLC_EQ, end); + } + TEST_END; + + TEST_CASE("reading and writing a finite field element are consistent") { + fp18_rand(a); + fp18_write_bin(bin, sizeof(bin), a, 0); + fp18_read_bin(b, bin, sizeof(bin)); + TEST_ASSERT(fp18_cmp(a, b) == RLC_EQ, end); + } + TEST_END; + + TEST_CASE("getting the size of a finite field element is correct") { + fp18_rand(a); + TEST_ASSERT(fp18_size_bin(a, 0) == 18 * RLC_FP_BYTES, end); + } + TEST_END; + } + RLC_CATCH_ANY { + RLC_ERROR(end); + } + code = RLC_OK; + end: + fp18_free(a); + fp18_free(b); + fp18_free(c); + return code; +} + +static int addition18(void) { + int code = RLC_ERR; + fp18_t a, b, c, d, e; + + fp18_null(a); + fp18_null(b); + fp18_null(c); + fp18_null(d); + fp18_null(e); + + RLC_TRY { + fp18_new(a); + fp18_new(b); + fp18_new(c); + fp18_new(d); + fp18_new(e); + + TEST_CASE("addition is commutative") { + fp18_rand(a); + fp18_rand(b); + fp18_add(d, a, b); + fp18_add(e, b, a); + TEST_ASSERT(fp18_cmp(d, e) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("addition is associative") { + fp18_rand(a); + fp18_rand(b); + fp18_rand(c); + fp18_add(d, a, b); + fp18_add(d, d, c); + fp18_add(e, b, c); + fp18_add(e, a, e); + TEST_ASSERT(fp18_cmp(d, e) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("addition has identity") { + fp18_rand(a); + fp18_zero(d); + fp18_add(e, a, d); + TEST_ASSERT(fp18_cmp(e, a) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("addition has inverse") { + fp18_rand(a); + fp18_neg(d, a); + fp18_add(e, a, d); + TEST_ASSERT(fp18_is_zero(e), end); + } TEST_END; + } + RLC_CATCH_ANY { + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + } + code = RLC_OK; + end: + fp18_free(a); + fp18_free(b); + fp18_free(c); + fp18_free(d); + fp18_free(e); + return code; +} + +static int subtraction18(void) { + int code = RLC_ERR; + fp18_t a, b, c, d; + + RLC_TRY { + fp18_new(a); + fp18_new(b); + fp18_new(c); + fp18_new(d); + + TEST_CASE("subtraction is anti-commutative") { + fp18_rand(a); + fp18_rand(b); + fp18_sub(c, a, b); + fp18_sub(d, b, a); + fp18_neg(d, d); + TEST_ASSERT(fp18_cmp(c, d) == RLC_EQ, end); + } + TEST_END; + + TEST_CASE("subtraction has identity") { + fp18_rand(a); + fp18_zero(c); + fp18_sub(d, a, c); + TEST_ASSERT(fp18_cmp(d, a) == RLC_EQ, end); + } + TEST_END; + + TEST_CASE("subtraction has inverse") { + fp18_rand(a); + fp18_sub(c, a, a); + TEST_ASSERT(fp18_is_zero(c), end); + } + TEST_END; + } + RLC_CATCH_ANY { + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + } + code = RLC_OK; + end: + fp18_free(a); + fp18_free(b); + fp18_free(c); + fp18_free(d); + return code; +} + +static int multiplication18(void) { + int code = RLC_ERR; + fp18_t a, b, c, d, e, f; + + RLC_TRY { + fp18_new(a); + fp18_new(b); + fp18_new(c); + fp18_new(d); + fp18_new(e); + fp18_new(f); + + TEST_CASE("multiplication is commutative") { + fp18_rand(a); + fp18_rand(b); + fp18_mul(d, a, b); + fp18_mul(e, b, a); + TEST_ASSERT(fp18_cmp(d, e) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("multiplication is associative") { + fp18_rand(a); fp18_rand(b); fp18_rand(c); fp18_mul(d, a, b); @@ -5271,38 +6087,40 @@ static int cyclotomic18(void) { } TEST_END; #endif - TEST_CASE("cyclotomic exponentiation is correct") { - fp18_rand(a); - fp18_conv_cyc(a, a); - pp_exp_k18(a, a); - bn_zero(f); - fp18_exp_cyc(c, a, f); - TEST_ASSERT(fp18_cmp_dig(c, 1) == RLC_EQ, end); - bn_set_dig(f, 1); - fp18_exp_cyc(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(c, a, f); - TEST_ASSERT(fp18_cmp(b, c) == RLC_EQ, end); - bn_rand(f, RLC_POS, RLC_FP_BITS); - fp18_exp_cyc(b, a, f); - bn_neg(f, f); - fp18_exp_cyc(c, a, f); - fp18_inv_cyc(c, c); - TEST_ASSERT(fp18_cmp(b, c) == RLC_EQ, end); - /* Try sparse exponents as well. */ - bn_set_2b(f, RLC_FP_BITS - 1); - bn_set_bit(f, RLC_FP_BITS / 2, 1); - bn_set_bit(f, 0, 1); - fp18_rand(a); - fp18_conv_cyc(a, a); - fp18_exp_cyc(b, a, f); - bn_neg(f, f); - fp18_exp_cyc(c, a, f); - fp18_inv_cyc(c, c); - TEST_ASSERT(fp18_cmp(b, c) == RLC_EQ, end); - } TEST_END; + if (ep_curve_is_pairf() == EP_K18) { + TEST_CASE("cyclotomic exponentiation is correct") { + fp18_rand(a); + fp18_conv_cyc(a, a); + pp_exp_k18(a, a); + bn_zero(f); + fp18_exp_cyc(c, a, f); + TEST_ASSERT(fp18_cmp_dig(c, 1) == RLC_EQ, end); + bn_set_dig(f, 1); + fp18_exp_cyc(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(c, a, f); + TEST_ASSERT(fp18_cmp(b, c) == RLC_EQ, end); + bn_rand(f, RLC_POS, RLC_FP_BITS); + fp18_exp_cyc(b, a, f); + bn_neg(f, f); + fp18_exp_cyc(c, a, f); + fp18_inv_cyc(c, c); + TEST_ASSERT(fp18_cmp(b, c) == RLC_EQ, end); + /* Try sparse exponents as well. */ + bn_set_2b(f, RLC_FP_BITS - 1); + bn_set_bit(f, RLC_FP_BITS / 2, 1); + bn_set_bit(f, 0, 1); + fp18_rand(a); + fp18_conv_cyc(a, a); + fp18_exp_cyc(b, a, f); + bn_neg(f, f); + fp18_exp_cyc(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}; @@ -7763,6 +8581,8 @@ int main(void) { } } + fp_param_print(); + /* Only execute these if there is an assigned quadratic non-residue. */ if (fp_prime_get_qnr()) { util_print("\n-- Quadratic extension: %d as QNR\n", fp_prime_get_qnr()); @@ -7885,7 +8705,7 @@ int main(void) { core_clean(); return 1; } - + if (square_root3() != RLC_OK) { core_clean(); return 1; @@ -7962,7 +8782,7 @@ int main(void) { } /* Fp^6 is defined as a cubic extension of Fp^2. */ - if (fp_prime_get_qnr()) { + if (fp_prime_get_qnr() && fp_prime_get_cnr()) { util_print("\n-- Sextic extension: (i + %d) as CNR\n", fp2_field_get_qnr()); util_banner("Utilities:", 1); @@ -8070,6 +8890,11 @@ int main(void) { core_clean(); return 1; } + + if (square_root8() != RLC_OK) { + core_clean(); + return 1; + } } /* Only execute these if there is an assigned cubic non-residue. */ @@ -8126,7 +8951,7 @@ int main(void) { } } - if (fp_prime_get_qnr() && (ep_param_embed() >= 12)) { + if (fp_prime_get_qnr() && fp_prime_get_cnr() && (ep_param_embed() >= 12)) { util_banner("Dodecic extension:", 0); util_banner("Utilities:", 1); @@ -8181,7 +9006,68 @@ int main(void) { core_clean(); return 1; } + } + + if (fp_prime_get_qnr() && (ep_param_embed() >= 16)) { + util_banner("Sextadecic extension:", 0); + util_banner("Utilities:", 1); + + if (memory16() != RLC_OK) { + core_clean(); + return 1; + } + + if (util16() != RLC_OK) { + core_clean(); + return 1; + } + + util_banner("Arithmetic:", 1); + + if (addition16() != RLC_OK) { + core_clean(); + return 1; + } + + if (subtraction16() != RLC_OK) { + core_clean(); + return 1; + } + + if (doubling16() != RLC_OK) { + core_clean(); + return 1; + } + + if (multiplication16() != RLC_OK) { + core_clean(); + return 1; + } + + if (squaring16() != RLC_OK) { + core_clean(); + return 1; + } + + if (cyclotomic16() != RLC_OK) { + core_clean(); + return 1; + } + + if (inversion16() != RLC_OK) { + core_clean(); + return 1; + } + + if (exponentiation16() != RLC_OK) { + core_clean(); + return 1; + } + if (square_root16() != RLC_OK) { + core_clean(); + return 1; + } } if (fp_prime_get_cnr() && (ep_param_embed() >= 18)) { diff --git a/test/test_pc.c b/test/test_pc.c index 0e30ae3f8..7890526b3 100644 --- a/test/test_pc.c +++ b/test/test_pc.c @@ -653,7 +653,7 @@ static int memory2(void) { int util2(void) { int l, code = RLC_ERR; g2_t a, b, c; - uint8_t bin[8 * RLC_PC_BYTES + 1]; + uint8_t bin[16 * RLC_PC_BYTES + 1]; g2_null(a); g2_null(b); @@ -1181,8 +1181,6 @@ static int validity2(void) { return code; } -#if FP_PRIME != 509 - static int hashing2(void) { int code = RLC_ERR; g2_t a; @@ -1216,8 +1214,6 @@ static int hashing2(void) { return code; } -#endif - static int memory(void) { err_t e = ERR_CAUGHT; int code = RLC_ERR; @@ -1749,11 +1745,9 @@ int test2(void) { return RLC_ERR; } -#if FP_PRIME != 509 if (hashing2() != RLC_OK) { return RLC_ERR; } -#endif return RLC_OK; } diff --git a/test/test_pp.c b/test/test_pp.c index 886bdf0e5..c120930eb 100644 --- a/test/test_pp.c +++ b/test/test_pp.c @@ -35,6 +35,455 @@ #include "relic_test.h" #include "relic_bench.h" +static int addition1(void) { + int code = RLC_ERR; + bn_t k, n; + ep_t p, q, r, s; + fp_t e1, e2, e3; + + bn_null(k); + bn_null(n); + ep_null(p); + ep_null(q); + ep_null(r); + ep_null(s); + fp_null(e1); + fp_null(e2); + fp_null(e3); + + RLC_TRY { + bn_new(n); + bn_new(k); + ep_new(p); + ep_new(q); + ep_new(r); + ep_new(s); + fp_new(e1); + fp_new(e2); + fp_new(e3); + + ep_curve_get_ord(n); + + TEST_CASE("miller addition is correct") { + ep_rand(p); + ep_rand(q); + ep_rand(r); + ep_copy(s, r); + pp_add_k1(e1, e2, r, q, p); + pp_norm_k1(r, r); + ep_add(s, s, q); + ep_norm(s, s); + TEST_ASSERT(ep_cmp(r, s) == RLC_EQ, end); + } TEST_END; + +#if EP_ADD == BASIC || !defined(STRIP) + TEST_CASE("miller addition in affine coordinates is correct") { + ep_rand(p); + ep_rand(q); + ep_rand(r); + ep_copy(s, r); + fp_zero(e1); + fp_zero(e2); + pp_add_k1(e1, e2, r, q, p); + fp_inv(e2, e2); + fp_mul(e1, e1, e2); + pp_add_k1_basic(e2, e3, s, q, p); + fp_inv(e3, e3); + fp_mul(e2, e2, e3); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + } TEST_END; +#endif + +#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP) + TEST_CASE("miller addition in projective coordinates is correct") { + ep_rand(p); + ep_rand(q); + ep_rand(r); + ep_copy(s, r); + fp_zero(e1); + fp_zero(e2); + pp_add_k1(e1, e2, r, q, p); + fp_inv(e2, e2); + fp_mul(e1, e1, e2); + pp_exp_k1(e1, e1); + pp_add_k1_projc(e2, e3, s, q, p); + fp_inv(e3, e3); + fp_mul(e2, e2, e3); + pp_exp_k1(e2, e2); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + } TEST_END; +#endif /* EP_ADD = PROJC */ + } + RLC_CATCH_ANY { + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + } + code = RLC_OK; + end: + bn_free(n); + bn_free(k); + ep_free(p); + ep_free(q); + ep_free(r); + ep_free(s); + fp_free(e1); + fp_free(e2); + fp_free(e3); + return code; +} + +static int doubling1(void) { + int code = RLC_ERR; + bn_t k, n; + ep_t p, q, r, s; + fp_t e1, e2, e3; + + bn_null(k); + bn_null(n); + ep_null(p); + ep_null(q); + ep_null(r); + ep_null(s); + fp_null(e1); + fp_null(e2); + fp_null(e3); + + RLC_TRY { + bn_new(n); + bn_new(k); + ep_new(p); + ep_new(q); + ep_new(r); + ep_new(s); + fp_new(e1); + fp_new(e2); + fp_new(e3); + + ep_curve_get_ord(n); + + TEST_CASE("miller doubling is correct") { + ep_rand(p); + ep_rand(q); + ep_rand(r); + pp_dbl_k1(e1, e2, r, q, p); + pp_norm_k1(r, r); + ep_dbl(s, q); + ep_norm(s, s); + TEST_ASSERT(ep_cmp(r, s) == RLC_EQ, end); + } TEST_END; + +#if EP_ADD == BASIC || !defined(STRIP) + TEST_CASE("miller doubling in affine coordinates is correct") { + ep_rand(p); + ep_rand(q); + ep_rand(r); + fp_zero(e1); + fp_zero(e2); + pp_dbl_k1(e1, e2, r, q, p); + fp_inv(e2, e2); + fp_mul(e1, e1, e2); + pp_exp_k1(e1, e1); + pp_dbl_k1_basic(e2, e3, r, q, p); + fp_inv(e3, e3); + fp_mul(e2, e2, e3); + pp_exp_k1(e2, e2); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + } TEST_END; +#endif + +#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP) + TEST_CASE("miller doubling in projective coordinates is correct") { + ep_rand(p); + ep_rand(q); + ep_rand(r); + fp_zero(e1); + fp_zero(e2); + pp_dbl_k1(e1, e2, r, q, p); + fp_inv(e2, e2); + fp_mul(e1, e1, e2); + pp_exp_k1(e1, e1); + pp_dbl_k1_projc(e2, e3, r, q, p); + fp_inv(e3, e3); + fp_mul(e2, e2, e3); + pp_exp_k1(e2, e2); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + } TEST_END; +#endif /* EP_ADD = PROJC */ + } + RLC_CATCH_ANY { + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + } + code = RLC_OK; + end: + bn_free(n); + bn_free(k); + ep_free(p); + ep_free(q); + ep_free(r); + ep_free(s); + fp_free(e1); + fp_free(e2); + fp_free(e3); + return code; +} + +static int pairing1(void) { + int j, code = RLC_ERR; + bn_t k, n; + ep_t p[2], q[2], r; + fp_t e1, e2; + + bn_null(k); + bn_null(n); + ep_null(r); + fp_null(e1); + fp_null(e2); + + RLC_TRY { + bn_new(n); + bn_new(k); + ep_new(r); + fp_new(e1); + fp_new(e2); + + for (j = 0; j < 2; j++) { + ep_null(p[j]); + ep_null(q[j]); + ep_new(p[j]); + ep_new(q[j]); + } + + ep_curve_get_ord(n); + TEST_CASE("pairing non-degeneracy is correct") { + ep_set_infty(p[0]); + pp_map_k1(e1, p[0], q[0]); + TEST_ASSERT(fp_cmp_dig(e1, 1) == RLC_EQ, end); + ep_rand(p[0]); + ep_set_infty(q[0]); + pp_map_k1(e1, p[0], q[0]); + TEST_ASSERT(fp_cmp_dig(e1, 1) == RLC_EQ, end); + ep_rand(p[0]); + pp_map_k1(e1, p[0], p[0]); + TEST_ASSERT(fp_cmp_dig(e1, 1) == RLC_EQ, end); + ep_rand(p[0]); + ep_dbl(q[0], p[0]); + ep_norm(q[0], q[0]); + pp_map_k1(e1, p[0], q[0]); + TEST_ASSERT(fp_cmp_dig(e1, 1) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("pairing is bilinear") { + ep_rand(p[0]); + ep_rand(q[0]); + ep_psi(q[0], q[0]); + bn_rand_mod(k, n); + ep_mul(r, q[0], k); + pp_map_k1(e1, p[0], r); + pp_map_k1(e2, p[0], q[0]); + fp_exp(e2, e2, k); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + ep_mul(p[0], p[0], k); + pp_map_k1(e2, p[0], q[0]); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + ep_dbl(p[0], p[0]); + pp_map_k1(e2, p[0], q[0]); + fp_sqr(e1, e1); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + ep_dbl(q[0], q[0]); + pp_map_k1(e2, p[0], q[0]); + fp_sqr(e1, e1); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("multi-pairing is correct") { + ep_rand(p[i % 2]); + ep_rand(q[i % 2]); + ep_psi(q[i % 2], q[i % 2]); + pp_map_k1(e1, p[i % 2], q[i % 2]); + ep_rand(p[1 - (i % 2)]); + ep_set_infty(q[1 - (i % 2)]); + pp_map_sim_k1(e2, p, q, 2); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + ep_set_infty(p[1 - (i % 2)]); + ep_rand(q[1 - (i % 2)]); + pp_map_sim_k1(e2, p, q, 2); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + ep_set_infty(q[i % 2]); + pp_map_sim_k1(e2, p, q, 2); + TEST_ASSERT(fp_cmp_dig(e2, 1) == RLC_EQ, end); + ep_rand(p[0]); + ep_rand(q[0]); + ep_psi(q[0], q[0]); + pp_map_k1(e1, p[0], q[0]); + ep_rand(p[1]); + ep_rand(q[1]); + ep_psi(q[1], q[1]); + pp_map_k1(e2, p[1], q[1]); + fp_mul(e1, e1, e2); + pp_map_sim_k1(e2, p, q, 2); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + } TEST_END; + +#if PP_MAP == TATEP || PP_MAP == OATEP || !defined(STRIP) + TEST_CASE("tate pairing non-degeneracy is correct") { + ep_set_infty(p[0]); + pp_map_tatep_k1(e1, p[0], q[0]); + TEST_ASSERT(fp_cmp_dig(e1, 1) == RLC_EQ, end); + ep_rand(p[0]); + ep_set_infty(q[0]); + pp_map_tatep_k1(e1, p[0], q[0]); + TEST_ASSERT(fp_cmp_dig(e1, 1) == RLC_EQ, end); + ep_rand(p[0]); + ep_dbl(q[0], p[0]); + ep_norm(q[0], q[0]); + /* If does not work for all multiples of P, but works for 2P. */ + pp_map_tatep_k1(e1, p[0], q[0]); + TEST_ASSERT(fp_cmp_dig(e1, 1) == RLC_EQ, end); + ep_psi(q[0], p[0]); + pp_map_tatep_k1(e1, p[0], q[0]); + TEST_ASSERT(fp_cmp_dig(e1, 1) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("tate pairing is bilinear") { + ep_rand(p[0]); + ep_rand(q[0]); + ep_psi(q[0], q[0]); + bn_rand_mod(k, n); + ep_mul(r, q[0], k); + pp_map_tatep_k1(e1, p[0], r); + pp_map_tatep_k1(e2, p[0], q[0]); + fp_exp(e2, e2, k); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + ep_mul(p[0], p[0], k); + pp_map_tatep_k1(e2, p[0], q[0]); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + ep_dbl(p[0], p[0]); + pp_map_tatep_k1(e2, p[0], q[0]); + fp_sqr(e1, e1); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + ep_dbl(q[0], q[0]); + pp_map_tatep_k1(e2, p[0], q[0]); + fp_sqr(e1, e1); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("tate multi-pairing is correct") { + ep_rand(p[i % 2]); + ep_rand(q[i % 2]); + ep_psi(q[i % 2], q[i % 2]); + pp_map_tatep_k1(e1, p[i % 2], q[i % 2]); + ep_rand(p[1 - (i % 2)]); + ep_set_infty(q[1 - (i % 2)]); + pp_map_sim_tatep_k1(e2, p, q, 2); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + ep_set_infty(p[1 - (i % 2)]); + ep_rand(q[1 - (i % 2)]); + pp_map_sim_tatep_k1(e2, p, q, 2); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + ep_set_infty(q[i % 2]); + pp_map_sim_tatep_k1(e2, p, q, 2); + TEST_ASSERT(fp_cmp_dig(e2, 1) == RLC_EQ, end); + ep_rand(p[0]); + ep_rand(q[0]); + pp_map_tatep_k1(e1, p[0], q[0]); + ep_rand(p[1]); + ep_rand(q[1]); + pp_map_tatep_k1(e2, p[1], q[1]); + fp_mul(e1, e1, e2); + pp_map_sim_tatep_k1(e2, p, q, 2); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + } TEST_END; +#endif + +#if PP_MAP == WEIL || !defined(STRIP) + TEST_CASE("weil pairing non-degeneracy is correct") { + ep_set_infty(p[0]); + pp_map_weilp_k1(e1, p[0], q[0]); + TEST_ASSERT(fp_cmp_dig(e1, 1) == RLC_EQ, end); + ep_rand(p[0]); + ep_set_infty(q[0]); + pp_map_weilp_k1(e1, p[0], q[0]); + TEST_ASSERT(fp_cmp_dig(e1, 1) == RLC_EQ, end); + ep_rand(p[0]); + pp_map_weilp_k1(e1, p[0], p[0]); + TEST_ASSERT(fp_cmp_dig(e1, 1) == RLC_EQ, end); + ep_rand(p[0]); + ep_rand(q[0]); + pp_map_weilp_k1(e1, p[0], q[0]); + TEST_ASSERT(fp_cmp_dig(e1, 1) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("weil pairing is bilinear") { + ep_rand(p[0]); + ep_rand(q[0]); + ep_psi(q[0], q[0]); + bn_rand_mod(k, n); + ep_mul(r, q[0], k); + pp_map_weilp_k1(e1, p[0], r); + pp_map_weilp_k1(e2, p[0], q[0]); + fp_exp(e2, e2, k); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + ep_mul(p[0], p[0], k); + pp_map_weilp_k1(e2, p[0], q[0]); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + ep_dbl(p[0], p[0]); + pp_map_weilp_k1(e2, p[0], q[0]); + fp_sqr(e1, e1); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + ep_dbl(q[0], q[0]); + pp_map_weilp_k1(e2, p[0], q[0]); + fp_sqr(e1, e1); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("weil multi-pairing is correct") { + ep_rand(p[i % 2]); + ep_rand(q[i % 2]); + pp_map_weilp_k1(e1, p[i % 2], q[i % 2]); + ep_rand(p[1 - (i % 2)]); + ep_set_infty(q[1 - (i % 2)]); + pp_map_sim_weilp_k1(e2, p, q, 2); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + ep_set_infty(p[1 - (i % 2)]); + ep_rand(q[1 - (i % 2)]); + pp_map_sim_weilp_k1(e2, p, q, 2); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + ep_set_infty(q[i % 2]); + pp_map_sim_weilp_k1(e2, p, q, 2); + TEST_ASSERT(fp_cmp_dig(e2, 1) == RLC_EQ, end); + ep_rand(p[0]); + ep_rand(q[0]); + pp_map_weilp_k1(e1, p[0], q[0]); + ep_rand(p[1]); + ep_rand(q[1]); + pp_map_weilp_k1(e2, p[1], q[1]); + fp_mul(e1, e1, e2); + pp_map_sim_weilp_k1(e2, p, q, 2); + TEST_ASSERT(fp_cmp(e1, e2) == RLC_EQ, end); + } TEST_END; +#endif + } + RLC_CATCH_ANY { + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + } + code = RLC_OK; + end: + bn_free(n); + bn_free(k); + ep_free(r); + fp_free(e1); + fp_free(e2); + + for (j = 0; j < 2; j++) { + ep_free(p[j]); + ep2_free(q[j]); + } + + return code; +} + static int addition2(void) { int code = RLC_ERR; bn_t k, n; @@ -327,29 +776,29 @@ static int pairing2(void) { } TEST_END; TEST_CASE("multi-pairing is correct") { - ep_rand(p[i % 2]); - ep_rand(q[i % 2]); - pp_map_k2(e1, p[i % 2], q[i % 2]); - ep_rand(p[1 - (i % 2)]); - ep_set_infty(q[1 - (i % 2)]); - pp_map_sim_k2(e2, p, q, 2); - TEST_ASSERT(fp2_cmp(e1, e2) == RLC_EQ, end); - ep_set_infty(p[1 - (i % 2)]); - ep_rand(q[1 - (i % 2)]); - pp_map_sim_k2(e2, p, q, 2); - TEST_ASSERT(fp2_cmp(e1, e2) == RLC_EQ, end); - ep_set_infty(q[i % 2]); - pp_map_sim_k2(e2, p, q, 2); - TEST_ASSERT(fp2_cmp_dig(e2, 1) == RLC_EQ, end); - ep_rand(p[0]); - ep_rand(q[0]); - pp_map_k2(e1, p[0], q[0]); - ep_rand(p[1]); - ep_rand(q[1]); - pp_map_k2(e2, p[1], q[1]); - fp2_mul(e1, e1, e2); - pp_map_sim_k2(e2, p, q, 2); - TEST_ASSERT(fp2_cmp(e1, e2) == RLC_EQ, end); + ep_rand(p[i % 2]); + ep_rand(q[i % 2]); + pp_map_k2(e1, p[i % 2], q[i % 2]); + ep_rand(p[1 - (i % 2)]); + ep_set_infty(q[1 - (i % 2)]); + pp_map_sim_k2(e2, p, q, 2); + TEST_ASSERT(fp2_cmp(e1, e2) == RLC_EQ, end); + ep_set_infty(p[1 - (i % 2)]); + ep_rand(q[1 - (i % 2)]); + pp_map_sim_k2(e2, p, q, 2); + TEST_ASSERT(fp2_cmp(e1, e2) == RLC_EQ, end); + ep_set_infty(q[i % 2]); + pp_map_sim_k2(e2, p, q, 2); + TEST_ASSERT(fp2_cmp_dig(e2, 1) == RLC_EQ, end); + ep_rand(p[0]); + ep_rand(q[0]); + pp_map_k2(e1, p[0], q[0]); + ep_rand(p[1]); + ep_rand(q[1]); + pp_map_k2(e2, p[1], q[1]); + fp2_mul(e1, e1, e2); + pp_map_sim_k2(e2, p, q, 2); + TEST_ASSERT(fp2_cmp(e1, e2) == RLC_EQ, end); } TEST_END; #if PP_MAP == TATEP || PP_MAP == OATEP || !defined(STRIP) @@ -549,7 +998,7 @@ static int doubling8(void) { fp_neg(p->y, p->y); pp_dbl_k8_basic(e2, r, q, p); pp_exp_k8(e2, e2); -#if EP_ADD == PROJC +#if EP_ADD == PROJC || EP_ADD == JACOB /* Precompute. */ fp_neg(p->y, p->y); fp_neg(p->x, p->x); @@ -1177,187 +1626,724 @@ static int pairing12(void) { TEST_CASE("tate pairing is bilinear") { ep_rand(p[0]); - ep2_rand(q[0]); + ep2_rand(q[0]); + bn_rand_mod(k, n); + ep2_mul(r, q[0], k); + pp_map_tatep_k12(e1, p[0], r); + pp_map_tatep_k12(e2, p[0], q[0]); + fp12_exp(e2, e2, k); + TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + ep_mul(p[0], p[0], k); + pp_map_tatep_k12(e2, p[0], q[0]); + TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + ep_dbl(p[0], p[0]); + pp_map_tatep_k12(e2, p[0], q[0]); + fp12_sqr(e1, e1); + TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + ep2_dbl(q[0], q[0]); + pp_map_tatep_k12(e2, p[0], q[0]); + fp12_sqr(e1, e1); + TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("tate multi-pairing is correct") { + ep_rand(p[i % 2]); + ep2_rand(q[i % 2]); + pp_map_tatep_k12(e1, p[i % 2], q[i % 2]); + ep_rand(p[1 - (i % 2)]); + ep2_set_infty(q[1 - (i % 2)]); + pp_map_sim_tatep_k12(e2, p, q, 2); + TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + ep_set_infty(p[1 - (i % 2)]); + ep2_rand(q[1 - (i % 2)]); + pp_map_sim_tatep_k12(e2, p, q, 2); + TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + ep2_set_infty(q[i % 2]); + pp_map_sim_tatep_k12(e2, p, q, 2); + TEST_ASSERT(fp12_cmp_dig(e2, 1) == RLC_EQ, end); + ep_rand(p[0]); + ep2_rand(q[0]); + pp_map_tatep_k12(e1, p[0], q[0]); + ep_rand(p[1]); + ep2_rand(q[1]); + pp_map_tatep_k12(e2, p[1], q[1]); + fp12_mul(e1, e1, e2); + pp_map_sim_tatep_k12(e2, p, q, 2); + TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + ep_neg(p[1], p[0]); + ep2_copy(q[1], q[0]); + pp_map_sim_tatep_k12(e1, p, q, 2); + TEST_ASSERT(fp12_cmp_dig(e1, 1) == RLC_EQ, end); + } TEST_END; +#endif + +#if PP_MAP == WEIL || !defined(STRIP) + TEST_CASE("weil pairing non-degeneracy is correct") { + ep_rand(p[0]); + ep2_rand(q[0]); + pp_map_weilp_k12(e1, p[0], q[0]); + TEST_ASSERT(fp12_cmp_dig(e1, 1) != RLC_EQ, end); + ep_set_infty(p[0]); + pp_map_weilp_k12(e1, p[0], q[0]); + TEST_ASSERT(fp12_cmp_dig(e1, 1) == RLC_EQ, end); + ep_rand(p[0]); + ep2_set_infty(q[0]); + pp_map_weilp_k12(e1, p[0], q[0]); + TEST_ASSERT(fp12_cmp_dig(e1, 1) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("weil pairing is bilinear") { + ep_rand(p[0]); + ep2_rand(q[0]); + bn_rand_mod(k, n); + ep2_mul(r, q[0], k); + pp_map_weilp_k12(e1, p[0], r); + pp_map_weilp_k12(e2, p[0], q[0]); + fp12_exp(e2, e2, k); + TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + ep_mul(p[0], p[0], k); + pp_map_weilp_k12(e2, p[0], q[0]); + TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + ep_dbl(p[0], p[0]); + pp_map_weilp_k12(e2, p[0], q[0]); + fp12_sqr(e1, e1); + TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + ep2_dbl(q[0], q[0]); + pp_map_weilp_k12(e2, p[0], q[0]); + fp12_sqr(e1, e1); + TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("weil multi-pairing is correct") { + ep_rand(p[i % 2]); + ep2_rand(q[i % 2]); + pp_map_weilp_k12(e1, p[i % 2], q[i % 2]); + ep_rand(p[1 - (i % 2)]); + ep2_set_infty(q[1 - (i % 2)]); + pp_map_sim_weilp_k12(e2, p, q, 2); + TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + ep_set_infty(p[1 - (i % 2)]); + ep2_rand(q[1 - (i % 2)]); + pp_map_sim_weilp_k12(e2, p, q, 2); + TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + ep2_set_infty(q[i % 2]); + pp_map_sim_weilp_k12(e2, p, q, 2); + TEST_ASSERT(fp12_cmp_dig(e2, 1) == RLC_EQ, end); + ep_rand(p[0]); + ep2_rand(q[0]); + pp_map_weilp_k12(e1, p[0], q[0]); + ep_rand(p[1]); + ep2_rand(q[1]); + pp_map_weilp_k12(e2, p[1], q[1]); + fp12_mul(e1, e1, e2); + pp_map_sim_weilp_k12(e2, p, q, 2); + TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + ep_neg(p[1], p[0]); + ep2_copy(q[1], q[0]); + pp_map_sim_weilp_k12(e1, p, q, 2); + TEST_ASSERT(fp12_cmp_dig(e1, 1) == RLC_EQ, end); + } TEST_END; +#endif + +#if PP_MAP == OATEP || !defined(STRIP) + TEST_CASE("optimal ate pairing non-degeneracy is correct") { + ep_rand(p[0]); + ep2_rand(q[0]); + pp_map_oatep_k12(e1, p[0], q[0]); + TEST_ASSERT(fp12_cmp_dig(e1, 1) != RLC_EQ, end); + ep_set_infty(p[0]); + pp_map_oatep_k12(e1, p[0], q[0]); + TEST_ASSERT(fp12_cmp_dig(e1, 1) == RLC_EQ, end); + ep_rand(p[0]); + ep2_set_infty(q[0]); + pp_map_oatep_k12(e1, p[0], q[0]); + TEST_ASSERT(fp12_cmp_dig(e1, 1) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("optimal ate pairing is bilinear") { + ep_rand(p[0]); + ep2_rand(q[0]); + bn_rand_mod(k, n); + ep2_mul(r, q[0], k); + pp_map_oatep_k12(e1, p[0], r); + ep_mul(p[0], p[0], k); + pp_map_oatep_k12(e2, p[0], q[0]); + TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + ep_dbl(p[0], p[0]); + pp_map_oatep_k12(e2, p[0], q[0]); + fp12_sqr(e1, e1); + TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + ep2_dbl(q[0], q[0]); + pp_map_oatep_k12(e2, p[0], q[0]); + fp12_sqr(e1, e1); + TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("optimal ate multi-pairing is correct") { + ep_rand(p[i % 2]); + ep2_rand(q[i % 2]); + pp_map_oatep_k12(e1, p[i % 2], q[i % 2]); + ep_rand(p[1 - (i % 2)]); + ep2_set_infty(q[1 - (i % 2)]); + pp_map_sim_oatep_k12(e2, p, q, 2); + TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + ep_set_infty(p[1 - (i % 2)]); + ep2_rand(q[1 - (i % 2)]); + pp_map_sim_oatep_k12(e2, p, q, 2); + TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + ep2_set_infty(q[i % 2]); + pp_map_sim_oatep_k12(e2, p, q, 2); + TEST_ASSERT(fp12_cmp_dig(e2, 1) == RLC_EQ, end); + ep_rand(p[0]); + ep2_rand(q[0]); + pp_map_oatep_k12(e1, p[0], q[0]); + ep_rand(p[1]); + ep2_rand(q[1]); + pp_map_oatep_k12(e2, p[1], q[1]); + fp12_mul(e1, e1, e2); + pp_map_sim_oatep_k12(e2, p, q, 2); + TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + ep_neg(p[1], p[0]); + ep2_copy(q[1], q[0]); + pp_map_sim_oatep_k12(e1, p, q, 2); + TEST_ASSERT(fp12_cmp_dig(e1, 1) == RLC_EQ, end); + } TEST_END; +#endif + } + RLC_CATCH_ANY { + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + } + code = RLC_OK; + end: + bn_free(n); + bn_free(k); + fp12_free(e1); + fp12_free(e2); + ep2_free(r); + + for (j = 0; j < 2; j++) { + ep_free(p[j]); + ep2_free(q[j]); + } + return code; +} + +static int doubling16(void) { + int code = RLC_ERR; + bn_t k, n; + ep_t p; + ep4_t q, r, s; + fp16_t e1, e2; + + bn_null(k); + bn_null(n); + ep_null(p); + ep4_null(q); + ep4_null(r); + ep4_null(s); + fp16_null(e1); + fp16_null(e2); + + RLC_TRY { + bn_new(n); + bn_new(k); + ep_new(p); + ep4_new(q); + ep4_new(r); + ep4_new(s); + fp16_new(e1); + fp16_new(e2); + + ep_curve_get_ord(n); + + TEST_CASE("miller doubling is correct") { + ep_rand(p); + ep4_rand(q); + ep4_rand(r); + pp_dbl_k16(e1, r, q, p); + pp_norm_k16(r, r); + ep4_dbl(s, q); + ep4_norm(s, s); + TEST_ASSERT(ep4_cmp(r, s) == RLC_EQ, end); + } TEST_END; + +#if EP_ADD == BASIC || !defined(STRIP) + TEST_CASE("miller doubling in affine coordinates is correct") { + ep_rand(p); + ep4_rand(q); + ep4_rand(r); + fp16_zero(e1); + fp16_zero(e2); + fp_neg(p->y, p->y); + pp_dbl_k16_basic(e2, r, q, p); + pp_exp_k16(e2, e2); +#if EP_ADD == PROJC || EP_ADD == JACOB + /* Precompute. */ + fp_neg(p->y, p->y); + fp_neg(p->x, p->x); +#endif + pp_dbl_k16(e1, r, q, p); + pp_exp_k16(e1, e1); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); + } TEST_END; +#endif + +#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP) + TEST_CASE("miller doubling in projective coordinates is correct") { + ep_rand(p); + ep4_rand(q); + ep4_rand(r); + fp16_zero(e1); + fp16_zero(e2); + /* Precompute. */ + fp_neg(p->x, p->x); + pp_dbl_k16_projc(e2, r, q, p); + pp_exp_k16(e2, e2); +#if EP_ADD == BASIC + /* Revert and fix precomputing. */ + fp_neg(p->x, p->x); + fp_neg(p->y, p->y); +#endif + pp_dbl_k16(e1, r, q, p); + pp_exp_k16(e1, e1); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); + } TEST_END; + +#if PP_EXT == BASIC || !defined(STRIP) + TEST_CASE("basic projective miller doubling is correct") { + ep_rand(p); + ep4_rand(q); + ep4_rand(r); + fp16_zero(e1); + fp16_zero(e2); + pp_dbl_k16_projc(e1, r, q, p); + pp_dbl_k16_projc_basic(e2, r, q, p); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); + } TEST_END; +#endif + +#if PP_EXT == LAZYR || !defined(STRIP) + TEST_CASE("lazy-reduced projective miller doubling is consistent") { + ep_rand(p); + ep4_rand(q); + ep4_rand(r); + fp16_zero(e1); + fp16_zero(e2); + pp_dbl_k16_projc(e1, r, q, p); + pp_dbl_k16_projc_lazyr(e2, r, q, p); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); + } TEST_END; +#endif +#endif /* EP_ADD = PROJC */ + } + RLC_CATCH_ANY { + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + } + code = RLC_OK; + end: + bn_free(n); + bn_free(k); + ep_free(p); + ep4_free(q); + ep4_free(r); + ep4_free(s); + fp16_free(e1); + fp16_free(e2); + return code; +} + +static int addition16(void) { + int code = RLC_ERR; + bn_t k, n; + ep_t p; + ep4_t q, r, s; + fp16_t e1, e2; + + bn_null(k); + bn_null(n); + ep_null(p); + ep4_null(q); + ep4_null(r); + ep4_null(s); + fp16_null(e1); + fp16_null(e2); + + RLC_TRY { + bn_new(n); + bn_new(k); + ep_new(p); + ep4_new(q); + ep4_new(r); + ep4_new(s); + fp16_new(e1); + fp16_new(e2); + + ep_curve_get_ord(n); + + TEST_CASE("miller addition is correct") { + ep_rand(p); + ep4_curve_get_gen(q); + ep4_dbl(r, q); + ep4_norm(r, r); + ep4_copy(s, r); + pp_add_k16(e1, r, q, p); + pp_norm_k16(r, r); + ep4_add(s, s, q); + ep4_norm(s, s); + TEST_ASSERT(ep4_cmp(r, s) == RLC_EQ, end); + } TEST_END; + +#if EP_ADD == BASIC || !defined(STRIP) + TEST_CASE("miller addition in affine coordinates is correct") { + ep_rand(p); + ep4_curve_get_gen(q); + ep4_dbl(r, q); + ep4_norm(r, r); + ep4_copy(s, r); + fp16_zero(e1); + fp16_zero(e2); +#if EP_ADD == PROJC + /* Precompute. */ + fp_neg(p->x, p->x); +#else + fp_neg(p->y, p->y); +#endif + pp_add_k16(e1, r, q, p); + pp_exp_k16(e1, e1); +#if EP_ADD == PROJC + /* Revert precompute. */ + fp_neg(p->x, p->x); + fp_neg(p->y, p->y); +#endif + pp_add_k16_basic(e2, s, q, p); + pp_exp_k16(e2, e2); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); + } TEST_END; +#endif + +#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP) + TEST_CASE("miller addition in projective coordinates is correct") { + ep_rand(p); + ep4_curve_get_gen(q); + ep4_dbl(r, q); + ep4_norm(r, r); + ep4_copy(s, r); + fp16_zero(e1); + fp16_zero(e2); +#if EP_ADD == PROJC + /* Precompute. */ + fp_neg(p->x, p->x); +#else + fp_neg(p->y, p->y); +#endif + pp_add_k16(e1, r, q, p); + pp_exp_k16(e1, e1); +#if EP_ADD == BASIC + fp_neg(p->x, p->x); + fp_neg(p->y, p->y); +#endif + pp_add_k16_projc(e2, s, q, p); + pp_exp_k16(e2, e2); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); + } TEST_END; +#endif + } + RLC_CATCH_ANY { + util_print("FATAL ERROR!\n"); + RLC_ERROR(end); + } + code = RLC_OK; + end: + bn_free(n); + bn_free(k); + ep_free(p); + ep4_free(q); + ep4_free(r); + ep4_free(s); + fp16_free(e1); + fp16_free(e2); + return code; +} + +static int pairing16(void) { + int j, code = RLC_ERR; + bn_t k, n; + ep_t p[2]; + ep4_t q[2], r; + fp16_t e1, e2; + + bn_null(k); + bn_null(n); + fp16_null(e1); + fp16_null(e2); + ep4_null(r); + + RLC_TRY { + bn_new(n); + bn_new(k); + fp16_new(e1); + fp16_new(e2); + ep4_new(r); + + for (j = 0; j < 2; j++) { + ep_null(p[j]); + ep4_null(q[j]); + ep_new(p[j]); + ep4_new(q[j]); + } + + ep_curve_get_ord(n); + + TEST_CASE("pairing non-degeneracy is correct") { + ep_rand(p[0]); + ep4_rand(q[0]); + pp_map_k16(e1, p[0], q[0]); + TEST_ASSERT(fp16_cmp_dig(e1, 1) != RLC_EQ, end); + ep_set_infty(p[0]); + pp_map_k16(e1, p[0], q[0]); + TEST_ASSERT(fp16_cmp_dig(e1, 1) == RLC_EQ, end); + ep_rand(p[0]); + ep4_set_infty(q[0]); + pp_map_k16(e1, p[0], q[0]); + TEST_ASSERT(fp16_cmp_dig(e1, 1) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("pairing is bilinear") { + ep_rand(p[0]); + ep4_rand(q[0]); + bn_rand_mod(k, n); + ep4_mul(r, q[0], k); + pp_map_k16(e1, p[0], r); + pp_map_k16(e2, p[0], q[0]); + fp16_exp(e2, e2, k); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); + ep_mul(p[0], p[0], k); + pp_map_k16(e2, p[0], q[0]); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); + ep_dbl(p[0], p[0]); + pp_map_k16(e2, p[0], q[0]); + fp16_sqr(e1, e1); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); + ep4_dbl(q[0], q[0]); + pp_map_k16(e2, p[0], q[0]); + fp16_sqr(e1, e1); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("multi-pairing is correct") { + ep_rand(p[i % 2]); + ep4_rand(q[i % 2]); + pp_map_k16(e1, p[i % 2], q[i % 2]); + ep_rand(p[1 - (i % 2)]); + ep4_set_infty(q[1 - (i % 2)]); + pp_map_sim_k16(e2, p, q, 2); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); + ep_set_infty(p[1 - (i % 2)]); + ep4_rand(q[1 - (i % 2)]); + pp_map_sim_k16(e2, p, q, 2); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); + ep4_set_infty(q[i % 2]); + pp_map_sim_k16(e2, p, q, 2); + TEST_ASSERT(fp16_cmp_dig(e2, 1) == RLC_EQ, end); + ep_rand(p[0]); + ep4_rand(q[0]); + pp_map_k16(e1, p[0], q[0]); + ep_rand(p[1]); + ep4_rand(q[1]); + pp_map_k16(e2, p[1], q[1]); + fp16_mul(e1, e1, e2); + pp_map_sim_k16(e2, p, q, 2); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); + } TEST_END; + +#if PP_MAP == TATEP || !defined(STRIP) + TEST_CASE("tate pairing non-degeneracy is correct") { + ep_rand(p[0]); + ep4_rand(q[0]); + pp_map_tatep_k16(e1, p[0], q[0]); + TEST_ASSERT(fp16_cmp_dig(e1, 1) != RLC_EQ, end); + ep_set_infty(p[0]); + pp_map_tatep_k16(e1, p[0], q[0]); + TEST_ASSERT(fp16_cmp_dig(e1, 1) == RLC_EQ, end); + ep_rand(p[0]); + ep4_set_infty(q[0]); + pp_map_tatep_k16(e1, p[0], q[0]); + TEST_ASSERT(fp16_cmp_dig(e1, 1) == RLC_EQ, end); + } TEST_END; + + TEST_CASE("tate pairing is bilinear") { + ep_rand(p[0]); + ep4_rand(q[0]); bn_rand_mod(k, n); - ep2_mul(r, q[0], k); - pp_map_tatep_k12(e1, p[0], r); - pp_map_tatep_k12(e2, p[0], q[0]); - fp12_exp(e2, e2, k); - TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + ep4_mul(r, q[0], k); + pp_map_tatep_k16(e1, p[0], r); + pp_map_tatep_k16(e2, p[0], q[0]); + fp16_exp(e2, e2, k); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); ep_mul(p[0], p[0], k); - pp_map_tatep_k12(e2, p[0], q[0]); - TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + pp_map_tatep_k16(e2, p[0], q[0]); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); ep_dbl(p[0], p[0]); - pp_map_tatep_k12(e2, p[0], q[0]); - fp12_sqr(e1, e1); - TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); - ep2_dbl(q[0], q[0]); - pp_map_tatep_k12(e2, p[0], q[0]); - fp12_sqr(e1, e1); - TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + pp_map_tatep_k16(e2, p[0], q[0]); + fp16_sqr(e1, e1); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); + ep4_dbl(q[0], q[0]); + pp_map_tatep_k16(e2, p[0], q[0]); + fp16_sqr(e1, e1); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); } TEST_END; TEST_CASE("tate multi-pairing is correct") { ep_rand(p[i % 2]); - ep2_rand(q[i % 2]); - pp_map_tatep_k12(e1, p[i % 2], q[i % 2]); + ep4_rand(q[i % 2]); + pp_map_tatep_k16(e1, p[i % 2], q[i % 2]); ep_rand(p[1 - (i % 2)]); - ep2_set_infty(q[1 - (i % 2)]); - pp_map_sim_tatep_k12(e2, p, q, 2); - TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + ep4_set_infty(q[1 - (i % 2)]); + pp_map_sim_tatep_k16(e2, p, q, 2); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); ep_set_infty(p[1 - (i % 2)]); - ep2_rand(q[1 - (i % 2)]); - pp_map_sim_tatep_k12(e2, p, q, 2); - TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); - ep2_set_infty(q[i % 2]); - pp_map_sim_tatep_k12(e2, p, q, 2); - TEST_ASSERT(fp12_cmp_dig(e2, 1) == RLC_EQ, end); + ep4_rand(q[1 - (i % 2)]); + pp_map_sim_tatep_k16(e2, p, q, 2); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); + ep4_set_infty(q[i % 2]); + pp_map_sim_tatep_k16(e2, p, q, 2); + TEST_ASSERT(fp16_cmp_dig(e2, 1) == RLC_EQ, end); ep_rand(p[0]); - ep2_rand(q[0]); - pp_map_tatep_k12(e1, p[0], q[0]); + ep4_rand(q[0]); + pp_map_tatep_k16(e1, p[0], q[0]); ep_rand(p[1]); - ep2_rand(q[1]); - pp_map_tatep_k12(e2, p[1], q[1]); - fp12_mul(e1, e1, e2); - pp_map_sim_tatep_k12(e2, p, q, 2); - TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); - ep_neg(p[1], p[0]); - ep2_copy(q[1], q[0]); - pp_map_sim_tatep_k12(e1, p, q, 2); - TEST_ASSERT(fp12_cmp_dig(e1, 1) == RLC_EQ, end); + ep4_rand(q[1]); + pp_map_tatep_k16(e2, p[1], q[1]); + fp16_mul(e1, e1, e2); + pp_map_sim_tatep_k16(e2, p, q, 2); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); } TEST_END; #endif #if PP_MAP == WEIL || !defined(STRIP) TEST_CASE("weil pairing non-degeneracy is correct") { ep_rand(p[0]); - ep2_rand(q[0]); - pp_map_weilp_k12(e1, p[0], q[0]); - TEST_ASSERT(fp12_cmp_dig(e1, 1) != RLC_EQ, end); + ep4_rand(q[0]); + pp_map_weilp_k16(e1, p[0], q[0]); + TEST_ASSERT(fp16_cmp_dig(e1, 1) != RLC_EQ, end); ep_set_infty(p[0]); - pp_map_weilp_k12(e1, p[0], q[0]); - TEST_ASSERT(fp12_cmp_dig(e1, 1) == RLC_EQ, end); + pp_map_weilp_k16(e1, p[0], q[0]); + TEST_ASSERT(fp16_cmp_dig(e1, 1) == RLC_EQ, end); ep_rand(p[0]); - ep2_set_infty(q[0]); - pp_map_weilp_k12(e1, p[0], q[0]); - TEST_ASSERT(fp12_cmp_dig(e1, 1) == RLC_EQ, end); + ep4_set_infty(q[0]); + pp_map_weilp_k16(e1, p[0], q[0]); + TEST_ASSERT(fp16_cmp_dig(e1, 1) == RLC_EQ, end); } TEST_END; TEST_CASE("weil pairing is bilinear") { ep_rand(p[0]); - ep2_rand(q[0]); + ep4_rand(q[0]); bn_rand_mod(k, n); - ep2_mul(r, q[0], k); - pp_map_weilp_k12(e1, p[0], r); - pp_map_weilp_k12(e2, p[0], q[0]); - fp12_exp(e2, e2, k); - TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + ep4_mul(r, q[0], k); + pp_map_weilp_k16(e1, p[0], r); + pp_map_weilp_k16(e2, p[0], q[0]); + fp16_exp(e2, e2, k); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); ep_mul(p[0], p[0], k); - pp_map_weilp_k12(e2, p[0], q[0]); - TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + pp_map_weilp_k16(e2, p[0], q[0]); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); ep_dbl(p[0], p[0]); - pp_map_weilp_k12(e2, p[0], q[0]); - fp12_sqr(e1, e1); - TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); - ep2_dbl(q[0], q[0]); - pp_map_weilp_k12(e2, p[0], q[0]); - fp12_sqr(e1, e1); - TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + pp_map_weilp_k16(e2, p[0], q[0]); + fp16_sqr(e1, e1); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); + ep4_dbl(q[0], q[0]); + pp_map_weilp_k16(e2, p[0], q[0]); + fp16_sqr(e1, e1); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); } TEST_END; TEST_CASE("weil multi-pairing is correct") { ep_rand(p[i % 2]); - ep2_rand(q[i % 2]); - pp_map_weilp_k12(e1, p[i % 2], q[i % 2]); + ep4_rand(q[i % 2]); + pp_map_weilp_k16(e1, p[i % 2], q[i % 2]); ep_rand(p[1 - (i % 2)]); - ep2_set_infty(q[1 - (i % 2)]); - pp_map_sim_weilp_k12(e2, p, q, 2); - TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + ep4_set_infty(q[1 - (i % 2)]); + pp_map_sim_weilp_k16(e2, p, q, 2); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); ep_set_infty(p[1 - (i % 2)]); - ep2_rand(q[1 - (i % 2)]); - pp_map_sim_weilp_k12(e2, p, q, 2); - TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); - ep2_set_infty(q[i % 2]); - pp_map_sim_weilp_k12(e2, p, q, 2); - TEST_ASSERT(fp12_cmp_dig(e2, 1) == RLC_EQ, end); + ep4_rand(q[1 - (i % 2)]); + pp_map_sim_weilp_k16(e2, p, q, 2); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); + ep4_set_infty(q[i % 2]); + pp_map_sim_weilp_k16(e2, p, q, 2); + TEST_ASSERT(fp16_cmp_dig(e2, 1) == RLC_EQ, end); ep_rand(p[0]); - ep2_rand(q[0]); - pp_map_weilp_k12(e1, p[0], q[0]); + ep4_rand(q[0]); + pp_map_weilp_k16(e1, p[0], q[0]); ep_rand(p[1]); - ep2_rand(q[1]); - pp_map_weilp_k12(e2, p[1], q[1]); - fp12_mul(e1, e1, e2); - pp_map_sim_weilp_k12(e2, p, q, 2); - TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); - ep_neg(p[1], p[0]); - ep2_copy(q[1], q[0]); - pp_map_sim_weilp_k12(e1, p, q, 2); - TEST_ASSERT(fp12_cmp_dig(e1, 1) == RLC_EQ, end); + ep4_rand(q[1]); + pp_map_weilp_k16(e2, p[1], q[1]); + fp16_mul(e1, e1, e2); + pp_map_sim_weilp_k16(e2, p, q, 2); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); } TEST_END; #endif #if PP_MAP == OATEP || !defined(STRIP) TEST_CASE("optimal ate pairing non-degeneracy is correct") { ep_rand(p[0]); - ep2_rand(q[0]); - pp_map_oatep_k12(e1, p[0], q[0]); - TEST_ASSERT(fp12_cmp_dig(e1, 1) != RLC_EQ, end); + ep4_rand(q[0]); + pp_map_oatep_k16(e1, p[0], q[0]); + TEST_ASSERT(fp16_cmp_dig(e1, 1) != RLC_EQ, end); ep_set_infty(p[0]); - pp_map_oatep_k12(e1, p[0], q[0]); - TEST_ASSERT(fp12_cmp_dig(e1, 1) == RLC_EQ, end); + pp_map_oatep_k16(e1, p[0], q[0]); + TEST_ASSERT(fp16_cmp_dig(e1, 1) == RLC_EQ, end); ep_rand(p[0]); - ep2_set_infty(q[0]); - pp_map_oatep_k12(e1, p[0], q[0]); - TEST_ASSERT(fp12_cmp_dig(e1, 1) == RLC_EQ, end); + ep4_set_infty(q[0]); + pp_map_oatep_k16(e1, p[0], q[0]); + TEST_ASSERT(fp16_cmp_dig(e1, 1) == RLC_EQ, end); } TEST_END; TEST_CASE("optimal ate pairing is bilinear") { ep_rand(p[0]); - ep2_rand(q[0]); + ep4_rand(q[0]); bn_rand_mod(k, n); - ep2_mul(r, q[0], k); - pp_map_oatep_k12(e1, p[0], r); + ep4_mul(r, q[0], k); + pp_map_oatep_k16(e1, p[0], r); ep_mul(p[0], p[0], k); - pp_map_oatep_k12(e2, p[0], q[0]); - TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + pp_map_oatep_k16(e2, p[0], q[0]); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); ep_dbl(p[0], p[0]); - pp_map_oatep_k12(e2, p[0], q[0]); - fp12_sqr(e1, e1); - TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); - ep2_dbl(q[0], q[0]); - pp_map_oatep_k12(e2, p[0], q[0]); - fp12_sqr(e1, e1); - TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + pp_map_oatep_k16(e2, p[0], q[0]); + fp16_sqr(e1, e1); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); + ep4_dbl(q[0], q[0]); + pp_map_oatep_k16(e2, p[0], q[0]); + fp16_sqr(e1, e1); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); } TEST_END; TEST_CASE("optimal ate multi-pairing is correct") { ep_rand(p[i % 2]); - ep2_rand(q[i % 2]); - pp_map_oatep_k12(e1, p[i % 2], q[i % 2]); + ep4_rand(q[i % 2]); + pp_map_oatep_k16(e1, p[i % 2], q[i % 2]); ep_rand(p[1 - (i % 2)]); - ep2_set_infty(q[1 - (i % 2)]); - pp_map_sim_oatep_k12(e2, p, q, 2); - TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); + ep4_set_infty(q[1 - (i % 2)]); + pp_map_sim_oatep_k16(e2, p, q, 2); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); ep_set_infty(p[1 - (i % 2)]); - ep2_rand(q[1 - (i % 2)]); - pp_map_sim_oatep_k12(e2, p, q, 2); - TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); - ep2_set_infty(q[i % 2]); - pp_map_sim_oatep_k12(e2, p, q, 2); - TEST_ASSERT(fp12_cmp_dig(e2, 1) == RLC_EQ, end); + ep4_rand(q[1 - (i % 2)]); + pp_map_sim_oatep_k16(e2, p, q, 2); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); + ep4_set_infty(q[i % 2]); + pp_map_sim_oatep_k16(e2, p, q, 2); + TEST_ASSERT(fp16_cmp_dig(e2, 1) == RLC_EQ, end); ep_rand(p[0]); - ep2_rand(q[0]); - pp_map_oatep_k12(e1, p[0], q[0]); + ep4_rand(q[0]); + pp_map_oatep_k16(e1, p[0], q[0]); ep_rand(p[1]); - ep2_rand(q[1]); - pp_map_oatep_k12(e2, p[1], q[1]); - fp12_mul(e1, e1, e2); - pp_map_sim_oatep_k12(e2, p, q, 2); - TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end); - ep_neg(p[1], p[0]); - ep2_copy(q[1], q[0]); - pp_map_sim_oatep_k12(e1, p, q, 2); - TEST_ASSERT(fp12_cmp_dig(e1, 1) == RLC_EQ, end); + ep4_rand(q[1]); + pp_map_oatep_k16(e2, p[1], q[1]); + fp16_mul(e1, e1, e2); + pp_map_sim_oatep_k16(e2, p, q, 2); + TEST_ASSERT(fp16_cmp(e1, e2) == RLC_EQ, end); } TEST_END; #endif } @@ -1369,13 +2355,13 @@ static int pairing12(void) { end: bn_free(n); bn_free(k); - fp12_free(e1); - fp12_free(e2); - ep2_free(r); + fp16_free(e1); + fp16_free(e2); + ep4_free(r); for (j = 0; j < 2; j++) { ep_free(p[j]); - ep2_free(q[j]); + ep4_free(q[j]); } return code; } @@ -2223,41 +3209,19 @@ static int pairing24(void) { return code; } -/* Put test vectors here until we implement E(Fp^8). */ -#define QX000 "266A6ACAA4B8DDCFBF97F09DFBEB01999BFBFF872276FA7700114F761E8971C6C25A53CC77E96BCC9579F63D8A39D641B8070B07EF40E93C301A5B49CE87110CC30E044BEE5A2D43" -#define QX001 "5009EEB2A67C52B79D0727B408A193FFCE76B4F80C8DCF4D61ECEE5471601CD7A94341F697CE9D375DB5470EA055B73C256CCC0AC12F52EAD276C26E001DDCE02DE634BEFCB9CC7C" -#define QX010 "11A8DDB59724C01696BE52862B5AC2C7E1C0C42EFCAF456A80F6C6D9F95F89649D5575DE3BA8D28D1012E14308DE1D8F15CE1617611F961032B0B5DFA27EF3E3670B9B537ACC66B9" -#define QX011 "4E8BDED03587581A173AD008DFF600EB24054E4CDDCA8D7BFABA2898822DB5ED701BF59BD3F108AD7C714B6A6C7ECB11A1BC5DEEC1D49AE7FCA597C43943A66441B03164975D9BE0" -#define QX100 "29E2751CAC7D0FBA8E12CC818BDE6F2A7173D3C2ED74EC1991B936071DEB1AED1E07CDF71EA3501BEB4645C86BDC8A575898303FF6A058C7062F079F594E5B865626D0C031CF7E44" -#define QX101 "2F3A1BE54DFFB814DA4AE6311B9B1EEE6198CDB9F36CE92084272416462F4D0AC9ACAC025FDA6D3D0D1C239FE8CE4B7F22A1D0F65582DDA36EEB328843FDE5C0BDA02E871796CC8E" -#define QX110 "2FEE7B15EB22B05476A462374860140DCC9F00910E0555918D6357F6E32E623B88B893647AD07B615F364093D6F6D2A7B7614590A8833385B5A833563C0DD6C89AF89D06428E8AFE" -#define QX111 "005082322BB5E610DC0E61E3D01B8BFF23D195117F58B1FA68EC04A6769FEB754A58742C7F729E2A684386C40EFB871CB3D32A040966155649DC45C49E6FB5DEE58DB1586CBFD33E" - -#define QY000 "3B603A4C408A402FB885B607C4A661BF92354D22F46945F222C6F51CCDEBF4006640346AE6BFD60F7E22240D4BF83EFDA1B575267A89597D7BC54FA4899BFBAAC4138E30C8DA55C0" -#define QY001 "35D3ECCC1F3C69A921E57CCDEA6C794A5ED01A53E19208854EA3B10D519CCCE64A30007CD7A57673567F2FFA070E5CE01C4E5C8BF1C61225DAC36A93C6524F4D0350C6358C67F85B" -#define QY010 "4228DA69A29E14E2CF00EC8FDD877CA9049DA161778A6ACE8DC275D4CE94C90AD9176280703AD9C6714A4865EF6160ED2FA7A5FC601025CF096AB6CF21B8FAA41421C7913DECF3B5" -#define QY011 "5273C1679E18D316C6988820E06335094FCCCD5E8FD870492EB96FCBC5B5494B2B9D0869C18309FF2D49CD80CF6E6FE1A660027A6E924831F8D5A070645A7B794BA7AE72507809AE" -#define QY100 "0ABD2F582F0D4C3C89770C13F02FF17CDEA5B22CDD661B6F82905ADCDC44E59900C5D09F8CAC90760CCC57D1987DE4BA21F34455E5B7394B68A7883E3F8D918AF308F0C3E6F98F4B" -#define QY101 "36FAE1DE9DD31FFE238526F618C14E5CB61EEA8E8E6D82235E43E45E306C5E60B4E5499BF4663516CE1202EF6CDE3B2E098E406B3186937483FC104A173707C6419F460A23ADF628" -#define QY110 "09E1BB455FCB47E98C5263B5098E2D148EC2EDEE5634B8F94F10AF9221D09BD60D28920342C11B1987A24B7F56AC4F5E290E7EA483727ED16FFC88C0F5EAD00892FDA66BA68FACE4" -#define QY111 "4F781C32F5CAFD446F299BE6BC600BF3482DF6ECAF4ABE3D410A7255B18A88DB77CC539CAC4A0D30A00690CCA8CC7661BCE042D0AC40FF8DC9171847A8E42696E4EF9DD8A5907A3D" - static int doubling48(void) { int code = RLC_ERR; bn_t k, n; ep_t p; - fp8_t qx, qy, qz, rx, ry, rz; + ep8_t q, r, s; fp48_t e1, e2; bn_null(k); bn_null(n); ep_null(p); - fp8_null(qx); - fp8_null(qy); - fp8_null(qz); - fp8_null(rx); - fp8_null(ry); - fp8_null(rz); + ep8_null(q); + ep8_null(r); + ep8_null(s); fp48_null(e1); fp48_null(e2); @@ -2265,70 +3229,40 @@ static int doubling48(void) { bn_new(n); bn_new(k); ep_new(p); - fp8_new(qx); - fp8_new(qy); - fp8_new(qz); - fp8_new(rx); - fp8_new(ry); - fp8_new(rz); + ep8_new(q); + ep8_new(r); + ep8_new(s); fp48_new(e1); fp48_new(e2); - fp_read_str(qx[0][0][0], QX000, strlen(QX000), 16); - fp_read_str(qx[0][0][1], QX001, strlen(QX001), 16); - fp_read_str(qx[0][1][0], QX010, strlen(QX010), 16); - fp_read_str(qx[0][1][1], QX011, strlen(QX011), 16); - fp_read_str(qx[1][0][0], QX100, strlen(QX100), 16); - fp_read_str(qx[1][0][1], QX101, strlen(QX101), 16); - fp_read_str(qx[1][1][0], QX110, strlen(QX110), 16); - fp_read_str(qx[1][1][1], QX111, strlen(QX111), 16); - - fp_read_str(qy[0][0][0], QY000, strlen(QY000), 16); - fp_read_str(qy[0][0][1], QY001, strlen(QY001), 16); - fp_read_str(qy[0][1][0], QY010, strlen(QY010), 16); - fp_read_str(qy[0][1][1], QY011, strlen(QY011), 16); - fp_read_str(qy[1][0][0], QY100, strlen(QY100), 16); - fp_read_str(qy[1][0][1], QY101, strlen(QY101), 16); - fp_read_str(qy[1][1][0], QY110, strlen(QY110), 16); - fp_read_str(qy[1][1][1], QY111, strlen(QY111), 16); - - fp8_set_dig(qz, 1); - ep_curve_get_ord(n); TEST_CASE("miller doubling is correct") { ep_rand(p); - fp8_copy(rx, qx); - fp8_copy(ry, qy); - fp8_copy(rz, qz); - pp_dbl_k48_projc(e1, rx, ry, rz, p); - fp8_inv(rz, rz); - fp8_mul(rx, rx, rz); - fp8_mul(ry, ry, rz); - pp_dbl_k48_basic(e2, qx, qy, p); - TEST_ASSERT(fp8_cmp(rx, qx) == RLC_EQ && fp8_cmp(ry, qy) == RLC_EQ, end); + ep8_rand(q); + ep8_rand(r); + pp_dbl_k48(e1, r, q, p); + pp_norm_k48(r, r); + ep8_dbl(s, q); + ep8_norm(s, s); + TEST_ASSERT(ep8_cmp(r, s) == RLC_EQ, end); } TEST_END; #if EP_ADD == BASIC || !defined(STRIP) TEST_CASE("miller doubling in affine coordinates is correct") { ep_rand(p); - fp8_copy(rx, qx); - fp8_copy(ry, qy); - fp8_copy(rz, qz); + ep8_rand(q); fp48_zero(e1); fp48_zero(e2); fp_neg(p->y, p->y); - pp_dbl_k48_basic(e2, rx, ry, p); + pp_dbl_k48_basic(e2, r, q, p); pp_exp_k48(e2, e2); #if EP_ADD == PROJC /* Precompute. */ fp_dbl(p->z, p->x); fp_add(p->x, p->z, p->x); #endif - fp8_copy(rx, qx); - fp8_copy(ry, qy); - fp8_copy(rz, qz); - pp_dbl_k48(e1, rx, ry, rz, p); + pp_dbl_k48(e1, r, q, p); pp_exp_k48(e1, e1); TEST_ASSERT(fp48_cmp(e1, e2) == RLC_EQ, end); } TEST_END; @@ -2337,25 +3271,20 @@ static int doubling48(void) { #if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP) TEST_CASE("miller doubling in projective coordinates is correct") { ep_rand(p); - fp8_copy(rx, qx); - fp8_copy(ry, qy); - fp8_copy(rz, qz); + ep8_rand(q); fp48_zero(e1); fp48_zero(e2); /* Precompute. */ fp_neg(p->y, p->y); fp_dbl(p->z, p->x); fp_add(p->x, p->z, p->x); - pp_dbl_k48_projc(e2, rx, ry, rz, p); + pp_dbl_k48_projc(e2, r, q, p); pp_exp_k48(e2, e2); #if EP_ADD == BASIC /* Revert precomputing. */ fp_hlv(p->x, p->z); #endif - fp8_copy(rx, qx); - fp8_copy(ry, qy); - fp8_copy(rz, qz); - pp_dbl_k48(e1, rx, ry, rz, p); + pp_dbl_k48(e1, r, q, p); pp_exp_k48(e1, e1); TEST_ASSERT(fp48_cmp(e1, e2) == RLC_EQ, end); } TEST_END; @@ -2370,12 +3299,9 @@ static int doubling48(void) { bn_free(n); bn_free(k); ep_free(p); - fp8_free(qx); - fp8_free(qy); - fp8_free(qz); - fp8_free(rx); - fp8_free(ry); - fp8_free(rz); + ep8_free(q); + ep8_free(r); + ep8_free(s); fp48_free(e1); fp48_free(e2); return code; @@ -2385,18 +3311,15 @@ static int addition48(void) { int code = RLC_ERR; bn_t k, n; ep_t p; - fp8_t qx, qy, qz, rx, ry, rz; + ep8_t q, r, s; fp48_t e1, e2; bn_null(k); bn_null(n); ep_null(p); - fp8_null(qx); - fp8_null(qy); - fp8_null(qz); - fp8_null(rx); - fp8_null(ry); - fp8_null(rz); + ep8_null(q); + ep8_null(r); + ep8_null(s); fp48_null(e1); fp48_null(e2); @@ -2404,104 +3327,53 @@ static int addition48(void) { bn_new(n); bn_new(k); ep_new(p); - fp8_new(qx); - fp8_new(qy); - fp8_new(qz); - fp8_new(rx); - fp8_new(ry); - fp8_new(rz); + ep8_new(q); + ep8_new(r); + ep8_new(s); fp48_new(e1); fp48_new(e2); - fp_read_str(qx[0][0][0], QX000, strlen(QX000), 16); - fp_read_str(qx[0][0][1], QX001, strlen(QX001), 16); - fp_read_str(qx[0][1][0], QX010, strlen(QX010), 16); - fp_read_str(qx[0][1][1], QX011, strlen(QX011), 16); - fp_read_str(qx[1][0][0], QX100, strlen(QX100), 16); - fp_read_str(qx[1][0][1], QX101, strlen(QX101), 16); - fp_read_str(qx[1][1][0], QX110, strlen(QX110), 16); - fp_read_str(qx[1][1][1], QX111, strlen(QX111), 16); - - fp_read_str(qy[0][0][0], QY000, strlen(QY000), 16); - fp_read_str(qy[0][0][1], QY001, strlen(QY001), 16); - fp_read_str(qy[0][1][0], QY010, strlen(QY010), 16); - fp_read_str(qy[0][1][1], QY011, strlen(QY011), 16); - fp_read_str(qy[1][0][0], QY100, strlen(QY100), 16); - fp_read_str(qy[1][0][1], QY101, strlen(QY101), 16); - fp_read_str(qy[1][1][0], QY110, strlen(QY110), 16); - fp_read_str(qy[1][1][1], QY111, strlen(QY111), 16); - - fp8_set_dig(qz, 1); - ep_curve_get_ord(n); TEST_CASE("miller addition is correct") { ep_rand(p); - fp8_copy(rx, qx); - fp8_copy(ry, qy); - fp8_copy(rz, qz); - pp_dbl_k48(e1, rx, ry, rz, p); - pp_add_k48_projc(e1, rx, ry, rz, qx, qy, p); - fp8_inv(rz, rz); - fp8_mul(rx, rx, rz); - fp8_mul(ry, ry, rz); - fp8_copy(e1[0][0], rx); - fp8_copy(e1[0][1], ry); - fp8_copy(rx, qx); - fp8_copy(ry, qy); - fp8_copy(rz, qz); - pp_dbl_k48(e2, rx, ry, rz, p); -#if EP_ADD == PROJC - fp8_inv(rz, rz); - fp8_mul(rx, rx, rz); - fp8_mul(ry, ry, rz); -#endif - pp_add_k48_basic(e2, rx, ry, qx, qy, p); - TEST_ASSERT(fp8_cmp(rx, e1[0][0]) == RLC_EQ && fp8_cmp(ry, e1[0][1]) == RLC_EQ, end); + ep8_rand(q); + ep8_rand(r); + ep8_copy(s, r); + pp_add_k48(e1, r, q, p); + pp_norm_k48(r, r); + ep8_add(s, s, q); + ep8_norm(s, s); + TEST_ASSERT(ep8_cmp(r, s) == RLC_EQ, end); } TEST_END; #if EP_ADD == BASIC || !defined(STRIP) TEST_CASE("miller addition in affine coordinates is correct") { ep_rand(p); - fp8_copy(rx, qx); - fp8_copy(ry, qy); - fp8_copy(rz, qz); + ep8_rand(q); + ep8_rand(r); + ep8_copy(s, r); fp48_zero(e1); fp48_zero(e2); - pp_dbl_k48(e1, rx, ry, rz, p); - pp_add_k48(e1, rx, ry, rz, qx, qy, p); + pp_add_k48(e1, r, q, p); pp_exp_k48(e1, e1); - fp8_copy(rx, qx); - fp8_copy(ry, qy); - fp8_copy(rz, qz); - pp_dbl_k48(e2, rx, ry, rz, p); -#if EP_ADD == PROJC - fp8_inv(rz, rz); - fp8_mul(rx, rx, rz); - fp8_mul(ry, ry, rz); -#endif - pp_add_k48_basic(e2, rx, ry, qx, qy, p); + pp_add_k48_basic(e2, s, q, p); pp_exp_k48(e2, e2); TEST_ASSERT(fp48_cmp(e1, e2) == RLC_EQ, end); } TEST_END; #endif -#if EP_ADD == BASIC || !defined(STRIP) +#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP) TEST_CASE("miller addition in projective coordinates is correct") { ep_rand(p); - fp8_copy(rx, qx); - fp8_copy(ry, qy); - fp8_copy(rz, qz); + ep8_rand(q); + ep8_rand(r); + ep8_copy(s, r); fp48_zero(e1); fp48_zero(e2); - pp_dbl_k48(e1, rx, ry, rz, p); - pp_add_k48(e1, rx, ry, rz, qx, qy, p); + pp_add_k48(e1, r, q, p); pp_exp_k48(e1, e1); - fp8_copy(rx, qx); - fp8_copy(ry, qy); - fp8_copy(rz, qz); - pp_dbl_k48(e2, rx, ry, rz, p); - pp_add_k48_projc(e2, rx, ry, rz, qx, qy, p); + pp_add_k48_projc(e2, s, q, p); pp_exp_k48(e2, e2); TEST_ASSERT(fp48_cmp(e1, e2) == RLC_EQ, end); } TEST_END; @@ -2516,87 +3388,108 @@ static int addition48(void) { bn_free(n); bn_free(k); ep_free(p); - fp8_free(qx); - fp8_free(qy); - fp8_free(qz); - fp8_free(rx); - fp8_free(ry); - fp8_free(rz); + ep8_free(q); + ep8_free(r); + ep8_free(s); fp48_free(e1); fp48_free(e2); return code; } static int pairing48(void) { - int code = RLC_ERR; + int j, code = RLC_ERR; bn_t k, n; - ep_t p; - fp8_t qx, qy, qz; + ep_t p[2]; + ep8_t q[2], r; fp48_t e1, e2; bn_null(k); bn_null(n); - ep_null(p); - fp8_null(qx); - fp8_null(qy); - fp8_null(qz); fp48_null(e1); fp48_null(e2); + ep8_null(r); RLC_TRY { bn_new(n); bn_new(k); - ep_new(p); - fp8_new(qx); - fp8_new(qy); - fp8_new(qz); fp48_new(e1); fp48_new(e2); + ep8_new(r); - ep_curve_get_ord(n); + for (j = 0; j < 2; j++) { + ep_null(p[j]); + ep8_null(q[j]); + ep_new(p[j]); + ep8_new(q[j]); + } - fp_read_str(qx[0][0][0], QX000, strlen(QX000), 16); - fp_read_str(qx[0][0][1], QX001, strlen(QX001), 16); - fp_read_str(qx[0][1][0], QX010, strlen(QX010), 16); - fp_read_str(qx[0][1][1], QX011, strlen(QX011), 16); - fp_read_str(qx[1][0][0], QX100, strlen(QX100), 16); - fp_read_str(qx[1][0][1], QX101, strlen(QX101), 16); - fp_read_str(qx[1][1][0], QX110, strlen(QX110), 16); - fp_read_str(qx[1][1][1], QX111, strlen(QX111), 16); - - fp_read_str(qy[0][0][0], QY000, strlen(QY000), 16); - fp_read_str(qy[0][0][1], QY001, strlen(QY001), 16); - fp_read_str(qy[0][1][0], QY010, strlen(QY010), 16); - fp_read_str(qy[0][1][1], QY011, strlen(QY011), 16); - fp_read_str(qy[1][0][0], QY100, strlen(QY100), 16); - fp_read_str(qy[1][0][1], QY101, strlen(QY101), 16); - fp_read_str(qy[1][1][0], QY110, strlen(QY110), 16); - fp_read_str(qy[1][1][1], QY111, strlen(QY111), 16); + ep_curve_get_ord(n); TEST_CASE("pairing non-degeneracy is correct") { - ep_rand(p); - pp_map_k48(e1, p, qx, qy); + ep_rand(p[0]); + ep8_rand(q[0]); + pp_map_k48(e1, p[0], q[0]); TEST_ASSERT(fp48_cmp_dig(e1, 1) != RLC_EQ, end); + ep_set_infty(p[0]); + pp_map_k48(e1, p[0], q[0]); + TEST_ASSERT(fp48_cmp_dig(e1, 1) == RLC_EQ, end); + ep_rand(p[0]); + ep8_set_infty(q[0]); + pp_map_k48(e1, p[0], q[0]); + TEST_ASSERT(fp48_cmp_dig(e1, 1) == RLC_EQ, end); } TEST_END; TEST_CASE("pairing is bilinear") { - ep_rand(p); + ep_rand(p[0]); + ep8_rand(q[0]); bn_rand_mod(k, n); - pp_map_k48(e1, p, qx, qy); - ep_mul(p, p, k); - pp_map_k48(e2, p, qx, qy); - fp48_exp(e1, e1, k); + ep8_mul(r, q[0], k); + pp_map_k48(e1, p[0], r); + pp_map_k48(e2, p[0], q[0]); + fp48_exp(e2, e2, k); + TEST_ASSERT(fp48_cmp(e1, e2) == RLC_EQ, end); + ep_mul(p[0], p[0], k); + pp_map_k48(e2, p[0], q[0]); + TEST_ASSERT(fp48_cmp(e1, e2) == RLC_EQ, end); + ep_dbl(p[0], p[0]); + pp_map_k48(e2, p[0], q[0]); + fp48_sqr(e1, e1); TEST_ASSERT(fp48_cmp(e1, e2) == RLC_EQ, end); - fp8_set_dig(qz, 1); - pp_dbl_k48(e2, qx, qy, qz, p); - fp8_inv(qz, qz); - fp8_mul(qx, qx, qz); - fp8_mul(qy, qy, qz); - fp8_set_dig(qz, 1); - pp_map_k48(e2, p, qx, qy); + ep8_dbl(q[0], q[0]); + pp_map_k48(e2, p[0], q[0]); fp48_sqr(e1, e1); TEST_ASSERT(fp48_cmp(e1, e2) == RLC_EQ, end); } TEST_END; + + TEST_CASE("multi-pairing is correct") { + ep_rand(p[i % 2]); + ep8_rand(q[i % 2]); + pp_map_k48(e1, p[i % 2], q[i % 2]); + ep_rand(p[1 - (i % 2)]); + ep8_set_infty(q[1 - (i % 2)]); + pp_map_sim_k48(e2, p, q, 2); + TEST_ASSERT(fp48_cmp(e1, e2) == RLC_EQ, end); + ep_set_infty(p[1 - (i % 2)]); + ep8_rand(q[1 - (i % 2)]); + pp_map_sim_k48(e2, p, q, 2); + TEST_ASSERT(fp48_cmp(e1, e2) == RLC_EQ, end); + ep8_set_infty(q[i % 2]); + pp_map_sim_k48(e2, p, q, 2); + TEST_ASSERT(fp48_cmp_dig(e2, 1) == RLC_EQ, end); + ep_rand(p[0]); + ep8_rand(q[0]); + pp_map_k48(e1, p[0], q[0]); + ep_rand(p[1]); + ep8_rand(q[1]); + pp_map_k48(e2, p[1], q[1]); + fp48_mul(e1, e1, e2); + pp_map_sim_k48(e2, p, q, 2); + TEST_ASSERT(fp48_cmp(e1, e2) == RLC_EQ, end); + ep_neg(p[1], p[0]); + ep8_copy(q[1], q[0]); + pp_map_sim_k48(e1, p, q, 2); + TEST_ASSERT(fp48_cmp_dig(e1, 1) == RLC_EQ, end); + } TEST_END; } RLC_CATCH_ANY { util_print("FATAL ERROR!\n"); @@ -2606,12 +3499,14 @@ static int pairing48(void) { end: bn_free(n); bn_free(k); - ep_free(p); - fp8_free(qx); - fp8_free(qy); - fp8_free(qz); fp48_free(e1); fp48_free(e2); + ep8_free(r); + + for (j = 0; j < 2; j++) { + ep_free(p[j]); + ep8_free(q[j]); + } return code; } @@ -3033,6 +3928,23 @@ int main(void) { util_banner("Arithmetic", 1); + if (ep_param_embed() == 1) { + if (doubling1() != RLC_OK) { + core_clean(); + return 1; + } + + if (addition1() != RLC_OK) { + core_clean(); + return 1; + } + + if (pairing1() != RLC_OK) { + core_clean(); + return 1; + } + } + if (ep_param_embed() == 2) { if (doubling2() != RLC_OK) { core_clean(); @@ -3067,35 +3979,35 @@ int main(void) { } } - if (ep_param_embed() == 24) { - if (doubling24() != RLC_OK) { + if (ep_param_embed() == 12) { + if (doubling12() != RLC_OK) { core_clean(); return 1; } - if (addition24() != RLC_OK) { + if (addition12() != RLC_OK) { core_clean(); return 1; } - if (pairing24() != RLC_OK) { + if (pairing12() != RLC_OK) { core_clean(); return 1; } } - if (ep_param_embed() == 12) { - if (doubling12() != RLC_OK) { + if (ep_param_embed() == 16) { + if (doubling16() != RLC_OK) { core_clean(); return 1; } - if (addition12() != RLC_OK) { + if (addition16() != RLC_OK) { core_clean(); return 1; } - if (pairing12() != RLC_OK) { + if (pairing16() != RLC_OK) { core_clean(); return 1; } @@ -3118,6 +4030,23 @@ int main(void) { } } + if (ep_param_embed() == 24) { + if (doubling24() != RLC_OK) { + core_clean(); + return 1; + } + + if (addition24() != RLC_OK) { + core_clean(); + return 1; + } + + if (pairing24() != RLC_OK) { + core_clean(); + return 1; + } + } + if (ep_param_embed() == 48) { if (doubling48() != RLC_OK) { core_clean(); @@ -3156,4 +4085,4 @@ int main(void) { core_clean(); return 0; -} +} \ No newline at end of file diff --git a/tools/relic-gen-label.sh b/tools/relic-gen-label.sh index 992f547d7..87b462e27 100755 --- a/tools/relic-gen-label.sh +++ b/tools/relic-gen-label.sh @@ -172,6 +172,13 @@ echo "#define ep4_t RLC_PREFIX(ep4_t)" echo REDEF2 epx ep4 +echo "#undef ep8_st" +echo "#undef ep8_t" +echo "#define ep8_st RLC_PREFIX(ep8_st)" +echo "#define ep8_t RLC_PREFIX(ep8_t)" +echo +REDEF2 epx ep8 + echo "#undef fp2_st" echo "#undef fp2_t" echo "#undef dv2_t" diff --git a/tools/run-pairings.sh b/tools/run-pairings.sh index c6b4988d5..0f091790f 100755 --- a/tools/run-pairings.sh +++ b/tools/run-pairings.sh @@ -9,5 +9,9 @@ for script in preset/x64-pbc-*; do ../$script ../ make ./bin/test_fpx && ./bin/test_pc + if [ $? -ne 0 ]; then + echo "FAILED: target-$file" + exit 1 + fi cd .. done